diff --git a/.b2r2-ci.json b/.b2r2-ci.json index c3ee42c3..4e0cc0c8 100644 --- a/.b2r2-ci.json +++ b/.b2r2-ci.json @@ -1,4 +1,4 @@ { - "evaltest": "311ef72ce3898f74d82ba3a1845042637eeb9fb9", - "switchtest": "ab771e0395067631afcd2a4522e7b038033e2451" + "evaltest": "main", + "switchtest": "main" } diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index c6a62142..04f80af0 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -7,6 +7,12 @@ "commands": [ "fsdocs" ] + }, + "dotnet-fsharplint": { + "version": "0.21.3", + "commands": [ + "dotnet-fsharplint" + ] } } -} \ No newline at end of file +} diff --git a/.editorconfig b/.editorconfig index f7c9b4a3..74bddf24 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,3 +5,12 @@ indent_style = space indent_size = 2 end_of_line = lf trim_trailing_whitespace = true + +[*.{fs,fsi,fsx}] +indent_size = 2 +max_line_length = 80 +fsharp_space_before_parameter = true +fsharp_space_before_lowercase_invocation = true +fsharp_space_before_uppercase_invocation = true +fsharp_space_before_class_constructor = true +fsharp_space_before_member = true diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3318dd8e..a555cbd5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,29 +1,46 @@ -image: mcr.microsoft.com/dotnet/sdk:6.0 - stages: - build - extra -build: +lint: + image: mcr.microsoft.com/dotnet/sdk:5.0.408-focal + stage: build + before_script: + - LATEST_COMMIT=$(git ls-remote https://gitlab-ci-token:${CI_JOB_TOKEN}@softsec.kaist.ac.kr:8000/B2R2/B2R2.git HEAD | awk '{print $1}') + - CHANGES=$(if [ "$LATEST_COMMIT" == "$CI_COMMIT_SHA" ]; then git diff-tree --diff-filter=ACM --no-commit-id --name-only -r $LATEST_COMMIT; else git diff-tree --diff-filter=ACM --no-commit-id --name-only -r $LATEST_COMMIT -r $CI_COMMIT_SHA; fi | sed '/.fs$/!d' | sed '/CFG.Tests.fs/d') + script: + - dotnet tool install --global dotnet-fsharplint --version 0.21.3 + - echo $CHANGES + - for f in $CHANGES; do echo $f; /root/.dotnet/tools/dotnet-fsharplint lint $f; done + tags: + - b2r2 + +build-debug: + image: mcr.microsoft.com/dotnet/sdk:8.0 stage: build script: - dotnet restore + - dotnet tool restore - dotnet test + tags: + - b2r2 + +build-release: + image: mcr.microsoft.com/dotnet/sdk:8.0 + stage: build + script: + - dotnet restore + - dotnet tool restore - dotnet test -c Release - dotnet pack -p:PackageVersion=0.0.0-test -c Release -o `pwd`/build/ - artifacts: - paths: - - build/ - expire_in: 3 hrs tags: - b2r2 extra: + image: mcr.microsoft.com/dotnet/sdk:8.0 stage: extra script: - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@softsec.kaist.ac.kr:8000/B2R2/ci-runner - dotnet run --project ci-runner/CIStarter -- $CI_URL $CI_COMMIT_SHA $CI_COMMIT_REF_NAME "$GITLAB_USER_NAME" - dependencies: - - build tags: - b2r2 diff --git a/AUTHORS.md b/AUTHORS.md index c1af911c..270f42a4 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -3,10 +3,11 @@ # Current Developers (alphabetical order) -- Jaeseung Choi - Su Geun Ji - Seung Il Jung +- Jun Tae Kim - Soomin Kim +- Hee Dong Yang # Contributors @@ -15,8 +16,11 @@ a list of the contributors in alphabetic order. - Anar Abbas - Mehdi Aghakishiyev +- Zunnoor Fayyaz Awan +- Jaeseung Choi - TA Thanh Dinh - HyungSeok Han +- Abdirakhman Ismail - Cheonhoo Jeon - Subin Jeong - Minkyu Jung @@ -24,13 +28,18 @@ a list of the contributors in alphabetic order. - Dongkwan Kim - Doyeon Kim - Hongsik Kim +- Hyungseok Kim - Jaemin Kim - JungHyun Kim - Kangsu Kim +- Yeonghun Kim +- JeongWoo Lee - Junoh Lee - Minsu Lee - Sihoon Lee - DongYeop Oh +- Geonwoo Park - Ali Ahmed Sheikh - MyeongGeun Shin - Michael Tegegn +- Hyungjoon Yoon diff --git a/B2R2.sln b/B2R2.sln index af4e4e5e..a19d050b 100644 --- a/B2R2.sln +++ b/B2R2.sln @@ -5,117 +5,105 @@ VisualStudioVersion = 17.0.32112.339 MinimumVisualStudioVersion = 15.0.26124.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{96279848-CA27-42C6-9488-498A8E696F67}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Core", "src\Core\B2R2.Core.fsproj", "{92A41F1C-8B77-4479-8CD3-FB8987269C60}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Core", "src\Core\B2R2.Core.fsproj", "{92A41F1C-8B77-4479-8CD3-FB8987269C60}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Core.Tests", "src\Core.Tests\B2R2.Core.Tests.fsproj", "{29FF59AD-E83D-4084-9DE5-564CA5687981}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Core.Tests", "src\Core.Tests\B2R2.Core.Tests.fsproj", "{29FF59AD-E83D-4084-9DE5-564CA5687981}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.BinIR", "src\BinIR\B2R2.BinIR.fsproj", "{7AE36E18-182E-4E36-AD0E-08F326B381B2}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinIR", "src\BinIR\B2R2.BinIR.fsproj", "{7AE36E18-182E-4E36-AD0E-08F326B381B2}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.BinIR.Tests", "src\BinIR.Tests\B2R2.BinIR.Tests.fsproj", "{A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.BinIR.Tests", "src\BinIR.Tests\B2R2.BinIR.Tests.fsproj", "{A015D2D5-EBB2-455C-BF72-EE8EEC2854D4}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FrontEnd", "FrontEnd", "{55E62B6F-2C33-4E89-ADD5-0CE9BAA76401}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BinLifter", "BinLifter", "{0CAF4618-5C72-4A71-BAEB-79AA4065B9D6}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Core", "src\FrontEnd\BinLifter\Core\B2R2.FrontEnd.BinLifter.Core.fsproj", "{717ED421-8AE2-435F-888F-91F676C87C32}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.Core", "src\FrontEnd\BinLifter\Core\B2R2.FrontEnd.BinLifter.Core.fsproj", "{717ED421-8AE2-435F-888F-91F676C87C32}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Intel", "src\FrontEnd\BinLifter\Intel\B2R2.FrontEnd.BinLifter.Intel.fsproj", "{B9E587C6-D492-478A-856D-A7FC67EB5FE0}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.Intel", "src\FrontEnd\BinLifter\Intel\B2R2.FrontEnd.BinLifter.Intel.fsproj", "{B9E587C6-D492-478A-856D-A7FC67EB5FE0}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.ARM32", "src\FrontEnd\BinLifter\ARM32\B2R2.FrontEnd.BinLifter.ARM32.fsproj", "{65784B83-F76F-4C1A-AAAD-6417614116C6}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.ARM32", "src\FrontEnd\BinLifter\ARM32\B2R2.FrontEnd.BinLifter.ARM32.fsproj", "{65784B83-F76F-4C1A-AAAD-6417614116C6}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.ARM64", "src\FrontEnd\BinLifter\ARM64\B2R2.FrontEnd.BinLifter.ARM64.fsproj", "{8CA197A9-96CE-4284-80B5-EC0132F20A62}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.ARM64", "src\FrontEnd\BinLifter\ARM64\B2R2.FrontEnd.BinLifter.ARM64.fsproj", "{8CA197A9-96CE-4284-80B5-EC0132F20A62}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.AVR", "src\FrontEnd\BinLifter\AVR\B2R2.FrontEnd.BinLifter.AVR.fsproj", "{A425AE4A-691C-4540-9CA0-2B7D32EFE230}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.AVR", "src\FrontEnd\BinLifter\AVR\B2R2.FrontEnd.BinLifter.AVR.fsproj", "{A425AE4A-691C-4540-9CA0-2B7D32EFE230}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.MIPS", "src\FrontEnd\BinLifter\MIPS\B2R2.FrontEnd.BinLifter.MIPS.fsproj", "{40C841D4-C7D0-489B-80FB-5B4D22DB60E7}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.MIPS", "src\FrontEnd\BinLifter\MIPS\B2R2.FrontEnd.BinLifter.MIPS.fsproj", "{40C841D4-C7D0-489B-80FB-5B4D22DB60E7}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.EVM", "src\FrontEnd\BinLifter\EVM\B2R2.FrontEnd.BinLifter.EVM.fsproj", "{49C21BFB-126B-473D-876E-C9965CCD3096}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.EVM", "src\FrontEnd\BinLifter\EVM\B2R2.FrontEnd.BinLifter.EVM.fsproj", "{49C21BFB-126B-473D-876E-C9965CCD3096}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.TMS320C6000", "src\FrontEnd\BinLifter\TMS320C6000\B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj", "{E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.TMS320C6000", "src\FrontEnd\BinLifter\TMS320C6000\B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj", "{E1311CDD-8C52-4F55-B05A-1FBAC7FB693D}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.CIL", "src\FrontEnd\BinLifter\CIL\B2R2.FrontEnd.BinLifter.CIL.fsproj", "{A0A5A856-7C41-46E5-B773-97B677E532B5}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.CIL", "src\FrontEnd\BinLifter\CIL\B2R2.FrontEnd.BinLifter.CIL.fsproj", "{A0A5A856-7C41-46E5-B773-97B677E532B5}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.SH4", "src\FrontEnd\BinLifter\SH4\B2R2.FrontEnd.BinLifter.SH4.fsproj", "{01233DB1-3B00-43D5-BF95-8D8A11F2613C}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.SH4", "src\FrontEnd\BinLifter\SH4\B2R2.FrontEnd.BinLifter.SH4.fsproj", "{01233DB1-3B00-43D5-BF95-8D8A11F2613C}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.PPC32", "src\FrontEnd\BinLifter\PPC32\B2R2.FrontEnd.BinLifter.PPC32.fsproj", "{96993893-7A1E-4F01-827E-BDE2FA8537C9}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.PARISC", "src\FrontEnd\BinLifter\PARISC\B2R2.FrontEnd.BinLifter.PARISC.fsproj", "{651E2062-CD12-46E1-9859-B90C0EE6ACC2}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Sparc64", "src\FrontEnd\BinLifter\Sparc64\B2R2.FrontEnd.BinLifter.Sparc64.fsproj", "{5A95A80D-9263-4573-9E2D-AACC5E225C3F}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.PPC32", "src\FrontEnd\BinLifter\PPC32\B2R2.FrontEnd.BinLifter.PPC32.fsproj", "{96993893-7A1E-4F01-827E-BDE2FA8537C9}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.WASM", "src\FrontEnd\BinLifter\WASM\B2R2.FrontEnd.BinLifter.WASM.fsproj", "{DDA77DD5-651E-4180-97C1-839A501773DD}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.Python", "src\FrontEnd\BinLifter\Python\B2R2.FrontEnd.BinLifter.Python.fsproj", "{6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Optimizer", "src\FrontEnd\BinLifter\Optimizer\B2R2.FrontEnd.BinLifter.Optimizer.fsproj", "{772A6D09-0FB3-46B0-A234-9196704D4657}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.RISCV", "src\FrontEnd\BinLifter\RISCV\B2R2.FrontEnd.BinLifter.RISCV.fsproj", "{BDD2D535-D893-40F4-BCCD-993454FF1BE7}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.Tests", "src\FrontEnd\BinLifter.Tests\B2R2.FrontEnd.BinLifter.Tests.fsproj", "{5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.S390", "src\FrontEnd\BinLifter\S390\B2R2.FrontEnd.BinLifter.S390.fsproj", "{60A4EA1F-3497-4837-976C-1AE15BFACB60}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinFile", "src\FrontEnd\BinFile\B2R2.FrontEnd.BinFile.fsproj", "{1CD7C68A-A371-49CE-8F54-A7E781EE332A}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.SPARC", "src\FrontEnd\BinLifter\SPARC\B2R2.FrontEnd.BinLifter.SPARC.fsproj", "{5A95A80D-9263-4573-9E2D-AACC5E225C3F}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinFile.Tests", "src\FrontEnd\BinFile.Tests\B2R2.FrontEnd.BinFile.Tests.fsproj", "{80DB4163-821F-4C85-80AB-B6E5E946C4F9}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.WASM", "src\FrontEnd\BinLifter\WASM\B2R2.FrontEnd.BinLifter.WASM.fsproj", "{DDA77DD5-651E-4180-97C1-839A501773DD}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinInterface", "src\FrontEnd\BinInterface\B2R2.FrontEnd.BinInterface.fsproj", "{C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.Optimizer", "src\FrontEnd\BinLifter\Optimizer\B2R2.FrontEnd.BinLifter.Optimizer.fsproj", "{772A6D09-0FB3-46B0-A234-9196704D4657}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.NameMangling", "src\FrontEnd\NameMangling\B2R2.FrontEnd.NameMangling.fsproj", "{ADB65D83-B476-4F0B-8B9F-8719A8AB7624}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinLifter.Tests", "src\FrontEnd\BinLifter.Tests\B2R2.FrontEnd.BinLifter.Tests.fsproj", "{5A9E82F6-3FAF-4459-A1DB-5AF7609F29C1}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.NameMangling.Tests", "src\FrontEnd\NameMangling.Tests\B2R2.FrontEnd.NameMangling.Tests.fsproj", "{26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinFile", "src\FrontEnd\BinFile\B2R2.FrontEnd.BinFile.fsproj", "{1CD7C68A-A371-49CE-8F54-A7E781EE332A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MiddleEnd", "MiddleEnd", "{B581729A-04EA-4F57-8347-795C1F14257D}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.BinFile.Tests", "src\FrontEnd\BinFile.Tests\B2R2.FrontEnd.BinFile.Tests.fsproj", "{80DB4163-821F-4C85-80AB-B6E5E946C4F9}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.ConcEval", "src\MiddleEnd\ConcEval\B2R2.MiddleEnd.ConcEval.fsproj", "{1EB78AE6-9233-4FE8-8EE1-292AF412D731}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.Core", "src\FrontEnd\Core\B2R2.FrontEnd.Core.fsproj", "{C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.BinGraph", "src\MiddleEnd\BinGraph\B2R2.MiddleEnd.BinGraph.fsproj", "{A831C214-9CEB-4B37-B2B2-2D25A34E43EF}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.NameMangling", "src\FrontEnd\NameMangling\B2R2.FrontEnd.NameMangling.fsproj", "{ADB65D83-B476-4F0B-8B9F-8719A8AB7624}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.BinGraph.Tests", "src\MiddleEnd\BinGraph.Tests\B2R2.MiddleEnd.BinGraph.Tests.fsproj", "{DBD08956-B4AA-449C-8408-FC0638A20795}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.ControlFlowGraph", "src\MiddleEnd\ControlFlowGraph\B2R2.MiddleEnd.ControlFlowGraph.fsproj", "{B008D195-BA7B-461D-93D4-284532F9274D}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.DataFlow", "src\MiddleEnd\DataFlow\B2R2.MiddleEnd.DataFlow.fsproj", "{D40C3359-5983-4021-9F0E-8E7D450EFEFF}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.DataFlow.Tests", "src\MiddleEnd\DataFlow.Tests\B2R2.MiddleEnd.DataFlow.Tests.fsproj", "{78363647-923A-446F-91BF-4CC09EA28CD0}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.ControlFlowAnalysis", "src\MiddleEnd\ControlFlowAnalysis\B2R2.MiddleEnd.ControlFlowAnalysis.fsproj", "{A18591FD-1A3C-488D-A814-FED8734FF1CE}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.BinEssence", "src\MiddleEnd\BinEssence\B2R2.MiddleEnd.BinEssence.fsproj", "{02EEDA2B-1311-4F68-879D-0F32686BA650}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.MiddleEnd.BinEssence.Tests", "src\MiddleEnd\BinEssence.Tests\B2R2.MiddleEnd.BinEssence.Tests.fsproj", "{27C13F72-B915-4F08-BC20-628AFDFCF088}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.FrontEnd.NameMangling.Tests", "src\FrontEnd\NameMangling.Tests\B2R2.FrontEnd.NameMangling.Tests.fsproj", "{26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RearEnd", "RearEnd", "{BBF63851-BC21-45CC-A671-9ED1A538E052}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Core", "src\RearEnd\Core\B2R2.RearEnd.Core.fsproj", "{42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.Core", "src\RearEnd\Core\B2R2.RearEnd.Core.fsproj", "{42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.FileViewer", "src\RearEnd\FileViewer\B2R2.RearEnd.FileViewer.fsproj", "{84AD21E8-23A0-4029-9767-50F7863E7A02}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.FileViewer", "src\RearEnd\FileViewer\B2R2.RearEnd.FileViewer.fsproj", "{84AD21E8-23A0-4029-9767-50F7863E7A02}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.BinDump", "src\RearEnd\BinDump\B2R2.RearEnd.BinDump.fsproj", "{44BFF304-5D42-4065-9260-E2C9E552EB24}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.BinDump", "src\RearEnd\BinDump\B2R2.RearEnd.BinDump.fsproj", "{44BFF304-5D42-4065-9260-E2C9E552EB24}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.ROP", "src\RearEnd\ROP\B2R2.RearEnd.ROP.fsproj", "{0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.ROP", "src\RearEnd\ROP\B2R2.RearEnd.ROP.fsproj", "{0794FC55-D4F9-43F1-8C2F-CAC0E455FCC4}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.Visualization", "src\RearEnd\Visualization\B2R2.RearEnd.Visualization.fsproj", "{7FACEAF5-30A5-4502-822C-485FE980A6C3}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Visualization", "src\RearEnd\Visualization\B2R2.RearEnd.Visualization.fsproj", "{7FACEAF5-30A5-4502-822C-485FE980A6C3}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.BinExplorer", "src\RearEnd\BinExplorer\B2R2.RearEnd.BinExplorer.fsproj", "{05276DA5-3CF1-4950-8923-9A5F4C1A15D8}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.BinExplorer", "src\RearEnd\BinExplorer\B2R2.RearEnd.BinExplorer.fsproj", "{05276DA5-3CF1-4950-8923-9A5F4C1A15D8}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.Assembler", "src\RearEnd\Assembler\B2R2.RearEnd.Assembler.fsproj", "{300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Assembler", "src\RearEnd\Assembler\B2R2.RearEnd.Assembler.fsproj", "{300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.Repl", "src\RearEnd\Repl\B2R2.RearEnd.Repl.fsproj", "{35184561-8AAB-4E74-9E0D-231D16E336BF}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Repl", "src\RearEnd\Repl\B2R2.RearEnd.Repl.fsproj", "{35184561-8AAB-4E74-9E0D-231D16E336BF}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.Transformer", "src\RearEnd\Transformer\B2R2.RearEnd.Transformer.fsproj", "{85F9D3FE-089B-4B93-BDE0-333775581FC9}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.RearEnd.Launcher", "src\RearEnd\Launcher\B2R2.RearEnd.Launcher.fsproj", "{ECF6ADAE-C222-41E9-BA5B-811866193A2B}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.RearEnd.Launcher", "src\RearEnd\Launcher\B2R2.RearEnd.Launcher.fsproj", "{ECF6ADAE-C222-41E9-BA5B-811866193A2B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Peripheral", "Peripheral", "{F0888151-28C5-4EF0-86CB-9C66218F89AE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Assembly", "Assembly", "{F90413F1-AB57-43C0-B401-E7C2EC83198C}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.Core", "src\Peripheral\Assembly\Core\B2R2.Peripheral.Assembly.Core.fsproj", "{D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.Core", "src\Peripheral\Assembly\Core\B2R2.Peripheral.Assembly.Core.fsproj", "{D332DFCA-E6EE-482B-BAE4-2592F5BB5D26}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.ARM32", "src\Peripheral\Assembly\ARM32\B2R2.Peripheral.Assembly.ARM32.fsproj", "{54652BFC-61CF-4DF0-B34A-64406A43F708}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.ARM32", "src\Peripheral\Assembly\ARM32\B2R2.Peripheral.Assembly.ARM32.fsproj", "{54652BFC-61CF-4DF0-B34A-64406A43F708}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.Intel", "src\Peripheral\Assembly\Intel\B2R2.Peripheral.Assembly.Intel.fsproj", "{F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.Intel", "src\Peripheral\Assembly\Intel\B2R2.Peripheral.Assembly.Intel.fsproj", "{F3EC4BDB-88C0-4CC7-963F-75ACB96A83D9}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.MIPS", "src\Peripheral\Assembly\MIPS\B2R2.Peripheral.Assembly.MIPS.fsproj", "{7C6A7725-FA4E-45FB-A4CB-8F581D017C05}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.MIPS", "src\Peripheral\Assembly\MIPS\B2R2.Peripheral.Assembly.MIPS.fsproj", "{7C6A7725-FA4E-45FB-A4CB-8F581D017C05}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.LowUIR", "src\Peripheral\Assembly\LowUIR\B2R2.Peripheral.Assembly.LowUIR.fsproj", "{DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.LowUIR", "src\Peripheral\Assembly\LowUIR\B2R2.Peripheral.Assembly.LowUIR.fsproj", "{DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.AsmInterface", "src\Peripheral\Assembly\AsmInterface\B2R2.Peripheral.Assembly.AsmInterface.fsproj", "{A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.AsmInterface", "src\Peripheral\Assembly\AsmInterface\B2R2.Peripheral.Assembly.AsmInterface.fsproj", "{A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.Peripheral.Assembly.Tests", "src\Peripheral\Assembly.Tests\B2R2.Peripheral.Assembly.Tests.fsproj", "{3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}" -EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.RISCV", "src\FrontEnd\BinLifter\RISCV\B2R2.FrontEnd.BinLifter.RISCV.fsproj", "{BDD2D535-D893-40F4-BCCD-993454FF1BE7}" +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "B2R2.Peripheral.Assembly.Tests", "src\Peripheral\Assembly.Tests\B2R2.Peripheral.Assembly.Tests.fsproj", "{3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -295,6 +283,18 @@ Global {01233DB1-3B00-43D5-BF95-8D8A11F2613C}.Release|x64.Build.0 = Release|Any CPU {01233DB1-3B00-43D5-BF95-8D8A11F2613C}.Release|x86.ActiveCfg = Release|Any CPU {01233DB1-3B00-43D5-BF95-8D8A11F2613C}.Release|x86.Build.0 = Release|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Debug|x64.ActiveCfg = Debug|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Debug|x64.Build.0 = Debug|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Debug|x86.ActiveCfg = Debug|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Debug|x86.Build.0 = Debug|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Release|Any CPU.Build.0 = Release|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Release|x64.ActiveCfg = Release|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Release|x64.Build.0 = Release|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Release|x86.ActiveCfg = Release|Any CPU + {651E2062-CD12-46E1-9859-B90C0EE6ACC2}.Release|x86.Build.0 = Release|Any CPU {96993893-7A1E-4F01-827E-BDE2FA8537C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {96993893-7A1E-4F01-827E-BDE2FA8537C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {96993893-7A1E-4F01-827E-BDE2FA8537C9}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -307,6 +307,42 @@ Global {96993893-7A1E-4F01-827E-BDE2FA8537C9}.Release|x64.Build.0 = Release|Any CPU {96993893-7A1E-4F01-827E-BDE2FA8537C9}.Release|x86.ActiveCfg = Release|Any CPU {96993893-7A1E-4F01-827E-BDE2FA8537C9}.Release|x86.Build.0 = Release|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Debug|x64.ActiveCfg = Debug|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Debug|x64.Build.0 = Debug|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Debug|x86.ActiveCfg = Debug|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Debug|x86.Build.0 = Debug|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Release|Any CPU.Build.0 = Release|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Release|x64.ActiveCfg = Release|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Release|x64.Build.0 = Release|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Release|x86.ActiveCfg = Release|Any CPU + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1}.Release|x86.Build.0 = Release|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x64.ActiveCfg = Debug|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x64.Build.0 = Debug|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x86.ActiveCfg = Debug|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x86.Build.0 = Debug|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|Any CPU.Build.0 = Release|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x64.ActiveCfg = Release|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x64.Build.0 = Release|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x86.ActiveCfg = Release|Any CPU + {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x86.Build.0 = Release|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Debug|x64.ActiveCfg = Debug|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Debug|x64.Build.0 = Debug|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Debug|x86.ActiveCfg = Debug|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Debug|x86.Build.0 = Debug|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Release|Any CPU.Build.0 = Release|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Release|x64.ActiveCfg = Release|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Release|x64.Build.0 = Release|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Release|x86.ActiveCfg = Release|Any CPU + {60A4EA1F-3497-4837-976C-1AE15BFACB60}.Release|x86.Build.0 = Release|Any CPU {5A95A80D-9263-4573-9E2D-AACC5E225C3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5A95A80D-9263-4573-9E2D-AACC5E225C3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5A95A80D-9263-4573-9E2D-AACC5E225C3F}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -415,114 +451,6 @@ Global {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x64.Build.0 = Release|Any CPU {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x86.ActiveCfg = Release|Any CPU {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C}.Release|x86.Build.0 = Release|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Debug|x64.ActiveCfg = Debug|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Debug|x64.Build.0 = Debug|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Debug|x86.ActiveCfg = Debug|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Debug|x86.Build.0 = Debug|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Release|Any CPU.Build.0 = Release|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Release|x64.ActiveCfg = Release|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Release|x64.Build.0 = Release|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Release|x86.ActiveCfg = Release|Any CPU - {1EB78AE6-9233-4FE8-8EE1-292AF412D731}.Release|x86.Build.0 = Release|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Debug|x64.ActiveCfg = Debug|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Debug|x64.Build.0 = Debug|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Debug|x86.ActiveCfg = Debug|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Debug|x86.Build.0 = Debug|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Release|Any CPU.Build.0 = Release|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Release|x64.ActiveCfg = Release|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Release|x64.Build.0 = Release|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Release|x86.ActiveCfg = Release|Any CPU - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF}.Release|x86.Build.0 = Release|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Debug|x64.ActiveCfg = Debug|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Debug|x64.Build.0 = Debug|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Debug|x86.ActiveCfg = Debug|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Debug|x86.Build.0 = Debug|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Release|Any CPU.Build.0 = Release|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Release|x64.ActiveCfg = Release|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Release|x64.Build.0 = Release|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Release|x86.ActiveCfg = Release|Any CPU - {DBD08956-B4AA-449C-8408-FC0638A20795}.Release|x86.Build.0 = Release|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Debug|x64.ActiveCfg = Debug|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Debug|x64.Build.0 = Debug|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Debug|x86.ActiveCfg = Debug|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Debug|x86.Build.0 = Debug|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Release|Any CPU.Build.0 = Release|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Release|x64.ActiveCfg = Release|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Release|x64.Build.0 = Release|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Release|x86.ActiveCfg = Release|Any CPU - {B008D195-BA7B-461D-93D4-284532F9274D}.Release|x86.Build.0 = Release|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Debug|x64.ActiveCfg = Debug|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Debug|x64.Build.0 = Debug|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Debug|x86.ActiveCfg = Debug|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Debug|x86.Build.0 = Debug|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Release|Any CPU.Build.0 = Release|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Release|x64.ActiveCfg = Release|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Release|x64.Build.0 = Release|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Release|x86.ActiveCfg = Release|Any CPU - {D40C3359-5983-4021-9F0E-8E7D450EFEFF}.Release|x86.Build.0 = Release|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Debug|x64.ActiveCfg = Debug|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Debug|x64.Build.0 = Debug|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Debug|x86.ActiveCfg = Debug|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Debug|x86.Build.0 = Debug|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Release|Any CPU.Build.0 = Release|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Release|x64.ActiveCfg = Release|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Release|x64.Build.0 = Release|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Release|x86.ActiveCfg = Release|Any CPU - {78363647-923A-446F-91BF-4CC09EA28CD0}.Release|x86.Build.0 = Release|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Debug|x64.ActiveCfg = Debug|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Debug|x64.Build.0 = Debug|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Debug|x86.ActiveCfg = Debug|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Debug|x86.Build.0 = Debug|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Release|Any CPU.Build.0 = Release|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Release|x64.ActiveCfg = Release|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Release|x64.Build.0 = Release|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Release|x86.ActiveCfg = Release|Any CPU - {A18591FD-1A3C-488D-A814-FED8734FF1CE}.Release|x86.Build.0 = Release|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Debug|Any CPU.Build.0 = Debug|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Debug|x64.ActiveCfg = Debug|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Debug|x64.Build.0 = Debug|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Debug|x86.ActiveCfg = Debug|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Debug|x86.Build.0 = Debug|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Release|Any CPU.ActiveCfg = Release|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Release|Any CPU.Build.0 = Release|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Release|x64.ActiveCfg = Release|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Release|x64.Build.0 = Release|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Release|x86.ActiveCfg = Release|Any CPU - {02EEDA2B-1311-4F68-879D-0F32686BA650}.Release|x86.Build.0 = Release|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Debug|Any CPU.Build.0 = Debug|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Debug|x64.ActiveCfg = Debug|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Debug|x64.Build.0 = Debug|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Debug|x86.ActiveCfg = Debug|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Debug|x86.Build.0 = Debug|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Release|Any CPU.ActiveCfg = Release|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Release|Any CPU.Build.0 = Release|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Release|x64.ActiveCfg = Release|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Release|x64.Build.0 = Release|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Release|x86.ActiveCfg = Release|Any CPU - {27C13F72-B915-4F08-BC20-628AFDFCF088}.Release|x86.Build.0 = Release|Any CPU {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|Any CPU.Build.0 = Debug|Any CPU {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -619,6 +547,18 @@ Global {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x64.Build.0 = Release|Any CPU {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x86.ActiveCfg = Release|Any CPU {35184561-8AAB-4E74-9E0D-231D16E336BF}.Release|x86.Build.0 = Release|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Debug|x64.ActiveCfg = Debug|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Debug|x64.Build.0 = Debug|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Debug|x86.ActiveCfg = Debug|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Debug|x86.Build.0 = Debug|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Release|Any CPU.Build.0 = Release|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Release|x64.ActiveCfg = Release|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Release|x64.Build.0 = Release|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Release|x86.ActiveCfg = Release|Any CPU + {85F9D3FE-089B-4B93-BDE0-333775581FC9}.Release|x86.Build.0 = Release|Any CPU {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU {ECF6ADAE-C222-41E9-BA5B-811866193A2B}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -715,18 +655,6 @@ Global {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x64.Build.0 = Release|Any CPU {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x86.ActiveCfg = Release|Any CPU {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5}.Release|x86.Build.0 = Release|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x64.ActiveCfg = Debug|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x64.Build.0 = Debug|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x86.ActiveCfg = Debug|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Debug|x86.Build.0 = Debug|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|Any CPU.Build.0 = Release|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x64.ActiveCfg = Release|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x64.Build.0 = Release|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x86.ActiveCfg = Release|Any CPU - {BDD2D535-D893-40F4-BCCD-993454FF1BE7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -748,7 +676,11 @@ Global {E1311CDD-8C52-4F55-B05A-1FBAC7FB693D} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} {A0A5A856-7C41-46E5-B773-97B677E532B5} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} {01233DB1-3B00-43D5-BF95-8D8A11F2613C} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {651E2062-CD12-46E1-9859-B90C0EE6ACC2} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} {96993893-7A1E-4F01-827E-BDE2FA8537C9} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {6AB8324D-C71B-4F3D-A5E2-30702C9BDFA1} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {BDD2D535-D893-40F4-BCCD-993454FF1BE7} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} + {60A4EA1F-3497-4837-976C-1AE15BFACB60} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} {5A95A80D-9263-4573-9E2D-AACC5E225C3F} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} {DDA77DD5-651E-4180-97C1-839A501773DD} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} {772A6D09-0FB3-46B0-A234-9196704D4657} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} @@ -758,16 +690,6 @@ Global {C07D0F30-B3EC-430B-9F4C-4A74E15CE7F0} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} {ADB65D83-B476-4F0B-8B9F-8719A8AB7624} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} {26427FEE-BE8D-4FDE-8944-BCAFC58EB13C} = {55E62B6F-2C33-4E89-ADD5-0CE9BAA76401} - {B581729A-04EA-4F57-8347-795C1F14257D} = {96279848-CA27-42C6-9488-498A8E696F67} - {1EB78AE6-9233-4FE8-8EE1-292AF412D731} = {B581729A-04EA-4F57-8347-795C1F14257D} - {A831C214-9CEB-4B37-B2B2-2D25A34E43EF} = {B581729A-04EA-4F57-8347-795C1F14257D} - {DBD08956-B4AA-449C-8408-FC0638A20795} = {B581729A-04EA-4F57-8347-795C1F14257D} - {B008D195-BA7B-461D-93D4-284532F9274D} = {B581729A-04EA-4F57-8347-795C1F14257D} - {D40C3359-5983-4021-9F0E-8E7D450EFEFF} = {B581729A-04EA-4F57-8347-795C1F14257D} - {78363647-923A-446F-91BF-4CC09EA28CD0} = {B581729A-04EA-4F57-8347-795C1F14257D} - {A18591FD-1A3C-488D-A814-FED8734FF1CE} = {B581729A-04EA-4F57-8347-795C1F14257D} - {02EEDA2B-1311-4F68-879D-0F32686BA650} = {B581729A-04EA-4F57-8347-795C1F14257D} - {27C13F72-B915-4F08-BC20-628AFDFCF088} = {B581729A-04EA-4F57-8347-795C1F14257D} {BBF63851-BC21-45CC-A671-9ED1A538E052} = {96279848-CA27-42C6-9488-498A8E696F67} {42288F1B-B3FC-4A6A-B39C-AE745F8E37C4} = {BBF63851-BC21-45CC-A671-9ED1A538E052} {84AD21E8-23A0-4029-9767-50F7863E7A02} = {BBF63851-BC21-45CC-A671-9ED1A538E052} @@ -777,6 +699,7 @@ Global {05276DA5-3CF1-4950-8923-9A5F4C1A15D8} = {BBF63851-BC21-45CC-A671-9ED1A538E052} {300ACCF4-DC0C-42ED-B2D6-3C9CAAE991BB} = {BBF63851-BC21-45CC-A671-9ED1A538E052} {35184561-8AAB-4E74-9E0D-231D16E336BF} = {BBF63851-BC21-45CC-A671-9ED1A538E052} + {85F9D3FE-089B-4B93-BDE0-333775581FC9} = {BBF63851-BC21-45CC-A671-9ED1A538E052} {ECF6ADAE-C222-41E9-BA5B-811866193A2B} = {BBF63851-BC21-45CC-A671-9ED1A538E052} {F0888151-28C5-4EF0-86CB-9C66218F89AE} = {96279848-CA27-42C6-9488-498A8E696F67} {F90413F1-AB57-43C0-B401-E7C2EC83198C} = {F0888151-28C5-4EF0-86CB-9C66218F89AE} @@ -787,7 +710,6 @@ Global {DF0B3D4E-2365-4D4F-82BD-0DC0E98ABA83} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} {A2A4BF9A-485B-4C39-9E13-E2B908BF1B4D} = {F90413F1-AB57-43C0-B401-E7C2EC83198C} {3FDFC8B9-AD97-4FD6-B1B9-D9E498BC34B5} = {F0888151-28C5-4EF0-86CB-9C66218F89AE} - {BDD2D535-D893-40F4-BCCD-993454FF1BE7} = {0CAF4618-5C72-4A71-BAEB-79AA4065B9D6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E18BA4C9-E1E4-42CD-8393-505DEDE479A2} diff --git a/CHANGELOG.md b/CHANGELOG.md index fa427982..a43d0e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,70 @@ # B2R2 Change Log +## 0.7.0 (2024-03-26) + +### Added + +- More instruction supports for Intel, AArch64, PPC, and RISCV. +- Support Intel's AT&T syntax. +- Support lazy loading of ELF metadata. +- Handle dwarf action `DW_CFA_same_value` +- Add a new rear-end module, Transformer, which allows users to transform + binary code into another form. +- Add initial SPARC support. +- Add initial SH4 support. + +### Changed + +- Use .NET 8 (and F# 8): Our framework is not compatible with prior + versions of .NET. +- Fix many lifting/parsing bugs for Intel, PPC, AArch64, and RISCV. +- Refactored many modules. Quite many modules/classes have been renamed. +- Improve XML documentation. +- Fix many bugs in the ELF parser. +- Add more unit tests. + +## 0.6.0 (2022-06-29) + +### Added +- More instruction supports for MIPS +- More instruction supports for Intel +- Added initial support for WASM (thanks to @kimdora) +- Added several more classes in the Core module + +### Changed +- Now we use .NET 6 (and F# 6). Our framework is not compatible with .NET 5. +- Fixed MIPS exception frame parser +- Optimized ELF parser for loading callsite tables +- Fixed several bugs in Intel assembler +- Changed ConcEval's interface +- We now avoid using non-standard register sizes, such as `2` and `3`; + we only use sizes multiple of 8 (e.g., 8, 16, 32, 64) or size 1. For those + register variables whose size is non-standard, e.g., `FTOP` in Intel, we + assign larger size for the variable. +- Fixed several bugs in Intel and MIPS lifters +- Fixed several bugs in BinFile module (ELF and PE) +- Fixed several bugs in the middle-end (such as tail-call detection logic, etc.) + +## 0.5.0 (2021-10-22) + +### Added +- Handle ELF exception frames +- Introduce new CFG recovery engine +- Introduce `BinaryPointer` type which allows accessing non-addressable region + of binary +- Add few more instruction support for x86-64 and ARMv7 +- Add a RearEnd.Launcher, which is a .NET CLI tool. You can now install B2R2 by + typing `dotnet tool install -g B2R2.RearEnd.Launcher` +- Add support for AVR architecture + +### Changed +- MiddleEnd has been largely rewritten +- Module and function names largely changed +- Hash-consing is now controlled with build macro `HASHCONS` +- MiddleEnd.ConcEval works with base address changes +- Local IR optimizer has been rewritten +- Optimized data-flow engine + ## 0.4.0 (2020-05-02) ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0d1ead59..afb228f6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,8 +60,14 @@ before you proceed as we mostly follow it. - We use nouns for variables (or parameters). - We *mostly* use verbs for function names. +### Line-endings + +We always use unix-style (LF) line-endings for every file. + #### Editor Settings +- See our [.editorconfig](.editorconfig) + - For Emacs users: ``` (setq-default fsharp-indent-offset 2) diff --git a/Directory.Build.props b/Directory.Build.props index aa5a8317..f5bffad3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,10 +1,10 @@ - net6.0 + net8.0 B2R2 SoftSec Lab. @ KAIST SoftSec Lab. @ KAIST - 0.6.0 + 0.7.0 Copyright (c) SoftSec Lab. @ KAIST, since 2016 true diff --git a/README.md b/README.md index 8145010e..5ca239bb 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ B2R2? 1. B2R2 is *easy* to play with: there is absolutely no dependency hell for B2R2 because it is a fully-managed library. All you need to do is to install - [.NET Core SDK](https://dotnet.microsoft.com/download), and you are ready to + [.NET SDK](https://dotnet.microsoft.com/download), and you are ready to go! Native [IntelliSense](https://docs.microsoft.com/en-us/visualstudio/ide/using-intellisense) support is another plus! @@ -59,17 +59,17 @@ progress, but we look forward to your contributions! Feel free to write a PR (Pull Request) while making sure that you have read our [contribution guideline](CONTRIBUTING.md). -| Feature | x86 | x86-64 | ARMv7 | ARMv8 | MIPS32 | MIPS64 | EVM | TMS320C600 | AVR | PPC | SPARC64 | SH4 | RISC-V | -|-----------------------|:-----------:|:-----------:|:--------------------:|:--------------------:|:--------------------:|:--------------------:|:-----------:|:-----------:|:-----------:|:-----------:|:----------:|:-----------:|:----------:| -| Instruction Parsing | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :full_moon: | :new_moon: | -| Disassembly | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :full_moon: | :new_moon: | -| Lifting | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | -| CFG Recovery | :full_moon: | :full_moon: | :first_quarter_moon: | :first_quarter_moon: | :first_quarter_moon: | :first_quarter_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | -| Data-Flow | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | -| Instruction Emulation | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | -| Assembly | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | -| REPL | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | -| ROP Compilation | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| Feature | x86 | x86-64 | ARMv7 | ARMv8 | MIPS32 | MIPS64 | EVM | TMS320C600 | AVR | PPC | SPARC | SH4 | RISC-V | +|-----------------------|:-----------:|:-----------:|:--------------------:|:--------------------:|:--------------------:|:--------------------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:---------------------:|:-----------:| +| Instruction Parsing | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :waxing_gibbous_moon: | :full_moon: | +| Disassembly | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :waxing_gibbous_moon: | :full_moon: | +| Lifting | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :full_moon: | :new_moon: | :full_moon: | :new_moon: | :full_moon: | +| CFG Recovery | :full_moon: | :full_moon: | :first_quarter_moon: | :first_quarter_moon: | :first_quarter_moon: | :first_quarter_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| Data-Flow | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| Instruction Emulation | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| Assembly | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| REPL | :full_moon: | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | +| ROP Compilation | :full_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | :new_moon: | Dependencies? ------------- @@ -78,8 +78,10 @@ B2R2 relies on a tiny set of external .NET libraries, and our design principle is to use a minimum number of libraries. Below is a list of libraries that we leverage. -- [System.Reflection.Metadata](https://www.nuget.org/packages/System.Reflection.Metadata/) -- [Microsoft.FSharpLu.Json](https://www.nuget.org/packages/Microsoft.FSharpLu.Json/) +- [System.Reflection.Metadata](https://www.nuget.org/packages/System.Reflection.Metadata) +- [System.IO.Hashing](https://www.nuget.org/packages/System.IO.Hashing) +- [Microsoft.FSharpLu.Json](https://www.nuget.org/packages/Microsoft.FSharpLu.Json) +- [FSharp.Compiler.Service](https://www.nuget.org/packages/FSharp.Compiler.Service) - [FParsec](https://www.nuget.org/packages/FParsec) API Documentation @@ -116,14 +118,14 @@ Let's try to use B2R2 APIs. ```fsharp open B2R2 - open B2R2.FrontEnd + open B2R2.FrontEnd.BinInterface [] let main argv = let isa = ISA.OfString "amd64" let bytes = [| 0x65uy; 0xffuy; 0x15uy; 0x10uy; 0x00uy; 0x00uy; 0x00uy |] let hdl = BinHandle.Init (isa, bytes) - let ins = BinHandle.ParseInstr hdl 0UL + let ins = BinHandle.ParseInstr (hdl, 0UL) ins.Translate hdl.TranslationContext |> printfn "%A" 0 ``` @@ -135,7 +137,7 @@ Let's try to use B2R2 APIs. Build ----- -Building B2R2 is fun and easy. All you need to do is to install .NET 6 SDK or +Building B2R2 is fun and easy. All you need to do is to install .NET 8 SDK or above. Yea, that's it! - To build B2R2 in release mode, type ```make release``` or ```dotnet build -c @@ -174,6 +176,7 @@ Publications Here are papers using our work. Please create a PR if you want to add yours. -- How'd Security Benefit Reverse Engineers? The Implication of Intel CET on Function Identification, In Proceedings of the International Conference on Dependable Systems Networks, 2022 [(PDF)](https://softsec.kaist.ac.kr/~sangkilc/papers/kim-dsn2022.pdf) -- Smartian: Enhancing Smart Contract Fuzzing with Static and Dynamic Data-Flow Analyses, In Proceedings of the IEEE/ACM International Conference on Automated Software Engineering, 2021 [(PDF)](https://softsec.kaist.ac.kr/~jschoi/data/ase2021.pdf) -- NTFuzz: Enabling Type-Aware Kernel Fuzzing on Windows with Static Binary Analysis, In Proceedings of the IEEE Symposium on Security and Privacy, 2021 [(PDF)](https://softsec.kaist.ac.kr/~jschoi/data/oakland2021.pdf) +- FunProbe: Probing Functions from Binary Code through Probabilistic Analysis, FSE 2023 +- How'd Security Benefit Reverse Engineers? The Implication of Intel CET on Function Identification, DSN 2022 [(PDF)](https://softsec.kaist.ac.kr/~sangkilc/papers/kim-dsn2022.pdf) +- Smartian: Enhancing Smart Contract Fuzzing with Static and Dynamic Data-Flow Analyses, ASE 2021 [(PDF)](https://softsec.kaist.ac.kr/~jschoi/data/ase2021.pdf) +- NTFuzz: Enabling Type-Aware Kernel Fuzzing on Windows with Static Binary Analysis, Oakland 2021 [(PDF)](https://softsec.kaist.ac.kr/~jschoi/data/oakland2021.pdf) diff --git a/assets/b2r2-240x240.png b/assets/b2r2-240x240.png index c7ca3f5f..aaa288ea 100644 Binary files a/assets/b2r2-240x240.png and b/assets/b2r2-240x240.png differ diff --git a/fsharplint.json b/fsharplint.json new file mode 100644 index 00000000..a78fa91e --- /dev/null +++ b/fsharplint.json @@ -0,0 +1,433 @@ +{ + "ignoreFiles": [ + "*.Assemblyinfo.*" + ], + "global": { + "numIndentationSpaces": 2 + }, + "typedItemSpacing": { + "enabled": false, + "config": { + "typedItemStyle": "NoSpaces" + } + }, + "typePrefixing": { "enabled": false }, + "unionDefinitionIndentation": { "enabled": false }, + "moduleDeclSpacing": { "enabled": false }, + "classMemberSpacing": { "enabled": false }, + "tupleCommaSpacing": { "enabled": false }, + "tupleIndentation": { "enabled": false }, + "tupleParentheses": { "enabled": false }, + "patternMatchClausesOnNewLine": { "enabled": false }, + "patternMatchOrClausesOnNewLine": { "enabled": false }, + "patternMatchClauseIndentation": { "enabled": false }, + "patternMatchExpressionIndentation": { "enabled": false }, + "recursiveAsyncFunction": { "enabled": false }, + "redundantNewKeyword": { "enabled": true }, + "nestedStatements": { + "enabled": false, + "config": { + "depth": 8 + } + }, + "cyclomaticComplexity": { + "enabled": false, + "config": { + "maxComplexity": 40 + } + }, + "reimplementsFunction": { "enabled": true }, + "canBeReplacedWithComposition": { "enabled": true }, + "failwithWithSingleArgument": { "enabled": true }, + "raiseWithSingleArgument": { "enabled": true }, + "nullArgWithSingleArgument": { "enabled": true }, + "invalidOpWithSingleArgument": { "enabled": true }, + "invalidArgWithTwoArguments": { "enabled": true }, + "failwithfWithArgumentsMatchingFormatString": { "enabled": true }, + "failwithBadUsage": { "enabled": true }, + "maxLinesInLambdaFunction": { + "enabled": false, + "config": { + "maxLines": 7 + } + }, + "maxLinesInMatchLambdaFunction": { + "enabled": false, + "config": { + "maxLines": 100 + } + }, + "maxLinesInValue": { + "enabled": false, + "config": { + "maxLines": 100 + } + }, + "maxLinesInFunction": { + "enabled": false, + "config": { + "maxLines": 100 + } + }, + "maxLinesInMember": { + "enabled": false, + "config": { + "maxLines": 100 + } + }, + "maxLinesInConstructor": { + "enabled": false, + "config": { + "maxLines": 100 + } + }, + "maxLinesInProperty": { + "enabled": false, + "config": { + "maxLines": 70 + } + }, + "maxLinesInModule": { + "enabled": false, + "config": { + "maxLines": 1000 + } + }, + "maxLinesInRecord": { + "enabled": false, + "config": { + "maxLines": 500 + } + }, + "maxLinesInEnum": { + "enabled": false, + "config": { + "maxLines": 500 + } + }, + "maxLinesInUnion": { + "enabled": false, + "config": { + "maxLines": 500 + } + }, + "maxLinesInClass": { + "enabled": false, + "config": { + "maxLines": 500 + } + }, + "interfaceNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None", + "prefix": "I" + } + }, + "exceptionNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None", + "suffix": "Exception" + } + }, + "typeNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "recordFieldNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "enumCasesNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "Allowany" + } + }, + "unionCasesNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "AllowAny" + } + }, + "moduleNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "literalNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "namespaceNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "memberNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "AllowPrefix" + } + }, + "parameterNames": { + "enabled": true, + "config": { + "naming": "CamelCase", + "underscores": "AllowPrefix" + } + }, + "measureTypeNames": { + "enabled": true, + "config": { + "underscores": "None" + } + }, + "activePatternNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "genericTypesNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None" + } + }, + "publicValuesNames": { + "enabled": true, + "config": { + "underscores": "AllowPrefix" + } + }, + "privateValuesNames": { + "enabled": true, + "config": { + "naming": "CamelCase", + "underscores": "AllowPrefix" + } + }, + "internalValuesNames": { + "enabled": true, + "config": { + "naming": "CamelCase", + "underscores": "AllowPrefix" + } + }, + "maxNumberOfItemsInTuple": { + "enabled": false, + "config": { + "maxItems": 4 + } + }, + "maxNumberOfFunctionParameters": { + "enabled": false, + "config": { + "maxItems": 5 + } + }, + "maxNumberOfMembers": { + "enabled": false, + "config": { + "maxItems": 32 + } + }, + "maxNumberOfBooleanOperatorsInCondition": { + "enabled": false, + "config": { + "maxItems": 4 + } + }, + "favourIgnoreOverLetWild": { "enabled": true }, + "wildcardNamedWithAsPattern": { "enabled": true }, + "uselessBinding": { "enabled": true }, + "tupleOfWildcards": { "enabled": true }, + "favourTypedIgnore": { "enabled": false }, + "favourReRaise": { "enabled": true }, + "favourStaticEmptyFields": { "enabled": false }, + "favourConsistentThis": { + "enabled": false, + "config": { + "symbol": "this" + } + }, + "avoidTooShortNames": { "enabled": false }, + "indentation": { + "enabled": false + }, + "maxCharactersOnLine": { + "enabled": true, + "config": { + "maxCharactersOnLine": 80 + } + }, + "trailingWhitespaceOnLine": { + "enabled": true, + "config": { + "numberOfSpacesAllowed": 0, + "oneSpaceAllowedAfterOperator": false, + "ignoreBlankLines": false + } + }, + "maxLinesInFile": { + "enabled": false, + "config": { + "maxLinesInFile": 1000 + } + }, + "trailingNewLineInFile": { "enabled": false}, + "noTabCharacters": { "enabled": true }, + "noPartialFunctions": { + "enabled": false, + "config": { + "allowedPartials": [], + "additionalPartials": [] + } + }, + "hints": { + "add": [ + "not (a = b) ===> a <> b", + "not (a <> b) ===> a = b", + "not (a > b) ===> a <= b", + "not (a >= b) ===> a < b", + "not (a < b) ===> a >= b", + "not (a <= b) ===> a > b", + "compare x y <> 1 ===> x <= y", + "compare x y = -1 ===> x < y", + "compare x y <> -1 ===> x >= y", + "compare x y = 1 ===> x > y", + "compare x y <= 0 ===> x <= y", + "compare x y < 0 ===> x < y", + "compare x y >= 0 ===> x >= y", + "compare x y > 0 ===> x > y", + "compare x y = 0 ===> x = y", + "compare x y <> 0 ===> x <> y", + + "List.head (List.sort x) ===> List.min x", + "List.head (List.sortBy f x) ===> List.minBy f x", + + "List.map f (List.map g x) ===> List.map (g >> f) x", + "Array.map f (Array.map g x) ===> Array.map (g >> f) x", + "Seq.map f (Seq.map g x) ===> Seq.map (g >> f) x", + "List.nth x 0 ===> List.head x", + "List.map f (List.replicate n x) ===> List.replicate n (f x)", + "List.rev (List.rev x) ===> x", + "Array.rev (Array.rev x) ===> x", + "List.fold (@) [] x ===> List.concat x", + "List.map id x ===> id x", + "Array.map id x ===> id x", + "Seq.map id x ===> id x", + "(List.length x) = 0 ===> List.isEmpty x", + "(Array.length x) = 0 ===> Array.isEmpty x", + "(Seq.length x) = 0 ===> Seq.isEmpty x", + "x = [] ===> List.isEmpty x", + "x = [||] ===> Array.isEmpty x", + "(List.length x) <> 0 ===> not (List.isEmpty x)", + "(Array.length x) <> 0 ===> not (Array.isEmpty x)", + "(Seq.length x) <> 0 ===> not (Seq.isEmpty x)", + "(List.length x) > 0 ===> not (List.isEmpty x)", + "(Array.length x) <> 0 ===> not (Array.isEmpty x)", + "(Seq.length x) <> 0 ===> not (Seq.isEmpty x)", + + "List.concat (List.map f x) ===> List.collect f x", + "Array.concat (Array.map f x) ===> Array.collect f x", + "Seq.concat (Seq.map f x) ===> Seq.collect f x", + + "List.isEmpty (List.filter f x) ===> not (List.exists f x)", + "Array.isEmpty (Array.filter f x) ===> not (Array.exists f x)", + "Seq.isEmpty (Seq.filter f x) ===> not (Seq.exists f x)", + "not (List.isEmpty (List.filter f x)) ===> List.exists f x", + "not (Array.isEmpty (Array.filter f x)) ===> Array.exists f x", + "not (Seq.isEmpty (Seq.filter f x)) ===> Seq.exists f x", + + "List.length x >= 0 ===> true", + "Array.length x >= 0 ===> true", + "Seq.length x >= 0 ===> true", + + "x = false ===> not x", + "true = a ===> a", + "false = a ===> not a", + "a <> true ===> not a", + "a <> false ===> a", + "true <> a ===> not a", + "false <> a ===> a", + "if a then true else false ===> a", + "if a then false else true ===> not a", + "not (not x) ===> x", + + "(fst x, snd x) ===> x", + + "true && x ===> x", + "false && x ===> false", + "true || x ===> true", + "false || x ===> x", + "not true ===> false", + "not false ===> true", + "fst (x, y) ===> x", + "snd (x, y) ===> y", + "List.fold f x [] ===> x", + "Array.fold f x [||] ===> x", + "List.foldBack f [] x ===> x", + "Array.foldBack f [||] x ===> x", + "x - 0 ===> x", + "x * 1 ===> x", + "x / 1 ===> x", + + "List.fold (+) 0 x ===> List.sum x", + "Array.fold (+) 0 x ===> Array.sum x", + "Seq.fold (+) 0 x ===> Seq.sum x", + "List.sum (List.map x y) ===> List.sumBy x y", + "Array.sum (Array.map x y) ===> Array.sumBy x y", + "Seq.sum (Seq.map x y) ===> Seq.sumBy x y", + "List.average (List.map x y) ===> List.averageBy x y", + "Array.average (Array.map x y) ===> Array.averageBy x y", + "Seq.average (Seq.map x y) ===> Seq.averageBy x y", + "(List.take x y, List.skip x y) ===> List.splitAt x y", + "(Array.take x y, Array.skip x y) ===> Array.splitAt x y", + "(Seq.take x y, Seq.skip x y) ===> Seq.splitAt x y", + + "List.empty ===> []", + "Array.empty ===> [||]", + + "x @ [] ===> x", + + "List.isEmpty [] ===> true", + "Array.isEmpty [||] ===> true", + + "fun _ -> () ===> ignore", + "fun x -> x ===> id", + "id x ===> x", + "id >> f ===> f", + "f >> id ===> f", + + "x = null ===> isNull x", + "null = x ===> isNull x", + "x <> null ===> not (isNull x)", + "null <> x ===> not (isNull x)", + + "Array.append a (Array.append b c) ===> Array.concat [|a; b; c|]" + ] + } +} diff --git a/samples/IActionExample/.gitignore b/samples/IActionExample/.gitignore new file mode 100644 index 00000000..ad2ea985 --- /dev/null +++ b/samples/IActionExample/.gitignore @@ -0,0 +1 @@ +MyAction.fs diff --git a/samples/IActionExample/MyAction.fs.example b/samples/IActionExample/MyAction.fs.example new file mode 100644 index 00000000..12219f55 --- /dev/null +++ b/samples/IActionExample/MyAction.fs.example @@ -0,0 +1,21 @@ +namespace B2R2.RearEnd.Transformer + +/// Sample Action for Transformer. +type MyAction () = + let rec toType (o: obj) = + let typ = o.GetType () + if typ = typeof then + (o :?> ObjCollection).Values + |> Array.map toType + |> String.concat ", " + else typ.ToString () + + interface IAction with + member __.ActionID with get() = "myaction" + member __.Signature with get() = "'a -> unit" + member __.Description with get() = """ + Take in an input object and prints out its type. +""" + member __.Transform _args o = + let res = box o |> toType + { Values = [| res |] } diff --git a/samples/IActionExample/MyAction.fsproj b/samples/IActionExample/MyAction.fsproj new file mode 100644 index 00000000..45633d9b --- /dev/null +++ b/samples/IActionExample/MyAction.fsproj @@ -0,0 +1,16 @@ + + + + net7.0 + true + + + + + + + + + + + diff --git a/samples/IActionExample/README.md b/samples/IActionExample/README.md new file mode 100644 index 00000000..e8a5c980 --- /dev/null +++ b/samples/IActionExample/README.md @@ -0,0 +1,9 @@ +# MyAction example + +To build a plugin DLL file for Transformer, follow the steps below. + +1. Copy `MyAction.fs.example` to `MyAction.fs`. +2. Modify `MyAction.fs` as you want. +3. Run `dotnet build` or `dotnet build -c Release` to get `MyAction.dll`, which + should be located at `bin/Debug` or `bin/Release` directory. +4. Run transformer using the `-d` option with the dll you just created. diff --git a/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj b/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj index 971981ba..9e53ce85 100644 --- a/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj +++ b/src/BinIR.Tests/B2R2.BinIR.Tests.fsproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/BinIR.Tests/Tests.fs b/src/BinIR.Tests/Tests.fs index 38f7abf6..1a7ab0f0 100644 --- a/src/BinIR.Tests/Tests.fs +++ b/src/BinIR.Tests/Tests.fs @@ -33,9 +33,9 @@ type BinIRTest () = [] member __.``Inline Optimization Test``() = - let n1 = AST.num <| BitVector.ofInt32 1 32 - let n2 = AST.num <| BitVector.ofInt32 2 32 - let n3 = AST.num <| BitVector.ofInt32 3 32 + let n1 = AST.num <| BitVector.OfInt32 1 32 + let n2 = AST.num <| BitVector.OfInt32 2 32 + let n3 = AST.num <| BitVector.OfInt32 3 32 let e1 = AST.add (AST.mul n1 n2) n3 let e2 = AST.sub (AST.mul n2 n3) n1 Assert.AreEqual (e1, e2) diff --git a/src/BinIR/BinOpType.fs b/src/BinIR/BinOpType.fs index 9d533a01..b9f55d5d 100644 --- a/src/BinIR/BinOpType.fs +++ b/src/BinIR/BinOpType.fs @@ -87,7 +87,6 @@ module BinOpType = | BinOpType.OR -> "|" | BinOpType.XOR -> "^" | BinOpType.CONCAT -> "++" - | BinOpType.APP -> "-|" | BinOpType.CONS -> "::" | BinOpType.FADD -> "+." | BinOpType.FSUB -> "-." @@ -112,7 +111,6 @@ module BinOpType = | "|" -> BinOpType. OR | "^" -> BinOpType. XOR | "++" -> BinOpType.CONCAT - | "-|" -> BinOpType.APP | "::" -> BinOpType.CONS | "+." -> BinOpType.FADD | "-." -> BinOpType.FSUB diff --git a/src/BinIR/CastKind.fs b/src/BinIR/CastKind.fs index 15f338e8..d44f9121 100644 --- a/src/BinIR/CastKind.fs +++ b/src/BinIR/CastKind.fs @@ -30,39 +30,73 @@ type CastKind = | SignExt = 0 /// Zero-extending conversion | ZeroExt = 1 - /// Integer to float conversion - | IntToFloat = 2 - /// Float to Nearest Integer rounded conversion - | FtoIRound = 3 - /// Float to Integer rounded up conversion (toward +inf). - | FtoICeil = 4 - /// Float to Integer rounded down conversion (toward -inf). - | FtoIFloor = 5 + /// Signed integer to float conversion + | SIntToFloat = 2 + /// Unsigned integer to float conversion + | UIntToFloat = 3 + /// Float to Nearest Integer rounded conversion. Ties to even. When the given + /// float is too large to be represented as an integer, the result is MIN_INT, + /// i.e., 0x80000000 for 32-bit integers and 0x8000000000000000 for 64-bit + /// integers. + | FtoIRound = 4 + /// Float to Integer rounded up conversion (toward +inf). When the given float + /// is too large to be represented as an integer, the result is MIN_INT, i.e., + /// 0x80000000 for 32-bit integers and 0x8000000000000000 for 64-bit integers. + | FtoICeil = 5 + /// Float to Integer rounded down conversion (toward -inf). When the given + /// float is too large to be represented as an integer, the result is MIN_INT, + /// i.e., 0x80000000 for 32-bit integers and 0x8000000000000000 for 64-bit + /// integers. + | FtoIFloor = 6 /// Float to Integer truncated conversion (closest to but no greater in - /// absolute value than the infinitely precise result). - | FtoITrunc = 6 + /// absolute value than the infinitely precise result). When the given float + /// is too large to be represented as an integer, the result is MIN_INT, i.e., + /// 0x80000000 for 32-bit integers and 0x8000000000000000 for 64-bit integers. + | FtoITrunc = 7 /// Float to Float conversion with different precisions - | FloatCast = 7 + | FloatCast = 8 + /// Float to Float conversion while rounding to nearest integer.. Ties to + /// even. + | FtoFRound = 9 + /// Float to Float conversion while rounding toward +inf. E.g., 23.2 -> 24.0, + /// and -23.7 -> -23. + | FtoFCeil = 10 + /// Float to Float conversion while rounding toward -inf. E.g., 23.7 -> 23.0, + /// and -23.2 -> -24. + | FtoFFloor = 11 + /// Float to Float conversion while rounding toward zero. E.g. 23.7 -> 23.0, + /// and -23.7 -> -23. + | FtoFTrunc = 12 module CastKind = let toString = function | CastKind.SignExt -> "sext" | CastKind.ZeroExt -> "zext" - | CastKind.IntToFloat -> "float" + | CastKind.SIntToFloat -> "sfloat" + | CastKind.UIntToFloat -> "ufloat" | CastKind.FtoIRound -> "round" | CastKind.FtoICeil -> "ceil" | CastKind.FtoIFloor -> "floor" | CastKind.FtoITrunc -> "trunc" | CastKind.FloatCast -> "fext" + | CastKind.FtoFRound -> "roundf" + | CastKind.FtoFCeil -> "ceilf" + | CastKind.FtoFFloor -> "floorf" + | CastKind.FtoFTrunc -> "truncf" | _ -> raise IllegalASTTypeException let ofString = function | "sext" -> CastKind.SignExt | "zext" -> CastKind.ZeroExt - | "float" -> CastKind.IntToFloat + | "sfloat" -> CastKind.SIntToFloat + | "ufloat" -> CastKind.UIntToFloat | "round" -> CastKind.FtoIRound | "ceil" -> CastKind.FtoICeil | "floor" -> CastKind.FtoIFloor | "trunc" -> CastKind.FtoITrunc | "fext" -> CastKind.FloatCast + | "roundf" -> CastKind.FtoFRound + | "ceilf" -> CastKind.FtoFCeil + | "floorf" -> CastKind.FtoFFloor + | "truncf" -> CastKind.FtoFTrunc | _ -> raise IllegalASTTypeException diff --git a/src/BinIR/Expr.fs b/src/BinIR/Expr.fs index c606627a..ce17ca32 100644 --- a/src/BinIR/Expr.fs +++ b/src/BinIR/Expr.fs @@ -26,22 +26,12 @@ namespace B2R2.BinIR.LowUIR open System.Text #if HASHCONS +open System open LanguagePrimitives #endif open B2R2 open B2R2.BinIR -/// ExprInfo summarizes several abstract information about the Expr. This is -/// useful for writing an efficient post analyses. -type ExprInfo = { - /// Is this expression contains memory load(s). - HasLoad: bool - /// A set of registers (their regids) used in this expression. - VarsUsed: RegisterSet - /// A set of temp variables (their IDs) used in this expression. - TempVarsUsed: Set -} - /// IR Expressions. /// NOTE: You MUST create Expr/Stmt through the AST module. *NEVER* directly /// construct Expr nor Stmt. @@ -58,7 +48,7 @@ type E = /// For example, (EAX:I32) represents the EAX register (of type I32). /// Note that name (n) is additional information that doesn't be used /// internally. - | Var of RegType * RegisterID * string * RegisterSet + | Var of RegType * RegisterID * string /// Nil to represent cons cells. This should only be used with BinOpType.CONS. | Nil @@ -74,7 +64,7 @@ type E = | TempVar of RegType * int /// Unary operation such as negation. - | UnOp of UnOpType * Expr * ExprInfo + | UnOp of UnOpType * Expr /// Symbolic constant for labels. | Name of Symbol @@ -84,26 +74,26 @@ type E = /// Binary operation such as add, sub, etc. The second argument is a result /// type after applying BinOp. - | BinOp of BinOpType * RegType * Expr * Expr * ExprInfo + | BinOp of BinOpType * RegType * Expr * Expr /// Relative operation such as eq, lt, etc. - | RelOp of RelOpType * Expr * Expr * ExprInfo + | RelOp of RelOpType * Expr * Expr /// Memory loading such as LE:[T_1:I32] - | Load of Endian * RegType * Expr * ExprInfo + | Load of Endian * RegType * Expr /// If-then-else expression. The first expression is a condition, and the /// second and the third are true and false expression respectively. - | Ite of Expr * Expr * Expr * ExprInfo + | Ite of Expr * Expr * Expr /// Type casting expression. The first argument is a casting type, and the /// second argument is a result type. - | Cast of CastKind * RegType * Expr * ExprInfo + | Cast of CastKind * RegType * Expr /// Extraction expression. The first argument is target expression, and the /// second argument is the number of bits for extraction, and the third is /// the start position. - | Extract of Expr * RegType * StartPos * ExprInfo + | Extract of Expr * RegType * StartPos /// Undefined expression. This is rarely used, and it is a fatal error when we /// encounter this expression while evaluating a program. Some CPU manuals @@ -118,26 +108,26 @@ with | :? E as rhs -> match __, rhs with | Num (n1), Num (n2) -> n1 = n2 - | Var (t1, r1, _, _), Var (t2, r2, _, _) -> t1 = t2 && r1 = r2 + | Var (t1, r1, _), Var (t2, r2, _) -> t1 = t2 && r1 = r2 | Nil, Nil -> true | PCVar (t1, _), PCVar (t2, _) -> t1 = t2 | TempVar (t1, n1), TempVar (t2, n2) -> t1 = t2 && n1 = n2 - | UnOp (t1, e1, _), UnOp (t2, e2, _) -> t1 = t2 && PhysicalEquality e1 e2 + | UnOp (t1, e1), UnOp (t2, e2) -> t1 = t2 && PhysicalEquality e1 e2 | Name (s1), Name (s2) -> s1 = s2 | FuncName (n1), FuncName (n2) -> n1 = n2 - | BinOp (o1, t1, lhs1, rhs1, _), BinOp (o2, t2, lhs2, rhs2, _) -> + | BinOp (o1, t1, lhs1, rhs1), BinOp (o2, t2, lhs2, rhs2) -> o1 = o2 && t1 = t2 && PhysicalEquality lhs1 lhs2 && PhysicalEquality rhs1 rhs2 - | RelOp (o1, lhs1, rhs1, _), RelOp (o2, lhs2, rhs2, _) -> + | RelOp (o1, lhs1, rhs1), RelOp (o2, lhs2, rhs2) -> o1 = o2 && PhysicalEquality lhs1 lhs2 && PhysicalEquality rhs1 rhs2 - | Load (n1, t1, e1, _), Load (n2, t2, e2, _) -> + | Load (n1, t1, e1), Load (n2, t2, e2) -> n1 = n2 && t1 = t2 && PhysicalEquality e1 e2 - | Ite (c1, t1, f1, _), Ite (c2, t2, f2, _) -> + | Ite (c1, t1, f1), Ite (c2, t2, f2) -> PhysicalEquality c1 c2 && PhysicalEquality t1 t2 && PhysicalEquality f1 f2 - | Cast (k1, t1, e1, _), Cast (k2, t2, e2, _) -> + | Cast (k1, t1, e1), Cast (k2, t2, e2) -> k1 = k2 && t1 = t2 && PhysicalEquality e1 e2 - | Extract (e1, t1, p1, _), Extract (e2, t2, p2, _) -> + | Extract (e1, t1, p1), Extract (e2, t2, p2) -> PhysicalEquality e1 e2 && t1 = t2 && p1 = p2 | Undefined (t1, s1), Undefined (t2, s2) -> t1 = t2 && s1 = s2 | _ -> false @@ -185,19 +175,19 @@ with override __.GetHashCode () = match __ with | Num n -> n.GetHashCode () - | Var (rt, rid, _, _) -> E.HashVar rt rid + | Var (rt, rid, _) -> E.HashVar rt rid | Nil -> 0 | PCVar (rt, _) -> E.HashPCVar rt | TempVar (rt, n) -> E.HashTempVar rt n - | UnOp (op, e, _) -> E.HashUnOp op e + | UnOp (op, e) -> E.HashUnOp op e | Name (s) -> E.HashName s | FuncName (s) -> E.HashFuncName s - | BinOp (op, rt, e1, e2, _) -> E.HashBinOp op rt e1 e2 - | RelOp (op, e1, e2, _) -> E.HashRelOp op e1 e2 - | Load (endian, rt, e, _) -> E.HashLoad endian rt e - | Ite (cond, t, f, _) -> E.HashIte cond t f - | Cast (k, rt, e, _) -> E.HashCast k rt e - | Extract (e, rt, pos, _) -> E.HashExtract e rt pos + | BinOp (op, rt, e1, e2) -> E.HashBinOp op rt e1 e2 + | RelOp (op, e1, e2) -> E.HashRelOp op e1 e2 + | Load (endian, rt, e) -> E.HashLoad endian rt e + | Ite (cond, t, f) -> E.HashIte cond t f + | Cast (k, rt, e) -> E.HashCast k rt e + | Extract (e, rt, pos) -> E.HashExtract e rt pos | Undefined (rt, s) -> E.HashUndef rt s #endif @@ -235,8 +225,8 @@ with module Expr = let rec appendToString expr (sb: StringBuilder) = match expr.E with - | Num n -> sb.Append (BitVector.toString n) |> ignore - | Var (_typ, _, n, _) -> sb.Append (n) |> ignore + | Num n -> sb.Append (BitVector.ToString n) |> ignore + | Var (_typ, _, n) -> sb.Append (n) |> ignore | Nil -> sb.Append ("nil") |> ignore | PCVar (_typ, n) -> sb.Append (n) |> ignore | TempVar (typ, n) -> @@ -246,19 +236,31 @@ module Expr = sb.Append (RegType.toString typ) |> ignore | Name (n) -> sb.Append (Symbol.getName n) |> ignore | FuncName (n) -> sb.Append (n) |> ignore - | UnOp (op, e, _) -> + | UnOp (op, e) -> sb.Append ("(") |> ignore sb.Append (UnOpType.toString op) |> ignore sb.Append (" ") |> ignore appendToString e sb sb.Append (")") |> ignore - | BinOp (BinOpType.FLOG, _typ, e1, e2, _) -> (* The only prefix operator *) + | BinOp (BinOpType.FLOG, _typ, e1, e2) -> (* The only prefix operator *) sb.Append ("(lg (") |> ignore appendToString e1 sb sb.Append (", ") |> ignore appendToString e2 sb sb.Append ("))") |> ignore - | BinOp (op, _typ, e1, e2, _) -> + | BinOp (BinOpType.APP, typ, e1, e2) -> + appendToString e1 sb + sb.Append ("(") |> ignore + appendToString e2 sb + sb.Append ("):") |> ignore + sb.Append (RegType.toString typ) |> ignore + | BinOp (BinOpType.CONS, _typ, e1, { E = Nil }) -> + appendToString e1 sb + | BinOp (BinOpType.CONS, _typ, e1, e2) -> + appendToString e1 sb + sb.Append (", ") |> ignore + appendToString e2 sb + | BinOp (op, _typ, e1, e2) -> sb.Append ("(") |> ignore appendToString e1 sb sb.Append (" ") |> ignore @@ -266,7 +268,7 @@ module Expr = sb.Append (" ") |> ignore appendToString e2 sb sb.Append (")") |> ignore - | RelOp (op, e1, e2, _) -> + | RelOp (op, e1, e2) -> sb.Append ("(") |> ignore appendToString e1 sb sb.Append (" ") |> ignore @@ -274,12 +276,12 @@ module Expr = sb.Append (" ") |> ignore appendToString e2 sb sb.Append (")") |> ignore - | Load (_endian, typ, e, _) -> + | Load (_endian, typ, e) -> sb.Append ("[") |> ignore appendToString e sb sb.Append ("]:") |> ignore sb.Append (RegType.toString typ) |> ignore - | Ite (cond, e1, e2, _) -> + | Ite (cond, e1, e2) -> sb.Append ("((") |> ignore appendToString cond sb sb.Append (") ? (") |> ignore @@ -287,14 +289,14 @@ module Expr = sb.Append (") : (") |> ignore appendToString e2 sb sb.Append ("))") |> ignore - | Cast (cast, typ, e, _) -> + | Cast (cast, typ, e) -> sb.Append (CastKind.toString cast) |> ignore sb.Append (":") |> ignore sb.Append (RegType.toString typ) |> ignore sb.Append ("(") |> ignore appendToString e sb sb.Append (")") |> ignore - | Extract (e, typ, p, _) -> + | Extract (e, typ, p) -> sb.Append ("(") |> ignore appendToString e sb sb.Append ("[") |> ignore @@ -307,6 +309,6 @@ module Expr = sb.Append (")") |> ignore let toString expr = - let sb = new StringBuilder () + let sb = StringBuilder () appendToString expr sb sb.ToString () \ No newline at end of file diff --git a/src/BinIR/LowUIR.AST.fs b/src/BinIR/LowUIR.AST.fs index 79f66c93..4b87066c 100644 --- a/src/BinIR/LowUIR.AST.fs +++ b/src/BinIR/LowUIR.AST.fs @@ -25,6 +25,7 @@ /// LowUIR AST construction must be done through this module. module B2R2.BinIR.LowUIR.AST +open System.Collections.Generic open B2R2 open B2R2.BinIR @@ -61,10 +62,6 @@ let inline private tryGetStmt (k: S) = | _ -> Error false #endif -/// Get the expression info from the given expression (Expr). -[] -let getExprInfo e = ASTHelper.getExprInfo e - /// Construct a number (Num). [] let num bv = @@ -83,11 +80,11 @@ let num bv = /// Construct a variable (Var). [] -let var t id name rs = +let var t id name = #if ! HASHCONS - Var (t, id, name, rs) |> ASTHelper.buildExpr + Var (t, id, name) |> ASTHelper.buildExpr #else - let k = Var (t, id, name, rs) + let k = Var (t, id, name) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -140,10 +137,10 @@ let unop op e = match e.E with | Num n -> ValueOptimizer.unop n op |> num #if ! HASHCONS - | _ -> UnOp (op, e, getExprInfo e) |> ASTHelper.buildExpr + | _ -> UnOp (op, e) |> ASTHelper.buildExpr #else | _ -> - let k = UnOp (op, e, getExprInfo e) + let k = UnOp (op, e) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -169,20 +166,15 @@ let name symb = e' #endif -let inline private (===) e1 e2 = - LanguagePrimitives.PhysicalEquality e1.E e2.E - let binopWithType op t e1 e2 = - match op, e1.E, e2.E with - | _, Num n1, Num n2 -> ValueOptimizer.binop n1 n2 op |> num - | BinOpType.XOR, _, _ when e1 === e2 -> BitVector.zero t |> num + match e1.E, e2.E with + | Num n1, Num n2 -> ValueOptimizer.binop n1 n2 op |> num #if ! HASHCONS | _ -> - BinOp (op, t, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2) - |> ASTHelper.buildExpr + BinOp (op, t, e1, e2) |> ASTHelper.buildExpr #else | _ -> - let k = BinOp (op, t, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2) + let k = BinOp (op, t, e1, e2) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -209,14 +201,13 @@ let binop op e1 e2 = /// Consing two expr. [] let cons a b = + let t = TypeCheck.typeOf a match b.E with | Nil -> - let t = TypeCheck.typeOf a #if ! HASHCONS - BinOp (BinOpType.CONS, t, a, b, ASTHelper.getExprInfo a) - |> ASTHelper.buildExpr + BinOp (BinOpType.CONS, t, a, b) |> ASTHelper.buildExpr #else - let k = BinOp (BinOpType.CONS, t, a, b, ASTHelper.getExprInfo a) + let k = BinOp (BinOpType.CONS, t, a, b) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -226,7 +217,7 @@ let cons a b = else exprs[k] <- WeakReference e' e' #endif - | _ -> binop BinOpType.CONS a b + | _ -> binopWithType BinOpType.CONS t a b /// Nil. [] @@ -260,11 +251,11 @@ let app name args retType = List.reduceBack cons (args @ [ nil ]) #if ! HASHCONS |> fun cons -> - BinOp (BinOpType.APP, retType, funName, cons, getExprInfo cons) + BinOp (BinOpType.APP, retType, funName, cons) |> ASTHelper.buildExpr #else |> fun cons -> - let k = BinOp (BinOpType.APP, retType, funName, cons, getExprInfo cons) + let k = BinOp (BinOpType.APP, retType, funName, cons) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -285,10 +276,10 @@ let relop op e1 e2 = | Num n1, Num n2 -> ValueOptimizer.relop n1 n2 op |> num #if ! HASHCONS | _ -> - RelOp (op, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2)|> ASTHelper.buildExpr + RelOp (op, e1, e2) |> ASTHelper.buildExpr #else | _ -> - let k = RelOp (op, e1, e2, ASTHelper.mergeTwoExprInfo e1 e2) + let k = RelOp (op, e1, e2) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -307,10 +298,10 @@ let load endian rt addr = | _ -> #endif #if ! HASHCONS - Load (endian, rt, addr, { getExprInfo addr with HasLoad = true }) + Load (endian, rt, addr) |> ASTHelper.buildExpr #else - let k = Load (endian, rt, addr, { getExprInfo addr with HasLoad = true }) + let k = Load (endian, rt, addr) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -336,13 +327,12 @@ let ite cond e1 e2 = TypeCheck.checkEquivalence (TypeCheck.typeOf e1) (TypeCheck.typeOf e2) #endif match cond.E with - | Num (n) -> if BitVector.isOne n then e1 else e2 (* Assume valid cond *) + | Num (n) -> if BitVector.IsOne n then e1 else e2 (* Assume valid cond *) | _ -> #if ! HASHCONS - Ite (cond, e1, e2, ASTHelper.mergeThreeExprInfo cond e1 e2) - |> ASTHelper.buildExpr + Ite (cond, e1, e2) |> ASTHelper.buildExpr #else - let k = Ite (cond, e1, e2, ASTHelper.mergeThreeExprInfo cond e1 e2) + let k = Ite (cond, e1, e2) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -361,9 +351,9 @@ let cast kind rt e = | _ -> if TypeCheck.canCast kind rt e then #if ! HASHCONS - Cast (kind, rt, e, getExprInfo e) |> ASTHelper.buildExpr + Cast (kind, rt, e) |> ASTHelper.buildExpr #else - let k = Cast (kind, rt, e, getExprInfo e) + let k = Cast (kind, rt, e) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -380,12 +370,12 @@ let extract expr rt pos = TypeCheck.extract rt pos (TypeCheck.typeOf expr) match expr.E with | Num n -> ValueOptimizer.extract n rt pos |> num - | Extract (e, _, p, ei) -> + | Extract (e, _, p) -> let pos = p + pos #if ! HASHCONS - Extract (e, rt, pos, ei) |> ASTHelper.buildExpr + Extract (e, rt, pos) |> ASTHelper.buildExpr #else - let k = Extract (e, rt, pos, ei) + let k = Extract (e, rt, pos) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -396,9 +386,9 @@ let extract expr rt pos = #endif | _ -> #if ! HASHCONS - Extract (expr, rt, pos, getExprInfo expr) |> ASTHelper.buildExpr + Extract (expr, rt, pos) |> ASTHelper.buildExpr #else - let k = Extract (expr, rt, pos, getExprInfo expr) + let k = Extract (expr, rt, pos) match tryGetExpr k with | Ok e -> e | Error isReclaimed -> @@ -426,19 +416,19 @@ let undef rt s = /// Construct a (Num 0) of size t. [] -let num0 rt = num (BitVector.zero rt) +let num0 rt = num (BitVector.Zero rt) /// Construct a (Num 1) of size t. [] -let num1 rt = num (BitVector.one rt) +let num1 rt = num (BitVector.One rt) /// Num expression for a one-bit number zero. [] -let b0 = num (BitVector.zero 1) +let b0 = num (BitVector.Zero 1) /// Num expression for a one-bit number one. [] -let b1 = num (BitVector.one 1) +let b1 = num (BitVector.One 1) /// Concatenation. [] @@ -462,8 +452,8 @@ let concatArr (arr: Expr[]) = [] let rec unwrap e = match e.E with - | Cast (_, _, e, _) - | Extract (e, _, _, _) -> unwrap e + | Cast (_, _, e) + | Extract (e, _, _) -> unwrap e | _ -> e /// Zero-extend an expression. @@ -717,7 +707,7 @@ let fadd e1 e2 = TypeCheck.typeOf e1 #endif #if ! HASHCONS - binopWithType BinOpType.FADD t e2 e1 + binopWithType BinOpType.FADD t e1 e2 #else if e1 < e2 then binopWithType BinOpType.FADD t e1 e2 else binopWithType BinOpType.FADD t e2 e1 @@ -744,7 +734,7 @@ let fmul e1 e2 = TypeCheck.typeOf e1 #endif #if ! HASHCONS - binopWithType BinOpType.FMUL t e2 e1 + binopWithType BinOpType.FMUL t e1 e2 #else if e1 < e2 then binopWithType BinOpType.FMUL t e1 e2 else binopWithType BinOpType.FMUL t e2 e1 @@ -761,6 +751,10 @@ let fdiv e1 e2 = #endif binopWithType BinOpType.FDIV t e1 e2 +/// Floating point equal. +[] +let feq e1 e2 = relop RelOpType.FEQ e1 e2 + /// Floating point greater than. [] let fgt e1 e2 = relop RelOpType.FGT e1 e2 @@ -885,19 +879,19 @@ let put dst src = let assignForExtractDst e1 e2 = match e1.E with - | Extract ({ E = Var (t, _, _, _) } as e1, eTyp, 0, _) - | Extract ({ E = TempVar (t, _) } as e1, eTyp, 0, _) -> + | Extract ({ E = Var (t, _, _) } as e1, eTyp, 0) + | Extract ({ E = TempVar (t, _) } as e1, eTyp, 0) -> let nMask = RegType.getMask t - RegType.getMask eTyp - let mask = BitVector.ofBInt nMask t |> num + let mask = BitVector.OfBInt nMask t |> num let src = cast CastKind.ZeroExt t e2 put e1 (binopWithType BinOpType.OR t (binopWithType BinOpType.AND t e1 mask) src) - | Extract ({ E = Var (t, _, _, _) } as e1, eTyp, pos, _) - | Extract ({ E = TempVar (t, _) } as e1, eTyp, pos, _) -> + | Extract ({ E = Var (t, _, _) } as e1, eTyp, pos) + | Extract ({ E = TempVar (t, _) } as e1, eTyp, pos) -> let nMask = RegType.getMask t - (RegType.getMask eTyp <<< pos) - let mask = BitVector.ofBInt nMask t |> num + let mask = BitVector.OfBInt nMask t |> num let src = cast CastKind.ZeroExt t e2 - let shift = BitVector.ofInt32 pos t |> num + let shift = BitVector.OfInt32 pos t |> num let src = binopWithType BinOpType.SHL t src shift put e1 (binopWithType BinOpType.OR t (binopWithType BinOpType.AND t e1 mask) src) @@ -927,7 +921,7 @@ let assign dst src = #endif match dst.E with | Var _ | TempVar _ | PCVar _ -> put dst src - | Load (_, _, e, _) -> store Endian.Little e src + | Load (endian, _, e) -> store endian e src | Extract (_) -> assignForExtractDst dst src | _ -> raise InvalidAssignmentException @@ -995,6 +989,22 @@ let intercjmp cond d1 d2 = s' #endif +/// An external call statement. +[] +let extCall appExpr = +#if ! HASHCONS + ExternalCall (appExpr) |> ASTHelper.buildStmt +#else + let k = ExternalCall appExpr + match tryGetStmt k with + | Ok s -> s + | Error isReclaimed -> + let s' = { S = k; Tag = newSTag (); HashKey = S.HashExtCall appExpr } + if isReclaimed then stmts[k].SetTarget s' + else stmts[k] <- WeakReference s' + s' +#endif + /// A SideEffect statement. [] let sideEffect eff = @@ -1011,6 +1021,86 @@ let sideEffect eff = s' #endif +/// Record the use of vars and tempvars from the given expression. +let rec updateAllVarsUses (rset: RegisterSet) (tset: HashSet) { E = e } = + match e with + | Num _ | Nil | PCVar _ | Name _ | FuncName _ | Undefined _ -> + () + | Var (_, rid, _) -> + rset.Add (int rid) + | TempVar (_, n) -> + tset.Add n |> ignore + | UnOp (_, e) -> + updateAllVarsUses rset tset e + | BinOp (_, _, lhs, rhs) -> + updateAllVarsUses rset tset lhs + updateAllVarsUses rset tset rhs + | RelOp (_, lhs, rhs) -> + updateAllVarsUses rset tset lhs + updateAllVarsUses rset tset rhs + | Load (_, _, e) -> + updateAllVarsUses rset tset e + | Ite (cond, e1, e2) -> + updateAllVarsUses rset tset cond + updateAllVarsUses rset tset e1 + updateAllVarsUses rset tset e2 + | Cast (_, _, e) -> + updateAllVarsUses rset tset e + | Extract (e, _, _) -> + updateAllVarsUses rset tset e + +/// Record the use of vars (registers) from the given expression. +let rec updateRegsUses (rset: RegisterSet) { E = e } = + match e with + | Num _ | Nil | PCVar _ | Name _ | FuncName _ | Undefined _ | TempVar _ -> + () + | Var (_, rid, _) -> + rset.Add (int rid) + | UnOp (_, e) -> + updateRegsUses rset e + | BinOp (_, _, lhs, rhs) -> + updateRegsUses rset lhs + updateRegsUses rset rhs + | RelOp (_, lhs, rhs) -> + updateRegsUses rset lhs + updateRegsUses rset rhs + | Load (_, _, e) -> + updateRegsUses rset e + | Ite (cond, e1, e2) -> + updateRegsUses rset cond + updateRegsUses rset e1 + updateRegsUses rset e2 + | Cast (_, _, e) -> + updateRegsUses rset e + | Extract (e, _, _) -> + updateRegsUses rset e + +/// Record the use of tempvars from the given expression. +let rec updateTempsUses (tset: HashSet) { E = e } = + match e with + | Num _ | Nil | PCVar _ | Name _ | FuncName _ | Undefined _ | Var _ -> + () + | TempVar (_, n) -> + tset.Add n |> ignore + | UnOp (_, e) -> + updateTempsUses tset e + | BinOp (_, _, lhs, rhs) -> + updateTempsUses tset lhs + updateTempsUses tset rhs + | RelOp (_, lhs, rhs) -> + updateTempsUses tset lhs + updateTempsUses tset rhs + | Load (_, _, e) -> + updateTempsUses tset e + | Ite (cond, e1, e2) -> + updateTempsUses tset cond + updateTempsUses tset e1 + updateTempsUses tset e2 + | Cast (_, _, e) -> + updateTempsUses tset e + | Extract (e, _, _) -> + updateTempsUses tset e + module InfixOp = /// Assignment. let inline (:=) e1 e2 = assign e1 e2 @@ -1054,10 +1144,10 @@ module InfixOp = /// Signed greater than or equal. let inline (?>=) e1 e2 = sge e1 e2 - /// Signed less than. + /// Unsigned less than. let inline (.<) e1 e2 = lt e1 e2 - /// Signed less than or equal. + /// Unsigned less than or equal. let inline (.<=) e1 e2 = le e1 e2 /// Signed less than. diff --git a/src/BinIR/LowUIR.ASTHelper.fs b/src/BinIR/LowUIR.ASTHelper.fs index 28791964..a1b549a0 100644 --- a/src/BinIR/LowUIR.ASTHelper.fs +++ b/src/BinIR/LowUIR.ASTHelper.fs @@ -31,71 +31,72 @@ open B2R2.BinIR [] module internal ValueOptimizer = let inline unop n = function - | UnOpType.NEG -> BitVector.neg n - | UnOpType.NOT -> BitVector.bnot n - | UnOpType.FSQRT -> BitVector.fsqrt n - | UnOpType.FCOS -> BitVector.fcos n - | UnOpType.FSIN -> BitVector.fsin n - | UnOpType.FTAN -> BitVector.ftan n - | UnOpType.FATAN -> BitVector.fatan n + | UnOpType.NEG -> BitVector.Neg n + | UnOpType.NOT -> BitVector.BNot n + | UnOpType.FSQRT -> BitVector.FSqrt n + | UnOpType.FCOS -> BitVector.FCos n + | UnOpType.FSIN -> BitVector.FSin n + | UnOpType.FTAN -> BitVector.FTan n + | UnOpType.FATAN -> BitVector.FAtan n | _ -> Utils.impossible () let inline binop n1 n2 = function - | BinOpType.ADD -> BitVector.add n1 n2 - | BinOpType.SUB -> BitVector.sub n1 n2 - | BinOpType.MUL -> BitVector.mul n1 n2 - | BinOpType.DIV -> BitVector.div n1 n2 - | BinOpType.SDIV -> BitVector.sdiv n1 n2 - | BinOpType.MOD -> BitVector.modulo n1 n2 - | BinOpType.SMOD -> BitVector.smodulo n1 n2 - | BinOpType.SHL -> BitVector.shl n1 n2 - | BinOpType.SAR -> BitVector.sar n1 n2 - | BinOpType.SHR -> BitVector.shr n1 n2 - | BinOpType.AND -> BitVector.band n1 n2 - | BinOpType.OR -> BitVector.bor n1 n2 - | BinOpType.XOR -> BitVector.bxor n1 n2 - | BinOpType.CONCAT -> BitVector.concat n1 n2 - | BinOpType.FADD -> BitVector.fadd n1 n2 - | BinOpType.FSUB -> BitVector.fsub n1 n2 - | BinOpType.FMUL -> BitVector.fmul n1 n2 - | BinOpType.FDIV -> BitVector.fdiv n1 n2 - | BinOpType.FPOW -> BitVector.fpow n1 n2 - | BinOpType.FLOG -> BitVector.flog n1 n2 + | BinOpType.ADD -> BitVector.Add (n1, n2) + | BinOpType.SUB -> BitVector.Sub (n1, n2) + | BinOpType.MUL -> BitVector.Mul (n1, n2) + | BinOpType.DIV -> BitVector.Div (n1, n2) + | BinOpType.SDIV -> BitVector.SDiv (n1, n2) + | BinOpType.MOD -> BitVector.Modulo (n1, n2) + | BinOpType.SMOD -> BitVector.SModulo (n1, n2) + | BinOpType.SHL -> BitVector.Shl (n1, n2) + | BinOpType.SAR -> BitVector.Sar (n1, n2) + | BinOpType.SHR -> BitVector.Shr (n1, n2) + | BinOpType.AND -> BitVector.BAnd (n1, n2) + | BinOpType.OR -> BitVector.BOr (n1, n2) + | BinOpType.XOR -> BitVector.BXor (n1, n2) + | BinOpType.CONCAT -> BitVector.Concat (n1, n2) + | BinOpType.FADD -> BitVector.FAdd (n1, n2) + | BinOpType.FSUB -> BitVector.FSub (n1, n2) + | BinOpType.FMUL -> BitVector.FMul (n1, n2) + | BinOpType.FDIV -> BitVector.FDiv (n1, n2) + | BinOpType.FPOW -> BitVector.FPow (n1, n2) + | BinOpType.FLOG -> BitVector.FLog (n1, n2) | _ -> Utils.impossible () let inline relop n1 n2 = function - | RelOpType.EQ -> BitVector.eq n1 n2 - | RelOpType.NEQ -> BitVector.neq n1 n2 - | RelOpType.GT -> BitVector.gt n1 n2 - | RelOpType.GE -> BitVector.ge n1 n2 - | RelOpType.SGT -> BitVector.sgt n1 n2 - | RelOpType.SGE -> BitVector.sge n1 n2 - | RelOpType.LT -> BitVector.lt n1 n2 - | RelOpType.LE -> BitVector.le n1 n2 - | RelOpType.SLT -> BitVector.slt n1 n2 - | RelOpType.SLE -> BitVector.sle n1 n2 - | RelOpType.FLT -> BitVector.flt n1 n2 - | RelOpType.FLE -> BitVector.fle n1 n2 - | RelOpType.FGT -> BitVector.fgt n1 n2 - | RelOpType.FGE -> BitVector.fge n1 n2 + | RelOpType.EQ -> BitVector.Eq (n1, n2) + | RelOpType.NEQ -> BitVector.Neq (n1, n2) + | RelOpType.GT -> BitVector.Gt (n1, n2) + | RelOpType.GE -> BitVector.Ge (n1, n2) + | RelOpType.SGT -> BitVector.SGt (n1, n2) + | RelOpType.SGE -> BitVector.SGe (n1, n2) + | RelOpType.LT -> BitVector.Lt (n1, n2) + | RelOpType.LE -> BitVector.Le (n1, n2) + | RelOpType.SLT -> BitVector.SLt (n1, n2) + | RelOpType.SLE -> BitVector.SLe (n1, n2) + | RelOpType.FLT -> BitVector.FLt (n1, n2) + | RelOpType.FLE -> BitVector.FLe (n1, n2) + | RelOpType.FGT -> BitVector.FGt (n1, n2) + | RelOpType.FGE -> BitVector.FGe (n1, n2) | _ -> Utils.impossible () let inline cast t n = function - | CastKind.SignExt -> BitVector.sext n t - | CastKind.ZeroExt -> BitVector.zext n t - | CastKind.FloatCast -> BitVector.fcast n t - | CastKind.IntToFloat -> BitVector.itof n t - | CastKind.FtoICeil -> BitVector.ftoiceil n t - | CastKind.FtoIFloor -> BitVector.ftoifloor n t - | CastKind.FtoIRound -> BitVector.ftoiround n t - | CastKind.FtoITrunc -> BitVector.ftoitrunc n t + | CastKind.SignExt -> BitVector.SExt (n, t) + | CastKind.ZeroExt -> BitVector.ZExt (n, t) + | CastKind.FloatCast -> BitVector.FCast (n, t) + | CastKind.SIntToFloat -> BitVector.Itof (n, t, true) + | CastKind.UIntToFloat -> BitVector.Itof (n, t, false) + | CastKind.FtoICeil -> BitVector.FtoiCeil (n, t) + | CastKind.FtoIFloor -> BitVector.FtoiFloor (n, t) + | CastKind.FtoIRound -> BitVector.FtoiRound (n, t) + | CastKind.FtoITrunc -> BitVector.FtoiTrunc (n, t) | _ -> Utils.impossible () - let inline extract e t pos = BitVector.extract e t pos + let inline extract e t pos = BitVector.Extract (e, t, pos) +#if ! HASHCONS [] module internal ASTHelper = -#if ! HASHCONS let inline buildExpr e = { E = e } @@ -103,45 +104,3 @@ module internal ASTHelper = { S = s } #endif - let emptyExprInfo = - { HasLoad = false - VarsUsed = RegisterSet.empty - TempVarsUsed = Set.empty } - - let getExprInfo e = - match e.E with - | Num _ | PCVar _ | Nil | Name _ | FuncName _ | Undefined _ -> emptyExprInfo - | Var (_, _, _, rset) -> - { HasLoad = false; VarsUsed = rset; TempVarsUsed = Set.empty } - | TempVar (_, name) -> - { HasLoad = false - VarsUsed = RegisterSet.empty - TempVarsUsed = Set.singleton name } - | UnOp (_, _, ei) - | BinOp (_, _, _, _, ei) - | RelOp (_, _, _, ei) - | Load (_, _, _, ei) - | Ite (_, _, _, ei) - | Cast (_, _, _, ei) - | Extract (_, _, _, ei) -> ei - - let mergeTwoExprInfo e1 e2 = - let ei1 = getExprInfo e1 - let ei2 = getExprInfo e2 - { HasLoad = ei1.HasLoad || ei2.HasLoad - VarsUsed = RegisterSet.union ei1.VarsUsed ei2.VarsUsed - TempVarsUsed = Set.union ei1.TempVarsUsed ei2.TempVarsUsed } - - let mergeThreeExprInfo e1 e2 e3 = - let ei1 = getExprInfo e1 - let ei2 = getExprInfo e2 - let ei3 = getExprInfo e3 - let vars = - RegisterSet.union ei1.VarsUsed ei2.VarsUsed - |> RegisterSet.union ei3.VarsUsed - let tmps = - Set.union ei1.TempVarsUsed ei2.TempVarsUsed - |> Set.union ei3.TempVarsUsed - { HasLoad = ei1.HasLoad || ei2.HasLoad || ei3.HasLoad - VarsUsed = vars - TempVarsUsed = tmps } diff --git a/src/BinIR/LowUIR.TypeCheck.fs b/src/BinIR/LowUIR.TypeCheck.fs index 8c7a2f60..93cdf111 100644 --- a/src/BinIR/LowUIR.TypeCheck.fs +++ b/src/BinIR/LowUIR.TypeCheck.fs @@ -32,16 +32,16 @@ open B2R2.BinIR let rec typeOf e = match e.E with | Num n -> n.Length - | Var (t, _, _, _) + | Var (t, _, _) | PCVar (t, _) | TempVar (t, _) -> t - | UnOp (_, e, _) -> typeOf e - | BinOp (_, t, _, _, _) -> t + | UnOp (_, e) -> typeOf e + | BinOp (_, t, _, _) -> t | RelOp (_) -> 1 - | Load (_, t, _, _) -> t - | Ite (_, e1, _, _) -> typeOf e1 - | Cast (_, t, _, _) -> t - | Extract (_, t, _, _) -> t + | Load (_, t, _) -> t + | Ite (_, e1, _) -> typeOf e1 + | Cast (_, t, _) -> t + | Extract (_, t, _) -> t | Undefined (t, _) -> t | FuncName (_) | Name (_) | Nil -> raise InvalidExprException @@ -82,7 +82,8 @@ let internal canCast kind newType e = if oldType < newType then true else if oldType = newType then false else castErr newType oldType - | CastKind.IntToFloat -> + | CastKind.SIntToFloat + | CastKind.UIntToFloat -> if isValidFloatType newType then true else raise InvalidFloatTypeException | CastKind.FloatCast -> if isValidFloatType oldType && isValidFloatType newType then true @@ -95,17 +96,17 @@ let internal extract (t: RegType) pos (t2: RegType) = let rec expr e = match e.E with - | UnOp (_, e, _) -> expr e - | BinOp (BinOpType.CONCAT, t, e1, e2, _) -> + | UnOp (_, e) -> expr e + | BinOp (BinOpType.CONCAT, t, e1, e2) -> expr e1 && expr e2 && concat e1 e2 = t - | BinOp (_, t, e1, e2, _) -> expr e1 && expr e2 && binop e1 e2 = t - | RelOp (_, e1, e2, _) -> expr e1 && expr e2 && typeOf e1 = typeOf e2 - | Load (_, _, addr, _) -> expr addr - | Ite (cond, e1, e2, _) -> + | BinOp (_, t, e1, e2) -> expr e1 && expr e2 && binop e1 e2 = t + | RelOp (_, e1, e2) -> expr e1 && expr e2 && typeOf e1 = typeOf e2 + | Load (_, _, addr) -> expr addr + | Ite (cond, e1, e2) -> typeOf cond = 1 && expr e1 && expr e2 && typeOf e1 = typeOf e2 - | Cast (CastKind.SignExt, t, e, _) - | Cast (CastKind.ZeroExt, t, e, _) -> expr e && t >= typeOf e - | Extract (e, t, p, _) -> + | Cast (CastKind.SignExt, t, e) + | Cast (CastKind.ZeroExt, t, e) -> expr e && t >= typeOf e + | Extract (e, t, p) -> expr e && ((t + LanguagePrimitives.Int32WithMeasure p) <= typeOf e) | _ -> true diff --git a/src/BinIR/RelOpType.fs b/src/BinIR/RelOpType.fs index f7b2ea62..39456507 100644 --- a/src/BinIR/RelOpType.fs +++ b/src/BinIR/RelOpType.fs @@ -46,14 +46,18 @@ type RelOpType = | SLT = 8 /// Signed less than or equal | SLE = 9 + /// Floating point equal + | FEQ = 10 + /// Floating point not equal + | FNEQ = 11 /// Floating point greater than - | FGT = 10 + | FGT = 12 /// Floating point greater than or equal - | FGE = 11 + | FGE = 13 /// Floating point less than - | FLT = 12 + | FLT = 14 /// Floating point less than or equal - | FLE = 13 + | FLE = 15 module RelOpType = let toString = function @@ -67,6 +71,8 @@ module RelOpType = | RelOpType.LE -> "<=" | RelOpType.SLT -> "?<" | RelOpType.SLE -> "?<=" + | RelOpType.FEQ -> "=." + | RelOpType.FNEQ -> "!=." | RelOpType.FGT -> ">." | RelOpType.FGE -> ">=." | RelOpType.FLT -> "<." @@ -84,6 +90,8 @@ module RelOpType = | "<=" -> RelOpType.LE | "?<" -> RelOpType.SLT | "?<=" -> RelOpType.SLE + | "=." -> RelOpType.FEQ + | "!=." -> RelOpType.FNEQ | ">." -> RelOpType.FGT | ">=." -> RelOpType.FGE | "<." -> RelOpType.FLT diff --git a/src/BinIR/SSA.AST.fs b/src/BinIR/SSA.AST.fs index 818d0f61..5f6f8756 100644 --- a/src/BinIR/SSA.AST.fs +++ b/src/BinIR/SSA.AST.fs @@ -29,7 +29,7 @@ open B2R2 open B2R2.BinIR let rec typeOf = function - | Num bv -> BitVector.getType bv + | Num bv -> BitVector.GetType bv | Var { Kind = RegVar (rt, _, _) } | Var { Kind = PCVar rt } | Var { Kind = TempVar (rt, _) } -> rt @@ -45,7 +45,7 @@ let rec typeOf = function | _ -> raise InvalidExprException let rec private translateDest = function - | LowUIR.Var (ty, r, n, _) -> { Kind = RegVar (ty, r, n); Identifier = -1 } + | LowUIR.Var (ty, r, n) -> { Kind = RegVar (ty, r, n); Identifier = -1 } | LowUIR.PCVar (ty, _) -> { Kind = PCVar (ty); Identifier = -1 } | LowUIR.TempVar (ty, n) -> { Kind = TempVar (ty, n); Identifier = -1 } | _ -> raise InvalidExprException @@ -61,21 +61,21 @@ let rec translateExpr (e: LowUIR.Expr) = | (LowUIR.Var _ as e) | (LowUIR.PCVar _ as e) | (LowUIR.TempVar _ as e) -> Var <| translateDest e - | LowUIR.UnOp (op, e, _) -> + | LowUIR.UnOp (op, e) -> let ty = LowUIR.TypeCheck.typeOf e UnOp (op, ty, translateExpr e) | LowUIR.FuncName s -> FuncName s - | LowUIR.BinOp (op, ty, e1, e2, _) -> + | LowUIR.BinOp (op, ty, e1, e2) -> BinOp (op, ty, translateExpr e1, translateExpr e2) - | LowUIR.RelOp (op, e1, e2, _) -> + | LowUIR.RelOp (op, e1, e2) -> RelOp (op, 1, translateExpr e1, translateExpr e2) - | LowUIR.Load (_, ty, e, _) -> + | LowUIR.Load (_, ty, e) -> Load ({ Kind = MemVar; Identifier = -1 }, ty, translateExpr e) - | LowUIR.Ite (e1, e2, e3, _) -> + | LowUIR.Ite (e1, e2, e3) -> let ty = LowUIR.TypeCheck.typeOf e2 Ite (translateExpr e1, ty, translateExpr e2, translateExpr e3) - | LowUIR.Cast (op, ty, e, _) -> Cast (op, ty, translateExpr e) - | LowUIR.Extract (e, ty, pos, _) -> Extract (translateExpr e, ty, pos) + | LowUIR.Cast (op, ty, e) -> Cast (op, ty, translateExpr e) + | LowUIR.Extract (e, ty, pos) -> Extract (translateExpr e, ty, pos) | LowUIR.Undefined (ty, s) -> Undefined (ty, s) | LowUIR.Nil -> Nil | _ -> raise InvalidExprException (* Name *) @@ -84,7 +84,7 @@ let rec private translateStmtAux defaultRegType addr (s: LowUIR.Stmt) = match s.S with | LowUIR.ISMark _ -> let pc = { Kind = PCVar (defaultRegType); Identifier = -1 } - let n = Num <| BitVector.ofUInt64 addr defaultRegType + let n = Num <| BitVector.OfUInt64 addr defaultRegType Def (pc, n) |> Some | LowUIR.IEMark _ -> None | LowUIR.LMark symb -> @@ -121,28 +121,11 @@ let rec private translateStmtAux defaultRegType addr (s: LowUIR.Stmt) = let expr3 = translateExpr expr3 let jmp = InterCJmp (expr1, expr2, expr3) Jmp jmp |> Some + | LowUIR.ExternalCall (args) -> + let e = args |> translateExpr + ExternalCall (e, [], []) |> Some | LowUIR.SideEffect s -> - let ssaForm = - match s with - | Breakpoint -> SSA.Breakpoint - | ClockCounter -> SSA.ClockCounter - | Fence -> SSA.Fence - | Delay -> SSA.Delay - | Terminate -> SSA.Terminate - | Interrupt (v) -> SSA.Interrupt (v) - | Exception (v) -> SSA.Exception (v) - | Lock -> SSA.Lock - | Unlock -> SSA.Unlock - | ProcessorID -> SSA.ProcessorID - | SysCall -> SSA.SysCall - | UndefinedInstr -> SSA.UndefinedInstr - | UnsupportedFP -> SSA.UnsupportedFP - | UnsupportedPrivInstr -> SSA.UnsupportedPrivInstr - | UnsupportedFAR -> SSA.UnsupportedFAR - | UnsupportedExtension -> SSA.UnsupportedExtension - | ExternalCall (expr) -> - expr |> translateExpr |> SSA.ExternalCall - SideEffect (ssaForm, [], []) |> Some + SideEffect s |> Some let translateStmts defaultRegType addr fnPostprocess stmts = stmts diff --git a/src/BinIR/SSA.Pp.fs b/src/BinIR/SSA.Pp.fs index 6773a4c6..137c1c0c 100644 --- a/src/BinIR/SSA.Pp.fs +++ b/src/BinIR/SSA.Pp.fs @@ -32,89 +32,87 @@ open B2R2.BinIR let rec private expToStringAux expr (sb: StringBuilder) = match expr with - | Num n -> sb.Append (BitVector.toString n) |> ignore - | Var (v) -> sb.Append (Variable.toString v) |> ignore - | Nil -> sb.Append ("nil") |> ignore - | FuncName (n) -> sb.Append (n) |> ignore + | Num n -> sb.Append (BitVector.ToString n) |> ignore + | Var (v) -> sb.Append (Variable.ToString v) |> ignore + | Nil -> sb.Append "nil" |> ignore + | FuncName (n) -> sb.Append n |> ignore | UnOp (op, _, e) -> - sb.Append ("(") |> ignore + sb.Append "(" |> ignore sb.Append (UnOpType.toString op) |> ignore - sb.Append (" ") |> ignore + sb.Append " " |> ignore expToStringAux e sb - sb.Append (")") |> ignore + sb.Append ")" |> ignore | BinOp (op, _, e1, e2) -> - sb.Append ("(") |> ignore + sb.Append "(" |> ignore expToStringAux e1 sb - sb.Append (" ") |> ignore + sb.Append " " |> ignore sb.Append (BinOpType.toString op) |> ignore - sb.Append (" ") |> ignore + sb.Append " " |> ignore expToStringAux e2 sb - sb.Append (")") |> ignore + sb.Append ")" |> ignore | RelOp (op, _, e1, e2) -> - sb.Append ("(") |> ignore + sb.Append "(" |> ignore expToStringAux e1 sb - sb.Append (" ") |> ignore + sb.Append " " |> ignore sb.Append (RelOpType.toString op) |> ignore - sb.Append (" ") |> ignore + sb.Append " " |> ignore expToStringAux e2 sb - sb.Append (")") |> ignore + sb.Append ")" |> ignore | Load (v, typ, e) -> - sb.Append (Variable.toString v) |> ignore - sb.Append ("[") |> ignore + sb.Append (Variable.ToString v) |> ignore + sb.Append "[" |> ignore expToStringAux e sb - sb.Append ("]:") |> ignore + sb.Append "]:" |> ignore sb.Append (RegType.toString typ) |> ignore | Store (v, _, addr, e) -> - sb.Append (Variable.toString v) |> ignore - sb.Append ("[") |> ignore + sb.Append (Variable.ToString v) |> ignore + sb.Append "[" |> ignore expToStringAux addr sb - sb.Append (" <- ") |> ignore + sb.Append " <- " |> ignore expToStringAux e sb - sb.Append ("]") |> ignore + sb.Append "]" |> ignore | Ite (cond, _, e1, e2) -> - sb.Append ("(ite (") |> ignore + sb.Append "(ite (" |> ignore expToStringAux cond sb - sb.Append (") (") |> ignore + sb.Append ") (" |> ignore expToStringAux e1 sb - sb.Append (") (") |> ignore + sb.Append ") (" |> ignore expToStringAux e2 sb - sb.Append ("))") |> ignore + sb.Append "))" |> ignore | Cast (cast, typ, e) -> sb.Append (CastKind.toString cast) |> ignore - sb.Append (":") |> ignore + sb.Append ":" |> ignore sb.Append (RegType.toString typ) |> ignore - sb.Append ("(") |> ignore + sb.Append "(" |> ignore expToStringAux e sb - sb.Append (")") |> ignore + sb.Append ")" |> ignore | Extract (e, typ, p) -> - sb.Append ("(") |> ignore + sb.Append "(" |> ignore expToStringAux e sb - sb.Append ("[") |> ignore + sb.Append "[" |> ignore sb.Append ((int typ + p - 1).ToString () + ":" + p.ToString ())|> ignore - sb.Append ("]") |> ignore - sb.Append (")") |> ignore + sb.Append "]" |> ignore + sb.Append ")" |> ignore | Undefined (_, reason) -> sb.Append ("Undefined expression (") |> ignore - sb.Append (reason) |> ignore - sb.Append (")") |> ignore + sb.Append reason |> ignore + sb.Append ")" |> ignore | ReturnVal (addr, ret, _) -> - sb.Append ("RetFromFunc(") |> ignore - sb.Append (String.u64ToHexNoPrefix addr) |> ignore - sb.Append (",") |> ignore - sb.Append (String.u64ToHexNoPrefix ret) |> ignore - sb.Append (")") |> ignore + sb.Append "RetFromFunc(" |> ignore + sb.Append $"{addr:x}" |> ignore + sb.Append "," |> ignore + sb.Append $"{ret:x}" |> ignore + sb.Append ")" |> ignore let private labelToString (addr: Addr, symb) (sb: StringBuilder) = - sb.Append (Symbol.getName symb) |> ignore - sb.Append (" @ ") |> ignore - sb.Append (String.u64ToHexNoPrefix addr) |> ignore + sb.Append $"{Symbol.getName symb} @ {addr:x}" |> ignore let private variablesToString (kind: string) vars (sb: StringBuilder) = sb.Append (" ") |> ignore sb.Append (kind) |> ignore sb.Append ("(") |> ignore vars |> List.iter (fun v -> - sb.Append (Variable.toString v) |> ignore + sb.Append (Variable.ToString v) |> ignore sb.Append (";") |> ignore) sb.Append (")") |> ignore @@ -125,7 +123,7 @@ let private stmtToStringAux stmt (sb: StringBuilder) = labelToString lbl sb sb.Append (")") |> ignore | Def (v, e) -> - sb.Append (Variable.toString v) |> ignore + sb.Append (Variable.ToString v) |> ignore sb.Append (" := ") |> ignore expToStringAux e sb | Jmp (IntraJmp (lbl))-> @@ -149,24 +147,27 @@ let private stmtToStringAux stmt (sb: StringBuilder) = sb.Append (" else Jmp ") |> ignore expToStringAux dst2 sb | Phi (def, indices) -> - sb.Append (Variable.toString def) |> ignore + sb.Append (Variable.ToString def) |> ignore sb.Append (" := phi(") |> ignore indices |> Array.iter (fun i -> sb.Append (i.ToString ()) |> ignore sb.Append (";") |> ignore) sb.Append (")") |> ignore - | SideEffect (eff, inVars, outVars) -> - sb.Append ("SideEffect " + eff.ToString ()) |> ignore + | ExternalCall (args, inVars, outVars) -> + sb.Append ("call ") |> ignore + expToStringAux args sb variablesToString "OutVars" outVars sb variablesToString "InVars" inVars sb + | SideEffect (eff) -> + sb.Append ("SideEffect " + SideEffect.toString eff) |> ignore let expToString expr = - let sb = new StringBuilder () + let sb = StringBuilder () expToStringAux expr sb sb.ToString () let stmtToString expr = - let sb = new StringBuilder () + let sb = StringBuilder () stmtToStringAux expr sb sb.ToString () diff --git a/src/BinIR/SSA.fs b/src/BinIR/SSA.fs index beb33e5d..daa1e9df 100644 --- a/src/BinIR/SSA.fs +++ b/src/BinIR/SSA.fs @@ -45,8 +45,7 @@ type VariableKind = /// Global variables. This variable is available only after the SSA promotion. | GlobalVar of RegType * Addr with - [] - static member toString = function + static member ToString = function | RegVar (_, _, n) -> n | PCVar (_) -> "PC" | TempVar (_, n) -> "T_" + n.ToString() @@ -60,12 +59,10 @@ type Variable = { mutable Identifier: int } with - [] - static member toString ({ Kind = k; Identifier = i }) = - VariableKind.toString k + "_" + i.ToString () + static member ToString ({ Kind = k; Identifier = i }) = + VariableKind.ToString k + "_" + i.ToString () - [] - static member isPC ({ Kind = k }) = + static member IsPC ({ Kind = k }) = match k with | PCVar (_) -> true | _ -> false @@ -122,11 +119,12 @@ type Expr = /// case). | Undefined of RegType * string - /// Value returned from a function located at the address (fnAddr). The second - /// argument indicates the return address (the fall-through address of the - /// call instruction), and the third argument indicates the live definition of - /// previously defined variable. A fake bbl will contain this expression. - | ReturnVal of fnAddr: Addr * retAddr: Addr * Variable + /// Value returned (i.e. defined) from a function located at the address + /// (fnAddr). The second argument indicates the return address (the + /// fall-through address of the call instruction), and the third argument + /// indicates the live value expression defined from the callee. A fake bbl + /// will contain this expression. + | ReturnVal of fnAddr: Addr * retAddr: Addr * value: Expr /// IR Label. Since we don't distinguish instruction boundary in SSA level, we /// want to specify where the label comes from. @@ -143,62 +141,6 @@ type JmpType = /// third Expr refer to true and false branch addresses, respectively. | InterCJmp of Expr * Expr * Expr -type SideEffect = - /// Software breakpoint. - | Breakpoint - /// CPU clock access, e.g., RDTSC on x86. - | ClockCounter - /// Memory fence operations, e.g., LFENCE/MFENCE/SFENCE on x86. - | Fence - /// Delay the execution for a while, e.g. HLT, PAUSE on x86. - | Delay - /// Terminate the execution. - | Terminate - /// Asynchronous event triggered by software (e.g. INT on x86) or hardware. - | Interrupt of int - /// Synchronous event generated when the execution encounters error condition. - | Exception of string - /// Acquire the instruction evaluation lock. - | Lock - /// Release the instruction evaluation lock. - | Unlock - /// Access CPU details, e.g., CPUID on x86. - | ProcessorID - /// System call. - | SysCall - /// Explicitly undefined instruction, e.g., UD2 on x86. - | UndefinedInstr - /// Unsupported floating point operations. - | UnsupportedFP - /// Unsupported privileged instructions. - | UnsupportedPrivInstr - /// Unsupported FAR branching. - | UnsupportedFAR - /// Unsupported processor extension. - | UnsupportedExtension - /// External function call. - | ExternalCall of Expr -with - [] - static member toString = function - | Breakpoint -> "Breakpoint" - | ClockCounter -> "ClockCounter" - | Fence -> "Fence" - | Delay -> "Delay" - | Terminate -> "Terminate" - | Interrupt (v) -> "Interrupt " + v.ToString () - | Exception (v) -> "Exception " + v - | Lock -> "Lock" - | Unlock -> "Unlock" - | ProcessorID -> "ProcessorID" - | SysCall -> "SysCall" - | UndefinedInstr -> "UndefinedInstr" - | UnsupportedFP -> "UnsupportedFP" - | UnsupportedPrivInstr -> "UnsupportedPrivInstr" - | UnsupportedFAR -> "UnsupportedFAR" - | UnsupportedExtension -> "UnsupportedExtension" - | ExternalCall (expr) -> "ExternalCall " + expr.ToString () - /// IR Statements. type Stmt = /// A label (as in an assembly language). LMark is only valid within a @@ -214,8 +156,11 @@ type Stmt = /// Branch statement. | Jmp of JmpType + /// External call. + | ExternalCall of Expr * inVars: Variable list * outVars: Variable list + /// This represents an instruction with side effects such as a system call. - | SideEffect of SideEffect * inVars: Variable list * outVars: Variable list + | SideEffect of SideEffect /// A program is a list of statements. type Prog = Stmt list list diff --git a/src/BinIR/SideEffect.fs b/src/BinIR/SideEffect.fs index b19d6855..b56013f3 100644 --- a/src/BinIR/SideEffect.fs +++ b/src/BinIR/SideEffect.fs @@ -24,8 +24,6 @@ namespace B2R2.BinIR -open B2R2.BinIR.LowUIR - /// Side effect kinds. type SideEffect = /// Software breakpoint. @@ -62,8 +60,10 @@ type SideEffect = | UnsupportedFAR /// Unsupported processor extension. | UnsupportedExtension - /// External function call. - | ExternalCall of Expr +#if EMULATION + /// EFLAGS lazy evaluation + | FlagsUpdate +#endif module SideEffect = let toString = function @@ -83,4 +83,6 @@ module SideEffect = | UnsupportedPrivInstr -> "PrivInstr" | UnsupportedFAR -> "FAR" | UnsupportedExtension -> "CPU extension" - | ExternalCall expr -> "Call " + Expr.toString expr +#if EMULATION + | FlagsUpdate -> "FlagsUpdate" +#endif diff --git a/src/BinIR/Stmt.fs b/src/BinIR/Stmt.fs index 82507c7a..850a76ef 100644 --- a/src/BinIR/Stmt.fs +++ b/src/BinIR/Stmt.fs @@ -43,10 +43,14 @@ type InterJmpKind = | IsRet = 2 /// An exit, which will terminate the process. | IsExit = 4 - /// A branch instructino that modifies the operation mode from Thumb to ARM. + /// A branch instruction that modifies the operation mode from Thumb to ARM. | SwitchToARM = 8 - /// A branch instructino that modifies the operation mode from ARM to Thumb. + /// A branch instruction that modifies the operation mode from ARM to Thumb. | SwitchToThumb = 16 + /// This is not a jump instruction. This is only useful in special cases such + /// as when representing a delay slot of MIPS, and should never be used in + /// other cases. + | NotAJmp = -1 /// IL Statements. /// NOTE: You MUST create Expr/Stmt through the AST module. *NEVER* directly @@ -107,6 +111,10 @@ type S = /// Otherwise, jump to the address specified by the third argument. | InterCJmp of Expr * Expr * Expr + /// External function call. This statement represents a uninterpreted function + /// call. The argument expression is in a curried form. + | ExternalCall of Expr + /// This represents an instruction with side effects such as a system call. | SideEffect of SideEffect #if ! HASHCONS @@ -158,8 +166,11 @@ with static member inline HashInterCJmp (cond: Expr) (t: Expr) (f: Expr) = 19 * (19 * (19 * cond.HashKey + t.HashKey) + f.HashKey) + 9 + static member inline HashExtCall (e: Expr) = + (19 * e.HashKey) + 10 + static member inline HashSideEffect (e: SideEffect) = - (19 * hash e) + 10 + (19 * hash e) + 11 override __.GetHashCode () = match __ with @@ -172,6 +183,7 @@ with | CJmp (cond, t, f) -> S.HashCJmp cond t f | InterJmp (e, k) -> S.HashInterJmp e k | InterCJmp (cond, t, f) -> S.HashInterCJmp cond t f + | ExternalCall (e) -> S.HashExtCall e | SideEffect (e) -> S.HashSideEffect e #endif @@ -242,10 +254,13 @@ module Stmt = Expr.appendToString t sb sb.Append (" else ijmp ") |> ignore Expr.appendToString f sb + | ExternalCall (args) -> + sb.Append ("call ") |> ignore + Expr.appendToString args sb | SideEffect eff -> sb.Append ("!!" + SideEffect.toString eff) |> ignore let toString stmt = - let sb = new StringBuilder () + let sb = StringBuilder () appendToString stmt sb sb.ToString () diff --git a/src/BinIR/UnOpType.fs b/src/BinIR/UnOpType.fs index df1f497d..34c46fd5 100644 --- a/src/BinIR/UnOpType.fs +++ b/src/BinIR/UnOpType.fs @@ -41,7 +41,6 @@ type UnOpType = /// Arc Tangent | FATAN = 8 - module UnOpType = let toString = function | UnOpType.NEG -> "-" diff --git a/src/BinIR/Utils.fs b/src/BinIR/Utils.fs index 7614ecf7..8664ba81 100644 --- a/src/BinIR/Utils.fs +++ b/src/BinIR/Utils.fs @@ -28,5 +28,5 @@ open B2R2.BinIR.LowUIR /// Is this IR statement a branch statement? let isBranch = function - | Jmp _ | CJmp _ | InterJmp _ | InterCJmp _ -> true + | Jmp _ | CJmp _ | InterJmp _ | InterCJmp _ | ExternalCall _ -> true | ISMark _ | IEMark _ | LMark _ | Put _ | Store _ | SideEffect _ -> false diff --git a/src/Core.Tests/B2R2.Core.Tests.fsproj b/src/Core.Tests/B2R2.Core.Tests.fsproj index a7e92b50..2f6625ec 100644 --- a/src/Core.Tests/B2R2.Core.Tests.fsproj +++ b/src/Core.Tests/B2R2.Core.Tests.fsproj @@ -5,6 +5,7 @@ + @@ -16,9 +17,9 @@ - - - + + + diff --git a/src/Core.Tests/BinReader.Tests.fs b/src/Core.Tests/BinReader.Tests.fs index 0a688d7c..85e1bbe9 100644 --- a/src/Core.Tests/BinReader.Tests.fs +++ b/src/Core.Tests/BinReader.Tests.fs @@ -31,117 +31,122 @@ open B2R2 type BinReaderTests () = [] - member __.``decodeUInt64 Test`` () = - let u64 = [| - ([| 0x00uy; |], 0x00UL) - ([| 0x7fuy; |], 0x7fUL) - ([| 0x80uy; 0x01uy; |], 0x80UL) - ([| 0xffuy; 0x01uy; |], 0xffUL) - ([| 0x9duy; 0x12uy; |], 0x091dUL) - ([| 0x97uy; 0xdeuy; 0x03uy; |], 0xef17UL) - ([| 0xe5uy; 0x8euy; 0x26uy; |], 0x098765UL) - ([| 0xffuy; 0xffuy; 0x03uy; |], 0xffffUL) - ([| 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0xffuy; - 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0x01uy; |], 18446744073709551615UL) - ([| 0x83uy; 0x00uy; |], 0x03UL) - |] - for arr, res in u64 do - let r = BinReader.binReaderLE - let v, _ = r.ReadUInt64LEB128 (arr, 0) - Assert.AreEqual(res, v) + member __.``Little-endian vs. Big-endian Test`` () = + let sample = [| 0x11uy; 0x22uy; 0x33uy; 0x44uy |] + let lr = BinReader.Init Endian.Little + let v = lr.ReadInt32 (System.ReadOnlySpan sample, 0) + Assert.AreEqual (expected=0x44332211, actual=v) + let br = BinReader.Init Endian.Big + let v = br.ReadInt32 (System.ReadOnlySpan sample, 0) + Assert.AreEqual (expected=0x11223344, actual=v) [] - member __.``decodeUInt32 Test`` () = - let u32 = [| - ([| 0x00uy; |], 0x00u) - ([| 0x7fuy; |], 0x7fu) - ([| 0x80uy; 0x01uy; |], 0x80u) - ([| 0xffuy; 0x01uy; |], 0xffu) - ([| 0x9duy; 0x12uy; |], 0x091du) - ([| 0x97uy; 0xdeuy; 0x03uy; |], 0xef17u) - ([| 0xe5uy; 0x8euy; 0x26uy; |], 0x098765u) - ([| 0xffuy; 0xffuy; 0x03uy; |], 0xffffu) - ([| 0x83uy; 0x00uy; |], 0x03u) - |] - for arr, res in u32 do - let r = BinReader.binReaderLE - let v, _ = r.ReadUInt32LEB128 (arr, 0) - Assert.AreEqual(res, v) + member __.``Read Overflow Test`` () = + let sample = [| 0x11uy; 0x22uy |] + let r = BinReader.Init Endian.Little + let v = + try r.ReadInt32 (System.ReadOnlySpan sample, 0) + with :? System.ArgumentOutOfRangeException -> 0 + Assert.AreEqual (expected=0, actual=v) [] - member __.``decodeSInt64 Test`` () = - let s64 = [| - ([| 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0xffuy; - 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0x00uy; |], 9223372036854775807L) - ([| 0x97uy; 0xdeuy; 0x03uy; |], 0xef17L) - ([| 0xC0uy; 0x00uy; |], 0x40L) - ([| 0x3fuy; |], 0x3fL) - ([| 0x01uy; |], 1L) - ([| 0x00uy; |], 0L) - ([| 0x7fuy; |], -1L) - ([| 0x40uy; |], -64L) - ([| 0xbfuy; 0x7fuy; |], -65L) - ([| 0x9Buy; 0xF1uy; 0x59uy; |], -624485L) - ([| 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x80uy; - 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy; |], -9223372036854775808L) - ([| 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy; |], -268435456L) - |] - for arr, res in s64 do - let r = BinReader.binReaderLE - let v, _ = r.ReadInt64LEB128 (arr, 0) - Assert.AreEqual(res, v) + member __.``LEB128 to UInt64 Test`` () = + let samples = + [| (* (LEB encoded bytes, Decoded number) *) + ([| 0x00uy |], 0x00UL) + ([| 0x7fuy |], 0x7fUL) + ([| 0x80uy; 0x01uy |], 0x80UL) + ([| 0xffuy; 0x01uy |], 0xffUL) + ([| 0x9duy; 0x12uy |], 0x091dUL) + ([| 0x97uy; 0xdeuy; 0x03uy |], 0xef17UL) + ([| 0xe5uy; 0x8euy; 0x26uy |], 0x098765UL) + ([| 0xffuy; 0xffuy; 0x03uy |], 0xffffUL) + ([| 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0xffuy; + 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0x01uy |], 18446744073709551615UL) + ([| 0x83uy; 0x00uy |], 0x03UL) + |] + for bytes, value in samples do + let r = BinReader.Init () + let v, _ = r.ReadUInt64LEB128 (bytes, 0) + Assert.AreEqual (expected=value, actual=v) [] - member __.``decodeSInt32 Test`` () = - let s32 = [| - ([| 0x97uy; 0xdeuy; 0x03uy; |], 0xef17) - ([| 0xC0uy; 0x00uy; |], 0x40) - ([| 0x3fuy; |], 0x3f) - ([| 0x01uy; |], 1) - ([| 0x00uy; |], 0) - ([| 0x7fuy; |], -1) - ([| 0x40uy; |], -64) - ([| 0xbfuy; 0x7fuy; |], -65) - ([| 0x9Buy; 0xF1uy; 0x59uy; |], -624485) - ([| 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy; |], -268435456) - |] - for arr, res in s32 do - let r = BinReader.binReaderLE - let v, _ = r.ReadInt32LEB128 (arr, 0) - Assert.AreEqual(res, v) + member __.``LEB128 to UInt32 Test`` () = + let samples = + [| (* (LEB encoded bytes, Decoded number) *) + ([| 0x00uy |], 0x00u) + ([| 0x7fuy |], 0x7fu) + ([| 0x80uy; 0x01uy |], 0x80u) + ([| 0xffuy; 0x01uy |], 0xffu) + ([| 0x9duy; 0x12uy |], 0x091du) + ([| 0x97uy; 0xdeuy; 0x03uy |], 0xef17u) + ([| 0xe5uy; 0x8euy; 0x26uy |], 0x098765u) + ([| 0xffuy; 0xffuy; 0x03uy |], 0xffffu) + ([| 0x83uy; 0x00uy |], 0x03u) + |] + for bytes, value in samples do + let r = BinReader.Init () + let v, _ = r.ReadUInt32LEB128 (bytes, 0) + Assert.AreEqual (expected=value, actual=v) [] - member __.``Overflow handling Test`` () = - let overflow = [| + member __.``LEB128 to SInt64 Test`` () = + let samples = + [| (* (LEB encoded bytes, Decoded number) *) + ([| 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0xffuy; + 0xffuy; 0xffuy; 0xffuy; 0xffuy; 0x00uy; |], 9223372036854775807L) + ([| 0x97uy; 0xdeuy; 0x03uy |], 0xef17L) + ([| 0xC0uy; 0x00uy |], 0x40L) + ([| 0x3fuy |], 0x3fL) + ([| 0x01uy |], 1L) + ([| 0x00uy |], 0L) + ([| 0x7fuy |], -1L) + ([| 0x40uy |], -64L) + ([| 0xbfuy; 0x7fuy |], -65L) + ([| 0x9Buy; 0xF1uy; 0x59uy |], -624485L) + ([| 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x80uy; + 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy; |], -9223372036854775808L) + ([| 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy |], -268435456L) + |] + for bytes, value in samples do + let r = BinReader.Init () + let v, _ = r.ReadInt64LEB128 (bytes, 0) + Assert.AreEqual (expected=value, actual=v) + + [] + member __.``LEB128 to SInt32 Test`` () = + let samples = + [| (* (LEB encoded bytes, Decoded number) *) + ([| 0x97uy; 0xdeuy; 0x03uy |], 0xef17) + ([| 0xC0uy; 0x00uy |], 0x40) + ([| 0x3fuy |], 0x3f) + ([| 0x01uy |], 1) + ([| 0x00uy |], 0) + ([| 0x7fuy |], -1) + ([| 0x40uy |], -64) + ([| 0xbfuy; 0x7fuy |], -65) + ([| 0x9Buy; 0xF1uy; 0x59uy |], -624485) + ([| 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy |], -268435456) + |] + for bytes, value in samples do + let r = BinReader.Init () + let v, _ = r.ReadInt32LEB128 (bytes, 0) + Assert.AreEqual (expected=value, actual=v) + + [] + member __.``LEB128 Overflow Handling Test`` () = + let testcase = [| 0xffuy; 0x80uy; 0x80uy; 0x80uy; 0x80uy; - 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy; |] - |] - let r = BinReader.binReaderLE - let decodeOverflowed func = + 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x80uy; 0x7fuy |] + let toBool decode = try - func () |> ignore + decode () |> ignore false with | :? LEB128DecodeException -> true | _ -> false - - let u64Result = - overflow - |> Array.map (fun arr -> - decodeOverflowed (fun () -> r.ReadUInt64LEB128 (arr, 0))) - Assert.IsTrue (Array.forall (fun ov -> ov) u64Result) - let u32Result = - overflow - |> Array.map (fun arr -> - decodeOverflowed (fun () -> r.ReadUInt32LEB128 (arr, 0))) - Assert.IsTrue (Array.forall (fun ov -> ov) u32Result) - let s64Result = - overflow - |> Array.map (fun arr -> - decodeOverflowed (fun () -> r.ReadInt64LEB128 (arr, 0))) - Assert.IsTrue (Array.forall (fun ov -> ov) s64Result) - let s32Result = - overflow - |> Array.map (fun arr -> - decodeOverflowed (fun () -> r.ReadInt32LEB128 (arr, 0))) - Assert.IsTrue (Array.forall (fun ov -> ov) s32Result) \ No newline at end of file + let r = BinReader.Init () + toBool (fun () -> r.ReadUInt64LEB128 (testcase, 0)) |> Assert.IsTrue + toBool (fun () -> r.ReadUInt32LEB128 (testcase, 0)) |> Assert.IsTrue + toBool (fun () -> r.ReadInt64LEB128 (testcase, 0)) |> Assert.IsTrue + toBool (fun () -> r.ReadInt32LEB128 (testcase, 0)) |> Assert.IsTrue \ No newline at end of file diff --git a/src/Core.Tests/BitVector.Tests.fs b/src/Core.Tests/BitVector.Tests.fs index 30f28f35..258e6ea9 100644 --- a/src/Core.Tests/BitVector.Tests.fs +++ b/src/Core.Tests/BitVector.Tests.fs @@ -33,376 +33,398 @@ type BitVectorTests () = [] member __.``Equality`` () = - Assert.AreEqual (BitVector.ofInt32 5l 16, - BitVector.ofBInt 5I 16) - Assert.AreEqual (BitVector.ofUInt32 5ul 16, - BitVector.ofInt64 5L 16) - Assert.AreEqual (BitVector.ofInt64 -5L 128, - BitVector.ofInt32 -5l 128) + Assert.AreEqual (BitVector.OfInt32 5l 16, + BitVector.OfBInt 5I 16) + Assert.AreEqual (BitVector.OfUInt32 5ul 16, + BitVector.OfInt64 5L 16) + Assert.AreEqual (BitVector.OfInt64 -5L 128, + BitVector.OfInt32 -5l 128) Assert.AreEqual (int64 -1, - BitVector.ofInt64 -1L 64 |> BitVector.toInt64) + BitVector.OfInt64 -1L 64 |> BitVector.ToInt64) [] member __.``Comparison`` () = - let lt = BitVector.lt - let gt = BitVector.gt - let ge = BitVector.ge - let tr = BitVector.one 1 - (lt (BitVector.ofInt32 5l 16) (BitVector.ofInt32 10l 16) = tr) + let lt = BitVector.Lt + let gt = BitVector.Gt + let ge = BitVector.Ge + let tr = BitVector.One 1 + (lt (BitVector.OfInt32 5l 16, BitVector.OfInt32 10l 16) = tr) |> Assert.IsTrue - (gt (BitVector.ofInt32 21l 128) (BitVector.ofInt32 20l 128) = tr) + (gt (BitVector.OfInt32 21l 128, BitVector.OfInt32 20l 128) = tr) |> Assert.IsTrue - (ge (BitVector.ofInt32 5l 32) (BitVector.ofInt32 5l 32) = tr) + (ge (BitVector.OfInt32 5l 32, BitVector.OfInt32 5l 32) = tr) |> Assert.IsTrue - (BitVector.ofInt32 1l 32 <> BitVector.ofInt32 -1l 32) + (BitVector.OfInt32 1l 32 <> BitVector.OfInt32 -1l 32) |> Assert.IsTrue - (BitVector.ofInt32 1l 64 <> BitVector.ofInt32 1l 8) + (BitVector.OfInt32 1l 64 <> BitVector.OfInt32 1l 8) |> Assert.IsTrue [] member __.``Basic Arithmetic 1`` () = - let n1 = BitVector.ofInt32 1l 64 - let n2 = BitVector.ofInt32 -1l 64 - Assert.AreEqual (BitVector.add n1 n2, BitVector.zero 64) - Assert.AreEqual (BitVector.sub n1 n2, BitVector.ofInt32 2l 64) - Assert.AreEqual (BitVector.sub n2 n1, BitVector.ofInt32 -2l 64) - Assert.AreEqual (BitVector.mul n1 n2, n2) - Assert.AreEqual (BitVector.div n1 n2, BitVector.zero 64) - Assert.AreEqual (BitVector.sdiv n1 n2, n2) + let n1 = BitVector.OfInt32 1l 64 + let n2 = BitVector.OfInt32 -1l 64 + Assert.AreEqual (BitVector.Add (n1, n2), BitVector.Zero 64) + Assert.AreEqual (BitVector.Sub (n1, n2), BitVector.OfInt32 2l 64) + Assert.AreEqual (BitVector.Sub (n2, n1), BitVector.OfInt32 -2l 64) + Assert.AreEqual (BitVector.Mul (n1, n2), n2) + Assert.AreEqual (BitVector.Div (n1, n2), BitVector.Zero 64) + Assert.AreEqual (BitVector.SDiv (n1, n2), n2) [] member __.``Basic Arithmetic 2`` () = - let e1 = BitVector.ofBInt 10I 8 - let e2 = BitVector.ofBInt 3I 8 - let n1 = BitVector.ofUInt64 (uint8 -10 |> uint64) 8 - let n2 = BitVector.ofUInt64 (uint8 -3 |> uint64) 8 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0xd:I8") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x7:I8") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, "0x1e:I8") - Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I8") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, "0xfd:I8") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, "0xfd:I8") - let e1 = BitVector.ofBInt 10000I 16 - let e2 = BitVector.ofBInt 3000I 16 - let n1 = BitVector.ofInt32 (-10000l) 16 - let n2 = BitVector.ofInt32 (-3000l) 16 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x32c8:I16") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x1b58:I16") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, "0xc380:I16") - Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I16") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, "0xfffd:I16") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, "0xfffd:I16") + let e1 = BitVector.OfBInt 10I 8 + let e2 = BitVector.OfBInt 3I 8 + let n1 = BitVector.OfUInt64 (uint8 -10 |> uint64) 8 + let n2 = BitVector.OfUInt64 (uint8 -3 |> uint64) 8 + Assert.AreEqual (BitVector.ToString <| BitVector.Add (e1, e2), "0xd:I8") + Assert.AreEqual (BitVector.ToString <| BitVector.Sub (e1, e2), "0x7:I8") + Assert.AreEqual (BitVector.ToString <| BitVector.Mul (e1, e2), "0x1e:I8") + Assert.AreEqual (BitVector.ToString <| BitVector.Div (e1, e2), "0x3:I8") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (e1, n2), "0xfd:I8") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, e2), "0xfd:I8") + let e1 = BitVector.OfBInt 10000I 16 + let e2 = BitVector.OfBInt 3000I 16 + let n1 = BitVector.OfInt32 (-10000l) 16 + let n2 = BitVector.OfInt32 (-3000l) 16 + Assert.AreEqual (BitVector.ToString <| BitVector.Add (e1, e2), "0x32c8:I16") + Assert.AreEqual (BitVector.ToString <| BitVector.Sub (e1, e2), "0x1b58:I16") + Assert.AreEqual (BitVector.ToString <| BitVector.Mul (e1, e2), "0xc380:I16") + Assert.AreEqual (BitVector.ToString <| BitVector.Div (e1, e2), "0x3:I16") + Assert.AreEqual + (BitVector.ToString <| BitVector.SDiv (e1, n2), "0xfffd:I16") + Assert.AreEqual + (BitVector.ToString <| BitVector.SDiv (n1, e2), "0xfffd:I16") [] member __.``Basic Arithmetic 3`` () = - let e1 = BitVector.ofBInt 100000I 32 - let e2 = BitVector.ofBInt 30000I 32 - let n1 = BitVector.ofInt32 (-100000l) 32 - let n2 = BitVector.ofInt32 (-30000l) 32 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x1fbd0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x11170:I32") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, - "0xb2d05e00:I32") - Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, - "0xfffffffd:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, - "0xfffffffd:I32") - let e1 = BitVector.ofBInt 1000000I 64 - let e2 = BitVector.ofBInt 300000I 64 - let n1 = BitVector.ofInt64 (-1000000L) 64 - let n2 = BitVector.ofInt64 (-300000L) 64 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0x13d620:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0xaae60:I64") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, + let e1 = BitVector.OfBInt 100000I 32 + let e2 = BitVector.OfBInt 30000I 32 + let n1 = BitVector.OfInt32 (-100000l) 32 + let n2 = BitVector.OfInt32 (-30000l) 32 + Assert.AreEqual + (BitVector.ToString <| BitVector.Add (e1, e2), "0x1fbd0:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Sub (e1, e2), "0x11170:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Mul (e1, e2), "0xb2d05e00:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Div (e1, e2), "0x3:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.SDiv (e1, n2), "0xfffffffd:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.SDiv (n1, e2), "0xfffffffd:I32") + let e1 = BitVector.OfBInt 1000000I 64 + let e2 = BitVector.OfBInt 300000I 64 + let n1 = BitVector.OfInt64 (-1000000L) 64 + let n2 = BitVector.OfInt64 (-300000L) 64 + Assert.AreEqual + (BitVector.ToString <| BitVector.Add (e1, e2), "0x13d620:I64") + Assert.AreEqual + (BitVector.ToString <| BitVector.Sub (e1, e2), "0xaae60:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.Mul (e1, e2), "0x45d964b800:I64") - Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, + Assert.AreEqual (BitVector.ToString <| BitVector.Div (e1, e2), "0x3:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (e1, n2), "0xfffffffffffffffd:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, e2), "0xfffffffffffffffd:I64") [] member __.``Basic Arithmetic 4`` () = - let e1 = BitVector.ofBInt 10000000I 128 - let e2 = BitVector.ofBInt 3000000I 128 - let n1 = BitVector.ofInt64 (-10000000L) 128 - let n2 = BitVector.ofInt64 (-3000000L) 128 - Assert.AreEqual (BitVector.toString <| BitVector.add e1 e2, "0xc65d40:I128") - Assert.AreEqual (BitVector.toString <| BitVector.sub e1 e2, "0x6acfc0:I128") - Assert.AreEqual (BitVector.toString <| BitVector.mul e1 e2, - "0x1b48eb57e000:I128") - Assert.AreEqual (BitVector.toString <| BitVector.div e1 e2, "0x3:I128") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv e1 n2, + let e1 = BitVector.OfBInt 10000000I 128 + let e2 = BitVector.OfBInt 3000000I 128 + let n1 = BitVector.OfInt64 (-10000000L) 128 + let n2 = BitVector.OfInt64 (-3000000L) 128 + Assert.AreEqual + (BitVector.ToString <| BitVector.Add (e1, e2), "0xc65d40:I128") + Assert.AreEqual + (BitVector.ToString <| BitVector.Sub (e1, e2), "0x6acfc0:I128") + Assert.AreEqual + (BitVector.ToString <| BitVector.Mul (e1, e2), "0x1b48eb57e000:I128") + Assert.AreEqual (BitVector.ToString <| BitVector.Div (e1, e2), "0x3:I128") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (e1, n2), "0xfffffffffffffffffffffffffffffffd:I128") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 e2, + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, e2), "0xfffffffffffffffffffffffffffffffd:I128") - let e1 = BitVector.ofInt32 0xDFFFFDEA 32 - let e2 = BitVector.ofInt32 1 32 - Assert.AreEqual (BitVector.toString <| BitVector.sar e1 e2, - "0xeffffef5:I32") + let e1 = BitVector.OfInt32 0xDFFFFDEA 32 + let e2 = BitVector.OfInt32 1 32 + Assert.AreEqual + (BitVector.ToString <| BitVector.Sar (e1, e2), "0xeffffef5:I32") [] member __.``Basic Arithmetic 5`` () = - // test for signed division - let n1 = BitVector.ofInt64 (-4L) 64 - let n2 = BitVector.ofInt64 (-2L) 64 - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 n2, "0x2:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n2 n1, "0x0:I64") - let n1 = BitVector.ofInt64 (-4L) 64 - let n2 = BitVector.ofInt64 (2L) 64 - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 n2, + (* test for signed division *) + let n1 = BitVector.OfInt64 (-4L) 64 + let n2 = BitVector.OfInt64 (-2L) 64 + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, n2), "0x2:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n2, n1), "0x0:I64") + let n1 = BitVector.OfInt64 (-4L) 64 + let n2 = BitVector.OfInt64 (2L) 64 + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, n2), "0xfffffffffffffffe:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n2 n1, "0x0:I64") - let n1 = BitVector.ofInt64 (4L) 64 - let n2 = BitVector.ofInt64 (-2L) 64 - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 n2, + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n2, n1), "0x0:I64") + let n1 = BitVector.OfInt64 (4L) 64 + let n2 = BitVector.OfInt64 (-2L) 64 + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, n2), "0xfffffffffffffffe:I64") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n2 n1, "0x0:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n2, n1), "0x0:I64") [] member __.``Basic Arithmetic 6`` () = - // test for shift operations - let n1 = BitVector.ofInt64 1L 32 - let n2 = BitVector.ofInt64 31L 32 - let n3 = BitVector.ofInt64 32L 32 - let n4 = BitVector.ofInt64 (-1L) 32 - Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n2, "0x80000000:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n3, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shl n4 n1, "0xfffffffe:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shl n4 n2, "0x80000000:I32") + (* test for shift operations *) + let n1 = BitVector.OfInt64 1L 32 + let n2 = BitVector.OfInt64 31L 32 + let n3 = BitVector.OfInt64 32L 32 + let n4 = BitVector.OfInt64 (-1L) 32 + Assert.AreEqual + (BitVector.ToString <| BitVector.Shl (n1, n2), "0x80000000:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n1, n3), "0x0:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Shl (n4, n1), "0xfffffffe:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Shl (n4, n2), "0x80000000:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shr n1 n2, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n2, "0x1:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n3, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shr n4 n1, "0x7fffffff:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n1, n2), "0x0:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n4, n2), "0x1:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n4, n3), "0x0:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Shr (n4, n1), "0x7fffffff:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n1 n2, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n3, "0xffffffff:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n1, "0xffffffff:I32") - Assert.AreEqual (BitVector.toString <| BitVector.sar n4 n3, "0xffffffff:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Sar (n1, n2), "0x0:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Sar (n4, n3), "0xffffffff:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Sar (n4, n1), "0xffffffff:I32") + Assert.AreEqual + (BitVector.ToString <| BitVector.Sar (n4, n3), "0xffffffff:I32") [] member __.``Basic Arithmetic 7`` () = - // test for 1 bit operation - let n0 = BitVector.ofInt64 (0L) 1 - let n1 = BitVector.ofInt64 (1L) 1 - Assert.AreEqual (BitVector.toString <| BitVector.add n1 n0, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.add n1 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sub n1 n0, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sub n1 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sub n0 n1, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.mul n1 n0, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.mul n0 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.mul n1 n1, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.div n0 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.div n1 n1, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n0 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sdiv n1 n1, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n0, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.shl n0 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.shr n1 n0, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.shr n0 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.shr n1 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sar n1 n0, "0x1:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sar n0 n1, "0x0:I1") - Assert.AreEqual (BitVector.toString <| BitVector.sar n1 n1, "0x0:I1") + (* test for 1 bit operation *) + let n0 = BitVector.OfInt64 (0L) 1 + let n1 = BitVector.OfInt64 (1L) 1 + Assert.AreEqual (BitVector.ToString <| BitVector.Add (n1, n0), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Add (n1, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Sub (n1, n0), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Sub (n1, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Sub (n0, n1), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Mul (n1, n0), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Mul (n0, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Mul (n1, n1), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Div (n0, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Div (n1, n1), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n0, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.SDiv (n1, n1), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n1, n0), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n0, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n1, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n1, n0), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n0, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n1, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Sar (n1, n0), "0x1:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Sar (n0, n1), "0x0:I1") + Assert.AreEqual (BitVector.ToString <| BitVector.Sar (n1, n1), "0x0:I1") [] member __.``Shift by a Large Amount`` () = - let n1 = BitVector.ofUInt32 1ul 32 - let n2 = BitVector.ofInt32 128 32 - let n3 = BitVector.ofUInt32 1ul 128 - let n4 = BitVector.ofInt32 128 128 - Assert.AreEqual (BitVector.toString <| BitVector.shr n1 n2, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shl n1 n2, "0x0:I32") - Assert.AreEqual (BitVector.toString <| BitVector.shr n3 n4, "0x0:I128") - Assert.AreEqual (BitVector.toString <| BitVector.shl n3 n4, "0x0:I128") + let n1 = BitVector.OfUInt32 1ul 32 + let n2 = BitVector.OfInt32 128 32 + let n3 = BitVector.OfUInt64 0x8000000000000000UL 64 + let n4 = BitVector.OfInt32 64 64 + let n5 = BitVector.OfBInt (1I <<< 127) 128 + let n6 = BitVector.OfInt32 128 128 + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n1, n2), "0x0:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n1, n2), "0x0:I32") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n3, n4), "0x0:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.Sar (n3, n4), "0x0:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n3, n4), "0x0:I64") + Assert.AreEqual (BitVector.ToString <| BitVector.Shr (n5, n6), "0x0:I128") + Assert.AreEqual (BitVector.ToString <| BitVector.Sar (n5, n6), "0x0:I128") + Assert.AreEqual (BitVector.ToString <| BitVector.Shl (n5, n6), "0x0:I128") [] member __.``Unsigned Modulo`` () = - let n1 = BitVector.ofUInt32 5ul 32 - let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.toString <| BitVector.modulo n1 n2, "0x5:I32") - let n1 = BitVector.ofBInt 5I 256 - let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.toString <| BitVector.modulo n1 n2, "0x5:I256") + let n1 = BitVector.OfUInt32 5ul 32 + let n2 = BitVector.OfInt32 -3l 32 + Assert.AreEqual (BitVector.ToString <| BitVector.Modulo (n1, n2), "0x5:I32") + let n1 = BitVector.OfBInt 5I 256 + let n2 = BitVector.OfInt64 -3L 256 + Assert.AreEqual + (BitVector.ToString <| BitVector.Modulo (n1, n2), "0x5:I256") [] member __.``Signed Modulo`` () = - // Added for signed modulo bug test - let n1 = BitVector.ofUInt32 5ul 32 - let n2 = BitVector.ofInt32 3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 32) - let n1 = BitVector.ofBInt 5I 256 - let n2 = BitVector.ofInt64 3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 256) - let n1 = BitVector.ofUInt32 5ul 32 - let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 32) - let n1 = BitVector.ofBInt 5I 256 - let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 2 256) - let n1 = BitVector.ofInt32 -5l 32 - let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 32) - let n1 = BitVector.ofBInt -5I 256 - let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 256) - let n1 = BitVector.ofInt32 -5l 32 - let n2 = BitVector.ofInt32 3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 32) - let n1 = BitVector.ofBInt -5I 256 - let n2 = BitVector.ofInt64 3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 -2 256) - // zero value test - let n1 = BitVector.ofUInt32 6ul 32 - let n2 = BitVector.ofInt32 3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofBInt 6I 256 - let n2 = BitVector.ofInt64 3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) - let n1 = BitVector.ofUInt32 6ul 32 - let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofBInt 6I 256 - let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) - let n1 = BitVector.ofInt32 -6l 32 - let n2 = BitVector.ofInt32 -3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofBInt -6I 256 - let n2 = BitVector.ofInt64 -3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) - let n1 = BitVector.ofInt32 -6l 32 - let n2 = BitVector.ofInt32 3l 32 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 32) - let n1 = BitVector.ofBInt -6I 256 - let n2 = BitVector.ofInt64 3L 256 - Assert.AreEqual (BitVector.smodulo n1 n2, BitVector.ofInt32 0l 256) + (* Added for signed modulo bug test *) + let n1 = BitVector.OfUInt32 5ul 32 + let n2 = BitVector.OfInt32 3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 2 32) + let n1 = BitVector.OfBInt 5I 256 + let n2 = BitVector.OfInt64 3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 2 256) + let n1 = BitVector.OfUInt32 5ul 32 + let n2 = BitVector.OfInt32 -3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 2 32) + let n1 = BitVector.OfBInt 5I 256 + let n2 = BitVector.OfInt64 -3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 2 256) + let n1 = BitVector.OfInt32 -5l 32 + let n2 = BitVector.OfInt32 -3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 -2 32) + let n1 = BitVector.OfBInt -5I 256 + let n2 = BitVector.OfInt64 -3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 -2 256) + let n1 = BitVector.OfInt32 -5l 32 + let n2 = BitVector.OfInt32 3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 -2 32) + let n1 = BitVector.OfBInt -5I 256 + let n2 = BitVector.OfInt64 3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 -2 256) + (* zero value test *) + let n1 = BitVector.OfUInt32 6ul 32 + let n2 = BitVector.OfInt32 3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 32) + let n1 = BitVector.OfBInt 6I 256 + let n2 = BitVector.OfInt64 3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 256) + let n1 = BitVector.OfUInt32 6ul 32 + let n2 = BitVector.OfInt32 -3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 32) + let n1 = BitVector.OfBInt 6I 256 + let n2 = BitVector.OfInt64 -3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 256) + let n1 = BitVector.OfInt32 -6l 32 + let n2 = BitVector.OfInt32 -3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 32) + let n1 = BitVector.OfBInt -6I 256 + let n2 = BitVector.OfInt64 -3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 256) + let n1 = BitVector.OfInt32 -6l 32 + let n2 = BitVector.OfInt32 3l 32 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 32) + let n1 = BitVector.OfBInt -6I 256 + let n2 = BitVector.OfInt64 3L 256 + Assert.AreEqual (BitVector.SModulo (n1, n2), BitVector.OfInt32 0l 256) [] member __.``Logical Operators`` () = - let n1 = BitVector.ofBInt 100I 32 - let n2 = BitVector.ofInt32 -500l 32 - Assert.AreEqual (BitVector.toString <| BitVector.band n1 n2, "0x4:I32") - let n1 = BitVector.ofBInt 100I 256 - let n2 = BitVector.ofInt32 -500l 256 - Assert.AreEqual (BitVector.toString <| BitVector.band n1 n2, "0x4:I256") - let n1 = BitVector.ofBInt 100I 32 - let n2 = BitVector.ofInt32 -500l 32 - Assert.AreEqual (BitVector.toString <| BitVector.bor n1 n2, + let n1 = BitVector.OfBInt 100I 32 + let n2 = BitVector.OfInt32 -500l 32 + Assert.AreEqual (BitVector.ToString <| BitVector.BAnd (n1, n2), "0x4:I32") + let n1 = BitVector.OfBInt 100I 256 + let n2 = BitVector.OfInt32 -500l 256 + Assert.AreEqual (BitVector.ToString <| BitVector.BAnd (n1, n2), "0x4:I256") + let n1 = BitVector.OfBInt 100I 32 + let n2 = BitVector.OfInt32 -500l 32 + Assert.AreEqual (BitVector.ToString <| BitVector.BOr (n1, n2), "0xfffffe6c:I32") - let n1 = BitVector.ofBInt 100I 256 - let n2 = BitVector.ofInt32 -500l 256 - Assert.AreEqual (BitVector.bor n1 n2, BitVector.ofInt64 -404L 256) - let n1 = BitVector.ofBInt 100I 32 - let n2 = BitVector.ofInt32 -500l 32 - Assert.AreEqual (BitVector.toString <| BitVector.bxor n1 n2, + let n1 = BitVector.OfBInt 100I 256 + let n2 = BitVector.OfInt32 -500l 256 + Assert.AreEqual (BitVector.BOr (n1, n2), BitVector.OfInt64 -404L 256) + let n1 = BitVector.OfBInt 100I 32 + let n2 = BitVector.OfInt32 -500l 32 + Assert.AreEqual (BitVector.ToString <| BitVector.BXor (n1, n2), "0xfffffe68:I32") - let n1 = BitVector.ofBInt 100I 256 - let n2 = BitVector.ofInt32 -500l 256 - Assert.AreEqual (BitVector.bxor n1 n2, BitVector.ofInt64 -408L 256) + let n1 = BitVector.OfBInt 100I 256 + let n2 = BitVector.OfInt32 -500l 256 + Assert.AreEqual (BitVector.BXor (n1, n2), BitVector.OfInt64 -408L 256) [] member __.``Comparison Operators`` () = - let n1 = BitVector.ofBInt 100I 32 - let n2 = BitVector.ofBInt 100I 32 - Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) - Assert.AreEqual (BitVector.sle n1 n2, BitVector.one 1) - let n1 = BitVector.ofBInt 100I 256 - let n2 = BitVector.ofBInt 100I 256 - Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) - Assert.AreEqual (BitVector.sle n1 n2, BitVector.one 1) - let n1 = BitVector.ofBInt 100I 32 - let n2 = BitVector.ofInt32 -500l 32 - Assert.AreEqual (BitVector.lt n1 n2, BitVector.one 1) - Assert.AreEqual (BitVector.le n1 n2, BitVector.one 1) - Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) - Assert.AreEqual (BitVector.sle n1 n2, BitVector.zero 1) - let n1 = BitVector.ofBInt 100I 256 - let n2 = BitVector.ofInt32 -500l 256 - Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) - Assert.AreEqual (BitVector.sle n1 n2, BitVector.zero 1) - let n1 = BitVector.ofInt32 -200 256 - let n2 = BitVector.ofInt32 -500 256 - Assert.AreEqual (BitVector.slt n1 n2, BitVector.zero 1) - Assert.AreEqual (BitVector.sle n1 n2, BitVector.zero 1) - let n1 = BitVector.ofInt32 0x5b 8 - let n2 = BitVector.ofInt32 0x98 8 - Assert.AreEqual (BitVector.sgt n1 n2, BitVector.one 1) + let n1 = BitVector.OfBInt 100I 32 + let n2 = BitVector.OfBInt 100I 32 + Assert.AreEqual (BitVector.SLt (n1, n2), BitVector.Zero 1) + Assert.AreEqual (BitVector.SLe (n1, n2), BitVector.One 1) + let n1 = BitVector.OfBInt 100I 256 + let n2 = BitVector.OfBInt 100I 256 + Assert.AreEqual (BitVector.SLt (n1, n2), BitVector.Zero 1) + Assert.AreEqual (BitVector.SLe (n1, n2), BitVector.One 1) + let n1 = BitVector.OfBInt 100I 32 + let n2 = BitVector.OfInt32 -500l 32 + Assert.AreEqual (BitVector.Lt (n1, n2), BitVector.One 1) + Assert.AreEqual (BitVector.Le (n1, n2), BitVector.One 1) + Assert.AreEqual (BitVector.SLt (n1, n2), BitVector.Zero 1) + Assert.AreEqual (BitVector.SLe (n1, n2), BitVector.Zero 1) + let n1 = BitVector.OfBInt 100I 256 + let n2 = BitVector.OfInt32 -500l 256 + Assert.AreEqual (BitVector.SLt (n1, n2), BitVector.Zero 1) + Assert.AreEqual (BitVector.SLe (n1, n2), BitVector.Zero 1) + let n1 = BitVector.OfInt32 -200 256 + let n2 = BitVector.OfInt32 -500 256 + Assert.AreEqual (BitVector.SLt (n1, n2), BitVector.Zero 1) + Assert.AreEqual (BitVector.SLe (n1, n2), BitVector.Zero 1) + let n1 = BitVector.OfInt32 0x5b 8 + let n2 = BitVector.OfInt32 0x98 8 + Assert.AreEqual (BitVector.SGt (n1, n2), BitVector.One 1) [] member __.``Unary Operators`` () = - let n1 = BitVector.ofBInt 100I 32 - let n2 = BitVector.ofBInt 0I 16 - let n3 = BitVector.ofInt32 0xffffffff 32 - Assert.AreEqual (BitVector.bnot n1, BitVector.ofInt32 0xffffff9bl 32) - Assert.AreEqual (BitVector.bnot n2, BitVector.ofInt32 0xffffl 16) - Assert.AreEqual (BitVector.bnot n3, BitVector.ofInt32 0 32) - Assert.AreEqual (BitVector.toString <| BitVector.neg n1, "0xffffff9c:I32") - Assert.AreEqual (BitVector.neg n2, BitVector.ofInt32 0l 16) - let n1 = BitVector.ofBInt 0I 128 - Assert.AreEqual (BitVector.neg n1, BitVector.ofInt32 0l 128) + let n1 = BitVector.OfBInt 100I 32 + let n2 = BitVector.OfBInt 0I 16 + let n3 = BitVector.OfInt32 0xffffffff 32 + Assert.AreEqual (BitVector.BNot n1, BitVector.OfInt32 0xffffff9bl 32) + Assert.AreEqual (BitVector.BNot n2, BitVector.OfInt32 0xffffl 16) + Assert.AreEqual (BitVector.BNot n3, BitVector.OfInt32 0 32) + Assert.AreEqual (BitVector.ToString <| BitVector.Neg n1, "0xffffff9c:I32") + Assert.AreEqual (BitVector.Neg n2, BitVector.OfInt32 0l 16) + let n1 = BitVector.OfBInt 0I 128 + Assert.AreEqual (BitVector.Neg n1, BitVector.OfInt32 0l 128) [] member __.``Concatenation Operator`` () = - let e1 = BitVector.ofBInt 1000I 32 - let e2 = BitVector.ofBInt 300I 32 - Assert.AreEqual (BitVector.toString <| BitVector.concat e1 e2, - "0x3e80000012c:I64") - let e1 = BitVector.ofBInt 1000I 32 - let e2 = BitVector.ofInt64 -300L 32 - Assert.AreEqual (BitVector.toString <| BitVector.concat e1 e2, - "0x3e8fffffed4:I64") + let e1 = BitVector.OfBInt 1000I 32 + let e2 = BitVector.OfBInt 300I 32 + Assert.AreEqual + (BitVector.ToString <| BitVector.Concat (e1, e2), "0x3e80000012c:I64") + let e1 = BitVector.OfBInt 1000I 32 + let e2 = BitVector.OfInt64 -300L 32 + Assert.AreEqual + (BitVector.ToString <| BitVector.Concat (e1, e2), "0x3e8fffffed4:I64") [] member __.``Size Extension``() = - // Extension. - let e1 = BitVector.ofInt32 -1 8 - Assert.AreEqual (BitVector.zext e1 32, BitVector.ofInt32 0xff 32) - let e1 = BitVector.ofUInt32 0xffu 8 - Assert.AreEqual (BitVector.sext e1 32, BitVector.ofInt32 -1 32) - let e1 = BitVector.ofInt32 0x1 8 - Assert.AreEqual (BitVector.sext e1 32, BitVector.ofInt32 1 32) + (* Extension. *) + let e1 = BitVector.OfInt32 -1 8 + Assert.AreEqual (BitVector.ZExt (e1, 32), BitVector.OfInt32 0xff 32) + let e1 = BitVector.OfUInt32 0xffu 8 + Assert.AreEqual (BitVector.SExt (e1, 32), BitVector.OfInt32 -1 32) + let e1 = BitVector.OfInt32 0x1 8 + Assert.AreEqual (BitVector.SExt (e1, 32), BitVector.OfInt32 1 32) [] member __.``Absolute Operator``() = - let e1 = BitVector.ofInt32 -1 8 - let e2 = BitVector.ofInt32 -16 32 - Assert.AreEqual (BitVector.toString <| BitVector.abs e1, "0x1:I8") - Assert.AreEqual (BitVector.toString <| BitVector.abs e2, "0x10:I32") + let e1 = BitVector.OfInt32 -1 8 + let e2 = BitVector.OfInt32 -16 32 + Assert.AreEqual (BitVector.ToString <| BitVector.Abs e1, "0x1:I8") + Assert.AreEqual (BitVector.ToString <| BitVector.Abs e2, "0x10:I32") [] member __.``Extract``() = - let e1 = BitVector.ofInt32 13453 32 - Assert.AreEqual (BitVector.toString <| BitVector.extract e1 16 4, - "0x348:I16") + let e1 = BitVector.OfInt32 13453 32 + Assert.AreEqual + (BitVector.ToString <| BitVector.Extract (e1, 16, 4), "0x348:I16") [] member __.``Infix Operator``() = - let e1 = BitVector.ofInt32 4 64 - let e2 = BitVector.ofInt32 20 64 - Assert.AreEqual (e1 + e2, BitVector.ofInt32 24 64) - Assert.AreEqual (e1 - e2, BitVector.ofInt32 -16 64) - Assert.AreEqual (e1 * e2, BitVector.ofInt32 80 64) - Assert.AreEqual (e1 &&& e2, BitVector.ofInt32 4 64) - Assert.AreEqual (e1 ||| e2, BitVector.ofInt32 20 64) - Assert.AreEqual (e1 ^^^ e2, BitVector.ofInt32 16 64) - Assert.AreEqual (e1 / e2, BitVector.zero 64) - Assert.AreEqual (e2 / e1, BitVector.ofInt32 5 64) - Assert.AreEqual (e1 % e2, BitVector.ofInt32 4 64) - Assert.AreEqual (e2 % e1, BitVector.zero 64) - Assert.AreEqual (-e1, BitVector.ofInt32 -4 64) + let e1 = BitVector.OfInt32 4 64 + let e2 = BitVector.OfInt32 20 64 + Assert.AreEqual (e1 + e2, BitVector.OfInt32 24 64) + Assert.AreEqual (e1 - e2, BitVector.OfInt32 -16 64) + Assert.AreEqual (e1 * e2, BitVector.OfInt32 80 64) + Assert.AreEqual (e1 &&& e2, BitVector.OfInt32 4 64) + Assert.AreEqual (e1 ||| e2, BitVector.OfInt32 20 64) + Assert.AreEqual (e1 ^^^ e2, BitVector.OfInt32 16 64) + Assert.AreEqual (e1 / e2, BitVector.Zero 64) + Assert.AreEqual (e2 / e1, BitVector.OfInt32 5 64) + Assert.AreEqual (e1 % e2, BitVector.OfInt32 4 64) + Assert.AreEqual (e2 % e1, BitVector.Zero 64) + Assert.AreEqual (-e1, BitVector.OfInt32 -4 64) [] member __.``BitVector from Array (Beware of the MSB)``() = let arr = [| 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 248uy; 127uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 240uy; 255uy |] - let e1 = BitVector.ofArr arr - let t1 = BitVector.ofUInt64 0xFFF0000000000000UL 64 - let t2 = BitVector.ofUInt64 0x7FF8000000000000UL 64 - let e2 = BitVector.concat t1 t2 - Assert.AreEqual(BitVector.T, BitVector.eq e1 e2) + let e1 = BitVector.OfArr arr + let t1 = BitVector.OfUInt64 0xFFF0000000000000UL 64 + let t2 = BitVector.OfUInt64 0x7FF8000000000000UL 64 + let e2 = BitVector.Concat (t1, t2) + Assert.AreEqual(BitVector.T, BitVector.Eq (e1, e2)) diff --git a/src/Core.Tests/RegisterSet.Tests.fs b/src/Core.Tests/RegisterSet.Tests.fs new file mode 100644 index 00000000..14cf2837 --- /dev/null +++ b/src/Core.Tests/RegisterSet.Tests.fs @@ -0,0 +1,78 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +namespace B2R2.Core.Tests + + +open System +open System.Collections.Generic +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 + +[] +type RegisterSetTests () = + + [] + member __.``Size Test 1`` () = + let s = RegisterSet (64) + Assert.AreEqual (64, s.MaxNumElems) + Assert.AreEqual (1, s.BitArray.Length) + + [] + member __.``Size Test 2`` () = + let s = RegisterSet (65) + Assert.AreEqual (65, s.MaxNumElems) + Assert.AreEqual (2, s.BitArray.Length) + + [] + member __.``Add Test 1`` () = + let s = RegisterSet (65) + let lst = List () + s.Add 0 + s.Add 8 + s.Add 42 + s.Add 64 + s.Iterate (lst.Add >> ignore) + CollectionAssert.AreEqual ([| 0; 8; 42; 64|], lst) + + [] + [)>] + member __.``Add Test 2`` () = + let s = RegisterSet (65) + s.Add 65 + + [] + member __.``Add/Remove Test`` () = + let s = RegisterSet (65) + let lst = List () + s.Add 0 + s.Add 8 + s.Add 42 + s.Add 64 + s.Remove 0 + s.Remove 42 + s.Remove 64 + s.Iterate (lst.Add >> ignore) + CollectionAssert.AreEqual ([| 8 |], lst) + diff --git a/src/Core/Addr.fs b/src/Core/Addr.fs index 90c1a9fd..4c179fca 100644 --- a/src/Core/Addr.fs +++ b/src/Core/Addr.fs @@ -27,12 +27,17 @@ namespace B2R2 /// Addresses are represented with a 64-bit integer in B2R2. type Addr = uint64 +[] module Addr = let [] private FunctionPrefix = "func_" + /// Convert an address of a given word size to a string. + [] let toString wordSize (addr: Addr) = if wordSize = WordSize.Bit32 then (uint32 addr).ToString ("x8") else addr.ToString ("x16") + /// Convert an address to a function name used in B2R2. + [] let toFuncName (addr: Addr) = FunctionPrefix + addr.ToString ("x") diff --git a/src/Core/AddrRange.fs b/src/Core/AddrRange.fs index 624d192e..4bd7a75f 100644 --- a/src/Core/AddrRange.fs +++ b/src/Core/AddrRange.fs @@ -44,7 +44,7 @@ type AddrRange = { Min = addr; Max = addr } override __.ToString () = - String.u64ToHexNoPrefix __.Min + " -- " + String.u64ToHexNoPrefix __.Max + $"{__.Min:x} -- {__.Max:x}" override __.Equals (rhs: obj) = match rhs with @@ -59,6 +59,11 @@ type AddrRange = member __.ToTuple () = __.Min, __.Max + member __.Slice (target: AddrRange) = + let l = max __.Min target.Min + let h = min __.Max target.Max + AddrRange (l, h) + /// Check if the address range is including the given address. member inline __.IsIncluding (addr: Addr) = __.Min <= addr && addr <= __.Max diff --git a/src/Core/AddrRange.fsi b/src/Core/AddrRange.fsi index 0f7a2892..fac314e8 100644 --- a/src/Core/AddrRange.fsi +++ b/src/Core/AddrRange.fsi @@ -74,6 +74,14 @@ type AddrRange = /// member ToTuple: unit -> Addr * Addr + /// + /// Slice the given AddrRange (target) based on my range, in such a way that + /// the resulting range is always included in my range. + /// + /// + /// + member Slice: target: AddrRange -> AddrRange + /// /// Check if the address range is including the given address. /// diff --git a/src/Core/ArchOperationMode.fs b/src/Core/ArchOperationMode.fs new file mode 100644 index 00000000..14a7180f --- /dev/null +++ b/src/Core/ArchOperationMode.fs @@ -0,0 +1,61 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2 + +/// Raised when an invalid ArchOperationMode is given. +exception InvalidTargetArchModeException + +/// Some ISA, such as ARM, have their own operation mode, which can vary at +/// runtime. For example, ARM architecture can switch between Thumb and ARM +/// mode. In such architectures, the parsing/lifting logic will vary depending +/// on the ArchOperationMode. For most other architectures, it will always be +/// NoMode. +type ArchOperationMode = + /// ARM mode. + | ARMMode = 1 + /// Thumb mode. + | ThumbMode = 2 + /// No mode. This is used for architectures that do not have any operation + /// mode. + | NoMode = 3 + +/// A helper module for ArchOperationMode. +[] +module ArchOperationMode = + /// Transform a string into an ArchOperationMode. + [] + let ofString (s: string) = + match s.ToLowerInvariant () with + | "arm" -> ArchOperationMode.ARMMode + | "thumb" -> ArchOperationMode.ThumbMode + | _ -> ArchOperationMode.NoMode + + /// Transform an ArchOperationMode into a string. + [] + let toString mode = + match mode with + | ArchOperationMode.ARMMode -> "arm" + | ArchOperationMode.ThumbMode -> "thumb" + | _ -> "nomode" diff --git a/src/Core/B2R2.Core.fsproj b/src/Core/B2R2.Core.fsproj index 4e66fafb..d4499b45 100644 --- a/src/Core/B2R2.Core.fsproj +++ b/src/Core/B2R2.Core.fsproj @@ -2,9 +2,9 @@ LICENSE.md b2r2-240x240.png - $(OtherFlags)--warnon:3390 README.md B2R2 core library. + $(OtherFlags)--warnon:3390 @@ -13,6 +13,9 @@ + + + @@ -23,6 +26,7 @@ + diff --git a/src/Core/BinReader.fs b/src/Core/BinReader.fs index 210011c4..14f5af66 100644 --- a/src/Core/BinReader.fs +++ b/src/Core/BinReader.fs @@ -26,29 +26,19 @@ namespace B2R2 open System open System.Buffers.Binary +open System.Runtime.InteropServices /// This is a type alias for `ReadOnlySpan`. We define this alias because /// B2R2 uses this type quite frequently. type ByteSpan = ReadOnlySpan -/// IBinReader provides an interface for reading byte sequences from a byte array -/// (or a Span). The way of reading can change depending on the endianness used -/// by the target binary. +/// IBinReader provides an interface for reading byte sequences from a byte +/// array (or a ByteSpan). The endianness is determined by the implementation +/// of the interface. type IBinReader = - /// Get a read-only span of bytes (ByteSpan) from the given byte - /// array. - abstract GetReadOnlySpan: - bs: byte[] * offset: int * size: int -> ByteSpan - /// The endianness of this reader. abstract Endianness: Endian - /// Read a single byte from the given byte array. - abstract ReadByte: bs: byte[] * offset: int -> byte - - /// Read a single byte from the given byte span. - abstract ReadByte: span: ByteSpan * offset: int -> byte - /// Read a single byte as an int8 from the given byte array. abstract ReadInt8: bs: byte[] * offset: int -> int8 @@ -97,13 +87,6 @@ type IBinReader = /// Read a uint64 value from the given byte span. abstract ReadUInt64: span: ByteSpan * offset: int -> uint64 - /// Read a byte array of `size` from the given byte array. - abstract ReadBytes: bs: byte[] * offset: int * size: int -> byte[] - - /// Read a byte array of `size` from the given byte span. - abstract ReadBytes: - span: ByteSpan * offset: int * size: int -> byte[] - /// Read a character array of size n from the given byte array. abstract ReadChars: bs: byte[] * offset: int * size: int -> char[] @@ -158,18 +141,8 @@ type IBinReader = /// Little-endian binary reader. type BinReaderLE () = interface IBinReader with - member __.GetReadOnlySpan (bs, offset, size) = - let span = ReadOnlySpan (bs) - span.Slice (offset, size) - member __.Endianness with get() = Endian.Little - member __.ReadByte (bs: byte[], offset) = - bs[offset] - - member __.ReadByte (span: ByteSpan, offset) = - span[offset] - member __.ReadInt8 (bs: byte[], offset) = bs[offset] |> int8 @@ -224,12 +197,6 @@ type BinReaderLE () = member __.ReadUInt64 (span: ByteSpan, offset) = BinaryPrimitives.ReadUInt64LittleEndian (span.Slice offset) - member __.ReadBytes (bs: byte[], offset, size) = - Array.sub bs offset size - - member __.ReadBytes (span: ByteSpan, offset, size) = - span.Slice(offset, size).ToArray() - member __.ReadChars (bs: byte[], offset, size) = Array.sub bs offset size |> Array.map char @@ -238,28 +205,28 @@ type BinReaderLE () = span.Slice(offset, size).ToArray() |> Array.map char - member __.ReadInt64LEB128 (bs, offset) = + member __.ReadInt64LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeSInt64 (span.Slice offset) member __.ReadInt64LEB128 (span: ByteSpan, offset) = LEB128.DecodeSInt64 (span.Slice offset) - member __.ReadUInt64LEB128 (bs, offset) = + member __.ReadUInt64LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeUInt64 (span.Slice offset) member __.ReadUInt64LEB128 (span: ByteSpan, offset) = LEB128.DecodeUInt64 (span.Slice offset) - member __.ReadInt32LEB128 (bs, offset) = + member __.ReadInt32LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeSInt32 (span.Slice offset) member __.ReadInt32LEB128 (span: ByteSpan, offset) = LEB128.DecodeSInt32 (span.Slice offset) - member __.ReadUInt32LEB128 (bs, offset) = + member __.ReadUInt32LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeUInt32 (span.Slice offset) @@ -269,18 +236,8 @@ type BinReaderLE () = /// Big-endian binary reader. type BinReaderBE () = interface IBinReader with - member __.GetReadOnlySpan (bs, offset, size) = - let span = ReadOnlySpan (bs) - span.Slice (offset, size) - member __.Endianness with get() = Endian.Big - member __.ReadByte (bs: byte[], offset) = - bs[offset] - - member __.ReadByte (span: ByteSpan, offset) = - span[offset] - member __.ReadInt8 (bs: byte[], offset) = bs[offset] |> int8 @@ -335,12 +292,6 @@ type BinReaderBE () = member __.ReadUInt64 (span: ByteSpan, offset) = BinaryPrimitives.ReadUInt64BigEndian (span.Slice offset) - member __.ReadBytes (bs: byte[], offset, size) = - Array.sub bs offset size - - member __.ReadBytes (span: ByteSpan, offset, size) = - span.Slice(offset, size).ToArray() - member __.ReadChars (bs: byte[], offset, size) = Array.sub bs offset size |> Array.map char @@ -349,38 +300,40 @@ type BinReaderBE () = span.Slice(offset, size).ToArray() |> Array.map char - member __.ReadInt64LEB128 (bs, offset) = + member __.ReadInt64LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeSInt64 (span.Slice offset) member __.ReadInt64LEB128 (span: ByteSpan, offset) = LEB128.DecodeSInt64 (span.Slice offset) - member __.ReadUInt64LEB128 (bs, offset) = + member __.ReadUInt64LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeUInt64 (span.Slice offset) member __.ReadUInt64LEB128 (span: ByteSpan, offset) = LEB128.DecodeUInt64 (span.Slice offset) - member __.ReadInt32LEB128 (bs, offset) = + member __.ReadInt32LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeSInt32 (span.Slice offset) member __.ReadInt32LEB128 (span: ByteSpan, offset) = LEB128.DecodeSInt32 (span.Slice offset) - member __.ReadUInt32LEB128 (bs, offset) = + member __.ReadUInt32LEB128 (bs: byte[], offset) = let span = ReadOnlySpan (bs) LEB128.DecodeUInt32 (span.Slice offset) member __.ReadUInt32LEB128 (span: ByteSpan, offset) = LEB128.DecodeUInt32 (span.Slice offset) -[] -module BinReader = - [] - let binReaderLE = BinReaderLE () :> IBinReader - - [] - let binReaderBE = BinReaderBE () :> IBinReader +/// A factory for creating a binary reader. +type BinReader = + /// Create a binary reader with the given endianness. The default endianness + /// is little-endian. + static member Init ([] endian) = + match endian with + | Endian.Little -> BinReaderLE () :> IBinReader + | _ -> BinReaderBE () :> IBinReader diff --git a/src/Core/BitVector.fs b/src/Core/BitVector.fs index 6a0f634f..8ea215c7 100644 --- a/src/Core/BitVector.fs +++ b/src/Core/BitVector.fs @@ -26,14 +26,6 @@ namespace B2R2 open System -[] -module BitVectorConstants = - /// BigInteger zero. - let bigZero = 0I - - /// BigInteger one. - let bigOne = 1I - /// A helper module for BitVector. [] module internal BitVectorHelper = @@ -47,15 +39,15 @@ module internal BitVectorHelper = (UInt64.MaxValue >>> (64 - int len)) &&& n let inline adaptBig (len: RegType) (n: bigint) = - ((bigOne <<< int len) - bigOne) &&& n + ((1I <<< int len) - 1I) &&& n let inline isSmallPositive (len: RegType) (n: uint64) = (n >>> (int len - 1)) &&& 1UL = 0UL let inline isBigPositive (len: RegType) (n: bigint) = - (n >>> (int len - 1)) &&& bigOne = bigZero + (n >>> (int len - 1)) &&& 1I = 0I - let inline neg (len: RegType) (n: bigint) = (bigOne <<< int len) - n + let inline neg (len: RegType) (n: bigint) = (1I <<< int len) - n let inline toFloat32 (n: uint64) = n |> int32 |> BitConverter.Int32BitsToSingle @@ -178,7 +170,7 @@ type BitVector internal (len) = abstract Cast: RegType -> BitVector /// Extract a sub-BitVector of size (RegType) starting from the index (int). - abstract Extract: RegType -> int -> BitVector + abstract Extract: RegType * int -> BitVector /// BitVector concatenation. abstract Concat: BitVector -> BitVector @@ -244,7 +236,7 @@ type BitVector internal (len) = abstract FCast: RegType -> BitVector /// Integer to float conversion. - abstract Itof: RegType -> BitVector + abstract Itof: RegType * bool -> BitVector /// Floating point to integer conversion with truncation. abstract FtoiTrunc: RegType -> BitVector @@ -300,16 +292,14 @@ type BitVector internal (len) = abstract IsNegative: unit -> bool /// Return zero (0) of the given bit length. - [] - static member zero t = + static member Zero t = if t <= 64 then BitVectorSmall (0UL, t) :> BitVector - else BitVectorBig (bigZero, t) :> BitVector + else BitVectorBig (0I, t) :> BitVector /// Return one (1) of the given bit length. - [] - static member one t = + static member One t = if t <= 64 then BitVectorSmall (1UL, t) :> BitVector - else BitVectorBig (bigOne, t) :> BitVector + else BitVectorBig (1I, t) :> BitVector /// True value. static member T = BitVectorSmall (1UL, 1) :> BitVector @@ -318,28 +308,23 @@ type BitVector internal (len) = static member F = BitVectorSmall (0UL, 1) :> BitVector /// Return a smaller BitVector. - [] - static member min (bv1: BitVector) bv2 = + static member Min (bv1: BitVector, bv2) = if bv1.Lt bv2 = BitVector.T then bv1 else bv2 /// Return a larger BitVector. - [] - static member max (bv1: BitVector) bv2 = + static member Max (bv1: BitVector, bv2) = if bv1.Gt bv2 = BitVector.T then bv1 else bv2 /// Return a smaller BitVector (with signed comparison). - [] - static member smin (bv1: BitVector) bv2 = + static member SMin (bv1: BitVector, bv2) = if bv1.SLt bv2 = BitVector.T then bv1 else bv2 /// Return a larger BitVector (with signed comparison). - [] - static member smax (bv1: BitVector) bv2 = + static member SMax (bv1: BitVector, bv2) = if bv1.SGt bv2 = BitVector.T then bv1 else bv2 /// Get a BitVector from an unsigned integer. - [] - static member inline ofUInt64 (i: uint64) typ = + static member inline OfUInt64 (i: uint64) typ = #if DEBUG if typ <= 0 then raise ArithTypeMismatchException else () #endif @@ -349,8 +334,7 @@ type BitVector internal (len) = else BitVectorBig (bigint i, typ) :> BitVector /// Get a BitVector from a signed integer. - [] - static member inline ofInt64 (i: int64) typ = + static member inline OfInt64 (i: int64) typ = #if DEBUG if typ <= 0 then raise ArithTypeMismatchException else () #endif @@ -359,36 +343,32 @@ type BitVector internal (len) = BitVectorSmall (uint64 i &&& mask, typ) :> BitVector else if i < 0L then - BitVectorBig ((bigOne <<< int typ) - (- i |> bigint), typ) :> BitVector + BitVectorBig ((1I <<< int typ) - (- i |> bigint), typ) :> BitVector else BitVectorBig (bigint i, typ) :> BitVector /// Get a BitVector from an unsigned integer. - [] - static member inline ofUInt32 (i: uint32) typ = - BitVector.ofUInt64 (uint64 i) typ + static member inline OfUInt32 (i: uint32) typ = + BitVector.OfUInt64 (uint64 i) typ /// Get a BitVector from a signed integer. - [] - static member inline ofInt32 (i: int32) typ = - BitVector.ofInt64 (int64 i) typ + static member inline OfInt32 (i: int32) typ = + BitVector.OfInt64 (int64 i) typ /// Get a BitVector from a bigint. We assume that the given RegType (typ) is /// big enough to hold the given bigint. Otherwise, the resulting BitVector /// may contain an unexpected value. - [] - static member ofBInt (i: bigint) typ = + static member OfBInt (i: bigint) typ = #if DEBUG if typ <= 0 then nSizeErr typ else () #endif - if typ <= 64 then BitVector.ofUInt64 (uint64 i) typ + if typ <= 64 then BitVector.OfUInt64 (uint64 i) typ else if i.Sign < 0 then - BitVectorBig ((bigOne <<< int typ) + i, typ) :> BitVector + BitVectorBig ((1I <<< int typ) + i, typ) :> BitVector else BitVectorBig (i, typ) :> BitVector /// Get a BitVector from a byte array (in little endian). - [] - static member ofArr (arr: byte []) = + static member OfArr (arr: byte []) = match arr.Length with | 1 -> BitVectorSmall (uint64 arr[0], 8) :> BitVector | 2 -> @@ -422,348 +402,275 @@ type BitVector internal (len) = else nSizeErr (sz * 8) /// Get a uint64 value from a BitVector. - [] - static member toUInt64 (bv: BitVector) = + static member ToUInt64 (bv: BitVector) = bv.SmallValue () /// Get an int64 value from a BitVector. - [] - static member toInt64 (bv: BitVector) = + static member ToInt64 (bv: BitVector) = bv.SmallValue () |> int64 /// Get a uint32 value from a BitVector. - [] - static member toUInt32 (bv: BitVector) = + static member ToUInt32 (bv: BitVector) = bv.SmallValue () |> uint32 /// Get an int32 value from a BitVector. - [] - static member toInt32 (bv: BitVector) = + static member ToInt32 (bv: BitVector) = bv.SmallValue () |> int32 /// Get a numeric value (bigint) from a BitVector. - [] - static member getValue (bv: BitVector) = + static member GetValue (bv: BitVector) = bv.BigValue () /// Get the type (length of the BitVector). - [] - static member getType (bv: BitVector) = bv.Length + static member GetType (bv: BitVector) = bv.Length /// Get the string representation of a BitVector without appended type info. - [] - static member valToString (n: BitVector) = n.ValToString () + static member ValToString (n: BitVector) = n.ValToString () /// Get the string representation of a BitVector. - [] - static member toString (n: BitVector) = n.ToString () + static member ToString (n: BitVector) = n.ToString () /// Bitvector of unsigned 8-bit maxvalue. - static member maxUInt8 = BitVector.ofUInt64 0xFFUL 8 + static member MaxUInt8 = BitVector.OfUInt64 0xFFUL 8 /// Bitvector of unsigned 16-bit maxvalue. - static member maxUInt16 = BitVector.ofUInt64 0xFFFFUL 16 + static member MaxUInt16 = BitVector.OfUInt64 0xFFFFUL 16 /// Bitvector of unsigned 32-bit maxvalue. - static member maxUInt32 = BitVector.ofUInt64 0xFFFFFFFFUL 32 + static member MaxUInt32 = BitVector.OfUInt64 0xFFFFFFFFUL 32 /// Bitvector of unsigned 64-bit maxvalue. - static member maxUInt64 = BitVector.ofUInt64 0xFFFFFFFFFFFFFFFFUL 64 + static member MaxUInt64 = BitVector.OfUInt64 0xFFFFFFFFFFFFFFFFUL 64 /// Check if the given BitVector is zero. - [] - static member isZero (bv: BitVector) = + static member IsZero (bv: BitVector) = bv.IsZero () /// Check if the given BitVector is one. - [] - static member isOne (bv: BitVector) = + static member IsOne (bv: BitVector) = bv.IsOne () /// Check if the given BitVector is "false". - [] - static member isFalse (bv: BitVector) = + static member IsFalse (bv: BitVector) = bv = BitVector.F /// Check if the given BitVector is "true". - [] - static member isTrue (bv: BitVector) = + static member IsTrue (bv: BitVector) = bv = BitVector.T /// Check if the given BitVector represents the specified number. - [] - static member isNum (bv: BitVector) (n: uint64) = + static member IsNum (bv: BitVector) (n: uint64) = if bv.Length <= 64 then bv.SmallValue () = n else bigint n = bv.BigValue () /// BitVector representing a unsigned maximum integer for the given RegType. - [] - static member unsignedMax rt = + static member UnsignedMax rt = #if DEBUG if rt <= 0 then nSizeErr rt else () #endif if rt <= 64 then BitVectorSmall (UInt64.MaxValue >>> (64 - int rt), rt) :> BitVector - else BitVectorBig ((bigOne <<< int rt) - bigOne, rt) :> BitVector + else BitVectorBig ((1I <<< int rt) - 1I, rt) :> BitVector /// BitVector representing a unsigned minimum integer for the given RegType. - [] - static member unsignedMin rt = + static member UnsignedMin rt = #if DEBUG if rt <= 0 then nSizeErr rt else () #endif if rt <= 64 then BitVectorSmall (0UL, rt) :> BitVector - else BitVectorBig (bigZero, rt) :> BitVector + else BitVectorBig (0I, rt) :> BitVector /// BitVector representing a signed maximum integer for the given RegType. - [] - static member signedMax rt = + static member SignedMax rt = #if DEBUG if rt <= 0 then nSizeErr rt else () #endif if rt <= 64 then BitVectorSmall (UInt64.MaxValue >>> (65 - int rt), rt) :> BitVector - else BitVectorBig ((bigOne <<< (int rt - 1)) - bigOne, rt) :> BitVector + else BitVectorBig ((1I <<< (int rt - 1)) - 1I, rt) :> BitVector /// BitVector representing a signed minimum integer for the given RegType. - [] - static member signedMin rt = + static member SignedMin rt = #if DEBUG if rt <= 0 then nSizeErr rt else () #endif if rt <= 64 then BitVectorSmall (1UL <<< (int rt - 1), rt) :> BitVector - else BitVectorBig (bigOne <<< (int rt - 1), rt) :> BitVector + else BitVectorBig (1I <<< (int rt - 1), rt) :> BitVector /// Does the bitvector represent an unsigned max value? - [] - static member isUnsignedMax (bv: BitVector) = - BitVector.unsignedMax bv.Length = bv + static member IsUnsignedMax (bv: BitVector) = + BitVector.UnsignedMax bv.Length = bv /// Does the bitvector represent a signed max value? - [] - static member isSignedMax (bv: BitVector) = - BitVector.signedMax bv.Length = bv + static member IsSignedMax (bv: BitVector) = + BitVector.SignedMax bv.Length = bv /// Does the bitvector represent a signed min value? - [] - static member isSignedMin (bv: BitVector) = - BitVector.signedMin bv.Length = bv + static member IsSignedMin (bv: BitVector) = + BitVector.SignedMin bv.Length = bv /// Is the bitvector positive? - [] - static member isPositive (bv: BitVector) = bv.IsPositive () + static member IsPositive (bv: BitVector) = bv.IsPositive () /// Is the bitvector negative? - [] - static member isNegative (bv: BitVector) = bv.IsNegative () + static member IsNegative (bv: BitVector) = bv.IsNegative () /// BitVector addition. - [] - static member inline add (v1: BitVector) (v2: BitVector) = v1.Add v2 + static member inline Add (v1: BitVector, v2: BitVector) = v1.Add v2 /// BitVector subtraction. - [] - static member inline sub (v1: BitVector) (v2: BitVector) = v1.Sub v2 + static member inline Sub (v1: BitVector, v2: BitVector) = v1.Sub v2 /// BitVector multiplication. - [] - static member inline mul (v1: BitVector) (v2: BitVector) = v1.Mul v2 + static member inline Mul (v1: BitVector, v2: BitVector) = v1.Mul v2 /// BitVector signed division. - [] - static member inline sdiv (v1: BitVector) (v2: BitVector) = v1.SDiv v2 + static member inline SDiv (v1: BitVector, v2: BitVector) = v1.SDiv v2 /// BitVector unsigned division. - [] - static member inline div (v1: BitVector) (v2: BitVector) = v1.Div v2 + static member inline Div (v1: BitVector, v2: BitVector) = v1.Div v2 /// BitVector signed modulo. - [] - static member inline smodulo (v1: BitVector) (v2: BitVector) = v1.SMod v2 + static member inline SModulo (v1: BitVector, v2: BitVector) = v1.SMod v2 /// BitVector unsigned modulo. - [] - static member inline modulo (v1: BitVector) (v2: BitVector) = v1.Mod v2 + static member inline Modulo (v1: BitVector, v2: BitVector) = v1.Mod v2 /// BitVector bitwise AND. - [] - static member inline band (v1: BitVector) (v2: BitVector) = v1.And v2 + static member inline BAnd (v1: BitVector, v2: BitVector) = v1.And v2 /// BitVector bitwise OR. - [] - static member inline bor (v1: BitVector) (v2: BitVector) = v1.Or v2 + static member inline BOr (v1: BitVector, v2: BitVector) = v1.Or v2 /// BitVector bitwise XOR. - [] - static member inline bxor (v1: BitVector) (v2: BitVector) = v1.Xor v2 + static member inline BXor (v1: BitVector, v2: BitVector) = v1.Xor v2 /// BitVector logical shift-left. - [] - static member inline shl (v1: BitVector) (v2: BitVector) = v1.Shl v2 + static member inline Shl (v1: BitVector, v2: BitVector) = v1.Shl v2 /// BitVector logical shift-right. - [] - static member inline shr (v1: BitVector) (v2: BitVector) = v1.Shr v2 + static member inline Shr (v1: BitVector, v2: BitVector) = v1.Shr v2 /// BitVector arithmetic shift-right. - [] - static member inline sar (v1: BitVector) (v2: BitVector) = v1.Sar v2 + static member inline Sar (v1: BitVector, v2: BitVector) = v1.Sar v2 /// BitVector bitwise NOT. - [] - static member inline bnot (v1: BitVector) = v1.Not () + static member inline BNot (v1: BitVector) = v1.Not () /// BitVector negation. - [] - static member inline neg (v1: BitVector) = v1.Neg () + static member inline Neg (v1: BitVector) = v1.Neg () /// BitVector type cast. - [] - static member inline cast (v1: BitVector) targetLen = v1.Cast targetLen + static member inline Cast (v1: BitVector, targetLen) = v1.Cast targetLen /// BitVector extraction. - [] - static member inline extract (v1: BitVector) rt pos = v1.Extract rt pos + static member inline Extract (v1: BitVector, rt, pos) = v1.Extract (rt, pos) /// BitVector concatenation. - [] - static member inline concat (v1: BitVector) (v2: BitVector) = v1.Concat v2 + static member inline Concat (v1: BitVector, v2: BitVector) = v1.Concat v2 /// BitVector sign-extension. - [] - static member inline sext (v1: BitVector) targetLen = v1.SExt targetLen + static member inline SExt (v1: BitVector, targetLen) = v1.SExt targetLen /// BitVector zero-extension. - [] - static member inline zext (v1: BitVector) targetLen = v1.ZExt targetLen + static member inline ZExt (v1: BitVector, targetLen) = v1.ZExt targetLen /// BitVector equal. - [] - static member inline eq (v1: BitVector) (v2: BitVector) = v1.Eq v2 + static member inline Eq (v1: BitVector, v2: BitVector) = v1.Eq v2 /// BitVector not equal. - [] - static member inline neq (v1: BitVector) (v2: BitVector) = v1.Neq v2 + static member inline Neq (v1: BitVector, v2: BitVector) = v1.Neq v2 /// BitVector greater than. - [] - static member inline gt (v1: BitVector) (v2: BitVector) = v1.Gt v2 + static member inline Gt (v1: BitVector, v2: BitVector) = v1.Gt v2 /// BitVector greater than or equal. - [] - static member inline ge (v1: BitVector) (v2: BitVector) = v1.Ge v2 + static member inline Ge (v1: BitVector, v2: BitVector) = v1.Ge v2 /// BitVector signed greater than. - [] - static member inline sgt (v1: BitVector) (v2: BitVector) = v1.SGt v2 + static member inline SGt (v1: BitVector, v2: BitVector) = v1.SGt v2 /// BitVector signed greater than or equal. - [] - static member inline sge (v1: BitVector) (v2: BitVector) = v1.SGe v2 + static member inline SGe (v1: BitVector, v2: BitVector) = v1.SGe v2 /// BitVector less than. - [] - static member inline lt (v1: BitVector) (v2: BitVector) = v1.Lt v2 + static member inline Lt (v1: BitVector, v2: BitVector) = v1.Lt v2 /// BitVector less than or equal. - [] - static member inline le (v1: BitVector) (v2: BitVector) = v1.Le v2 + static member inline Le (v1: BitVector, v2: BitVector) = v1.Le v2 /// BitVector signed less than. - [] - static member inline slt (v1: BitVector) (v2: BitVector) = v1.SLt v2 + static member inline SLt (v1: BitVector, v2: BitVector) = v1.SLt v2 /// BitVector signed less than or equal. - [] - static member inline sle (v1: BitVector) (v2: BitVector) = v1.SLe v2 + static member inline SLe (v1: BitVector, v2: BitVector) = v1.SLe v2 /// BitVector absolute value. - [] - static member inline abs (v1: BitVector) = v1.Abs () + static member inline Abs (v1: BitVector) = v1.Abs () /// BitVector floating point addition. - [] - static member inline fadd (v1: BitVector) (v2: BitVector) = v1.FAdd v2 + static member inline FAdd (v1: BitVector, v2: BitVector) = v1.FAdd v2 /// BitVector floating point subtraction. - [] - static member inline fsub (v1: BitVector) (v2: BitVector) = v1.FSub v2 + static member inline FSub (v1: BitVector, v2: BitVector) = v1.FSub v2 /// BitVector floating point multiplication. - [] - static member inline fmul (v1: BitVector) (v2: BitVector) = v1.FMul v2 + static member inline FMul (v1: BitVector, v2: BitVector) = v1.FMul v2 /// BitVector floating point division. - [] - static member inline fdiv (v1: BitVector) (v2: BitVector) = v1.FDiv v2 + static member inline FDiv (v1: BitVector, v2: BitVector) = v1.FDiv v2 /// BitVector floating point logarithm. - [] - static member inline flog (v1: BitVector) (v2: BitVector) = v1.FLog v2 + static member inline FLog (v1: BitVector, v2: BitVector) = v1.FLog v2 /// BitVector floating point power. - [] - static member inline fpow (v1: BitVector) (v2: BitVector) = v1.FPow v2 + static member inline FPow (v1: BitVector, v2: BitVector) = v1.FPow v2 /// BitVector floating point casting. - [] - static member inline fcast (v1: BitVector) rt = v1.FCast rt + static member inline FCast (v1: BitVector, rt) = v1.FCast rt /// BitVector integer to float conversion. - [] - static member inline itof (v1: BitVector) rt = v1.Itof rt + static member inline Itof (v1: BitVector, rt, isSigned) = + v1.Itof (rt, isSigned) /// BitVector float to integer conversion with truncation. - [] - static member inline ftoitrunc (v1: BitVector) rt = v1.FtoiTrunc rt + static member inline FtoiTrunc (v1: BitVector, rt) = v1.FtoiTrunc rt /// BitVector float to integer conversion with round. - [] - static member inline ftoiround (v1: BitVector) rt = v1.FtoiRound rt + static member inline FtoiRound (v1: BitVector, rt) = v1.FtoiRound rt /// BitVector float to integer conversion with flooring. - [] - static member inline ftoifloor (v1: BitVector) rt = v1.FtoiFloor rt + static member inline FtoiFloor (v1: BitVector, rt) = v1.FtoiFloor rt /// BitVector float to integer conversion with ceiling. - [] - static member inline ftoiceil (v1: BitVector) rt = v1.FtoiCeil rt + static member inline FtoiCeil (v1: BitVector, rt) = v1.FtoiCeil rt /// BitVector square root. - [] - static member inline fsqrt (v1: BitVector) = v1.FSqrt () + static member inline FSqrt (v1: BitVector) = v1.FSqrt () /// BitVector tangent. - [] - static member inline ftan (v1: BitVector) = v1.FTan () + static member inline FTan (v1: BitVector) = v1.FTan () /// BitVector sine. - [] - static member inline fsin (v1: BitVector) = v1.FSin () + static member inline FSin (v1: BitVector) = v1.FSin () /// BitVector cosine. - [] - static member inline fcos (v1: BitVector) = v1.FCos () + static member inline FCos (v1: BitVector) = v1.FCos () /// BitVector arc tangent. - [] - static member inline fatan (v1: BitVector) = v1.FATan () + static member inline FAtan (v1: BitVector) = v1.FATan () /// BitVector floating point greater than. - [] - static member inline fgt (v1: BitVector) (v2: BitVector) = v1.FGt v2 + static member inline FGt (v1: BitVector, v2: BitVector) = v1.FGt v2 /// BitVector floating point greater than or equal. - [] - static member inline fge (v1: BitVector) (v2: BitVector) = v1.FGe v2 + static member inline FGe (v1: BitVector, v2: BitVector) = v1.FGe v2 /// BitVector floating point less than. - [] - static member inline flt (v1: BitVector) (v2: BitVector) = v1.FLt v2 + static member inline FLt (v1: BitVector, v2: BitVector) = v1.FLt v2 /// BitVector floating point less than or equal. - [] - static member inline fle (v1: BitVector) (v2: BitVector) = v1.FLe v2 + static member inline FLe (v1: BitVector, v2: BitVector) = v1.FLe v2 /// BitVector addition. static member inline (+) (v1: BitVector, v2: uint64) = v1.Add v2 @@ -844,7 +751,7 @@ and BitVectorSmall (n, len) = member __.Value with get(): uint64 = n - override __.ValToString () = String.u64ToHex n + override __.ValToString () = HexString.ofUInt64 n override __.Equals obj = match obj with @@ -855,7 +762,7 @@ and BitVectorSmall (n, len) = #if DEBUG if len <> rhs.Length then raise ArithTypeMismatchException else () #endif - let shifter = BitVector.ofInt32 1 len + let shifter = BitVector.OfInt32 1 len let v1 = __.Shr shifter let v2 = rhs.Shr shifter v1.Eq v2 @@ -969,25 +876,28 @@ and BitVectorSmall (n, len) = override __.Shr (rhs: BitVector) = if len <> rhs.Length then raise ArithTypeMismatchException else () let v1 = n - let v2 = rhs.SmallValue () |> uint16 |> int + let v2 = rhs.SmallValue () (* In .NET, 1UL >>> 63 = 0, but 1UL >>> 64 = 1 *) - BitVectorSmall (v1 >>> (min v2 63), len) :> BitVector + if v2 >= 64UL then BitVectorSmall (0UL, len) :> BitVector + else BitVectorSmall (v1 >>> (int v2), len) :> BitVector override __.Sar (rhs: BitVector) = if len <> rhs.Length then raise ArithTypeMismatchException else () let v1 = n - let v2 = rhs.SmallValue () |> uint16 |> int + let v2 = rhs.SmallValue () (* In .NET, 1UL >>> 63 = 0, but 1UL >>> 64 = 1 *) - let res = v1 >>> (min v2 63) - if len = 1 then - if v2 = 0 then __ :> BitVector else BitVector.zero len - elif isSmallPositive len v1 then BitVectorSmall (res, len) :> BitVector + if v2 >= 64UL then BitVectorSmall (0UL, len) :> BitVector else - let pad = - (UInt64.MaxValue >>> (64 - int len)) - - (if int len <= v2 then 0UL - else UInt64.MaxValue >>> (64 - (int len - v2))) - BitVectorSmall (res ||| pad, len) :> BitVector + let res = v1 >>> (int v2) + if len = 1 then + if v2 = 0UL then __ :> BitVector else BitVector.Zero len + elif isSmallPositive len v1 then BitVectorSmall (res, len) :> BitVector + else + let pad = + (UInt64.MaxValue >>> (64 - int len)) + - (if int len <= int v2 then 0UL + else UInt64.MaxValue >>> (64 - (int len - int v2))) + BitVectorSmall (res ||| pad, len) :> BitVector override __.Not () = BitVectorSmall ((~~~ n) |> adaptSmall len, len) :> BitVector @@ -1001,7 +911,7 @@ and BitVectorSmall (n, len) = else BitVectorBig (adaptBig targetLen (__.BigValue ()), targetLen) :> BitVector - override __.Extract targetLen pos = + override __.Extract (targetLen, pos) = if len < targetLen then raise ArithTypeMismatchException elif len = targetLen then __ :> BitVector else @@ -1032,7 +942,7 @@ and BitVectorSmall (n, len) = let n' = adaptBig targetLen (__.BigValue ()) if isSmallPositive len n then BitVectorBig (n', targetLen) :> BitVector else - let mask = (bigOne <<< int targetLen) - (bigOne <<< int len) + let mask = (1I <<< int targetLen) - (1I <<< int len) BitVectorBig (n' + mask, targetLen) :> BitVector override __.ZExt targetLen = @@ -1233,17 +1143,19 @@ and BitVectorSmall (n, len) = BitVectorBig (__.SmallValue () |> encodeBigFloat, targetLen) :> BitVector | _ -> raise ArithTypeMismatchException - override __.Itof targetLen = - let signedInt = n |> int64 + override __.Itof (targetLen, isSigned) = match targetLen with | 32 -> - let u64 = BitConverter.SingleToInt32Bits (float32 signedInt) |> uint64 + let fpv = if isSigned then n |> int64 |> float32 else n |> float32 + let u64 = BitConverter.SingleToInt32Bits fpv |> uint64 BitVectorSmall (u64, targetLen) :> BitVector | 64 -> - let u64 = BitConverter.DoubleToInt64Bits (float signedInt) |> uint64 + let fpv = if isSigned then n |> int64 |> float else n |> float + let u64 = BitConverter.DoubleToInt64Bits fpv |> uint64 BitVectorSmall (u64, targetLen) :> BitVector | 80 -> - let u64 = BitConverter.DoubleToInt64Bits (float signedInt) |> uint64 + let fpv = if isSigned then n |> int64 |> float else n |> float + let u64 = BitConverter.DoubleToInt64Bits fpv |> uint64 BitVectorBig (bigint u64, targetLen) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1411,7 +1323,7 @@ and BitVectorBig (n, len) = member __.Value with get(): bigint = n override __.ValToString () = - if n = bigZero then "0x0" + if n = 0I then "0x0" else "0x" + n.ToString("x").TrimStart('0') override __.Equals obj = @@ -1424,7 +1336,7 @@ and BitVectorBig (n, len) = if len <> rhs.Length then raise ArithTypeMismatchException else () #endif if len = 80 then - let shifter = BitVector.ofInt32 12 80 + let shifter = BitVector.OfInt32 12 80 let v1 = __.Shr shifter let v2 = rhs.Shr shifter v1.Eq v2 @@ -1546,24 +1458,27 @@ and BitVectorBig (n, len) = if len <> rhs.Length then raise ArithTypeMismatchException else () let v1 = n let v2 = rhs.SmallValue () |> uint16 |> int - let res = v1 >>> v2 - if isBigPositive len v1 then BitVectorBig (res, len) :> BitVector + if v2 >= int len then BitVectorBig (0I, len) :> BitVector else - let pad = ((bigOne <<< int len) - bigOne) - ((bigOne <<< (int len - v2))) - BitVectorBig (res ||| pad, len) :> BitVector + let res = v1 >>> v2 + if isBigPositive len v1 then BitVectorBig (res, len) :> BitVector + else + let pad = + ((1I <<< int len) - 1I) - ((1I <<< (int len - v2))) + BitVectorBig (res ||| pad, len) :> BitVector override __.Not () = - BitVectorBig ((bigOne <<< (int len)) - bigOne - n, len) :> BitVector + BitVectorBig ((1I <<< (int len)) - 1I - n, len) :> BitVector override __.Neg () = - BitVectorBig (adaptBig len ((bigOne <<< (int len)) - n), len) :> BitVector + BitVectorBig (adaptBig len ((1I <<< (int len)) - n), len) :> BitVector override __.Cast targetLen = if targetLen <= 64 then BitVectorSmall (adaptSmall targetLen (uint64 n), targetLen) :> BitVector else BitVectorBig (adaptBig targetLen n, targetLen) :> BitVector - override __.Extract targetLen pos = + override __.Extract (targetLen, pos) = if len < targetLen then raise ArithTypeMismatchException elif len = targetLen then __ :> BitVector elif targetLen <= 64 then @@ -1586,7 +1501,7 @@ and BitVectorBig (n, len) = if isBigPositive len n then BitVectorBig (n', targetLen) :> BitVector else - let mask = (bigOne <<< int targetLen) - (bigOne <<< int len) + let mask = (1I <<< int targetLen) - (1I <<< int len) BitVectorBig (n' + mask, targetLen) :> BitVector override __.ZExt targetLen = @@ -1669,7 +1584,7 @@ and BitVectorBig (n, len) = let v1 = __.BigValue () |> toBigFloat let v2 = rhs.BigValue () |> toBigFloat let n = v1 + v2 |> BitConverter.DoubleToInt64Bits |> uint64 - if n = 0UL then BitVector.zero len + if n = 0UL then BitVector.Zero len else BitVectorBig (encodeBigFloat n, len) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1680,7 +1595,7 @@ and BitVectorBig (n, len) = let v1 = __.BigValue () |> toBigFloat let v2 = rhs.BigValue () |> toBigFloat let n = v1 - v2 |> BitConverter.DoubleToInt64Bits |> uint64 - if n = 0UL then BitVector.zero len + if n = 0UL then BitVector.Zero len else BitVectorBig (encodeBigFloat n, len) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1691,7 +1606,7 @@ and BitVectorBig (n, len) = let v1 = __.BigValue () |> toBigFloat let v2 = rhs.BigValue () |> toBigFloat let n = v1 * v2 |> BitConverter.DoubleToInt64Bits |> uint64 - if n = 0UL then BitVector.zero len + if n = 0UL then BitVector.Zero len else BitVectorBig (encodeBigFloat n, len) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1702,7 +1617,7 @@ and BitVectorBig (n, len) = let v1 = __.BigValue () |> toBigFloat let v2 = rhs.BigValue () |> toBigFloat let n = v1 / v2 |> BitConverter.DoubleToInt64Bits |> uint64 - if n = 0UL then BitVector.zero len + if n = 0UL then BitVector.Zero len else BitVectorBig (encodeBigFloat n, len) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1713,7 +1628,7 @@ and BitVectorBig (n, len) = let v1 = __.BigValue () |> toBigFloat let v2 = rhs.BigValue () |> toBigFloat let n = Math.Log (v2, v1) |> BitConverter.DoubleToInt64Bits |> uint64 - if n = 0UL then BitVector.zero len + if n = 0UL then BitVector.Zero len else BitVectorBig (encodeBigFloat n, len) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1724,7 +1639,7 @@ and BitVectorBig (n, len) = let v1 = __.BigValue () |> toBigFloat let v2 = rhs.BigValue () |> toBigFloat let n = Math.Pow (v1, v2) |> BitConverter.DoubleToInt64Bits |> uint64 - if n = 0UL then BitVector.zero len + if n = 0UL then BitVector.Zero len else BitVectorBig (encodeBigFloat n, len) :> BitVector | _ -> raise ArithTypeMismatchException @@ -1741,7 +1656,7 @@ and BitVectorBig (n, len) = | 80, 80 -> __ :> BitVector | _ -> raise ArithTypeMismatchException - override __.Itof targetLen = + override __.Itof (targetLen, _) = let v = if isBigPositive len n then n else - n match targetLen with | 32 -> diff --git a/src/Core/ByteArray.fs b/src/Core/ByteArray.fs index 0d1d7ed1..823decb5 100644 --- a/src/Core/ByteArray.fs +++ b/src/Core/ByteArray.fs @@ -29,18 +29,17 @@ open System.Text open System.Globalization open System.Runtime.InteropServices +[] let ofHexString (s: string) = Seq.windowed 2 s |> Seq.mapi (fun i j -> i, j) |> Seq.filter (fun (i, _) -> i % 2 = 0) - |> Seq.map (fun (_, j) -> Byte.Parse(String(j), - NumberStyles.AllowHexSpecifier)) + |> Seq.map (fun (_, j) -> + Byte.Parse (String (j), NumberStyles.AllowHexSpecifier)) |> Array.ofSeq -let toReadOnlySpan (bs: byte []) = - ReadOnlySpan (bs) - -let readInt32 (bs: byte []) offset = +[] +let readInt32 (bs: byte[]) offset = try let span = ReadOnlySpan (bs, offset, 4) MemoryMarshal.Read span |> Ok @@ -54,10 +53,12 @@ let rec private extractCStringFromSpanAux span (acc: StringBuilder) offset = | 0uy -> acc.ToString () | b -> extractCStringFromSpanAux span (char b |> acc.Append) (offset + 1) -let extractCString (bytes: byte []) offset = +[] +let extractCString (bytes: byte[]) offset = if bytes.Length = 0 || bytes.Length <= offset then "" else extractCStringFromSpanAux (ReadOnlySpan bytes) (StringBuilder()) offset +[] let extractCStringFromSpan (span: ReadOnlySpan) offset = if span.Length = 0 || span.Length <= offset then "" else extractCStringFromSpanAux span (StringBuilder ()) offset @@ -68,21 +69,21 @@ let makeDelta1 pattern patlen = Array.iteri iter pattern delta1 -let isPrefix (pattern: byte []) patlen pos = +let isPrefix (pattern: byte[]) patlen pos = let slen = patlen - pos let rec loop idx = if idx < slen && pattern[idx] = pattern[pos + idx] then loop (idx + 1) else idx loop 0 = slen -let getSuffixLength (pattern: byte []) patlen pos = +let getSuffixLength (pattern: byte[]) patlen pos = let rec loop idx = if idx < pos && pattern[pos - idx] = pattern[patlen - 1 - idx] then loop (idx + 1) else idx loop 0 -let makeDelta2 (pattern: byte []) patlen = +let makeDelta2 (pattern: byte[]) patlen = let delta2 = Array.zeroCreate patlen let mutable idx = patlen - 1 let mutable last = patlen - 1 @@ -98,12 +99,12 @@ let makeDelta2 (pattern: byte []) patlen = idx <- idx + 1 delta2 -let rec getMatch (pattern: byte []) (buf: byte []) struct (i, j) = +let rec getMatch (pattern: byte[]) (buf: byte[]) struct (i, j) = if j >= 0 && buf[i] = pattern[j] then getMatch pattern buf struct (i - 1, j - 1) else struct (i, j) -let rec searchOne i (buf: byte []) (pattern: byte []) (d1: int[]) (d2: int[]) = +let rec searchOne i (buf: byte[]) (pattern: byte[]) (d1: int[]) (d2: int[]) = if i < buf.Length then let struct (i, j) = getMatch pattern buf struct (i, pattern.Length - 1) if j < 0 then Some (i + 1) @@ -120,21 +121,14 @@ let bmSearch pattern buf = | None -> ret searchAll (patlen - 1) [] +[] let findIdxs offset pattern buf = bmSearch pattern buf |> List.map (fun x -> (uint64 x) + offset) +[] let tryFindIdx offset pattern buf = let patlen = Array.length pattern let delta1 = makeDelta1 pattern patlen let delta2 = makeDelta2 pattern patlen searchOne (patlen - 1) buf pattern delta1 delta2 |> Option.map (fun idx -> uint64 idx + offset) - -let toUInt32Arr (src: byte []) = - let srcLen = Array.length src - let dstLen = - if srcLen % 4 = 0 then srcLen/4 - else (srcLen / 4) + 1 - let dst = Array.init dstLen (fun _ -> 0u) - Buffer.BlockCopy (src, 0, dst, 0, srcLen) - dst diff --git a/src/Core/ByteArray.fsi b/src/Core/ByteArray.fsi index 46068361..70d78d51 100644 --- a/src/Core/ByteArray.fsi +++ b/src/Core/ByteArray.fsi @@ -29,27 +29,27 @@ module B2R2.ByteArray open System /// Convert a hex string to a byte array. -val ofHexString: string -> byte [] - -/// Convert a byte array into a read-only span. -val toReadOnlySpan: byte [] -> ReadOnlySpan +[] +val ofHexString: string -> byte[] /// Read int32 from the given byte array at the given offset. -val readInt32: byte [] -> offset: int -> Result +[] +val readInt32: byte[] -> offset: int -> Result /// Extract a C-string (string that ends with a NULL char) from a byte array. -val extractCString: byte [] -> int -> string +[] +val extractCString: byte[] -> int -> string /// Extract a C-string (string that ends with a NULL char) from a byte array. +[] val extractCStringFromSpan: ReadOnlySpan -> int -> string /// Find and return the offsets of all the matching byte positions. The final /// byte positions are adjusted by the given offset. -val findIdxs: offset: uint64 -> pattern: byte [] -> buf: byte [] -> uint64 list +[] +val findIdxs: offset: uint64 -> pattern: byte[] -> buf: byte[] -> uint64 list /// Find a matching byte position. If there is no match, this function will /// return None. -val tryFindIdx: uint64 -> byte [] -> byte [] -> uint64 option - -/// Convert a byte array into a uint32 array. -val toUInt32Arr: byte [] -> uint32 [] +[] +val tryFindIdx: uint64 -> byte[] -> byte[] -> uint64 option diff --git a/src/Core/BytePattern.fs b/src/Core/BytePattern.fs index 3874ab21..0097536e 100644 --- a/src/Core/BytePattern.fs +++ b/src/Core/BytePattern.fs @@ -26,15 +26,15 @@ namespace B2R2 open System -type ByteValue = +/// Represents a byte pattern. +type BytePattern = ByteValue[] + +and ByteValue = /// This matches any byte, i.e., it is like a kleene star. | AnyByte /// This matches only one single byte value. | OneByte of byte -/// Represents a byte pattern. -type BytePattern = ByteValue [] - module BytePattern = let private isEqual bv v = match bv with @@ -43,6 +43,7 @@ module BytePattern = /// Check if the given byte array (bs) matches the pattern. The comparison /// starts at the very first byte of the arrays. + [] let ``match`` (pattern: BytePattern) (bs: byte []) = let patternLen = Array.length pattern if patternLen > bs.Length then false @@ -52,6 +53,7 @@ module BytePattern = /// Check if the given span matches the pattern. The comparison starts at the /// offset zero. + [] let matchSpan pattern (span: ReadOnlySpan) = let mutable matched = true let patternLen = Array.length pattern diff --git a/src/Core/Color.fs b/src/Core/Color.fs new file mode 100644 index 00000000..3930afc0 --- /dev/null +++ b/src/Core/Color.fs @@ -0,0 +1,52 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2 + +/// Color type used to represent colors to print out in the console. +type Color = + | Red + | Green + | Yellow + | Blue + | DarkCyan + | DarkYellow + | NoColor + | RedHighlight + | GreenHighlight + +[] +module Color = + /// Returns a string representation of a color. + [] + let toString = function + | NoColor -> "nocolor" + | Red -> "red" + | Green -> "green" + | Yellow -> "yellow" + | Blue -> "blue" + | DarkCyan -> "darkcyan" + | DarkYellow -> "darkyellow" + | RedHighlight -> "redhighlight" + | GreenHighlight -> "greenhighlight" diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32RegisterSet.fs b/src/Core/ColoredSegment.fs similarity index 57% rename from src/FrontEnd/BinLifter/PPC32/PPC32RegisterSet.fs rename to src/Core/ColoredSegment.fs index 4bc0b19c..6018a763 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32RegisterSet.fs +++ b/src/Core/ColoredSegment.fs @@ -22,38 +22,33 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.PPC32 +namespace B2R2 -open B2R2 - -module private RegisterSetLiteral = - let [] arrLen = 2 - -open RegisterSetLiteral - -type PPC32RegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = - PPC32RegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) - - override __.Tag = RegisterSetTag.PPC32 - - override __.ArrSize = arrLen - - override __.New arr s = new PPC32RegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | _ -> Utils.futureFeature () - - override __.IndexToRegID _index: RegisterID = - Utils.futureFeature () - - override __.ToString () = - sprintf "PPC32RegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] +/// String segment with color. Multiple segments can be concatenated to form a +/// colored string. +type ColoredSegment = Color * string [] -module PPC32RegisterSet = - let singleton rid = PPC32RegisterSet().Add(rid) - let empty = PPC32RegisterSet () :> RegisterSet +module ColoredSegment = + let private getColor b = + if Byte.isNull b then NoColor + elif Byte.isPrintable b then Green + elif Byte.isWhitespace b then Blue + elif Byte.isControl b then Red + else Yellow + + /// Return a colored hexadeciaml representation of a byte. + [] + let hexOfByte b = + getColor b, b.ToString ("X2") + + /// Return a colored ASCII representation of a byte. + [] + let asciiOfByte b = + getColor b, Byte.getRepresentation b + + /// Append a string (of the same color) to a colored segment. + [] + let appendString tail (segment: ColoredSegment) = + let color, string = segment + ColoredSegment (color, string + tail) diff --git a/src/Core/ColoredString.fs b/src/Core/ColoredString.fs index 17d92256..78b19f97 100644 --- a/src/Core/ColoredString.fs +++ b/src/Core/ColoredString.fs @@ -26,84 +26,37 @@ namespace B2R2 open System -type Color = Red | Green | Yellow | Blue | DarkCyan | DarkYellow | NoColor - -module Color = - let toString = function - | NoColor -> "nocolor" - | Red -> "red" - | Green -> "green" - | Yellow -> "yellow" - | Blue -> "blue" - | DarkCyan -> "darkcyan" - | DarkYellow -> "darkyellow" - -type ColoredSegment = Color * string - -[] -module ColoredSegment = - let private isNull b = b = 0uy - - let private isPrintable b = b >= 33uy && b <= 126uy - - let private isWhitespace b = b = 32uy || (b >= 9uy && b <= 13uy) - - let private isControl b = - b = 127uy || (b >= 1uy && b <= 8uy) || (b >= 14uy && b <= 31uy) - - let private getColor b = - if isNull b then NoColor - elif isPrintable b then Green - elif isWhitespace b then Blue - elif isControl b then Red - else Yellow - - let getRepresentation b = - if isNull b then "." - elif isPrintable b then (char b).ToString () - elif isWhitespace b then "_" - elif isControl b then "*" - else "." - - let byteToHex b = - getColor b, b.ToString ("X2") - - let byteToHexWithTail b tail = - getColor b, (b.ToString ("X2") + tail) - - let byteToAscii b = - getColor b, getRepresentation b - - let colorBytes (bs: byte []) = - let lastIdx = bs.Length - 1 - bs - |> Array.mapi (fun i b -> - if i = lastIdx then byteToHex b - else byteToHexWithTail b " ") - |> Array.toList - - let inline nocolor str: ColoredSegment = NoColor, str - let inline red str: ColoredSegment = Red, str - let inline green str: ColoredSegment = Green, str - let inline yellow str: ColoredSegment = Yellow, str - let inline blue str: ColoredSegment = Blue, str - let inline dcyan str: ColoredSegment = DarkCyan, str - let inline dyellow str: ColoredSegment = DarkYellow, str - +/// String that can be printed out in the console with colors. A colored string +/// is a list of colored segments, each of which represents a string with a +/// specific color. type ColoredString = ColoredSegment list [] module ColoredString = /// Set the color. let private setColor = function - | NoColor -> Console.ResetColor () - | Red -> Console.ForegroundColor <- ConsoleColor.Red - | Green -> Console.ForegroundColor <- ConsoleColor.Green - | Yellow -> Console.ForegroundColor <- ConsoleColor.Yellow - | Blue -> Console.ForegroundColor <- ConsoleColor.Blue - | DarkCyan -> Console.ForegroundColor <- ConsoleColor.DarkCyan - | DarkYellow -> Console.ForegroundColor <- ConsoleColor.DarkYellow - + | NoColor -> + Console.ResetColor () + | Red -> + Console.ForegroundColor <- ConsoleColor.Red + | Green -> + Console.ForegroundColor <- ConsoleColor.Green + | Yellow -> + Console.ForegroundColor <- ConsoleColor.Yellow + | Blue -> + Console.ForegroundColor <- ConsoleColor.Blue + | DarkCyan -> + Console.ForegroundColor <- ConsoleColor.DarkCyan + | DarkYellow -> + Console.ForegroundColor <- ConsoleColor.DarkYellow + | RedHighlight -> + Console.ForegroundColor <- ConsoleColor.Red + Console.BackgroundColor <- ConsoleColor.Red + | GreenHighlight -> + Console.ForegroundColor <- ConsoleColor.Green + Console.BackgroundColor <- ConsoleColor.Green + + /// Compile the given colored string into a concise form. let compile (s: ColoredString): ColoredString = let rec loop prev acc = function | [] -> prev :: acc |> List.rev |> List.choose id @@ -111,7 +64,7 @@ module ColoredString = match prev with | Some (prevCol, prevStr) when prevCol = col -> loop (Some (prevCol, prevStr + str)) acc rest - | Some (_, _) -> loop (Some cur) (prev :: acc) rest + | Some (_) -> loop (Some cur) (prev :: acc) rest | None -> loop (Some cur) acc rest loop None [] s @@ -126,5 +79,18 @@ module ColoredString = toConsole s Console.WriteLine () + /// Colored string to a normal string. + [] let toString (s: ColoredString) = s |> List.map snd |> String.concat "" + + /// Construct a colored string from a byte array. + [] + let ofBytes (bs: byte[]) = + let lastIdx = bs.Length - 1 + bs + |> Array.mapi (fun i b -> + if i = lastIdx then ColoredSegment.hexOfByte b + else ColoredSegment.hexOfByte b |> ColoredSegment.appendString " ") + |> Array.toList + diff --git a/src/Core/Endian.fs b/src/Core/Endian.fs index 82a8923c..77c92b97 100644 --- a/src/Core/Endian.fs +++ b/src/Core/Endian.fs @@ -35,6 +35,7 @@ type Endian = | Big = 2 /// A helper module for Endian type. +[] module Endian = /// /// Get Endian from a string. @@ -43,8 +44,9 @@ module Endian = /// /// Endian. /// + [] let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "l" | "le" | "little" -> Endian.Little | "b" | "be" | "big" -> Endian.Big | _ -> failwith "Wrong endian specified." @@ -52,6 +54,7 @@ module Endian = /// /// Get the string representation from an Endian. /// + [] let toString = function | Endian.Little -> "Little" | Endian.Big -> "Big" diff --git a/src/Core/Errors.fs b/src/Core/Errors.fs index 9169125b..f58ebc63 100644 --- a/src/Core/Errors.fs +++ b/src/Core/Errors.fs @@ -26,7 +26,7 @@ namespace B2R2 /// Error cases and corresponding numbers for B2R2. type ErrorCase = - /// Failed to parse instruction(s). + /// Failed to parse instruction(s), or encoded data. | ParsingFailure = 0 /// Invalid access to memory. | InvalidMemoryRead = 1 @@ -36,31 +36,34 @@ type ErrorCase = | SymbolNotFound = 3 /// Item does not exist. | ItemNotFound = 4 - /// Invalid file format. - | InvalidFileFormat = 5 - /// Invalid function address is encountered during a CFG analysis. - | InvalidFunctionAddress = 6 + /// Invalid format. + | InvalidFormat = 5 /// The IR is not implemented yet. - | NotImplementedIR = 7 + | NotImplementedIR = 6 /// Invalid use of operand has been encountered. - | InvalidOperand = 8 + | InvalidOperand = 7 /// Invalid operand size has been used. - | InvalidOperandSize = 9 + | InvalidOperandSize = 8 /// Invalid opcode has been used. - | InvalidOpcode = 10 + | InvalidOpcode = 9 /// Invalid register has been used. - | InvalidRegister = 11 + | InvalidRegister = 10 /// Encountered register expression that is not yet handled. - | UnhandledRegExpr = 12 + | UnhandledRegExpr = 11 /// Encountered a not executable address while parsing binaries. - | NotExecutableAddress = 13 + | NotExecutableAddress = 12 + /// Invalid function address is encountered during a CFG analysis. + | InvalidFunctionAddress = 13 /// Encountered an instruction address at the middle of an exisitng /// instruction while parsing binaries. | IntrudingInstruction = 14 /// Encountered fatal error while recovering CFG. | FailedToRecoverCFG = 15 +[] module ErrorCase = + /// Convert an error case type to a string. + [] let toString errCase = match errCase with | ErrorCase.ParsingFailure -> "Failed to parse." @@ -68,8 +71,7 @@ module ErrorCase = | ErrorCase.InvalidExprEvaluation -> "Attempted to evalute invalid expr." | ErrorCase.SymbolNotFound -> "Symbol not found." | ErrorCase.ItemNotFound -> "Item not found." - | ErrorCase.InvalidFileFormat -> "Given invalid file format." - | ErrorCase.InvalidFunctionAddress -> "Given invalid function address." + | ErrorCase.InvalidFormat -> "Given invalid format." | ErrorCase.NotImplementedIR -> "Not implemented IR." | ErrorCase.InvalidOperand -> "Invalid operand." | ErrorCase.InvalidOperandSize -> "Invalid operand size." @@ -77,6 +79,7 @@ module ErrorCase = | ErrorCase.InvalidRegister -> "Invalid register." | ErrorCase.UnhandledRegExpr -> "Unhandled register expression." | ErrorCase.NotExecutableAddress -> "Not executable address." + | ErrorCase.InvalidFunctionAddress -> "Given invalid function address." | ErrorCase.IntrudingInstruction -> "Intruding instruction." | ErrorCase.FailedToRecoverCFG -> "Failed to recover CFG." | _ -> invalidArg (nameof errCase) "Unknown error case." diff --git a/src/Core/FileFormat.fs b/src/Core/FileFormat.fs index 6a671a9e..a0e9f9d1 100644 --- a/src/Core/FileFormat.fs +++ b/src/Core/FileFormat.fs @@ -38,15 +38,20 @@ type FileFormat = | WasmBinary = 5 /// A helper module for FileFormat type. +[] module FileFormat = + /// Transform a string into a FileFormat. + [] let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "elf" -> FileFormat.ELFBinary | "pe" -> FileFormat.PEBinary | "mach" | "mach-o" -> FileFormat.MachBinary | "wasm" -> FileFormat.WasmBinary | _ -> FileFormat.RawBinary + /// Transform a FileFormat into a string. + [] let toString fmt = match fmt with | FileFormat.RawBinary -> "Raw" @@ -57,4 +62,13 @@ module FileFormat = | _ -> invalidArg (nameof fmt) "Unknown FileFormat used." /// Check whether the given format is ELF. + [] let isELF fmt = fmt = FileFormat.ELFBinary + + /// Check whether the given format is PE. + [] + let isPE fmt = fmt = FileFormat.PEBinary + + /// Check whether the given format is Mach-O. + [] + let isMach fmt = fmt = FileFormat.MachBinary diff --git a/src/Core/FingerTree.fs b/src/Core/FingerTree.fs index 1b9a632c..32abf6ae 100644 --- a/src/Core/FingerTree.fs +++ b/src/Core/FingerTree.fs @@ -30,73 +30,73 @@ exception InvalidDigitException exception InvalidNodeException /// Monoid with an identity, and an associative operation. -type IMonoid<'a> = - abstract member Zero: 'a - abstract member Assoc: 'a -> 'a +type IMonoid<'A> = + abstract member Zero: 'A + abstract member Assoc: 'A -> 'A /// A "typeclass" that has a measurement. The measurement should be a monoid. -type IMeasured<'v when 'v :> IMonoid<'v>> = - abstract member Measurement: 'v +type IMeasured<'V when 'V :> IMonoid<'V>> = + abstract member Measurement: 'V /// Returns the measurement. let inline calib (m: IMeasured<_>) = m.Measurement -let inline combine<'v, 'a when 'v :> IMonoid<'v> - and 'a :> IMeasured<'v> - > (a: 'v) (b: 'v) = a.Assoc b +let inline combine<'V, 'A when 'V :> IMonoid<'V> + and 'A :> IMeasured<'V> + > (a: 'V) (b: 'V) = a.Assoc b let inline (++) a b = combine a b -type Prio<'a when 'a : comparison> = +type Prio<'A when 'A : comparison> = | MInfty (* Minus infinity. *) - | Prio of 'a + | Prio of 'A /// A monoid that represents a priority. -type Priority<'a when 'a : comparison> (p) = +type Priority<'A when 'A : comparison> (p) = new () = Priority (MInfty) - member inline __.Value: Prio<'a> = p + member inline __.Value: Prio<'A> = p override __.ToString () = match p with | MInfty -> "" | Prio p -> p.ToString () - interface IMonoid> with + interface IMonoid> with member __.Zero = Priority (MInfty) - member __.Assoc (rhs: Priority<'a>) = + member __.Assoc (rhs: Priority<'A>) = match __.Value, rhs.Value with | Prio m, Prio n -> Priority (Prio (if m > n then m else n)) | MInfty, p | p, MInfty -> Priority (p) -type Key<'a when 'a : comparison> = +type Key<'A when 'A : comparison> = | NoKey - | Key of 'a + | Key of 'A /// A monoid that represents ordering. -type Ordered<'a when 'a : comparison> (k) = +type Ordered<'A when 'A : comparison> (k) = new () = Ordered (NoKey) - member inline __.Key: Key<'a> = k + member inline __.Key: Key<'A> = k override __.ToString () = match k with | NoKey -> "" | Key (k) -> k.ToString () - interface IMonoid> with + interface IMonoid> with member __.Zero = Ordered (NoKey) - member __.Assoc (rhs: Ordered<'a>) = + member __.Assoc (rhs: Ordered<'A>) = match rhs.Key with | NoKey -> Ordered (k) | b -> Ordered (b) /// A monoid that represents an interval (uint64 * uint64). -type InterMonoid<'a when 'a : comparison> (o, p) = +type InterMonoid<'A when 'A : comparison> (o, p) = let v = o, p - new () = InterMonoid<'a> (new Ordered<'a>(), new Priority<'a>()) - member inline __.Value: Ordered<'a> * Priority<'a> = v + new () = InterMonoid<'A> (Ordered<'A>(), Priority<'A>()) + member inline __.Value: Ordered<'A> * Priority<'A> = v member __.GetMin () = o.Key member __.GetMax () = p.Value override __.ToString () = "(" + o.ToString () + "," + p.ToString () + ")" - interface IMonoid> with + interface IMonoid> with member __.Zero = - InterMonoid (new Ordered<'a>(), new Priority<'a>()) - member __.Assoc (rhs: InterMonoid<'a>) = + InterMonoid (Ordered<'A>(), Priority<'A>()) + member __.Assoc (rhs: InterMonoid<'A>) = let a1, b1 = __.Value let a2, b2 = rhs.Value InterMonoid (a1 ++ a2, b1 ++ b2) @@ -111,9 +111,9 @@ type Size (s) = member __.Assoc (rhs: Size) = Size (s + rhs.Value) /// 2-3 tree node. -type Node<'v, 'a when 'v :> IMonoid<'v>> = - | Node2 of 'v * 'a * 'a - | Node3 of 'v * 'a * 'a * 'a +type Node<'V, 'A when 'V :> IMonoid<'V>> = + | Node2 of 'V * 'A * 'A + | Node3 of 'V * 'A * 'A * 'A with override __.ToString () = match __ with @@ -135,19 +135,19 @@ with | Node2 (_, b, a) -> fn (fn acc b) a | Node3 (_, c, b, a) -> fn (fn (fn acc c) b) a - interface IMeasured<'v> with + interface IMeasured<'V> with member this.Measurement = match this with | Node2 (v, _, _) | Node3 (v, _, _, _) -> v /// Digit nodes actually store values. -type Digit<'v, 'a when 'v :> IMonoid<'v> - and 'a :> IMeasured<'v>> = - | One of 'a - | Two of 'a * 'a - | Three of 'a * 'a * 'a - | Four of 'a * 'a * 'a * 'a +type Digit<'V, 'A when 'V :> IMonoid<'V> + and 'A :> IMeasured<'V>> = + | One of 'A + | Two of 'A * 'A + | Three of 'A * 'A * 'A + | Four of 'A * 'A * 'A * 'A with override __.ToString () = match __ with @@ -161,8 +161,8 @@ with + c.ToString () + ", " + d.ToString () + ")" - interface IMeasured<'v> with - member this.Measurement: 'v = + interface IMeasured<'V> with + member this.Measurement: 'V = match this with | Three (a, b, c) -> calib a ++ calib b ++ calib c | Two (a, b) -> calib a ++ calib b @@ -184,15 +184,15 @@ with | Four (d, c, b, a) -> fn (fn (fn ((fn acc d)) c) b) a /// FingerTree defined in [Hinze 2006]. N.B. non-regular type is used. -type FingerTree<'v, 'a when 'v :> IMonoid<'v> - and 'v : (new: unit -> 'v) - and 'a :> IMeasured<'v>> = +type FingerTree<'V, 'A when 'V :> IMonoid<'V> + and 'V : (new: unit -> 'V) + and 'A :> IMeasured<'V>> = | Empty - | Single of 'a - | Deep of 'v - * Digit<'v, 'a> - * FingerTree<'v, Node<'v, 'a>> - * Digit<'v, 'a> + | Single of 'A + | Deep of 'V + * Digit<'V, 'A> + * FingerTree<'V, Node<'V, 'A>> + * Digit<'V, 'A> with override __.ToString () = match __ with @@ -203,25 +203,25 @@ with + t.ToString () + ", " + r.ToString () + ")" - member __.Monoid: 'v = new 'v () + member __.Monoid: 'V = new 'V () - interface IMeasured<'v> with - member this.Measurement: 'v = + interface IMeasured<'V> with + member this.Measurement: 'V = match this with | Empty -> this.Monoid.Zero | Single x -> calib x | Deep (v, _, _, _) -> v /// View of a FingerMap. -type View<'a, 'b> = +type View<'A, 'B> = | Nil - | Cons of 'a * rest: 'b + | Cons of 'A * rest: 'B /// Split represents an element in a FingerTree with containers of elements to /// its left and right. -type Split<'v, 'a> = 'v (* Left *) - * 'a - * 'v (* Right *) +type Split<'V, 'A> = 'V (* Left *) + * 'A + * 'V (* Right *) let inline snocDigit lhs rhs = match lhs with @@ -238,51 +238,51 @@ let inline consDigit lhs rhs = | _ -> raise InvalidDigitException /// Reduce a FingerTree from the right. -let rec foldr<'v, 'a, 'b when 'v :> IMonoid<'v> - and 'v : (new: unit -> 'v) - and 'a :> IMeasured<'v> - > (f: 'a -> 'b -> 'b) (t: FingerTree<'v, 'a>) (acc: 'b) : 'b = +let rec foldr<'V, 'A, 'B when 'V :> IMonoid<'V> + and 'V : (new: unit -> 'V) + and 'A :> IMeasured<'V> + > (f: 'A -> 'B -> 'B) (t: FingerTree<'V, 'A>) (acc: 'B) : 'B = match t with | Empty -> acc | Single x -> f x acc | Deep (_, pr, m, sf) -> - let acc = Digit<'v, 'a>.Foldr f sf acc - let acc = foldr (fun node acc -> Node<'v, 'a>.Foldr f node acc) m acc - Digit<'v, 'a>.Foldr f pr acc + let acc = Digit<'V, 'A>.Foldr f sf acc + let acc = foldr (fun node acc -> Node<'V, 'A>.Foldr f node acc) m acc + Digit<'V, 'A>.Foldr f pr acc /// Reduce a FingerTree from the left. -let rec foldl<'v, 'a, 'b when 'v :> IMonoid<'v> - and 'v : (new: unit -> 'v) - and 'a :> IMeasured<'v> - > (fn: 'b -> 'a -> 'b) (acc: 'b) (t: FingerTree<'v, 'a>) : 'b = +let rec foldl<'V, 'A, 'B when 'V :> IMonoid<'V> + and 'V : (new: unit -> 'V) + and 'A :> IMeasured<'V> + > (fn: 'B -> 'A -> 'B) (acc: 'B) (t: FingerTree<'V, 'A>) : 'B = match t with | Empty -> acc | Single x -> fn acc x | Deep (_, pr, m, sf) -> - let acc = Digit<'v, 'a>.Foldl fn acc pr - let acc = foldl (fun acc node -> Node<'v, 'a>.Foldl fn acc node) acc m - Digit<'v, 'a>.Foldl fn acc sf + let acc = Digit<'V, 'A>.Foldl fn acc pr + let acc = foldl (fun acc node -> Node<'V, 'A>.Foldl fn acc node) acc m + Digit<'V, 'A>.Foldl fn acc sf /// This is a helper class that defines FingerTree operations. This class /// contains only static members. We use this class to simplify type annotations /// for polymorphic recursion. -type Op<'v, 'a when 'v :> IMonoid<'v> - and 'v : (new: unit -> 'v) - and 'a :> IMeasured<'v>> () = +type Op<'V, 'A when 'V :> IMonoid<'V> + and 'V : (new: unit -> 'V) + and 'A :> IMeasured<'V>> () = - static member private Node2 a b : Node<'v, 'a> = + static member private Node2 a b : Node<'V, 'A> = Node2 (calib a ++ calib b, a, b) - static member private Node3 a b c : Node<'v, 'a> = + static member private Node3 a b c : Node<'V, 'A> = Node3 (calib a ++ calib b ++ calib c, a, b, c) - static member private Deep (pr: Digit<'v, 'a>, - m: FingerTree<'v, Node<'v, 'a>>, - sf: Digit<'v, 'a>) : FingerTree<'v, 'a> = + static member private Deep (pr: Digit<'V, 'A>, + m: FingerTree<'V, Node<'V, 'A>>, + sf: Digit<'V, 'A>) : FingerTree<'V, 'A> = Deep (calib pr ++ calib m ++ calib sf, pr, m, sf) /// (infixr): Prepend an element to a FingerTree. - static member Cons (a: 'a) (tree: FingerTree<'v, 'a>) : FingerTree<'v, 'a> = + static member Cons (a: 'A) (tree: FingerTree<'V, 'A>) : FingerTree<'V, 'A> = match tree with | Empty -> Single a | Single b -> Deep (calib a ++ calib b, One a, Empty, One b) @@ -292,7 +292,7 @@ type Op<'v, 'a when 'v :> IMonoid<'v> Deep (calib a ++ v, consDigit a prefix, m, suffix) /// (infixl): Append an element to a FingerTree. - static member Snoc (tree: FingerTree<'v, 'a>) (a: 'a) : FingerTree<'v, 'a> = + static member Snoc (tree: FingerTree<'V, 'A>) (a: 'A) : FingerTree<'V, 'A> = match tree with | Empty -> Single a | Single b -> Deep (calib b ++ calib a, One b, Empty, One a) @@ -301,16 +301,16 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | Deep (v, prefix, m, suffix) -> Deep (v ++ calib a, prefix, m, snocDigit suffix a) - static member private DigitToTree s : FingerTree<'v, 'a> = - Digit<'v, 'a>.Foldr Op.Cons s Empty + static member private DigitToTree s : FingerTree<'V, 'A> = + Digit<'V, 'A>.Foldr Op.Cons s Empty - static member private NodeToDigit (node: Node<'v, 'a>) = + static member private NodeToDigit (node: Node<'V, 'A>) = match node with | Node2 (_, a, b) -> Two (a, b) | Node3 (_, a, b, c) -> Three (a, b, c) - static member ViewL (tree: FingerTree<'v, 'a>) - : View<'a, FingerTree<'v, 'a>> = + static member ViewL (tree: FingerTree<'V, 'A>) + : View<'A, FingerTree<'V, 'A>> = match tree with | Empty -> Nil | Single x -> Cons (x, Empty) @@ -323,14 +323,14 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | _ -> raise InvalidDigitException Cons (hd, Op.Deep (tl, m, sf)) - static member DeepL (m: FingerTree<'v, Node<'v, 'a>>) - (suffix: Digit<'v, 'a>) : FingerTree<'v, 'a> = + static member DeepL (m: FingerTree<'V, Node<'V, 'A>>) + (suffix: Digit<'V, 'A>) : FingerTree<'V, 'A> = match Op.ViewL m with | Nil -> Op.DigitToTree suffix | Cons (a, m') -> Op.Deep (Op.NodeToDigit a, m', suffix) - static member ViewR (tree: FingerTree<'v, 'a>) - : View<'a, FingerTree<'v, 'a>> = + static member ViewR (tree: FingerTree<'V, 'A>) + : View<'A, FingerTree<'V, 'A>> = match tree with | Empty -> Nil | Single x -> Cons (x, Empty) @@ -343,61 +343,61 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | _ -> raise InvalidDigitException Cons (l, Op.Deep (pr, m, rest)) - static member DeepR (m: FingerTree<'v, Node<'v, 'a>>) (prefix: Digit<'v, 'a>) - : FingerTree<'v, 'a> = + static member DeepR (m: FingerTree<'V, Node<'V, 'A>>) (prefix: Digit<'V, 'A>) + : FingerTree<'V, 'A> = match Op.ViewR m with | Nil -> Op.DigitToTree prefix | Cons (a, m') -> Op.Deep (prefix, m', Op.NodeToDigit a) - static member IsEmpty (tree: FingerTree<'v, 'a>) = + static member IsEmpty (tree: FingerTree<'V, 'A>) = match tree with | Empty -> true | _ -> false /// Return head of the left subtree. - static member HeadL (tree: FingerTree<'v, 'a>) = + static member HeadL (tree: FingerTree<'V, 'A>) = match Op.ViewL tree with | Nil -> raise EmptyTreeException | Cons (a, _) -> a /// Return tail of the left subtree. - static member TailL (tree: FingerTree<'v, 'a>) = + static member TailL (tree: FingerTree<'V, 'A>) = match Op.ViewL tree with | Nil -> raise EmptyTreeException | Cons (_, m) -> m /// Return head of the right subtree. - static member HeadR (tree: FingerTree<'v, 'a>) = + static member HeadR (tree: FingerTree<'V, 'A>) = match Op.ViewR tree with | Nil -> raise EmptyTreeException | Cons (a, _) -> a /// Return tail of the right subtree. - static member TailR (tree: FingerTree<'v, 'a>) = + static member TailR (tree: FingerTree<'V, 'A>) = match Op.ViewR tree with | Nil -> raise EmptyTreeException | Cons (_, m) -> m - static member private AddToLst acc (digit: Digit<'v, 'a>) = + static member private AddToLst acc (digit: Digit<'V, 'A>) = match digit with | One a -> a :: acc | Two (a, b) -> a :: b :: acc | Three (a, b, c) -> a :: b :: c :: acc | Four (a, b, c, d) -> a :: b :: c :: d :: acc - static member private NodeAcc : 'a list -> Node<'v, 'a> list = function + static member private NodeAcc : 'A list -> Node<'V, 'A> list = function | [a; b] -> [ Op.Node2 a b ] | [a; b; c] -> [ Op.Node3 a b c ] | [a; b; c; d] -> [ Op.Node2 a b; Op.Node2 c d ] | a :: b :: c :: xs -> Op.Node3 a b c :: Op.NodeAcc xs | _ -> raise InvalidNodeException - static member private Nodes sf1 ts pr2 : Node<'v, 'a> list = + static member private Nodes sf1 ts pr2 : Node<'V, 'A> list = Op.AddToLst ts sf1 @ Op.AddToLst [] pr2 |> Op.NodeAcc - static member private App3 (t1: FingerTree<'v, 'a>) - (ts: 'a list) - (t2: FingerTree<'v, 'a>) : FingerTree<'v, 'a> = + static member private App3 (t1: FingerTree<'V, 'A>) + (ts: 'A list) + (t2: FingerTree<'V, 'A>) : FingerTree<'V, 'A> = match t1, t2 with | Empty, xs -> List.foldBack Op.Cons ts xs | xs, Empty -> List.fold Op.Snoc xs ts @@ -406,7 +406,7 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | Deep (_, pr1, m1, sf1), Deep (_, pr2, m2, sf2) -> Op.Deep (pr1, Op.App3 m1 (Op.Nodes sf1 ts pr2) m2, sf2) - static member private SplitDigit pred i (digit: Digit<'v, 'a>) = + static member private SplitDigit pred i (digit: Digit<'V, 'A>) = match digit with | One (a) -> [], a, [] | Two (a, b) -> @@ -427,7 +427,7 @@ type Op<'v, 'a when 'v :> IMonoid<'v> if pred i''' then [a; b], c, [d] else [a; b; c], d, [] - static member private LstToDigit (lst: 'a list) = + static member private LstToDigit (lst: 'A list) = match lst with | [a] -> One (a) | [a; b] -> Two (a, b) @@ -435,7 +435,7 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | [a; b; c; d] -> Four (a, b, c, d) | _ -> raise InvalidDigitException - static member private ToTree (lst: 'a list) = + static member private ToTree (lst: 'A list) = match lst with | [] -> Empty | [a] -> Single a @@ -444,10 +444,10 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | [a; b; c; d] -> Op.Deep (Three (a, b, c), Empty, One d) | _ -> raise InvalidDigitException - static member SplitTree (p: 'v -> bool) - (i: 'v) - (tree: FingerTree<'v, 'a>) - : Split, 'a> = + static member SplitTree (p: 'V -> bool) + (i: 'V) + (tree: FingerTree<'V, 'A>) + : Split, 'A> = match tree with | Empty -> raise EmptyTreeException | Single x -> Empty, x, Empty @@ -476,8 +476,8 @@ type Op<'v, 'a when 'v :> IMonoid<'v> l, x, Op.ToTree r /// Split a FingerTree into two based on a predicate (p). - static member Split (p: 'v -> bool) (tree: FingerTree<'v, 'a>) - : FingerTree<'v, 'a> * FingerTree<'v, 'a> = + static member Split (p: 'V -> bool) (tree: FingerTree<'V, 'A>) + : FingerTree<'V, 'A> * FingerTree<'V, 'A> = match tree with | Empty -> (Empty, Empty) | xs when p (calib xs) -> @@ -486,19 +486,19 @@ type Op<'v, 'a when 'v :> IMonoid<'v> | xs -> (xs, Empty) /// Take a subset of a FingerTree that satisfies the predicate (p). - static member TakeUntil p (tree: FingerTree<'v, 'a>) = + static member TakeUntil p (tree: FingerTree<'V, 'A>) = Op.Split p tree |> fst /// Take a subset of a FingerTree that does not satisfies the predicate (p). - static member DropUntil p (tree: FingerTree<'v, 'a>) = + static member DropUntil p (tree: FingerTree<'V, 'A>) = Op.Split p tree |> snd /// Concatenate two FingerTrees into one. - static member Concat (xs: FingerTree<'v, 'a>) (ys: FingerTree<'v, 'a>) = + static member Concat (xs: FingerTree<'V, 'A>) (ys: FingerTree<'V, 'A>) = Op.App3 xs [] ys /// TODO: (faster) lookup functions without building extra trees - static member Lookup (p: 'v -> bool) i (tree: FingerTree<'v, 'a>) : 'v * 'a = + static member Lookup (p: 'V -> bool) i (tree: FingerTree<'V, 'A>) : 'V * 'A = let zero = tree.Monoid.Zero let l, x, _ = Op.SplitTree p zero tree (i ++ calib l, x) diff --git a/src/MiddleEnd/ControlFlowGraph/IRCFG.fs b/src/Core/HexString.fs similarity index 58% rename from src/MiddleEnd/ControlFlowGraph/IRCFG.fs rename to src/Core/HexString.fs index 200176a6..2678dc6b 100644 --- a/src/MiddleEnd/ControlFlowGraph/IRCFG.fs +++ b/src/Core/HexString.fs @@ -22,30 +22,37 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2.MiddleEnd.BinGraph - -type IRVertex = Vertex - -type IRCFG = ControlFlowGraph +namespace B2R2 +/// Useful functions in handling hexademical strings. [] -module IRCFG = - let private initializer core = - IRCFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> IRCFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> IRCFG - :> DiGraph - - /// Initialize IRCFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () +module HexString = + /// Convert an int16 value to a hex string. + [] + let inline ofInt16 (v: int16) = + $"0x{v:x}" + + /// Convert a uint16 value to a hex string. + [] + let inline ofUInt16 (v: uint16) = + $"0x{v:x}" + + /// Convert an int32 value to a hex string. + [] + let inline ofInt32 (v: int) = + $"0x{v:x}" + + /// Convert a uint32 value to a hex string. + [] + let inline ofUInt32 (v: uint32) = + $"0x{v:x}" + + /// Convert an int64 value to a hex string. + [] + let inline ofInt64 (v: int64) = + $"0x{v:x}" + + /// Convert a uint64 value to a hex string. + [] + let inline ofUInt64 (v: uint64) = + $"0x{v:x}" diff --git a/src/Core/ISA.fs b/src/Core/ISA.fs index bc941b7d..1f015a57 100644 --- a/src/Core/ISA.fs +++ b/src/Core/ISA.fs @@ -27,9 +27,6 @@ namespace B2R2 /// Raised when an invalid ISA is given as a parameter. exception InvalidISAException -/// Raised when an invalid ArchOperationMode is given. -exception InvalidTargetArchModeException - /// Architecture types. type Architecture = /// x86 (i386). @@ -42,28 +39,10 @@ type Architecture = | AARCH32 = 4 /// ARMv8 64-bit mode. | AARCH64 = 5 - /// MIPS1 (32-bit mode). - | MIPS1 = 6 - /// MIPS2 (32-bit mode). - | MIPS2 = 7 - /// MIPS3 (64-bit mode). - | MIPS3 = 8 - /// MIPS4 (64-bit mode). - | MIPS4 = 9 - /// MIPS5 (64-bit mode). - | MIPS5 = 10 - /// MIPS32 (32-bit mode). - | MIPS32 = 11 - /// MIPS32 Release2 (32-bit mode). - | MIPS32R2 = 12 - /// MIPS32 Release6 (32-bit mode). - | MIPS32R6 = 13 - /// MIPS64 (64-bit mode). - | MIPS64 = 14 - /// MIPS64R2 (64-bit mode). - | MIPS64R2 = 15 - /// MIPS64R6 (64-bit mode). - | MIPS64R6 = 16 + /// MIPS 32-bit mode. + | MIPS32 = 6 + /// MIPS 64-bit mode. + | MIPS64 = 7 /// Ethereum Vritual Machine. | EVM = 17 /// TMS320C54x, TMS320C55x, etc. @@ -80,47 +59,27 @@ type Architecture = | AVR = 23 /// SuperH (SH-4). | SH4 = 24 + /// PA-RISC. + | PARISC = 25 + /// PA-RISC 64-bit. + | PARISC64 = 26 /// PowerPC 32-bit. - | PPC32 = 25 + | PPC32 = 27 + /// Python bytecode. + | Python = 28 + /// IBM System/390 + | S390 = 29 + /// IBM System/390 (64-bit) + | S390X = 30 /// Sparc 64-bit. - | Sparc64 = 26 + | SPARC = 31 /// RISCV 64-bit - | RISCV64 = 27 + | RISCV64 = 32 /// WASM | WASM = 40 /// Unknown ISA. | UnknownISA = 42 -type Arch = Architecture - -/// Some ISA, such as ARM, have their own operation mode, which can vary at -/// runtime. For example, ARM architecture can switch between Thumb and ARM -/// mode. ArchOperationMode decides which mode to consider at the time of -/// parsing/lifting machine instructions. -type ArchOperationMode = - /// ARM mode. - | ARMMode = 1 - /// Thumb mode. - | ThumbMode = 2 - /// No mode. This is used for architectures that do not have any operation - /// mode. - | NoMode = 3 - -/// A helper module for ArchOperationMode. -[] -module ArchOperationMode = - let ofString (s: string) = - match s.ToLower () with - | "arm" -> ArchOperationMode.ARMMode - | "thumb" -> ArchOperationMode.ThumbMode - | _ -> ArchOperationMode.NoMode - - let toString mode = - match mode with - | ArchOperationMode.ARMMode -> "arm" - | ArchOperationMode.ThumbMode -> "thumb" - | _ -> "nomode" - /// Instruction Set Architecture (ISA). type ISA = { Arch: Architecture @@ -129,99 +88,134 @@ type ISA = { } with static member DefaultISA = - { Arch = Arch.IntelX64; Endian = Endian.Little; WordSize = WordSize.Bit64 } + { Arch = Architecture.IntelX64 + Endian = Endian.Little + WordSize = WordSize.Bit64 } static member Init arch endian = match arch with - | Arch.IntelX86 -> + | Architecture.IntelX86 -> { Arch = arch; Endian = Endian.Little; WordSize = WordSize.Bit32 } - | Arch.IntelX64 -> ISA.DefaultISA - | Arch.ARMv7 - | Arch.AARCH32 - | Arch.MIPS1 - | Arch.MIPS2 - | Arch.MIPS32 - | Arch.MIPS32R2 - | Arch.MIPS32R6 -> + | Architecture.IntelX64 -> ISA.DefaultISA + | Architecture.ARMv7 + | Architecture.AARCH32 + | Architecture.MIPS32 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } - | Arch.AARCH64 - | Arch.MIPS3 - | Arch.MIPS4 - | Arch.MIPS5 - | Arch.MIPS64 - | Arch.MIPS64R2 - | Arch.MIPS64R6 -> + | Architecture.AARCH64 + | Architecture.MIPS64 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } - | Arch.EVM -> + | Architecture.EVM -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit256 } - | Arch.TMS320C6000 -> + | Architecture.TMS320C6000 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } - | Arch.CILOnly -> + | Architecture.CILOnly -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } - | Arch.AVR -> + | Architecture.AVR -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit8 } - | Arch.SH4 -> + | Architecture.SH4 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } - | Arch.PPC32 -> + | Architecture.PARISC -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } - | Arch.Sparc64 -> + | Architecture.PARISC64 -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } + | Architecture.PPC32 -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } + | Architecture.Python -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } + | Architecture.S390 -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } + | Architecture.S390X -> + { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } + | Architecture.SPARC -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } - | Arch.RISCV64 -> + | Architecture.RISCV64 -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit64 } - | Arch.WASM -> + | Architecture.WASM -> { Arch = arch; Endian = endian; WordSize = WordSize.Bit32 } | _ -> raise InvalidISAException static member OfString (s: string) = - match s.ToLower () with - | "x86" | "i386" -> ISA.Init Arch.IntelX86 Endian.Little - | "x64" | "x86-64" | "amd64" -> ISA.DefaultISA - | "armv7" | "armv7le" - | "armel" | "armhf" -> ISA.Init Arch.ARMv7 Endian.Little - | "armv7be" -> ISA.Init Arch.ARMv7 Endian.Big - | "armv8a32" | "aarch32" -> ISA.Init Arch.AARCH32 Endian.Little - | "armv8a32be" | "aarch32be" -> ISA.Init Arch.AARCH32 Endian.Big - | "armv8a64" | "aarch64"-> ISA.Init Arch.AARCH64 Endian.Little - | "armv8a64be" | "aarch64be" -> ISA.Init Arch.AARCH64 Endian.Big - | "mips32r2" -> ISA.Init Arch.MIPS32R2 Endian.Little - | "mips32r2be" -> ISA.Init Arch.MIPS32R2 Endian.Big - | "mips32r6" -> ISA.Init Arch.MIPS32R6 Endian.Little - | "mips32r6be" -> ISA.Init Arch.MIPS32R6 Endian.Big - | "mips64r2" -> ISA.Init Arch.MIPS64R2 Endian.Little - | "mips64r2be" -> ISA.Init Arch.MIPS64R2 Endian.Big - | "mips64r6" -> ISA.Init Arch.MIPS64R6 Endian.Little - | "mips64r6be" -> ISA.Init Arch.MIPS64R6 Endian.Big - | "evm" -> ISA.Init Arch.EVM Endian.Big - | "tms320c6000" -> ISA.Init Arch.TMS320C6000 Endian.Little - | "cil" -> ISA.Init Arch.CILOnly Endian.Little - | "avr" | "avr8" -> ISA.Init Arch.AVR Endian.Little - | "sh4" | "sh-4" -> ISA.Init Arch.SH4 Endian.Little - | "sh4be" | "sh-4be" -> ISA.Init Arch.SH4 Endian.Big - | "ppc32" -> ISA.Init Arch.PPC32 Endian.Little - | "sparc" | "sparc64" -> ISA.Init Arch.Sparc64 Endian.Big - | "riscv64" -> ISA.Init Arch.RISCV64 Endian.Little - | "wasm" -> ISA.Init Arch.WASM Endian.Little + match s.ToLowerInvariant () with + | "x86" | "i386" -> + ISA.Init Architecture.IntelX86 Endian.Little + | "x64" | "x86-64" | "amd64" -> + ISA.DefaultISA + | "armv7" | "armv7le" | "armel" | "armhf" -> + ISA.Init Architecture.ARMv7 Endian.Little + | "armv7be" -> + ISA.Init Architecture.ARMv7 Endian.Big + | "armv8a32" | "aarch32" -> + ISA.Init Architecture.AARCH32 Endian.Little + | "armv8a32be" | "aarch32be" -> + ISA.Init Architecture.AARCH32 Endian.Big + | "armv8a64" | "aarch64"-> + ISA.Init Architecture.AARCH64 Endian.Little + | "armv8a64be" | "aarch64be" -> + ISA.Init Architecture.AARCH64 Endian.Big + | "mipsel" | "mips32" | "mips32le" -> + ISA.Init Architecture.MIPS32 Endian.Little + | "mips32be" -> + ISA.Init Architecture.MIPS32 Endian.Big + | "mips64el" | "mips64" | "mips64le" -> + ISA.Init Architecture.MIPS64 Endian.Little + | "mips64be" -> + ISA.Init Architecture.MIPS64 Endian.Big + | "evm" -> + ISA.Init Architecture.EVM Endian.Big + | "tms320c6000" -> + ISA.Init Architecture.TMS320C6000 Endian.Little + | "cil" -> + ISA.Init Architecture.CILOnly Endian.Little + | "avr" | "avr8" -> + ISA.Init Architecture.AVR Endian.Little + | "sh4" | "sh-4" -> + ISA.Init Architecture.SH4 Endian.Little + | "sh4be" | "sh-4be" -> + ISA.Init Architecture.SH4 Endian.Big + | "parisc" | "hppa" -> + ISA.Init Architecture.PARISC Endian.Big + | "parisc64" | "hppa64" -> + ISA.Init Architecture.PARISC64 Endian.Big + | "ppc32" | "ppc32le" -> + ISA.Init Architecture.PPC32 Endian.Little + | "ppc32be" -> + ISA.Init Architecture.PPC32 Endian.Big + | "python" -> + ISA.Init Architecture.Python Endian.Little + | "s390" -> + ISA.Init Architecture.S390 Endian.Big + | "s390x" -> + ISA.Init Architecture.S390X Endian.Big + | "sparc" | "sparc64" -> + ISA.Init Architecture.SPARC Endian.Big + | "riscv64" -> + ISA.Init Architecture.RISCV64 Endian.Little + | "wasm" -> + ISA.Init Architecture.WASM Endian.Little | _ -> raise InvalidISAException static member ArchToString arch = match arch with - | Arch.IntelX86 -> "x86" - | Arch.IntelX64 -> "x86-64" - | Arch.ARMv7 -> "ARMv7" - | Arch.AARCH32 -> "AARCH32" - | Arch.AARCH64 -> "AARCH64" - | Arch.MIPS32R2 -> "MIPS32 Release 2" - | Arch.MIPS32R6 -> "MIPS32 Release 6" - | Arch.MIPS64R2 -> "MIPS64 Release 2" - | Arch.MIPS64R6 -> "MIPS64 Release 6" - | Arch.EVM -> "EVM" - | Arch.TMS320C6000 -> "TMS320C6000" - | Arch.CILOnly -> "CIL" - | Arch.AVR -> "AVR" - | Arch.SH4 -> "SH4" - | Arch.PPC32 -> "PPC32" - | Arch.Sparc64 -> "SPARC64" - | Arch.RISCV64 -> "RISCV64" - | Arch.WASM -> "WASM" - | Arch.UnknownISA -> "Unknown" + | Architecture.IntelX86 -> "x86" + | Architecture.IntelX64 -> "x86-64" + | Architecture.ARMv7 -> "ARMv7" + | Architecture.AARCH32 -> "AARCH32" + | Architecture.AARCH64 -> "AARCH64" + | Architecture.MIPS32 -> "MIPS32" + | Architecture.MIPS64 -> "MIPS64" + | Architecture.EVM -> "EVM" + | Architecture.TMS320C6000 -> "TMS320C6000" + | Architecture.CILOnly -> "CIL" + | Architecture.AVR -> "AVR" + | Architecture.SH4 -> "SH4" + | Architecture.PARISC -> "PARISC" + | Architecture.PARISC64 -> "PARISC64" + | Architecture.PPC32 -> "PPC32" + | Architecture.Python -> "Python" + | Architecture.S390 -> "S390" + | Architecture.S390X -> "S390X" + | Architecture.SPARC -> "SPARC64" + | Architecture.RISCV64 -> "RISCV64" + | Architecture.WASM -> "WASM" + | Architecture.UnknownISA -> "Unknown" | _ -> "Not supported ISA" diff --git a/src/Core/IntervalMap.fs b/src/Core/IntervalMap.fs index 494a1e94..5fbe5b9f 100644 --- a/src/Core/IntervalMap.fs +++ b/src/Core/IntervalMap.fs @@ -27,9 +27,9 @@ namespace B2R2 open B2R2.FingerTree /// An element for our interval map. -type IntervalMapElem<'a> (k, v) = +type IntervalMapElem<'T> (k, v) = member val Key: AddrRange = k - member val Val: 'a = v + member val Val: 'T = v member __.Min = __.Key.Min member __.Max = __.Key.Max override __.ToString () = __.Key.ToString () @@ -38,18 +38,18 @@ type IntervalMapElem<'a> (k, v) = InterMonoid (Ordered(Key(__.Key.Min)), Priority(Prio(__.Key.Max))) /// Interval-tree-based map, which maps an interval of type (AddrRange) to an -/// IntervalMapElement ('a). -type IntervalMap<'a> = +/// IntervalMapElement ('T). +type IntervalMap<'T> = private - IntervalMap of FingerTree, IntervalMapElem<'a>> + IntervalMap of FingerTree, IntervalMapElem<'T>> /// Helper module for IntervalMap. module IntervalMap = /// Empty interval tree. - let empty: IntervalMap<'a> = IntervalMap Empty + let empty: IntervalMap<'T> = IntervalMap Empty - let isEmpty (m: IntervalMap<'a>) = m = IntervalMap Empty + let isEmpty (m: IntervalMap<'T>) = m = IntervalMap Empty /// Add an item to the interval tree. let add (i: AddrRange) v (IntervalMap m) = @@ -74,9 +74,9 @@ module IntervalMap = |> matches /// Find exactly matching interval. - let tryFind range (m: IntervalMap<'a>) = + let tryFind range (m: IntervalMap<'T>) = findAll range m - |> List.tryFind (fun (elt: IntervalMapElem<'a>) -> elt.Key = range) + |> List.tryFind (fun (elt: IntervalMapElem<'T>) -> elt.Key = range) |> Option.map (fun v -> v.Val) /// Find an interval that has the same low bound (Min) as the given address. @@ -104,19 +104,19 @@ module IntervalMap = let containsAddr addr m = includeRange (AddrRange (addr, addr)) m /// Check whether the exact range exists in the interval tree. - let contains (range: AddrRange) (m: IntervalMap<'a>) = + let contains (range: AddrRange) (m: IntervalMap<'T>) = match tryFind range m with | None -> false | _ -> true /// Replace the exactly matched interval from the map to the given one. - let replace (i: AddrRange) (v: 'a) (IntervalMap m) = + let replace (i: AddrRange) (v: 'T) (IntervalMap m) = let l, r = Op.Split (fun (e: InterMonoid) -> Key i.Min <= e.GetMin ()) m let rec replaceLoop l r = match Op.ViewL r with | Nil -> raise InvalidAddrRangeException - | Cons (x: IntervalMapElem<'a>, xs) + | Cons (x: IntervalMapElem<'T>, xs) when x.Min = i.Min && x.Max = i.Max -> Op.Concat l (Op.Cons (IntervalMapElem (i, v)) xs) | Cons (x, xs) -> @@ -126,7 +126,7 @@ module IntervalMap = /// Add a new mapping to the IntervalMap when there is no exactly matching /// interval. If there is, replace the mapping with the new value. - let addOrReplace (i: AddrRange) (v: 'a) m = + let addOrReplace (i: AddrRange) (v: 'T) m = if contains i m then replace i v m else add i v m @@ -137,7 +137,7 @@ module IntervalMap = let rec rmLoop l r = match Op.ViewL r with | Nil -> raise InvalidAddrRangeException - | Cons (x: IntervalMapElem<'a>, xs) + | Cons (x: IntervalMapElem<'T>, xs) when x.Min = i.Min && x.Max = i.Max -> Op.Concat l xs | Cons (x, xs) -> @@ -147,7 +147,7 @@ module IntervalMap = /// Fold the map. let fold fn acc (IntervalMap m) = - foldl (fun acc (elt: IntervalMapElem<'a>) -> fn acc elt.Key elt.Val) acc m + foldl (fun acc (elt: IntervalMapElem<'T>) -> fn acc elt.Key elt.Val) acc m /// Iterate the map. let iter fn m = fold (fun _ range elt -> fn range elt) () m diff --git a/src/Core/LEB128.fs b/src/Core/LEB128.fs index 8e1b4be3..a638d7e1 100644 --- a/src/Core/LEB128.fs +++ b/src/Core/LEB128.fs @@ -30,6 +30,7 @@ open System /// incorrect encoding. exception LEB128DecodeException +[] module private LEB128Helper = let rec decodeLoop acc (bs: ReadOnlySpan) offset b len = let offset' = offset + 1 @@ -57,8 +58,6 @@ module private LEB128Helper = else currentValue -open LEB128Helper - type LEB128 = static member Max32 = 5 static member Max64 = 10 @@ -70,7 +69,7 @@ type LEB128 = /// Decode a LEB128-encoded integer into uint64. This function returns a tuple /// of (the decoded uint64, and the count of how many bytes were read). - static member DecodeUInt64 (bytes: byte []) = + static member DecodeUInt64 (bytes: byte[]) = LEB128.DecodeUInt64 (ReadOnlySpan bytes) /// Decode a LEB128-encoded integer into uint32. This function returns a tuple @@ -80,7 +79,7 @@ type LEB128 = /// Decode a LEB128-encoded integer into uint32. This function returns a tuple /// of (the decoded uint32, and the count of how many bytes were read). - static member DecodeUInt32 bytes = + static member DecodeUInt32 (bytes: byte[]) = LEB128.DecodeUInt32 (ReadOnlySpan bytes) /// Decode a LEB128-encoded integer into int64. This function returns a tuple @@ -92,7 +91,7 @@ type LEB128 = /// Decode a LEB128-encoded integer into int64. This function returns a tuple /// of (the decoded int64, and the count of how many bytes were read). - static member DecodeSInt64 bytes = + static member DecodeSInt64 (bytes: byte[]) = LEB128.DecodeSInt64 (ReadOnlySpan bytes) /// Decode a LEB128-encoded integer into int32. This function returns a tuple @@ -104,5 +103,5 @@ type LEB128 = /// Decode a LEB128-encoded integer into int32. This function returns a tuple /// of (the decoded int32, and the count of how many bytes were read). - static member DecodeSInt32 bytes = + static member DecodeSInt32 (bytes: byte[]) = LEB128.DecodeSInt32 (ReadOnlySpan bytes) diff --git a/src/Core/LRUCache.fs b/src/Core/LRUCache.fs index 84e2146d..6edd2f6f 100644 --- a/src/Core/LRUCache.fs +++ b/src/Core/LRUCache.fs @@ -37,7 +37,7 @@ type LRUCache<'K, 'V when 'K: equality and 'V: equality> (capacity: int) = let mutable size = 0 member inline private __.InsertBack v = - if head = null then head <- v else tail.Next <- v + if isNull head then head <- v else tail.Next <- v v.Prev <- tail v.Next <- null v.RefCount <- v.RefCount + 1 @@ -45,8 +45,8 @@ type LRUCache<'K, 'V when 'K: equality and 'V: equality> (capacity: int) = size <- size + 1 member inline private __.Remove (v: DoublyLinkedKeyValue<'K, 'V>) = - if v.Prev = null then head <- v.Next else v.Prev.Next <- v.Next - if v.Next = null then tail <- v.Prev else v.Next.Prev <- v.Prev + if isNull v.Prev then head <- v.Next else v.Prev.Next <- v.Next + if isNull v.Next then tail <- v.Prev else v.Next.Prev <- v.Prev size <- size - 1 member __.Count with get () = size @@ -107,7 +107,7 @@ type ConcurrentLRUCache<'K, 'V when 'K: equality and 'V: equality> Monitor.Exit (lock) member private __.InsertBack v = - if head = null then head <- v else tail.Next <- v + if isNull head then head <- v else tail.Next <- v v.Prev <- tail v.Next <- null tail <- v @@ -115,8 +115,8 @@ type ConcurrentLRUCache<'K, 'V when 'K: equality and 'V: equality> v member private __.Remove (v: DoublyLinkedKeyValue<'K, 'V>) = - if v.Prev = null then head <- v.Next else v.Prev.Next <- v.Next - if v.Next = null then tail <- v.Prev else v.Next.Prev <- v.Prev + if isNull v.Prev then head <- v.Next else v.Prev.Next <- v.Next + if isNull v.Next then tail <- v.Prev else v.Next.Prev <- v.Prev size <- size - 1 member __.Count with get () = size diff --git a/src/Core/Logger.fs b/src/Core/Logger.fs index de10d180..8f6a0baa 100644 --- a/src/Core/Logger.fs +++ b/src/Core/Logger.fs @@ -24,6 +24,7 @@ namespace B2R2 +open System open System.IO /// How verbose do we want to log messages? @@ -41,14 +42,16 @@ type LogLevel = [] module LogLevel = /// Get LogLevel from a given string. + [] let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "1" | "l1" | "quiet" | "q" -> LogLevel.L1 | "3" | "l3" | "verbose" | "v" -> LogLevel.L3 | "4" | "l4" -> LogLevel.L4 | _ -> LogLevel.L2 /// Return a string representing the given LogLevel. + [] let toString = function | LogLevel.L1 -> "L1" | LogLevel.L2 -> "L2" @@ -58,6 +61,8 @@ module LogLevel = /// Basic logging facility. type ILogger = + inherit IDisposable + /// Write a log message (without newline). If the given verbosity level (lvl) /// is lower than it of the logger's, this will print out the given message. /// If the logger's verbosity level is L4, then this function will always @@ -75,10 +80,9 @@ type FileLogger(filepath, ?level: LogLevel) = let fs = File.CreateText (filepath, AutoFlush = true) let llev = defaultArg level LogLevel.L2 - override __.Finalize () = - try fs.Close () with _ -> () - interface ILogger with + member __.Dispose () = fs.Dispose () + member __.Log (str, ?lvl) = let lvl = defaultArg lvl LogLevel.L2 if lvl <= llev then fs.Write str else () diff --git a/src/Core/Monads.fs b/src/Core/Monads.fs index 24f68c46..1547fd5c 100644 --- a/src/Core/Monads.fs +++ b/src/Core/Monads.fs @@ -30,7 +30,7 @@ module Maybe = begin /// A builder for Maybe computation expression. type MaybeBuilder () = member __.Return (x) = Some x - member __.ReturnFrom (x: 'a option) = x + member __.ReturnFrom (x: Option<_>) = x member __.Bind (m, f) = Option.bind f m member __.Zero () = None diff --git a/src/Core/OS.fs b/src/Core/OS.fs index 82c53ba9..f766a271 100644 --- a/src/Core/OS.fs +++ b/src/Core/OS.fs @@ -39,11 +39,13 @@ type OS = | UnknownOS = 4 /// A helper module for OS type. +[] module OS = open System.IO /// Test if the given program name is runnable in the current environment /// by analyzing the PATH environment variable. + [] let isRunnable progName = let testPath path = let fullPath = Path.Combine (path, progName) @@ -54,8 +56,9 @@ module OS = vars.Split (Path.PathSeparator) |> Array.exists testPath /// Obtain an OS type from the given string. + [] let ofString (s: string) = - match s.ToLower () with + match s.ToLowerInvariant () with | "windows" | "win" -> OS.Windows | "linux" -> OS.Linux | "macos" | "macosx" | "mac" | "osx" -> OS.MacOSX @@ -63,6 +66,7 @@ module OS = | _ -> invalidArg (nameof s) "Unknown OS string" /// Return a string representation from the given OS type. + [] let toString os = match os with | OS.Windows -> "Windows" diff --git a/src/Core/Printer.fs b/src/Core/Printer.fs index 704c3033..bf7a24cb 100644 --- a/src/Core/Printer.fs +++ b/src/Core/Printer.fs @@ -32,7 +32,7 @@ type TableColumn = | RightAligned of width: int | LeftAligned of width: int with - static member ofPaddedString isLast (s: string) column = + static member OfPaddedString isLast (s: string) column = match column with | RightAligned w -> let s = s.PadLeft (w) in if isLast then s else s + " " | LeftAligned w -> if isLast then s else s.PadRight (w) + " " @@ -40,8 +40,6 @@ with /// Define a output configuration of a table. type TableConfig = TableColumn list -module CS = ColoredSegment - module private PrinterConst = let [] ColWidth = 24 let [] CacheLimit = 16777216 @@ -106,31 +104,35 @@ type Printer () = /// Flush out everything. abstract Flush: unit -> unit - [] - static member printErrorToConsole str = - [ CS.nocolor "[*] Error: "; CS.red str ] |> Printer.printToConsoleLine - Printer.printToConsoleLine () + static member PrintToConsole s = + OutString.toConsole s - [] - static member printToConsole s = + static member PrintToConsole s = ColoredString.toConsole s - [] - static member printToConsole (s: string, [] args) = + static member PrintToConsole (s: string, [] args) = Console.Write (s, args) - [] - static member printToConsoleLine s = + static member PrintToConsoleLine s = + OutString.toConsoleLine s + + static member PrintToConsoleLine s = ColoredString.toConsoleLine s - [] - static member printToConsoleLine (s: string, [] args) = + static member PrintToConsoleLine (s: string) = + Console.WriteLine s + + static member PrintToConsoleLine (s: string, [] args) = Console.WriteLine (s, args) - [] - static member printToConsoleLine () = + static member PrintToConsoleLine () = Console.WriteLine () + static member PrintErrorToConsole str = + [ ColoredSegment (NoColor, "[*] Error: ") + ColoredSegment (Red, str) ] |> Printer.PrintToConsoleLine + Printer.PrintToConsoleLine () + /// ConsolePrinter simply prints out strings to console whenever a print method /// is called. This printer does not perform any caching, so it immediately /// flushes out all the strings to console. @@ -180,7 +182,7 @@ type ConsolePrinter () = if indent then Console.Write (" ") else () match cs with | (c, s) :: rest -> - (c, TableColumn.ofPaddedString (i = lastIdx) s col) :: rest + (c, TableColumn.OfPaddedString (i = lastIdx) s col) :: rest |> __.Print | [] -> ()) Console.WriteLine () @@ -192,12 +194,13 @@ type ConsolePrinter () = |> List.iteri (fun i (c, s) -> if indent then Console.Write (" ") - Console.Write (TableColumn.ofPaddedString (i = lastIdx) s c)) + Console.Write (TableColumn.OfPaddedString (i = lastIdx) s c)) Console.WriteLine () lastLineWasEmpty <- false override __.PrintSectionTitle title = - [ CS.red "# "; CS.nocolor title ] + [ ColoredSegment (Red, "# ") + ColoredSegment (NoColor, title) ] |> __.PrintLine __.PrintLine () lastLineWasEmpty <- true @@ -278,7 +281,7 @@ type ConsoleCachedPrinter () = if indent then __.Add (" ") else () match cs with | (_, s) :: rest -> - (TableColumn.ofPaddedString (i = lastIdx) s col + (TableColumn.OfPaddedString (i = lastIdx) s col + ColoredString.toString rest) |> __.Add | [] -> ()) @@ -290,7 +293,7 @@ type ConsoleCachedPrinter () = List.zip cfg strs |> List.iteri (fun i (c, s) -> if indent then __.Add (" ") - TableColumn.ofPaddedString (i = lastIdx) s c |> __.Add) + TableColumn.OfPaddedString (i = lastIdx) s c |> __.Add) __.Add Environment.NewLine lastLineWasEmpty <- false diff --git a/src/Core/ProgramPoint.fs b/src/Core/ProgramPoint.fs index 925117ba..ba468099 100644 --- a/src/Core/ProgramPoint.fs +++ b/src/Core/ProgramPoint.fs @@ -29,20 +29,25 @@ namespace B2R2 /// (Address of the instruction, Index of the IR stmt for the instruction). type ProgramPoint (addr, pos) = /// Address of the instruction. - member val Address: Addr = addr + member __.Address with get(): Addr = addr /// Index of the IR statement within the instruction. - member val Position: int = pos + member __.Position with get(): int = pos + override __.Equals (o) = match o with | :? ProgramPoint as o -> o.Address = __.Address && o.Position = __.Position | _ -> false + override __.GetHashCode () = hash (__.Address, __.Position) - override __.ToString () = String.u64ToHexNoPrefix addr + ":" + pos.ToString () + + override __.ToString () = + $"{addr:x}:{pos}" /// Get a fake program point to represent a fake vertex, which does not exist /// in a CFG. Fake vertices are useful for representing external function /// calls and their nodes in the SCFG. static member GetFake () = ProgramPoint (0UL, -1) + static member IsFake (p: ProgramPoint) = p.Address = 0UL && p.Position = -1 static member Next (p: ProgramPoint) = diff --git a/src/Core/RandomAccessQueue.fs b/src/Core/RandomAccessQueue.fs index 7889f879..aa48d0e1 100644 --- a/src/Core/RandomAccessQueue.fs +++ b/src/Core/RandomAccessQueue.fs @@ -27,26 +27,26 @@ namespace B2R2 open B2R2.FingerTree /// An element for our random access queue. -type RandomAccessQueueElem<'a> (v) = - member val Val: 'a = v +type RandomAccessQueueElem<'T> (v) = + member val Val: 'T = v override __.ToString () = __.Val.ToString () interface IMeasured with member __.Measurement = Size (1u) /// Interval tree-based map: an interval of type (Addr) -> an /// RandomAccessQueueElement ('a). -type RandomAccessQueue<'a> = +type RandomAccessQueue<'T> = private - RandomAccessQueue of FingerTree> + RandomAccessQueue of FingerTree> /// A helper module for RandomAccessQueue<'a>. [] module RandomAccessQueue = /// Empty interval tree. - let empty: RandomAccessQueue<'a> = RandomAccessQueue Empty + let empty: RandomAccessQueue<_> = RandomAccessQueue Empty - let isEmpty (q: RandomAccessQueue<'a>) = q = RandomAccessQueue Empty + let isEmpty (q: RandomAccessQueue<_>) = q = RandomAccessQueue Empty let length (RandomAccessQueue q) = ((q :> IMeasured<_>).Measurement).Value |> int @@ -88,14 +88,14 @@ module RandomAccessQueue = let rec loop cnt q = match Op.ViewL q with | Nil -> None - | Cons (hd: RandomAccessQueueElem<'a>, tl) -> + | Cons (hd: RandomAccessQueueElem<_>, tl) -> if pred hd.Val then Some cnt else loop (cnt + 1) tl loop 0 q let rec findBack pred (RandomAccessQueue q) = match Op.ViewR q with | Nil -> None - | Cons (hd: RandomAccessQueueElem<'a>, tl) -> + | Cons (hd: RandomAccessQueueElem<_>, tl) -> let tl = RandomAccessQueue tl if pred hd.Val then length tl |> Some else findBack pred tl @@ -103,6 +103,6 @@ module RandomAccessQueue = Op.Concat q1 q2 |> RandomAccessQueue let toList (RandomAccessQueue q) = - foldr (fun (elt: RandomAccessQueueElem<'a>) acc -> elt.Val :: acc) q [] + foldr (fun (elt: RandomAccessQueueElem<_>) acc -> elt.Val :: acc) q [] // vim: set tw=80 sts=2 sw=2: diff --git a/src/Core/RegType.fs b/src/Core/RegType.fs index fefd15b1..54dc6ca7 100644 --- a/src/Core/RegType.fs +++ b/src/Core/RegType.fs @@ -24,6 +24,9 @@ namespace B2R2 +/// This exception is raised when an invalid RegType is encountered. +exception InvalidRegTypeException + /// A unit for RegType. [] type rt @@ -32,43 +35,31 @@ type rt /// the register. type RegType = int -/// This exception is raised when an invalid RegType is encountered. -exception InvalidRegTypeException - /// /// A helper for . /// [] module RegType = - /// - /// Convert to string. - /// - /// RegType. - /// - /// A string representation for RegType. For example, I32 means a 32-bit - /// integer type. - /// - let toString (t: RegType) = - if t >= 0 then "I" + t.ToString () - else "F" + t.ToString () - #if DEBUG let checkIfValidRegType t = if t > 0 then () - elif t < 0 && t >= -512 then () else raise InvalidRegTypeException #endif /// - /// Check if the given is a floating-point (FP) - /// type. + /// Convert to string. /// /// RegType. /// - /// A Boolean value that is true if the given RegType is a floating-point - /// type, false otherwise. + /// A string representation for RegType. For example, I32 means a 32-bit + /// integer type. /// - let isFP (t: RegType) = t < 0 + [] + let toString (t: RegType) = +#if DEBUG + checkIfValidRegType t +#endif + "I" + t.ToString () /// /// Convert a to an integer of bit width. @@ -77,11 +68,12 @@ module RegType = /// /// A bit width in integer of the given RegType. /// + [] let toBitWidth (t: RegType) = #if DEBUG checkIfValidRegType t #endif - if t > 0 then int t else int (-t) + int t /// /// Get a byte width from a RegType. @@ -90,19 +82,20 @@ module RegType = /// /// A byte width in integer of the given RegType. /// + [] let toByteWidth t = let t = toBitWidth t if t % 8 = 0 then t / 8 - else Utils.impossible () + else raise InvalidRegTypeException /// - /// Get the corresponding integer RegType from the given bit width. When a - /// negative integer is given, it will return a floating point type. + /// Get the corresponding integer RegType from the given bit width. /// /// Bit width in integer. /// /// A . /// + [] let inline fromBitWidth n = let t = LanguagePrimitives.Int32WithMeasure n #if DEBUG @@ -117,23 +110,16 @@ module RegType = /// /// A . /// + [] let fromByteWidth n = fromBitWidth (n * 8) - /// - /// Get a double-sized RegType from a given RegType. - /// - /// RegType. - /// - /// A . - /// - let double (t: RegType) = 2 * t - /// /// Get a bitmask (in integer) from the given RegType. /// /// /// A bit mask in big integer. /// + [] let getMask t = if t <= 64 then System.UInt64.MaxValue >>> (64 - int t) |> bigint else (bigint.One <<< (int t)) - bigint.One diff --git a/src/Core/RegisterSet.fs b/src/Core/RegisterSet.fs index 37bace77..ee64fc6c 100644 --- a/src/Core/RegisterSet.fs +++ b/src/Core/RegisterSet.fs @@ -24,210 +24,73 @@ namespace B2R2 -/// Raised when two RegisterSets with two distinct tags operate. -exception RegisterSetTagMismatchException - -/// A tag used in RegisterSet for identifying distinct set of registers for -/// different ISAs. -type RegisterSetTag = - | Empty = 0 - | Intel = 1 - | ARM32 = 2 - | ARM64 = 3 - | MIPS = 4 - | EVM = 5 - | TMS320C6000 = 6 - | CIL = 7 - | AVR = 8 - | SH4 = 9 - | PPC32 = 10 - | Sparc64 = 11 - | RISCV64 = 12 - | WASM = 20 - -/// RegisterSet is an efficient set data structure using arrays for managing a -/// set of registers. -[] -type RegisterSet () = - /// Tag identifies ISA. - abstract member Tag: RegisterSetTag - - /// Create a new RegisterSet from a given array and a set. This method should - /// be overridden by ISA-specific RegisterSet implementation. - abstract member New: uint64 [] -> Set -> RegisterSet - - /// Obtain a unique index to the internal array from a given RegisterID. - abstract member RegIDToIndex: RegisterID -> int - - /// Obtain a RegisterID from a given index. - abstract member IndexToRegID: int -> RegisterID - - /// Size of the internal array. - abstract member ArrSize: int - - /// An internal array storing the register set. - abstract member BitArray: uint64 [] - - /// A backup storage for unknown variables, which does not have a RegisterID. - /// For example, when writing a symbolic executor, we may encounter unknown - /// variables, i.e., fresh symbolic variables. We store them in this set. - abstract member AuxSet: Set - - /// Add a register to the set. - abstract member Add: RegisterID -> RegisterSet - - /// Remove a register from the set. - abstract member Remove: RegisterID -> RegisterSet - - /// Union of two register sets. - abstract member Union: RegisterSet -> RegisterSet - - /// Intersection of two register sets. - abstract member Intersect: RegisterSet -> RegisterSet - - /// Check if a register exists in the set. - abstract member Exists: RegisterID -> bool +open System +open System.Numerics - /// Check if the set is empty. - abstract member IsEmpty: unit -> bool - - /// Return the set of register indices. - abstract member ToSet: unit -> Set +/// RegisterSet is an efficient set data structure for managing a set of +/// registers. Since RegisterID always starts from 0, we can use it directly as +/// an index to the bit array. +type RegisterSet (maxNumElems: int) = + let arr: int64[] = Array.zeroCreate ((maxNumElems + 63) / 64) - /// Create an internal bit array of size. - static member inline MakeInternalBitArray size = - Array.zeroCreate size + new () = RegisterSet (378) (* Number of registers for AARCH64 = 378 *) /// Get the bucket and the offset from the given index. - static member inline GetBucketAndOffset (idx) = + member inline private __.GetBucketAndOffset idx = struct (idx / 64, idx &&& 0x3F) - /// Get the register index from the given bucket id and the offset. - static member inline GetIndex bucketId offset = - bucketId * 64 + offset - - /// Check if the nth bit is set on the value v. - static member inline IsBitSet nth v = - (v &&& (1UL <<< nth)) <> 0UL - -/// Empty register set. -type EmptyRegisterSet () = - inherit RegisterSet () - override __.Tag = RegisterSetTag.Empty - override __.ArrSize = 0 - override __.New _ _ = Utils.impossible () - override __.RegIDToIndex _ = Utils.impossible () - override __.IndexToRegID _ = Utils.impossible () - override __.BitArray = [||] - override __.AuxSet = Set.empty - override __.Add _ = Utils.impossible () - override __.Remove _ = __ :> RegisterSet - override __.Union o = o - override __.Intersect o = __ :> RegisterSet - override __.Exists _ = false - override __.IsEmpty () = true - override __.ToSet () = Set.empty - -module private EmptyRegisterSet = - let instance = EmptyRegisterSet () :> RegisterSet - -/// Non-empty register set. -[] -type NonEmptyRegisterSet (bitArray: uint64 [], s: Set) = - inherit RegisterSet () - -#if DEBUG - member __.CheckTag (o: RegisterSet) = - if __.Tag = o.Tag then () - else raise RegisterSetTagMismatchException -#endif - - override __.GetHashCode () = hash __.BitArray - - override __.Equals obj = - match obj with - | :? NonEmptyRegisterSet as rhs -> __.BitArray = rhs.BitArray - | _ -> false - - override __.BitArray = bitArray - - override __.AuxSet = s - - override __.Add rid = - match __.RegIDToIndex rid with - | -1 -> __.New bitArray (Set.add rid s) - | idx -> - let struct (bucket, offset) = RegisterSet.GetBucketAndOffset idx - let newArr = Array.copy bitArray - newArr[bucket] <- newArr[bucket] ||| (1UL <<< offset) - __.New newArr s - - override __.Remove id = - match __.RegIDToIndex id with - | -1 -> __.New bitArray (Set.remove id s) - | id -> - let struct (bucket, offset) = RegisterSet.GetBucketAndOffset id - let newArr = Array.copy bitArray - newArr[bucket] <- newArr[bucket] &&& ~~~(1UL <<< offset) - __.New newArr s - - override __.Union (other: RegisterSet) = - if other.Tag = RegisterSetTag.Empty then __ :> RegisterSet - else -#if DEBUG - __.CheckTag other -#endif - let newArr = Array.mapi (fun i e -> e ||| other.BitArray[i]) bitArray - __.New newArr (Set.union __.AuxSet other.AuxSet) - - override __.Intersect (other: RegisterSet) = - if other.Tag = RegisterSetTag.Empty then EmptyRegisterSet.instance - else -#if DEBUG - __.CheckTag other -#endif - let newArr = Array.mapi (fun i e -> e &&& other.BitArray[i]) bitArray - __.New newArr <| Set.intersect __.AuxSet other.AuxSet - - override __.Exists id = - match __.RegIDToIndex id with - | -1 -> Set.contains id __.AuxSet - | id -> - let struct (bucket, offset) = RegisterSet.GetBucketAndOffset id - (bitArray[bucket] &&& (1UL <<< offset)) <> 0UL - - override __.IsEmpty () = - (Array.exists (fun x -> x <> 0UL) bitArray |> not) && Set.isEmpty __.AuxSet - - member private __.FoldRegIndicesAux set bid v offset = - if offset < 64 then - let set = - if (v &&& 1UL) = 1UL then Set.add (RegisterSet.GetIndex bid offset) set - else set - __.FoldRegIndicesAux set bid (v >>> 1) (offset + 1) - else set - - member private __.FoldRegIndices set bid v = __.FoldRegIndicesAux set bid v 0 - - override __.ToSet () = - Array.foldi __.FoldRegIndices Set.empty bitArray - |> fst - |> Set.map __.IndexToRegID - |> Set.union __.AuxSet - -/// A helper module for RegisterSet. -[] -module RegisterSet = - let empty = EmptyRegisterSet.instance - - let inline union (lhs: RegisterSet) rhs = lhs.Union rhs - - let inline intersect (lhs: RegisterSet) rhs = lhs.Intersect rhs - - let inline remove id (s: RegisterSet) = s.Remove id - - let inline add id (s: RegisterSet) = s.Add id - - let inline exist id (s: RegisterSet) = s.Exists id - - let inline isEmpty (s: RegisterSet) = s.IsEmpty () + /// Maximum number of elements that this set can hold. + member __.MaxNumElems with get() = maxNumElems + + /// The bit array representing the set. + member __.BitArray with get() = arr + + /// Add a register to the set by marking the corresponding bit. + member __.Add (idx: int) = + if idx >= __.MaxNumElems then raise (IndexOutOfRangeException ()) else () + let struct (bucket, offset) = __.GetBucketAndOffset idx + arr[bucket] <- arr[bucket] ||| (1L <<< offset) + + /// Remove a register from the set by unmarking the corresponding bit. + member __.Remove (idx: int) = + if idx >= __.MaxNumElems then raise (IndexOutOfRangeException ()) else () + let struct (bucket, offset) = __.GetBucketAndOffset idx + arr[bucket] <- arr[bucket] &&& ~~~(1L <<< offset) + + /// Update the current register set by making a union with the given set. + member __.Union (other: RegisterSet) = + assert (other.MaxNumElems = __.MaxNumElems) + let otherArray = other.BitArray + for i = 0 to otherArray.Length - 1 do + arr[i] <- arr[i] ||| otherArray[i] + + /// Update the current register set by making an intersection with the given + /// set. + member __.Intersect (other: RegisterSet) = + assert (other.MaxNumElems = __.MaxNumElems) + let otherArray = other.BitArray + for i = 0 to otherArray.Length - 1 do + arr[i] <- arr[i] &&& otherArray[i] + + /// Check if the set contains the given register indexed by `idx`. + member __.Contains (idx: int) = + let struct (bucket, offset) = __.GetBucketAndOffset idx + (arr[bucket] &&& (1L <<< offset)) <> 0L + + /// Check if the set is empty. + member __.IsEmpty () = + arr |> Array.forall (fun x -> x = 0L) + + /// Clear the set. + member __.Clear () = + for i = 0 to arr.Length - 1 do + arr.[i] <- 0L + + /// Iterate over the set and apply the given function to each element. + member inline __.Iterate ([] fn) = + for i = 0 to __.BitArray.Length - 1 do + let mutable bucket = __.BitArray[i] + while bucket <> 0L do + let offset = BitOperations.TrailingZeroCount bucket + fn (i * 64 + offset) + bucket <- bucket ^^^ (bucket &&& (- bucket)) diff --git a/src/Core/Syscalls.fs b/src/Core/Syscalls.fs index c679af3d..0a897f0c 100644 --- a/src/Core/Syscalls.fs +++ b/src/Core/Syscalls.fs @@ -38,104 +38,104 @@ type LinuxSyscall = | Alarm = 6 | AllocHugePages = 7 | ArcGetTLS = 8 - | ArcSetTLS = 9 - | ArcUsrCmpxchg = 10 - | ArchPrctl = 11 - | AtomicBarrier = 12 - | AtomicCmpxchg32 = 13 - | Bdflush = 14 - | BfinSpinlock = 15 - | Bind = 16 - | Bpf = 17 - | Brk = 18 - | Breakpoint = 19 - | CacheFlush = 20 - | CapGet = 21 - | CapSet = 22 - | Chdir = 23 - | Chmod = 24 - | Chown = 25 - | Chown32 = 26 - | Chroot = 27 - | ClockAdjtime = 28 - | ClockAdjtime64 = 29 - | ClockGetres = 30 - | ClockGetres64 = 31 - | ClockGettime = 32 - | ClockGettime64 = 33 - | ClockNanosleep = 34 - | ClockNanosleep64 = 35 - | ClockSettime = 36 - | ClockSettime64 = 37 - | Clone2 = 38 - | Clone = 39 - | Clone3 = 40 - | Close = 41 - | CmpxchgBadaddr = 42 - | Connect = 43 - | CopyFileRange = 44 - | Creat = 45 - | CreateModule = 46 - | DeleteModule = 47 - | DmaMemcpy = 48 - | Dup = 49 - | Dup2 = 50 - | Dup3 = 51 - | EpollCreate = 52 - | EpollCreate1 = 53 - | EpollCtl = 54 - | EpollPwait = 55 - | EpollWait = 56 - | Eventfd = 57 - | Eventfd2 = 58 - | Execv = 59 - | Execve = 60 - | Execveat = 61 - | Exit = 62 - | ExitGroup = 63 - | Faccessat = 64 - | Fadvise64 = 65 - | Fadvise64_64 = 66 - | Fallocate = 67 - | FanotifyInit = 68 - | FanotifyMark = 69 - | Fchdir = 70 - | Fchmod = 71 - | Fchmodat = 72 - | Fchown = 73 - | Fchown32 = 74 - | Fchownat = 75 - | Fcntl = 76 - | Fcntl64 = 77 - | Fdatasync = 78 - | Fgetxattr = 79 - | FinitModule = 80 - | Flistxattr = 81 - | Flock = 82 - | Fork = 83 - | FreeHugepages = 84 - | Fremovexattr = 85 - | Fsconfig = 86 - | Fsetxattr = 87 - | Fsmount = 88 - | Fsopen = 89 - | Fspick = 90 - | Fstat = 91 - | Fstat64 = 92 - | Fstatat64 = 93 - | Fstatfs = 94 - | Fstatfs64 = 95 - | Fsync = 96 - | Ftruncate = 97 - | Ftruncate64 = 98 - | Futex = 99 - | Futex64 = 100 - | Futimesat = 101 - | GetKernelSyms = 102 - | GetMempolicy = 103 - | GetRobustList = 104 - | GetThreadArea = 105 - | GetTLS = 106 + | ArchPrctl = 9 + | ArcSetTLS = 10 + | ArcUsrCmpxchg = 11 + | ArmFadvise64 = 12 + | ArmSyncFileRange = 13 + | AtomicBarrier = 14 + | AtomicCmpxchg32 = 15 + | Bdflush = 16 + | BfinSpinlock = 17 + | Bind = 18 + | Bpf = 19 + | Breakpoint = 20 + | Brk = 21 + | CacheCtl = 22 + | CacheFlush = 23 + | CapGet = 24 + | CapSet = 25 + | Chdir = 26 + | Chmod = 27 + | Chown = 28 + | Chown32 = 29 + | Chroot = 30 + | ClockAdjtime = 31 + | ClockAdjtime64 = 32 + | ClockGetres = 33 + | ClockGetres64 = 34 + | ClockGettime = 35 + | ClockGettime64 = 36 + | ClockNanosleep = 37 + | ClockNanosleep64 = 38 + | ClockSettime = 39 + | ClockSettime64 = 40 + | Clone = 41 + | Clone2 = 42 + | Clone3 = 43 + | Close = 44 + | CloseRange = 45 + | CmpxchgBadaddr = 46 + | Connect = 47 + | CopyFileRange = 48 + | Creat = 49 + | CreateModule = 50 + | DeleteModule = 51 + | DmaMemcpy = 52 + | Dup = 53 + | Dup2 = 54 + | Dup3 = 55 + | EpollCreate = 56 + | EpollCreate1 = 57 + | EpollCtl = 58 + | EpollPwait = 59 + | EpollWait = 60 + | Eventfd = 61 + | Eventfd2 = 62 + | Execv = 63 + | Execve = 64 + | Execveat = 65 + | Exit = 66 + | ExitGroup = 67 + | Faccessat = 68 + | Faccessat2 = 69 + | Fadvise64 = 70 + | Fadvise64_64 = 71 + | Fallocate = 72 + | FanotifyInit = 73 + | FanotifyMark = 74 + | Fchdir = 75 + | Fchmod = 76 + | Fchmodat = 77 + | Fchown = 78 + | Fchown32 = 79 + | Fchownat = 80 + | Fcntl = 81 + | Fcntl64 = 82 + | Fdatasync = 83 + | Fgetxattr = 84 + | FinitModule = 85 + | Flistxattr = 86 + | Flock = 87 + | Fork = 88 + | FreeHugepages = 89 + | Fremovexattr = 90 + | Fsconfig = 91 + | Fsetxattr = 92 + | Fsmount = 93 + | Fsopen = 94 + | Fspick = 95 + | Fstat = 96 + | Fstat64 = 97 + | Fstatat64 = 98 + | Fstatfs = 99 + | Fstatfs64 = 100 + | Fsync = 101 + | Ftruncate = 102 + | Ftruncate64 = 103 + | Futex = 104 + | Futex64 = 105 + | Futimesat = 106 | Getcpu = 107 | Getcwd = 108 | Getdents = 109 @@ -152,243 +152,243 @@ type LinuxSyscall = | Getgroups32 = 120 | Gethostname = 121 | Getitimer = 122 - | Getpeername = 123 - | Getpagesize = 124 - | Getpgid = 125 - | Getpgrp = 126 - | Getpid = 127 - | Getppid = 128 - | Getpriority = 129 - | Getrandom = 130 - | Getresgid = 131 - | Getresgid32 = 132 - | Getresuid = 133 - | Getresuid32 = 134 - | Getrlimit = 135 - | Getrusage = 136 - | Getsid = 137 - | Getsockname = 138 - | Getsockopt = 139 - | Gettid = 140 - | Gettimeofday = 141 - | Getuid = 142 - | Getuid32 = 143 - | Getunwind = 144 - | Getxattr = 145 - | Getxgid = 146 - | Getxpid = 147 - | Getxuid = 148 - | InitModule = 149 - | InotifyAddWatch = 150 - | InotifyInit = 151 - | InotifyInit1 = 152 - | InotifyRmWatch = 153 - | IoCancel = 154 - | IoDestroy = 155 - | IoGetevents = 156 - | IoPgetevents = 157 - | IoPgetevents64 = 158 - | IoSetup = 159 - | IoSubmit = 160 - | IoUringEnter = 161 - | IoUringRegister = 162 - | IoUringSetup = 163 - | Ioctl = 164 - | Ioperm = 165 + | GetKernelSyms = 123 + | GetMempolicy = 124 + | Getpagesize = 125 + | Getpeername = 126 + | Getpgid = 127 + | Getpgrp = 128 + | Getpid = 129 + | Getppid = 130 + | Getpriority = 131 + | Getrandom = 132 + | Getresgid = 133 + | Getresgid32 = 134 + | Getresuid = 135 + | Getresuid32 = 136 + | Getrlimit = 137 + | GetRobustList = 138 + | Getrusage = 139 + | Getsid = 140 + | Getsockname = 141 + | Getsockopt = 142 + | GetThreadArea = 143 + | Gettid = 144 + | Gettimeofday = 145 + | GetTLS = 146 + | Getuid = 147 + | Getuid32 = 148 + | Getunwind = 149 + | Getxattr = 150 + | Getxgid = 151 + | Getxpid = 152 + | Getxuid = 153 + | InitModule = 154 + | InotifyAddWatch = 155 + | InotifyInit = 156 + | InotifyInit1 = 157 + | InotifyRmWatch = 158 + | IoCancel = 159 + | Ioctl = 160 + | IoDestroy = 161 + | IoGetevents = 162 + | Ioperm = 163 + | IoPgetevents = 164 + | IoPgetevents64 = 165 | Iopl = 166 | IoprioGet = 167 | IoprioSet = 168 - | Ipc = 169 - | Kcmp = 170 - | KernFeatures = 171 - | KexecFileLoad = 172 - | KexecLoad = 173 - | Keyctl = 174 - | Kill = 175 - | Lchown = 176 - | Lchown32 = 177 - | Lgetxattr = 178 - | Link = 179 - | Linkat = 180 - | Listen = 181 - | Listxattr = 182 - | Llistxattr = 183 - | LookupDcookie = 184 - | Lremovexattr = 185 - | Lseek = 186 - | LLseek = 187 - | Lsetxattr = 188 - | Lstat = 189 - | Lstat64 = 190 - | Madvise = 191 - | Mbind = 192 - | MemoryOrdering = 193 - | MetagGetTLS = 194 - | MetagSetFpuFlags = 195 - | MetagSetTLS = 196 - | MetagSetglobalbit = 197 + | IoSetup = 169 + | IoSubmit = 170 + | IoUringEnter = 171 + | IoUringRegister = 172 + | IoUringSetup = 173 + | Ipc = 174 + | Kcmp = 175 + | KernFeatures = 176 + | KexecFileLoad = 177 + | KexecLoad = 178 + | Keyctl = 179 + | Kill = 180 + | Lchown = 181 + | Lchown32 = 182 + | Lgetxattr = 183 + | Link = 184 + | Linkat = 185 + | Listen = 186 + | Listxattr = 187 + | Llistxattr = 188 + | LLseek = 189 + | LookupDcookie = 190 + | Lremovexattr = 191 + | Lseek = 192 + | Lsetxattr = 193 + | Lstat = 194 + | Lstat64 = 195 + | Madvise = 196 + | Mbind = 197 | Membarrier = 198 | MemfdCreate = 199 - | MigratePages = 200 - | Mincore = 201 - | Mkdir = 202 - | Mkdirat = 203 - | Mknod = 204 - | Mknodat = 205 - | Mlock = 206 - | Mlock2 = 207 - | Mlockall = 208 - | Mmap = 209 - | Mmap2 = 210 - | ModifyLdt = 211 - | Mount = 212 - | MoveMount = 213 - | MovePages = 214 - | Mprotect = 215 - | MqGetsetattr = 216 - | MqNotify = 217 - | MqOpen = 218 - | MqTimedreceive = 219 - | MqTimedreceive64 = 220 - | MqTimedsend = 221 - | MqTimedsend64 = 222 - | MqUnlink = 223 - | Mremap = 224 - | Msgctl = 225 - | Msgget = 226 - | Msgrcv = 227 - | Msgsnd = 228 - | Msync = 229 - | Munlock = 230 - | Munlockall = 231 - | Munmap = 232 - | NameToHandleAt = 233 - | Nanosleep = 234 - | Newfstatat = 235 - | NewSelect = 236 - | Nfsservctl = 237 - | Nice = 238 - | OldAdjtimex = 239 - | OldGetrlimit = 240 - | Oldfstat = 241 - | Oldlstat = 242 - | Oldolduname = 243 - | Oldstat = 244 - | Oldumount = 245 - | Olduname = 246 - | Open = 247 - | OpenByHandleAt = 248 - | OpenTree = 249 - | Openat = 250 - | Openat2 = 251 - | Or1kAtomic = 252 - | Pause = 253 - | PciconfigIobase = 254 - | PciconfigRead = 255 - | PciconfigWrite = 256 - | PerfEventOpen = 257 - | Personality = 258 - | Perfctr = 259 - | Perfmonctl = 260 - | PidfdGetfd = 261 - | PidfdSendSignal = 262 - | PidfdOpen = 263 - | Pipe = 264 - | Pipe2 = 265 - | PivotRoot = 266 - | PkeyAlloc = 267 - | PkeyFree = 268 - | PkeyMprotect = 269 - | Poll = 270 - | Ppoll = 271 - | Ppoll64 = 272 - | Prctl = 273 - | Pread = 274 - | Pread64 = 275 - | Preadv = 276 - | Preadv2 = 277 - | Prlimit64 = 278 - | ProcessVmReadv = 279 - | ProcessVmWritev = 280 - | Pselect6 = 281 - | Pselect6_64 = 282 - | Ptrace = 283 - | Pwrite = 284 - | Pwrite64 = 285 - | Pwritev = 286 - | Pwritev2 = 287 - | QueryModule = 288 - | Quotactl = 289 - | Read = 290 - | Readahead = 291 - | Readdir = 292 - | Readlink = 293 - | Readlinkat = 294 - | Readv = 295 - | Reboot = 296 - | Recv = 297 - | Recvfrom = 298 - | Recvmsg = 299 - | Recvmmsg = 300 - | Recvmmsg64 = 301 - | RemapFilePages = 302 - | Removexattr = 303 - | Rename = 304 - | Renameat = 305 - | Renameat2 = 306 - | RequestKey = 307 - | RestartSyscall = 308 - | RiscvFlushIcache = 309 - | Rmdir = 310 - | Rseq = 311 - | RtSigaction = 312 - | RtSigpending = 313 - | RtSigprocmask = 314 - | RtSigqueueinfo = 315 - | RtSigreturn = 316 - | RtSigsuspend = 317 - | RtSigtimedwait = 318 - | RtSigtimedwait64 = 319 - | RtTgsigqueueinfo = 320 - | Rtas = 321 - | S390RuntimeInstr = 322 - | S390PciMmioRead = 323 - | S390PciMmioWrite = 324 - | S390Sthyi = 325 - | S390GuardedStorage = 326 - | SchedGetAffinity = 327 - | SchedGetPriorityMax = 328 - | SchedGetPriorityMin = 329 - | SchedGetaffinity = 330 - | SchedGetattr = 331 - | SchedGetparam = 332 - | SchedGetscheduler = 333 - | SchedRrGetInterval = 334 - | SchedRrGetInterval64 = 335 - | SchedSetAffinity = 336 - | SchedSetaffinity = 337 - | SchedSetattr = 338 - | SchedSetparam = 339 - | SchedSetscheduler = 340 - | SchedYield = 341 - | Seccomp = 342 - | Select = 343 - | Semctl = 344 - | Semget = 345 - | Semop = 346 - | Semtimedop = 347 - | Semtimedop64 = 348 - | Send = 349 - | Sendfile = 350 - | Sendfile64 = 351 - | Sendmmsg = 352 - | Sendmsg = 353 - | Sendto = 354 - | SetMempolicy = 355 - | SetRobustList = 356 - | SetThreadArea = 357 - | SetTidAddress = 358 - | SetTLS = 359 + | MemoryOrdering = 200 + | MetagGetTLS = 201 + | MetagSetFpuFlags = 202 + | MetagSetglobalbit = 203 + | MetagSetTLS = 204 + | MigratePages = 205 + | Mincore = 206 + | Mkdir = 207 + | Mkdirat = 208 + | Mknod = 209 + | Mknodat = 210 + | Mlock = 211 + | Mlock2 = 212 + | Mlockall = 213 + | Mmap = 214 + | Mmap2 = 215 + | ModifyLdt = 216 + | Mount = 217 + | MoveMount = 218 + | MovePages = 219 + | Mprotect = 220 + | MqGetsetattr = 221 + | MqNotify = 222 + | MqOpen = 223 + | MqTimedreceive = 224 + | MqTimedreceive64 = 225 + | MqTimedsend = 226 + | MqTimedsend64 = 227 + | MqUnlink = 228 + | Mremap = 229 + | Msgctl = 230 + | Msgget = 231 + | Msgrcv = 232 + | Msgsnd = 233 + | Msync = 234 + | Munlock = 235 + | Munlockall = 236 + | Munmap = 237 + | NameToHandleAt = 238 + | Nanosleep = 239 + | Newfstatat = 240 + | NewSelect = 241 + | Nfsservctl = 242 + | Nice = 243 + | OldAdjtimex = 244 + | Oldfstat = 245 + | OldGetrlimit = 246 + | Oldlstat = 247 + | Oldolduname = 248 + | Oldstat = 249 + | Oldumount = 250 + | Olduname = 251 + | Open = 252 + | Openat = 253 + | Openat2 = 254 + | OpenByHandleAt = 255 + | OpenTree = 256 + | Or1kAtomic = 257 + | Pause = 258 + | PciconfigIobase = 259 + | PciconfigRead = 260 + | PciconfigWrite = 261 + | Perfctr = 262 + | PerfEventOpen = 263 + | Perfmonctl = 264 + | Personality = 265 + | PidfdGetfd = 266 + | PidfdOpen = 267 + | PidfdSendSignal = 268 + | Pipe = 269 + | Pipe2 = 270 + | PivotRoot = 271 + | PkeyAlloc = 272 + | PkeyFree = 273 + | PkeyMprotect = 274 + | Poll = 275 + | Ppoll = 276 + | Ppoll64 = 277 + | Prctl = 278 + | Pread = 279 + | Pread64 = 280 + | Preadv = 281 + | Preadv2 = 282 + | Prlimit64 = 283 + | ProcessVmReadv = 284 + | ProcessVmWritev = 285 + | Pselect6 = 286 + | Pselect6_64 = 287 + | Ptrace = 288 + | Pwrite = 289 + | Pwrite64 = 290 + | Pwritev = 291 + | Pwritev2 = 292 + | QueryModule = 293 + | Quotactl = 294 + | Read = 295 + | Readahead = 296 + | Readdir = 297 + | Readlink = 298 + | Readlinkat = 299 + | Readv = 300 + | Reboot = 301 + | Recv = 302 + | Recvfrom = 303 + | Recvmmsg = 304 + | Recvmmsg64 = 305 + | Recvmsg = 306 + | RemapFilePages = 307 + | Removexattr = 308 + | Rename = 309 + | Renameat = 310 + | Renameat2 = 311 + | RequestKey = 312 + | RestartSyscall = 313 + | RiscvFlushIcache = 314 + | Rmdir = 315 + | Rseq = 316 + | Rtas = 317 + | RtSigaction = 318 + | RtSigpending = 319 + | RtSigprocmask = 320 + | RtSigqueueinfo = 321 + | RtSigreturn = 322 + | RtSigsuspend = 323 + | RtSigtimedwait = 324 + | RtSigtimedwait64 = 325 + | RtTgsigqueueinfo = 326 + | S390GuardedStorage = 327 + | S390PciMmioRead = 328 + | S390PciMmioWrite = 329 + | S390RuntimeInstr = 330 + | S390Sthyi = 331 + | SchedGetaffinity = 332 + | SchedGetAffinity = 333 + | SchedGetattr = 334 + | SchedGetparam = 335 + | SchedGetPriorityMax = 336 + | SchedGetPriorityMin = 337 + | SchedGetscheduler = 338 + | SchedRrGetInterval = 339 + | SchedRrGetInterval64 = 340 + | SchedSetaffinity = 341 + | SchedSetAffinity = 342 + | SchedSetattr = 343 + | SchedSetparam = 344 + | SchedSetscheduler = 345 + | SchedYield = 346 + | Seccomp = 347 + | Select = 348 + | Semctl = 349 + | Semget = 350 + | Semop = 351 + | Semtimedop = 352 + | Semtimedop64 = 353 + | Send = 354 + | Sendfile = 355 + | Sendfile64 = 356 + | Sendmmsg = 357 + | Sendmsg = 358 + | Sendto = 359 | Setdomainname = 360 | Setfsgid = 361 | Setfsgid32 = 362 @@ -401,124 +401,130 @@ type LinuxSyscall = | Sethae = 369 | Sethostname = 370 | Setitimer = 371 - | Setns = 372 - | Setpgid = 373 - | Setpgrp = 374 - | Setpriority = 375 - | Setregid = 376 - | Setregid32 = 377 - | Setresgid = 378 - | Setresgid32 = 379 - | Setresuid = 380 - | Setresuid32 = 381 - | Setreuid = 382 - | Setreuid32 = 383 - | Setrlimit = 384 - | Setsid = 385 - | Setsockopt = 386 - | Settimeofday = 387 - | Setuid = 388 - | Setuid32 = 389 - | Setup = 390 - | Setxattr = 391 - | Sgetmask = 392 - | Shmat = 393 - | Shmctl = 394 - | Shmdt = 395 - | Shmget = 396 - | Shutdown = 397 - | Sigaction = 398 - | Sigaltstack = 399 - | Signal = 400 - | Signalfd = 401 - | Signalfd4 = 402 - | Sigpending = 403 - | Sigprocmask = 404 - | Sigreturn = 405 - | Sigsuspend = 406 - | Socket = 407 - | Socketcall = 408 - | Socketpair = 409 - | Spill = 410 - | Splice = 411 - | SpuCreate = 412 - | SpuRun = 413 - | SramAlloc = 414 - | SramFree = 415 - | Ssetmask = 416 - | Stat = 417 - | Stat64 = 418 - | Statfs = 419 - | Statfs64 = 420 - | Statx = 421 - | Stime = 422 - | SubpageProt = 423 - | SwitchEndian = 424 - | Swapcontext = 425 - | Swapoff = 426 - | Swapon = 427 - | Symlink = 428 - | Symlinkat = 429 - | Sync = 430 - | SyncFileRange = 431 - | SyncFileRange2 = 432 - | Syncfs = 433 - | SysDebugSetcontext = 434 - | Syscall = 435 - | Sysctl = 436 - | Sysfs = 437 - | Sysinfo = 438 - | Syslog = 439 - | Sysmips = 440 - | Tee = 441 - | Tgkill = 442 - | Time = 443 - | TimerCreate = 444 - | TimerDelete = 445 - | TimerGetoverrun = 446 - | TimerGettime = 447 - | TimerGettime64 = 448 - | TimerSettime = 449 - | TimerSettime64 = 450 - | TimerfdCreate = 451 - | TimerfdGettime = 452 - | TimerfdGettime64 = 453 - | TimerfdSettime = 454 - | TimerfdSettime64 = 455 - | Times = 456 - | Tkill = 457 - | Truncate = 458 - | Truncate64 = 459 - | Ugetrlimit = 460 - | Umask = 461 - | Umount = 462 - | Umount2 = 463 - | Uname = 464 - | Unlink = 465 - | Unlinkat = 466 - | Unshare = 467 - | Uselib = 468 - | Ustat = 469 - | Userfaultfd = 470 - | Usr26 = 471 - | Usr32 = 472 - | Utime = 473 - | Utimensat = 474 - | Utimensat64 = 475 - | Utimes = 476 - | UtrapInstall = 477 - | Vfork = 478 - | Vhangup = 479 - | Vm86old = 480 - | Vm86 = 481 - | Vmsplice = 482 - | Vserver = 483 - | Wait4 = 484 - | Waitid = 485 - | Waitpid = 486 - | Write = 487 - | Writev = 488 - | Xtensa = 489 + | SetMempolicy = 372 + | Setns = 373 + | Setpgid = 374 + | Setpgrp = 375 + | Setpriority = 376 + | Setregid = 377 + | Setregid32 = 378 + | Setresgid = 379 + | Setresgid32 = 380 + | Setresuid = 381 + | Setresuid32 = 382 + | Setreuid = 383 + | Setreuid32 = 384 + | Setrlimit = 385 + | SetRobustList = 386 + | Setsid = 387 + | Setsockopt = 388 + | SetThreadArea = 389 + | SetTidAddress = 390 + | Settimeofday = 391 + | SetTLS = 392 + | Setuid = 393 + | Setuid32 = 394 + | Setup = 395 + | Setxattr = 396 + | Sgetmask = 397 + | Shmat = 398 + | Shmctl = 399 + | Shmdt = 400 + | Shmget = 401 + | Shutdown = 402 + | Sigaction = 403 + | Sigaltstack = 404 + | Signal = 405 + | Signalfd = 406 + | Signalfd4 = 407 + | Sigpending = 408 + | Sigprocmask = 409 + | Sigreturn = 410 + | Sigsuspend = 411 + | Socket = 412 + | Socketcall = 413 + | Socketpair = 414 + | Spill = 415 + | Splice = 416 + | SpuCreate = 417 + | SpuRun = 418 + | SramAlloc = 419 + | SramFree = 420 + | Ssetmask = 421 + | Stat = 422 + | Stat64 = 423 + | Statfs = 424 + | Statfs64 = 425 + | Statx = 426 + | Stime = 427 + | SubpageProt = 428 + | Swapcontext = 429 + | Swapoff = 430 + | Swapon = 431 + | SwitchEndian = 432 + | Symlink = 433 + | Symlinkat = 434 + | Sync = 435 + | SyncFileRange = 436 + | SyncFileRange2 = 437 + | Syncfs = 438 + | Syscall = 439 + | Sysctl = 440 + | SysDebugSetcontext = 441 + | Sysfs = 442 + | Sysinfo = 443 + | Syslog = 444 + | Sysmips = 445 + | Tee = 446 + | Tgkill = 447 + | Time = 448 + | TimerCreate = 449 + | TimerDelete = 450 + | Timerfd = 451 + | TimerfdCreate = 452 + | TimerfdGettime = 453 + | TimerfdGettime64 = 454 + | TimerfdSettime = 455 + | TimerfdSettime64 = 456 + | TimerGetoverrun = 457 + | TimerGettime = 458 + | TimerGettime64 = 459 + | TimerSettime = 460 + | TimerSettime64 = 461 + | Times = 462 + | Tkill = 463 + | Truncate = 464 + | Truncate64 = 465 + | Ugetrlimit = 466 + | Umask = 467 + | Umount = 468 + | Umount2 = 469 + | Uname = 470 + | Unlink = 471 + | Unlinkat = 472 + | Unshare = 473 + | Uselib = 474 + | Userfaultfd = 475 + | Usr26 = 476 + | Usr32 = 477 + | Ustat = 478 + | Utime = 479 + | Utimensat = 480 + | Utimensat64 = 481 + | Utimes = 482 + | UtrapInstall = 483 + | Vfork = 484 + | Vhangup = 485 + | Vm86 = 486 + | Vm86old = 487 + | Vmsplice = 488 + | Vserver = 489 + | Wait4 = 490 + | Waitid = 491 + | Waitpid = 492 + | Write = 493 + | Writev = 494 + | Xtensa = 495 [] module LinuxSyscall = @@ -1219,12 +1225,2121 @@ module LinuxSyscall = | LinuxSyscall.PkeyAlloc -> 330 | LinuxSyscall.PkeyFree -> 331 | LinuxSyscall.Statx -> 332 + | LinuxSyscall.IoPgetevents -> 333 + | LinuxSyscall.Rseq -> 334 | _ -> raise UnhandledSyscallException + let private getARMEABINumber = function + | LinuxSyscall.RestartSyscall -> 0 + | LinuxSyscall.Exit -> 1 + | LinuxSyscall.Fork -> 2 + | LinuxSyscall.Read -> 3 + | LinuxSyscall.Write -> 4 + | LinuxSyscall.Open -> 5 + | LinuxSyscall.Close -> 6 + | LinuxSyscall.Creat -> 8 + | LinuxSyscall.Link -> 9 + | LinuxSyscall.Unlink -> 10 + | LinuxSyscall.Execve -> 11 + | LinuxSyscall.Chdir -> 12 + | LinuxSyscall.Mknod -> 14 + | LinuxSyscall.Chmod -> 15 + | LinuxSyscall.Lchown -> 16 + | LinuxSyscall.Lseek -> 19 + | LinuxSyscall.Getpid -> 20 + | LinuxSyscall.Mount -> 21 + | LinuxSyscall.Setuid -> 23 + | LinuxSyscall.Getuid -> 24 + | LinuxSyscall.Ptrace -> 26 + | LinuxSyscall.Pause -> 29 + | LinuxSyscall.Access -> 33 + | LinuxSyscall.Nice -> 34 + | LinuxSyscall.Sync -> 36 + | LinuxSyscall.Kill -> 37 + | LinuxSyscall.Rename -> 38 + | LinuxSyscall.Mkdir -> 39 + | LinuxSyscall.Rmdir -> 40 + | LinuxSyscall.Dup -> 41 + | LinuxSyscall.Pipe -> 42 + | LinuxSyscall.Times -> 43 + | LinuxSyscall.Brk -> 45 + | LinuxSyscall.Setgid -> 46 + | LinuxSyscall.Getgid -> 47 + | LinuxSyscall.Geteuid -> 49 + | LinuxSyscall.Getegid -> 50 + | LinuxSyscall.Acct -> 51 + | LinuxSyscall.Umount2 -> 52 + | LinuxSyscall.Ioctl -> 54 + | LinuxSyscall.Fcntl -> 55 + | LinuxSyscall.Setpgid -> 57 + | LinuxSyscall.Umask -> 60 + | LinuxSyscall.Chroot -> 61 + | LinuxSyscall.Ustat -> 62 + | LinuxSyscall.Dup2 -> 63 + | LinuxSyscall.Getppid -> 64 + | LinuxSyscall.Getpgrp -> 65 + | LinuxSyscall.Setsid -> 66 + | LinuxSyscall.Sigaction -> 67 + | LinuxSyscall.Setreuid -> 70 + | LinuxSyscall.Setregid -> 71 + | LinuxSyscall.Sigsuspend -> 72 + | LinuxSyscall.Sigpending -> 73 + | LinuxSyscall.Sethostname -> 74 + | LinuxSyscall.Setrlimit -> 75 + | LinuxSyscall.Getrusage -> 77 + | LinuxSyscall.Gettimeofday -> 78 + | LinuxSyscall.Settimeofday -> 79 + | LinuxSyscall.Getgroups -> 80 + | LinuxSyscall.Setgroups -> 81 + | LinuxSyscall.Symlink -> 83 + | LinuxSyscall.Readlink -> 85 + | LinuxSyscall.Uselib -> 86 + | LinuxSyscall.Swapon -> 87 + | LinuxSyscall.Reboot -> 88 + | LinuxSyscall.Munmap -> 91 + | LinuxSyscall.Truncate -> 92 + | LinuxSyscall.Ftruncate -> 93 + | LinuxSyscall.Fchmod -> 94 + | LinuxSyscall.Fchown -> 95 + | LinuxSyscall.Getpriority -> 96 + | LinuxSyscall.Setpriority -> 97 + | LinuxSyscall.Statfs -> 99 + | LinuxSyscall.Fstatfs -> 100 + | LinuxSyscall.Syslog -> 103 + | LinuxSyscall.Setitimer -> 104 + | LinuxSyscall.Getitimer -> 105 + | LinuxSyscall.Stat -> 106 + | LinuxSyscall.Lstat -> 107 + | LinuxSyscall.Fstat -> 108 + | LinuxSyscall.Vhangup -> 111 + | LinuxSyscall.Wait4 -> 114 + | LinuxSyscall.Swapoff -> 115 + | LinuxSyscall.Sysinfo -> 116 + | LinuxSyscall.Fsync -> 118 + | LinuxSyscall.Sigreturn -> 119 + | LinuxSyscall.Clone -> 120 + | LinuxSyscall.Setdomainname -> 121 + | LinuxSyscall.Uname -> 122 + | LinuxSyscall.AdjTimex -> 124 + | LinuxSyscall.Mprotect -> 125 + | LinuxSyscall.Sigprocmask -> 126 + | LinuxSyscall.InitModule -> 128 + | LinuxSyscall.DeleteModule -> 129 + | LinuxSyscall.Quotactl -> 131 + | LinuxSyscall.Getpgid -> 132 + | LinuxSyscall.Fchdir -> 133 + | LinuxSyscall.Bdflush -> 134 + | LinuxSyscall.Sysfs -> 135 + | LinuxSyscall.Personality -> 136 + | LinuxSyscall.Setfsuid -> 138 + | LinuxSyscall.Setfsgid -> 139 + | LinuxSyscall.LLseek -> 140 + | LinuxSyscall.Getdents -> 141 + | LinuxSyscall.NewSelect -> 142 + | LinuxSyscall.Flock -> 143 + | LinuxSyscall.Msync -> 144 + | LinuxSyscall.Readv -> 145 + | LinuxSyscall.Writev -> 146 + | LinuxSyscall.Getsid -> 147 + | LinuxSyscall.Fdatasync -> 148 + | LinuxSyscall.Sysctl -> 149 + | LinuxSyscall.Mlock -> 150 + | LinuxSyscall.Munlock -> 151 + | LinuxSyscall.Mlockall -> 152 + | LinuxSyscall.Munlockall -> 153 + | LinuxSyscall.SchedSetparam -> 154 + | LinuxSyscall.SchedGetparam -> 155 + | LinuxSyscall.SchedSetscheduler -> 156 + | LinuxSyscall.SchedGetscheduler -> 157 + | LinuxSyscall.SchedYield -> 158 + | LinuxSyscall.SchedGetPriorityMax -> 159 + | LinuxSyscall.SchedGetPriorityMin -> 160 + | LinuxSyscall.SchedRrGetInterval -> 161 + | LinuxSyscall.Nanosleep -> 162 + | LinuxSyscall.Mremap -> 163 + | LinuxSyscall.Setresuid -> 164 + | LinuxSyscall.Getresuid -> 165 + | LinuxSyscall.Poll -> 168 + | LinuxSyscall.Nfsservctl -> 169 + | LinuxSyscall.Setresgid -> 170 + | LinuxSyscall.Getresgid -> 171 + | LinuxSyscall.Prctl -> 172 + | LinuxSyscall.RtSigreturn -> 173 + | LinuxSyscall.RtSigaction -> 174 + | LinuxSyscall.RtSigprocmask -> 175 + | LinuxSyscall.RtSigpending -> 176 + | LinuxSyscall.RtSigtimedwait -> 177 + | LinuxSyscall.RtSigqueueinfo -> 178 + | LinuxSyscall.RtSigsuspend -> 179 + | LinuxSyscall.Pread64 -> 180 + | LinuxSyscall.Pwrite64 -> 181 + | LinuxSyscall.Chown -> 182 + | LinuxSyscall.Getcwd -> 183 + | LinuxSyscall.CapGet -> 184 + | LinuxSyscall.CapSet -> 185 + | LinuxSyscall.Sigaltstack -> 186 + | LinuxSyscall.Sendfile -> 187 + | LinuxSyscall.Vfork -> 190 + | LinuxSyscall.Ugetrlimit -> 191 + | LinuxSyscall.Mmap2 -> 192 + | LinuxSyscall.Truncate64 -> 193 + | LinuxSyscall.Ftruncate64 -> 194 + | LinuxSyscall.Stat64 -> 195 + | LinuxSyscall.Lstat64 -> 196 + | LinuxSyscall.Fstat64 -> 197 + | LinuxSyscall.Lchown32 -> 198 + | LinuxSyscall.Getuid32 -> 199 + | LinuxSyscall.Getgid32 -> 200 + | LinuxSyscall.Geteuid32 -> 201 + | LinuxSyscall.Getegid32 -> 202 + | LinuxSyscall.Setreuid32 -> 203 + | LinuxSyscall.Setregid32 -> 204 + | LinuxSyscall.Getgroups32 -> 205 + | LinuxSyscall.Setgroups32 -> 206 + | LinuxSyscall.Fchown32 -> 207 + | LinuxSyscall.Setresuid32 -> 208 + | LinuxSyscall.Getresuid32 -> 209 + | LinuxSyscall.Setresgid32 -> 210 + | LinuxSyscall.Getresgid32 -> 211 + | LinuxSyscall.Chown32 -> 212 + | LinuxSyscall.Setuid32 -> 213 + | LinuxSyscall.Setgid32 -> 214 + | LinuxSyscall.Setfsuid32 -> 215 + | LinuxSyscall.Setfsgid32 -> 216 + | LinuxSyscall.Getdents64 -> 217 + | LinuxSyscall.PivotRoot -> 218 + | LinuxSyscall.Mincore -> 219 + | LinuxSyscall.Madvise -> 220 + | LinuxSyscall.Fcntl64 -> 221 + | LinuxSyscall.Gettid -> 224 + | LinuxSyscall.Readahead -> 225 + | LinuxSyscall.Setxattr -> 226 + | LinuxSyscall.Lsetxattr -> 227 + | LinuxSyscall.Fsetxattr -> 228 + | LinuxSyscall.Getxattr -> 229 + | LinuxSyscall.Lgetxattr -> 230 + | LinuxSyscall.Fgetxattr -> 231 + | LinuxSyscall.Listxattr -> 232 + | LinuxSyscall.Llistxattr -> 233 + | LinuxSyscall.Flistxattr -> 234 + | LinuxSyscall.Removexattr -> 235 + | LinuxSyscall.Lremovexattr -> 236 + | LinuxSyscall.Fremovexattr -> 237 + | LinuxSyscall.Tkill -> 238 + | LinuxSyscall.Sendfile64 -> 239 + | LinuxSyscall.Futex -> 240 + | LinuxSyscall.SchedSetaffinity -> 241 + | LinuxSyscall.SchedGetaffinity -> 242 + | LinuxSyscall.IoSetup -> 243 + | LinuxSyscall.IoDestroy -> 244 + | LinuxSyscall.IoGetevents -> 245 + | LinuxSyscall.IoSubmit -> 246 + | LinuxSyscall.IoCancel -> 247 + | LinuxSyscall.ExitGroup -> 248 + | LinuxSyscall.LookupDcookie -> 249 + | LinuxSyscall.EpollCreate -> 250 + | LinuxSyscall.EpollCtl -> 251 + | LinuxSyscall.EpollWait -> 252 + | LinuxSyscall.RemapFilePages -> 253 + | LinuxSyscall.SetTidAddress -> 256 + | LinuxSyscall.TimerCreate -> 257 + | LinuxSyscall.TimerSettime -> 258 + | LinuxSyscall.TimerGettime -> 259 + | LinuxSyscall.TimerGetoverrun -> 260 + | LinuxSyscall.TimerDelete -> 261 + | LinuxSyscall.ClockSettime -> 262 + | LinuxSyscall.ClockGettime -> 263 + | LinuxSyscall.ClockGetres -> 264 + | LinuxSyscall.ClockNanosleep -> 265 + | LinuxSyscall.Statfs64 -> 266 + | LinuxSyscall.Fstatfs64 -> 267 + | LinuxSyscall.Tgkill -> 268 + | LinuxSyscall.Utimes -> 269 + | LinuxSyscall.ArmFadvise64 -> 270 + | LinuxSyscall.PciconfigIobase -> 271 + | LinuxSyscall.PciconfigRead -> 272 + | LinuxSyscall.PciconfigWrite -> 273 + | LinuxSyscall.MqOpen -> 274 + | LinuxSyscall.MqUnlink -> 275 + | LinuxSyscall.MqTimedsend -> 276 + | LinuxSyscall.MqTimedreceive -> 277 + | LinuxSyscall.MqNotify -> 278 + | LinuxSyscall.MqGetsetattr -> 279 + | LinuxSyscall.Waitid -> 280 + | LinuxSyscall.Socket -> 281 + | LinuxSyscall.Bind -> 282 + | LinuxSyscall.Connect -> 283 + | LinuxSyscall.Listen -> 284 + | LinuxSyscall.Accept -> 285 + | LinuxSyscall.Getsockname -> 286 + | LinuxSyscall.Getpeername -> 287 + | LinuxSyscall.Socketpair -> 288 + | LinuxSyscall.Send -> 289 + | LinuxSyscall.Sendto -> 290 + | LinuxSyscall.Recv -> 291 + | LinuxSyscall.Recvfrom -> 292 + | LinuxSyscall.Shutdown -> 293 + | LinuxSyscall.Setsockopt -> 294 + | LinuxSyscall.Getsockopt -> 295 + | LinuxSyscall.Sendmsg -> 296 + | LinuxSyscall.Recvmsg -> 297 + | LinuxSyscall.Semop -> 298 + | LinuxSyscall.Semget -> 299 + | LinuxSyscall.Semctl -> 300 + | LinuxSyscall.Msgsnd -> 301 + | LinuxSyscall.Msgrcv -> 302 + | LinuxSyscall.Msgget -> 303 + | LinuxSyscall.Msgctl -> 304 + | LinuxSyscall.Shmat -> 305 + | LinuxSyscall.Shmdt -> 306 + | LinuxSyscall.Shmget -> 307 + | LinuxSyscall.Shmctl -> 308 + | LinuxSyscall.AddKey -> 309 + | LinuxSyscall.RequestKey -> 310 + | LinuxSyscall.Keyctl -> 311 + | LinuxSyscall.Semtimedop -> 312 + | LinuxSyscall.Vserver -> 313 + | LinuxSyscall.IoprioSet -> 314 + | LinuxSyscall.IoprioGet -> 315 + | LinuxSyscall.InotifyInit -> 316 + | LinuxSyscall.InotifyAddWatch -> 317 + | LinuxSyscall.InotifyRmWatch -> 318 + | LinuxSyscall.Mbind -> 319 + | LinuxSyscall.GetMempolicy -> 320 + | LinuxSyscall.SetMempolicy -> 321 + | LinuxSyscall.Openat -> 322 + | LinuxSyscall.Mkdirat -> 323 + | LinuxSyscall.Mknodat -> 324 + | LinuxSyscall.Fchownat -> 325 + | LinuxSyscall.Futimesat -> 326 + | LinuxSyscall.Fstatat64 -> 327 + | LinuxSyscall.Unlinkat -> 328 + | LinuxSyscall.Renameat -> 329 + | LinuxSyscall.Linkat -> 330 + | LinuxSyscall.Symlinkat -> 331 + | LinuxSyscall.Readlinkat -> 332 + | LinuxSyscall.Fchmodat -> 333 + | LinuxSyscall.Faccessat -> 334 + | LinuxSyscall.Pselect6 -> 335 + | LinuxSyscall.Ppoll -> 336 + | LinuxSyscall.Unshare -> 337 + | LinuxSyscall.SetRobustList -> 338 + | LinuxSyscall.GetRobustList -> 339 + | LinuxSyscall.Splice -> 340 + | LinuxSyscall.ArmSyncFileRange -> 341 + | LinuxSyscall.Tee -> 342 + | LinuxSyscall.Vmsplice -> 343 + | LinuxSyscall.MovePages -> 344 + | LinuxSyscall.Getcpu -> 345 + | LinuxSyscall.EpollPwait -> 346 + | LinuxSyscall.KexecLoad -> 347 + | LinuxSyscall.Utimensat -> 348 + | LinuxSyscall.Signalfd -> 349 + | LinuxSyscall.TimerfdCreate -> 350 + | LinuxSyscall.Eventfd -> 351 + | LinuxSyscall.Fallocate -> 352 + | LinuxSyscall.TimerfdSettime -> 353 + | LinuxSyscall.TimerfdGettime -> 354 + | LinuxSyscall.Signalfd4 -> 355 + | LinuxSyscall.Eventfd2 -> 356 + | LinuxSyscall.EpollCreate1 -> 357 + | LinuxSyscall.Dup3 -> 358 + | LinuxSyscall.Pipe2 -> 359 + | LinuxSyscall.InotifyInit1 -> 360 + | LinuxSyscall.Preadv -> 361 + | LinuxSyscall.Pwritev -> 362 + | LinuxSyscall.RtTgsigqueueinfo -> 363 + | LinuxSyscall.PerfEventOpen -> 364 + | LinuxSyscall.Recvmmsg -> 365 + | LinuxSyscall.Accept4 -> 366 + | LinuxSyscall.FanotifyInit -> 367 + | LinuxSyscall.FanotifyMark -> 368 + | LinuxSyscall.Prlimit64 -> 369 + | LinuxSyscall.NameToHandleAt -> 370 + | LinuxSyscall.OpenByHandleAt -> 371 + | LinuxSyscall.ClockAdjtime -> 372 + | LinuxSyscall.Syncfs -> 373 + | LinuxSyscall.Sendmmsg -> 374 + | LinuxSyscall.Setns -> 375 + | LinuxSyscall.ProcessVmReadv -> 376 + | LinuxSyscall.ProcessVmWritev -> 377 + | LinuxSyscall.Kcmp -> 378 + | LinuxSyscall.FinitModule -> 379 + | LinuxSyscall.SchedSetattr -> 380 + | LinuxSyscall.SchedGetattr -> 381 + | LinuxSyscall.Renameat2 -> 382 + | LinuxSyscall.Seccomp -> 383 + | LinuxSyscall.Getrandom -> 384 + | LinuxSyscall.MemfdCreate -> 385 + | LinuxSyscall.Bpf -> 386 + | LinuxSyscall.Execveat -> 387 + | LinuxSyscall.Userfaultfd -> 388 + | LinuxSyscall.Membarrier -> 389 + | LinuxSyscall.Mlock2 -> 390 + | LinuxSyscall.CopyFileRange -> 391 + | LinuxSyscall.Preadv2 -> 392 + | LinuxSyscall.Pwritev2 -> 393 + | LinuxSyscall.PkeyMprotect -> 394 + | LinuxSyscall.PkeyAlloc -> 395 + | LinuxSyscall.PkeyFree -> 396 + | LinuxSyscall.Statx -> 397 + | LinuxSyscall.Rseq -> 398 + | LinuxSyscall.IoPgetevents -> 399 + | LinuxSyscall.MigratePages -> 400 + | LinuxSyscall.KexecFileLoad -> 401 + | LinuxSyscall.ClockGettime64 -> 403 + | LinuxSyscall.ClockSettime64 -> 404 + | LinuxSyscall.ClockAdjtime64 -> 405 + | LinuxSyscall.TimerGettime64 -> 408 + | LinuxSyscall.TimerSettime64 -> 409 + | LinuxSyscall.TimerfdGettime64 -> 410 + | LinuxSyscall.TimerfdSettime64 -> 411 + | LinuxSyscall.SchedRrGetInterval64 -> 423 + | LinuxSyscall.PidfdSendSignal -> 424 + | LinuxSyscall.IoUringSetup -> 425 + | LinuxSyscall.IoUringEnter -> 426 + | LinuxSyscall.IoUringRegister -> 427 + | LinuxSyscall.OpenTree -> 428 + | LinuxSyscall.MoveMount -> 429 + | LinuxSyscall.Fsopen -> 430 + | LinuxSyscall.Fsconfig -> 431 + | LinuxSyscall.Fsmount -> 432 + | LinuxSyscall.Fspick -> 433 + | LinuxSyscall.PidfdOpen -> 434 + | LinuxSyscall.Clone3 -> 435 + | LinuxSyscall.Openat2 -> 437 + | LinuxSyscall.PidfdGetfd -> 438 + | LinuxSyscall.Breakpoint -> 0x0f0001 (* __ARM_NR_breakpoint *) + | LinuxSyscall.CacheFlush -> 0x0f0002 (* __ARM_NR_cacheflush *) + | LinuxSyscall.Usr26 -> 0x0f0003 (* __ARM_NR_usr26 *) + | LinuxSyscall.Usr32 -> 0x0f0004 (* __ARM_NR_usr32 *) + | LinuxSyscall.SetTLS -> 0x0f0005 (* __ARM_NR_set_tls *) + | LinuxSyscall.GetTLS -> 0x0f0006 (* __ARM_NR_get_tls *) + | _ -> raise UnhandledSyscallException + + let private getAARCH64Number = function + | LinuxSyscall.IoSetup -> 0 + | LinuxSyscall.IoDestroy -> 1 + | LinuxSyscall.IoSubmit -> 2 + | LinuxSyscall.IoCancel -> 3 + | LinuxSyscall.IoGetevents -> 4 + | LinuxSyscall.Setxattr -> 5 + | LinuxSyscall.Lsetxattr -> 6 + | LinuxSyscall.Fsetxattr -> 7 + | LinuxSyscall.Getxattr -> 8 + | LinuxSyscall.Lgetxattr -> 9 + | LinuxSyscall.Fgetxattr -> 10 + | LinuxSyscall.Listxattr -> 11 + | LinuxSyscall.Llistxattr -> 12 + | LinuxSyscall.Flistxattr -> 13 + | LinuxSyscall.Removexattr -> 14 + | LinuxSyscall.Lremovexattr -> 15 + | LinuxSyscall.Fremovexattr -> 16 + | LinuxSyscall.Getcwd -> 17 + | LinuxSyscall.LookupDcookie -> 18 + | LinuxSyscall.Eventfd2 -> 19 + | LinuxSyscall.EpollCreate1 -> 20 + | LinuxSyscall.EpollCtl -> 21 + | LinuxSyscall.EpollPwait -> 22 + | LinuxSyscall.Dup -> 23 + | LinuxSyscall.Dup3 -> 24 + | LinuxSyscall.Fcntl -> 25 + | LinuxSyscall.InotifyInit1 -> 26 + | LinuxSyscall.InotifyAddWatch -> 27 + | LinuxSyscall.InotifyRmWatch -> 28 + | LinuxSyscall.Ioctl -> 29 + | LinuxSyscall.IoprioSet -> 30 + | LinuxSyscall.IoprioGet -> 31 + | LinuxSyscall.Flock -> 32 + | LinuxSyscall.Mknodat -> 33 + | LinuxSyscall.Mkdirat -> 34 + | LinuxSyscall.Unlinkat -> 35 + | LinuxSyscall.Symlinkat -> 36 + | LinuxSyscall.Linkat -> 37 + | LinuxSyscall.Renameat -> 38 + | LinuxSyscall.Umount2 -> 39 + | LinuxSyscall.Mount -> 40 + | LinuxSyscall.PivotRoot -> 41 + | LinuxSyscall.Nfsservctl -> 42 + | LinuxSyscall.Statfs -> 43 + | LinuxSyscall.Fstatfs -> 44 + | LinuxSyscall.Truncate -> 45 + | LinuxSyscall.Ftruncate -> 46 + | LinuxSyscall.Fallocate -> 47 + | LinuxSyscall.Faccessat -> 48 + | LinuxSyscall.Chdir -> 49 + | LinuxSyscall.Fchdir -> 50 + | LinuxSyscall.Chroot -> 51 + | LinuxSyscall.Fchmod -> 52 + | LinuxSyscall.Fchmodat -> 53 + | LinuxSyscall.Fchownat -> 54 + | LinuxSyscall.Fchown -> 55 + | LinuxSyscall.Openat -> 56 + | LinuxSyscall.Close -> 57 + | LinuxSyscall.Vhangup -> 58 + | LinuxSyscall.Pipe2 -> 59 + | LinuxSyscall.Quotactl -> 60 + | LinuxSyscall.Getdents64 -> 61 + | LinuxSyscall.Lseek -> 62 + | LinuxSyscall.Read -> 63 + | LinuxSyscall.Write -> 64 + | LinuxSyscall.Readv -> 65 + | LinuxSyscall.Writev -> 66 + | LinuxSyscall.Pread64 -> 67 + | LinuxSyscall.Pwrite64 -> 68 + | LinuxSyscall.Preadv -> 69 + | LinuxSyscall.Pwritev -> 70 + | LinuxSyscall.Sendfile -> 71 + | LinuxSyscall.Pselect6 -> 72 + | LinuxSyscall.Ppoll -> 73 + | LinuxSyscall.Signalfd4 -> 74 + | LinuxSyscall.Vmsplice -> 75 + | LinuxSyscall.Splice -> 76 + | LinuxSyscall.Tee -> 77 + | LinuxSyscall.Readlinkat -> 78 + | LinuxSyscall.Newfstatat -> 79 + | LinuxSyscall.Fstat -> 80 + | LinuxSyscall.Sync -> 81 + | LinuxSyscall.Fsync -> 82 + | LinuxSyscall.Fdatasync -> 83 + | LinuxSyscall.SyncFileRange -> 84 + | LinuxSyscall.TimerfdCreate -> 85 + | LinuxSyscall.TimerfdSettime -> 86 + | LinuxSyscall.TimerfdGettime -> 87 + | LinuxSyscall.Utimensat -> 88 + | LinuxSyscall.Acct -> 89 + | LinuxSyscall.CapGet -> 90 + | LinuxSyscall.CapSet -> 91 + | LinuxSyscall.Personality -> 92 + | LinuxSyscall.Exit -> 93 + | LinuxSyscall.ExitGroup -> 94 + | LinuxSyscall.Waitid -> 95 + | LinuxSyscall.SetTidAddress -> 96 + | LinuxSyscall.Unshare -> 97 + | LinuxSyscall.Futex -> 98 + | LinuxSyscall.SetRobustList -> 99 + | LinuxSyscall.GetRobustList -> 100 + | LinuxSyscall.Nanosleep -> 101 + | LinuxSyscall.Getitimer -> 102 + | LinuxSyscall.Setitimer -> 103 + | LinuxSyscall.KexecLoad -> 104 + | LinuxSyscall.InitModule -> 105 + | LinuxSyscall.DeleteModule -> 106 + | LinuxSyscall.TimerCreate -> 107 + | LinuxSyscall.TimerGettime -> 108 + | LinuxSyscall.TimerGetoverrun -> 109 + | LinuxSyscall.TimerSettime -> 110 + | LinuxSyscall.TimerDelete -> 111 + | LinuxSyscall.ClockSettime -> 112 + | LinuxSyscall.ClockGettime -> 113 + | LinuxSyscall.ClockGetres -> 114 + | LinuxSyscall.ClockNanosleep -> 115 + | LinuxSyscall.Syslog -> 116 + | LinuxSyscall.Ptrace -> 117 + | LinuxSyscall.SchedSetparam -> 118 + | LinuxSyscall.SchedSetscheduler -> 119 + | LinuxSyscall.SchedGetscheduler -> 120 + | LinuxSyscall.SchedGetparam -> 121 + | LinuxSyscall.SchedSetaffinity -> 122 + | LinuxSyscall.SchedGetaffinity -> 123 + | LinuxSyscall.SchedYield -> 124 + | LinuxSyscall.SchedGetPriorityMax -> 125 + | LinuxSyscall.SchedGetPriorityMin -> 126 + | LinuxSyscall.SchedRrGetInterval -> 127 + | LinuxSyscall.RestartSyscall -> 128 + | LinuxSyscall.Kill -> 129 + | LinuxSyscall.Tkill -> 130 + | LinuxSyscall.Tgkill -> 131 + | LinuxSyscall.Sigaltstack -> 132 + | LinuxSyscall.RtSigsuspend -> 133 + | LinuxSyscall.RtSigaction -> 134 + | LinuxSyscall.RtSigprocmask -> 135 + | LinuxSyscall.RtSigpending -> 136 + | LinuxSyscall.RtSigtimedwait -> 137 + | LinuxSyscall.RtSigqueueinfo -> 138 + | LinuxSyscall.RtSigreturn -> 139 + | LinuxSyscall.Setpriority -> 140 + | LinuxSyscall.Getpriority -> 141 + | LinuxSyscall.Reboot -> 142 + | LinuxSyscall.Setregid -> 143 + | LinuxSyscall.Setgid -> 144 + | LinuxSyscall.Setreuid -> 145 + | LinuxSyscall.Setuid -> 146 + | LinuxSyscall.Setresuid -> 147 + | LinuxSyscall.Getresuid -> 148 + | LinuxSyscall.Setresgid -> 149 + | LinuxSyscall.Getresgid -> 150 + | LinuxSyscall.Setfsuid -> 151 + | LinuxSyscall.Setfsgid -> 152 + | LinuxSyscall.Times -> 153 + | LinuxSyscall.Setpgid -> 154 + | LinuxSyscall.Getpgid -> 155 + | LinuxSyscall.Getsid -> 156 + | LinuxSyscall.Setsid -> 157 + | LinuxSyscall.Getgroups -> 158 + | LinuxSyscall.Setgroups -> 159 + | LinuxSyscall.Uname -> 160 + | LinuxSyscall.Sethostname -> 161 + | LinuxSyscall.Setdomainname -> 162 + | LinuxSyscall.Getrlimit -> 163 + | LinuxSyscall.Setrlimit -> 164 + | LinuxSyscall.Getrusage -> 165 + | LinuxSyscall.Umask -> 166 + | LinuxSyscall.Prctl -> 167 + | LinuxSyscall.Getcpu -> 168 + | LinuxSyscall.Gettimeofday -> 169 + | LinuxSyscall.Settimeofday -> 170 + | LinuxSyscall.AdjTimex -> 171 + | LinuxSyscall.Getpid -> 172 + | LinuxSyscall.Getppid -> 173 + | LinuxSyscall.Getuid -> 174 + | LinuxSyscall.Geteuid -> 175 + | LinuxSyscall.Getgid -> 176 + | LinuxSyscall.Getegid -> 177 + | LinuxSyscall.Gettid -> 178 + | LinuxSyscall.Sysinfo -> 179 + | LinuxSyscall.MqOpen -> 180 + | LinuxSyscall.MqUnlink -> 181 + | LinuxSyscall.MqTimedsend -> 182 + | LinuxSyscall.MqTimedreceive -> 183 + | LinuxSyscall.MqNotify -> 184 + | LinuxSyscall.MqGetsetattr -> 185 + | LinuxSyscall.Msgget -> 186 + | LinuxSyscall.Msgctl -> 187 + | LinuxSyscall.Msgrcv -> 188 + | LinuxSyscall.Msgsnd -> 189 + | LinuxSyscall.Semget -> 190 + | LinuxSyscall.Semctl -> 191 + | LinuxSyscall.Semtimedop -> 192 + | LinuxSyscall.Semop -> 193 + | LinuxSyscall.Shmget -> 194 + | LinuxSyscall.Shmctl -> 195 + | LinuxSyscall.Shmat -> 196 + | LinuxSyscall.Shmdt -> 197 + | LinuxSyscall.Socket -> 198 + | LinuxSyscall.Socketpair -> 199 + | LinuxSyscall.Bind -> 200 + | LinuxSyscall.Listen -> 201 + | LinuxSyscall.Accept -> 202 + | LinuxSyscall.Connect -> 203 + | LinuxSyscall.Getsockname -> 204 + | LinuxSyscall.Getpeername -> 205 + | LinuxSyscall.Sendto -> 206 + | LinuxSyscall.Recvfrom -> 207 + | LinuxSyscall.Setsockopt -> 208 + | LinuxSyscall.Getsockopt -> 209 + | LinuxSyscall.Shutdown -> 210 + | LinuxSyscall.Sendmsg -> 211 + | LinuxSyscall.Recvmsg -> 212 + | LinuxSyscall.Readahead -> 213 + | LinuxSyscall.Brk -> 214 + | LinuxSyscall.Munmap -> 215 + | LinuxSyscall.Mremap -> 216 + | LinuxSyscall.AddKey -> 217 + | LinuxSyscall.RequestKey -> 218 + | LinuxSyscall.Keyctl -> 219 + | LinuxSyscall.Clone -> 220 + | LinuxSyscall.Execve -> 221 + | LinuxSyscall.Mmap -> 222 + | LinuxSyscall.Fadvise64 -> 223 + | LinuxSyscall.Swapon -> 224 + | LinuxSyscall.Swapoff -> 225 + | LinuxSyscall.Mprotect -> 226 + | LinuxSyscall.Msync -> 227 + | LinuxSyscall.Mlock -> 228 + | LinuxSyscall.Munlock -> 229 + | LinuxSyscall.Mlockall -> 230 + | LinuxSyscall.Munlockall -> 231 + | LinuxSyscall.Mincore -> 232 + | LinuxSyscall.Madvise -> 233 + | LinuxSyscall.RemapFilePages -> 234 + | LinuxSyscall.Mbind -> 235 + | LinuxSyscall.GetMempolicy -> 236 + | LinuxSyscall.SetMempolicy -> 237 + | LinuxSyscall.MigratePages -> 238 + | LinuxSyscall.MovePages -> 239 + | LinuxSyscall.RtTgsigqueueinfo -> 240 + | LinuxSyscall.PerfEventOpen -> 241 + | LinuxSyscall.Accept4 -> 242 + | LinuxSyscall.Recvmmsg -> 243 + | LinuxSyscall.Wait4 -> 260 + | LinuxSyscall.Prlimit64 -> 261 + | LinuxSyscall.FanotifyInit -> 262 + | LinuxSyscall.FanotifyMark -> 263 + | LinuxSyscall.NameToHandleAt -> 264 + | LinuxSyscall.OpenByHandleAt -> 265 + | LinuxSyscall.ClockAdjtime -> 266 + | LinuxSyscall.Syncfs -> 267 + | LinuxSyscall.Setns -> 268 + | LinuxSyscall.Sendmmsg -> 269 + | LinuxSyscall.ProcessVmReadv -> 270 + | LinuxSyscall.ProcessVmWritev -> 271 + | LinuxSyscall.Kcmp -> 272 + | LinuxSyscall.FinitModule -> 273 + | LinuxSyscall.SchedSetattr -> 274 + | LinuxSyscall.SchedGetattr -> 275 + | LinuxSyscall.Renameat2 -> 276 + | LinuxSyscall.Seccomp -> 277 + | LinuxSyscall.Getrandom -> 278 + | LinuxSyscall.MemfdCreate -> 279 + | LinuxSyscall.Bpf -> 280 + | LinuxSyscall.Execveat -> 281 + | LinuxSyscall.Userfaultfd -> 282 + | LinuxSyscall.Membarrier -> 283 + | LinuxSyscall.Mlock2 -> 284 + | LinuxSyscall.CopyFileRange -> 285 + | LinuxSyscall.Preadv2 -> 286 + | LinuxSyscall.Pwritev2 -> 287 + | LinuxSyscall.PkeyMprotect -> 288 + | LinuxSyscall.PkeyAlloc -> 289 + | LinuxSyscall.PkeyFree -> 290 + | LinuxSyscall.Statx -> 291 + | LinuxSyscall.IoPgetevents -> 292 + | LinuxSyscall.Rseq -> 293 + | LinuxSyscall.KexecFileLoad -> 294 + | LinuxSyscall.ClockGettime64 -> 403 + | LinuxSyscall.ClockSettime64 -> 404 + | LinuxSyscall.ClockAdjtime64 -> 405 + | LinuxSyscall.ClockGetres64 -> 406 + | LinuxSyscall.ClockNanosleep64 -> 407 + | LinuxSyscall.TimerGettime64 -> 408 + | LinuxSyscall.TimerSettime64 -> 409 + | LinuxSyscall.TimerfdGettime64 -> 410 + | LinuxSyscall.TimerfdSettime64 -> 411 + | LinuxSyscall.Utimensat64 -> 412 + | LinuxSyscall.Pselect6_64 -> 413 + | LinuxSyscall.Ppoll64 -> 414 + | LinuxSyscall.IoPgetevents64 -> 416 + | LinuxSyscall.Recvmmsg64 -> 417 + | LinuxSyscall.MqTimedsend64 -> 418 + | LinuxSyscall.MqTimedreceive64 -> 419 + | LinuxSyscall.Semtimedop64 -> 420 + | LinuxSyscall.RtSigtimedwait64 -> 421 + | LinuxSyscall.Futex64 -> 422 + | LinuxSyscall.SchedRrGetInterval64 -> 423 + | LinuxSyscall.PidfdSendSignal -> 424 + | LinuxSyscall.IoUringSetup -> 425 + | LinuxSyscall.IoUringEnter -> 426 + | LinuxSyscall.IoUringRegister -> 427 + | LinuxSyscall.OpenTree -> 428 + | LinuxSyscall.MoveMount -> 429 + | LinuxSyscall.Fsopen -> 430 + | LinuxSyscall.Fsconfig -> 431 + | LinuxSyscall.Fsmount -> 432 + | LinuxSyscall.Fspick -> 433 + | LinuxSyscall.PidfdOpen -> 434 + | LinuxSyscall.Clone3 -> 435 + | LinuxSyscall.Openat2 -> 437 + | LinuxSyscall.PidfdGetfd -> 438 + | _ -> raise UnhandledSyscallException + + let private getMIPSO32Number = function + | LinuxSyscall.Exit -> 4001 + | LinuxSyscall.Fork -> 4002 + | LinuxSyscall.Read -> 4003 + | LinuxSyscall.Write -> 4004 + | LinuxSyscall.Open -> 4005 + | LinuxSyscall.Close -> 4006 + | LinuxSyscall.Waitpid -> 4007 + | LinuxSyscall.Creat -> 4008 + | LinuxSyscall.Link -> 4009 + | LinuxSyscall.Unlink -> 4010 + | LinuxSyscall.Execve -> 4011 + | LinuxSyscall.Chdir -> 4012 + | LinuxSyscall.Time -> 4013 + | LinuxSyscall.Mknod -> 4014 + | LinuxSyscall.Chmod -> 4015 + | LinuxSyscall.Lchown -> 4016 + | LinuxSyscall.Breakpoint -> 4017 + | LinuxSyscall.Lseek -> 4019 + | LinuxSyscall.Getpid -> 4020 + | LinuxSyscall.Mount -> 4021 + | LinuxSyscall.Umount -> 4022 + | LinuxSyscall.Setuid -> 4023 + | LinuxSyscall.Getuid -> 4024 + | LinuxSyscall.Stime -> 4025 + | LinuxSyscall.Ptrace -> 4026 + | LinuxSyscall.Alarm -> 4027 + | LinuxSyscall.Pause -> 4029 + | LinuxSyscall.Utime -> 4030 + | LinuxSyscall.Access -> 4033 + | LinuxSyscall.Nice -> 4034 + | LinuxSyscall.Sync -> 4036 + | LinuxSyscall.Kill -> 4037 + | LinuxSyscall.Rename -> 4038 + | LinuxSyscall.Mkdir -> 4039 + | LinuxSyscall.Rmdir -> 4040 + | LinuxSyscall.Dup -> 4041 + | LinuxSyscall.Pipe -> 4042 + | LinuxSyscall.Times -> 4043 + | LinuxSyscall.Brk -> 4045 + | LinuxSyscall.Setgid -> 4046 + | LinuxSyscall.Getgid -> 4047 + | LinuxSyscall.Signal -> 4048 + | LinuxSyscall.Geteuid -> 4049 + | LinuxSyscall.Getegid -> 4050 + | LinuxSyscall.Acct -> 4051 + | LinuxSyscall.Umount2 -> 4052 + | LinuxSyscall.Ioctl -> 4054 + | LinuxSyscall.Fcntl -> 4055 + | LinuxSyscall.Setpgid -> 4057 + | LinuxSyscall.Umask -> 4060 + | LinuxSyscall.Chroot -> 4061 + | LinuxSyscall.Ustat -> 4062 + | LinuxSyscall.Dup2 -> 4063 + | LinuxSyscall.Getppid -> 4064 + | LinuxSyscall.Getpgrp -> 4065 + | LinuxSyscall.Setsid -> 4066 + | LinuxSyscall.Sigaction -> 4067 + | LinuxSyscall.Sgetmask -> 4068 + | LinuxSyscall.Ssetmask -> 4069 + | LinuxSyscall.Setreuid -> 4070 + | LinuxSyscall.Setregid -> 4071 + | LinuxSyscall.Sigsuspend -> 4072 + | LinuxSyscall.Sigpending -> 4073 + | LinuxSyscall.Sethostname -> 4074 + | LinuxSyscall.Setrlimit -> 4075 + | LinuxSyscall.Getrlimit -> 4076 + | LinuxSyscall.Getrusage -> 4077 + | LinuxSyscall.Gettimeofday -> 4078 + | LinuxSyscall.Settimeofday -> 4079 + | LinuxSyscall.Getgroups -> 4080 + | LinuxSyscall.Setgroups -> 4081 + | LinuxSyscall.Symlink -> 4083 + | LinuxSyscall.Readlink -> 4085 + | LinuxSyscall.Uselib -> 4086 + | LinuxSyscall.Swapon -> 4087 + | LinuxSyscall.Reboot -> 4088 + | LinuxSyscall.Readdir -> 4089 + | LinuxSyscall.Mmap -> 4090 + | LinuxSyscall.Munmap -> 4091 + | LinuxSyscall.Truncate -> 4092 + | LinuxSyscall.Ftruncate -> 4093 + | LinuxSyscall.Fchmod -> 4094 + | LinuxSyscall.Fchown -> 4095 + | LinuxSyscall.Getpriority -> 4096 + | LinuxSyscall.Setpriority -> 4097 + | LinuxSyscall.Statfs -> 4099 + | LinuxSyscall.Fstatfs -> 4100 + | LinuxSyscall.Ioperm -> 4101 + | LinuxSyscall.Socketcall -> 4102 + | LinuxSyscall.Syslog -> 4103 + | LinuxSyscall.Setitimer -> 4104 + | LinuxSyscall.Getitimer -> 4105 + | LinuxSyscall.Stat -> 4106 + | LinuxSyscall.Lstat -> 4107 + | LinuxSyscall.Fstat -> 4108 + | LinuxSyscall.Iopl -> 4110 + | LinuxSyscall.Vhangup -> 4111 + | LinuxSyscall.Vm86 -> 4113 + | LinuxSyscall.Wait4 -> 4114 + | LinuxSyscall.Swapoff -> 4115 + | LinuxSyscall.Sysinfo -> 4116 + | LinuxSyscall.Ipc -> 4117 + | LinuxSyscall.Fsync -> 4118 + | LinuxSyscall.Sigreturn -> 4119 + | LinuxSyscall.Clone -> 4120 + | LinuxSyscall.Setdomainname -> 4121 + | LinuxSyscall.Uname -> 4122 + | LinuxSyscall.ModifyLdt -> 4123 + | LinuxSyscall.OldAdjtimex -> 4124 + | LinuxSyscall.Mprotect -> 4125 + | LinuxSyscall.Sigprocmask -> 4126 + | LinuxSyscall.CreateModule -> 4127 + | LinuxSyscall.InitModule -> 4128 + | LinuxSyscall.DeleteModule -> 4129 + | LinuxSyscall.GetKernelSyms -> 4130 + | LinuxSyscall.Quotactl -> 4131 + | LinuxSyscall.Getpgid -> 4132 + | LinuxSyscall.Fchdir -> 4133 + | LinuxSyscall.Bdflush -> 4134 + | LinuxSyscall.Sysfs -> 4135 + | LinuxSyscall.Personality -> 4136 + | LinuxSyscall.Setfsuid -> 4138 + | LinuxSyscall.Setfsgid -> 4139 + | LinuxSyscall.LLseek -> 4140 + | LinuxSyscall.Getdents -> 4141 + | LinuxSyscall.NewSelect -> 4142 + | LinuxSyscall.Flock -> 4143 + | LinuxSyscall.Msync -> 4144 + | LinuxSyscall.Readv -> 4145 + | LinuxSyscall.Writev -> 4146 + | LinuxSyscall.CacheFlush -> 4147 + | LinuxSyscall.Sysmips -> 4149 + | LinuxSyscall.Getsid -> 4151 + | LinuxSyscall.Fdatasync -> 4152 + | LinuxSyscall.Mlock -> 4154 + | LinuxSyscall.Munlock -> 4155 + | LinuxSyscall.Mlockall -> 4156 + | LinuxSyscall.Munlockall -> 4157 + | LinuxSyscall.SchedSetparam -> 4158 + | LinuxSyscall.SchedGetparam -> 4159 + | LinuxSyscall.SchedSetscheduler -> 4160 + | LinuxSyscall.SchedGetscheduler -> 4161 + | LinuxSyscall.SchedYield -> 4162 + | LinuxSyscall.SchedGetPriorityMax -> 4163 + | LinuxSyscall.SchedGetPriorityMin -> 4164 + | LinuxSyscall.SchedRrGetInterval -> 4165 + | LinuxSyscall.Nanosleep -> 4166 + | LinuxSyscall.Mremap -> 4167 + | LinuxSyscall.Accept -> 4168 + | LinuxSyscall.Bind -> 4169 + | LinuxSyscall.Connect -> 4170 + | LinuxSyscall.Getpeername -> 4171 + | LinuxSyscall.Getsockname -> 4172 + | LinuxSyscall.Getsockopt -> 4173 + | LinuxSyscall.Listen -> 4174 + | LinuxSyscall.Recv -> 4175 + | LinuxSyscall.Recvfrom -> 4176 + | LinuxSyscall.Recvmsg -> 4177 + | LinuxSyscall.Send -> 4178 + | LinuxSyscall.Sendmsg -> 4179 + | LinuxSyscall.Sendto -> 4180 + | LinuxSyscall.Setsockopt -> 4181 + | LinuxSyscall.Shutdown -> 4182 + | LinuxSyscall.Socket -> 4183 + | LinuxSyscall.Socketpair -> 4184 + | LinuxSyscall.Setresuid -> 4185 + | LinuxSyscall.Getresuid -> 4186 + | LinuxSyscall.QueryModule -> 4187 + | LinuxSyscall.Poll -> 4188 + | LinuxSyscall.Nfsservctl -> 4189 + | LinuxSyscall.Setresgid -> 4190 + | LinuxSyscall.Getresgid -> 4191 + | LinuxSyscall.Prctl -> 4192 + | LinuxSyscall.RtSigreturn -> 4193 + | LinuxSyscall.RtSigaction -> 4194 + | LinuxSyscall.RtSigprocmask -> 4195 + | LinuxSyscall.RtSigpending -> 4196 + | LinuxSyscall.RtSigtimedwait -> 4197 + | LinuxSyscall.RtSigqueueinfo -> 4198 + | LinuxSyscall.RtSigsuspend -> 4199 + | LinuxSyscall.Pread64 -> 4200 + | LinuxSyscall.Pwrite64 -> 4201 + | LinuxSyscall.Chown -> 4202 + | LinuxSyscall.Getcwd -> 4203 + | LinuxSyscall.CapGet -> 4204 + | LinuxSyscall.CapSet -> 4205 + | LinuxSyscall.Sigaltstack -> 4206 + | LinuxSyscall.Sendfile -> 4207 + | LinuxSyscall.Mmap2 -> 4210 + | LinuxSyscall.Truncate64 -> 4211 + | LinuxSyscall.Ftruncate64 -> 4212 + | LinuxSyscall.Stat64 -> 4213 + | LinuxSyscall.Lstat64 -> 4214 + | LinuxSyscall.Fstat64 -> 4215 + | LinuxSyscall.PivotRoot -> 4216 + | LinuxSyscall.Mincore -> 4217 + | LinuxSyscall.Madvise -> 4218 + | LinuxSyscall.Getdents64 -> 4219 + | LinuxSyscall.Fcntl64 -> 4220 + | LinuxSyscall.Gettid -> 4222 + | LinuxSyscall.Readahead -> 4223 + | LinuxSyscall.Setxattr -> 4224 + | LinuxSyscall.Lsetxattr -> 4225 + | LinuxSyscall.Fsetxattr -> 4226 + | LinuxSyscall.Getxattr -> 4227 + | LinuxSyscall.Lgetxattr -> 4228 + | LinuxSyscall.Fgetxattr -> 4229 + | LinuxSyscall.Listxattr -> 4230 + | LinuxSyscall.Llistxattr -> 4231 + | LinuxSyscall.Flistxattr -> 4232 + | LinuxSyscall.Removexattr -> 4233 + | LinuxSyscall.Lremovexattr -> 4234 + | LinuxSyscall.Fremovexattr -> 4235 + | LinuxSyscall.Tkill -> 4236 + | LinuxSyscall.Sendfile64 -> 4237 + | LinuxSyscall.Futex -> 4238 + | LinuxSyscall.SchedSetaffinity -> 4239 + | LinuxSyscall.SchedGetaffinity -> 4240 + | LinuxSyscall.IoSetup -> 4241 + | LinuxSyscall.IoDestroy -> 4242 + | LinuxSyscall.IoGetevents -> 4243 + | LinuxSyscall.IoSubmit -> 4244 + | LinuxSyscall.IoCancel -> 4245 + | LinuxSyscall.ExitGroup -> 4246 + | LinuxSyscall.LookupDcookie -> 4247 + | LinuxSyscall.EpollCreate -> 4248 + | LinuxSyscall.EpollCtl -> 4249 + | LinuxSyscall.EpollWait -> 4250 + | LinuxSyscall.RemapFilePages -> 4251 + | LinuxSyscall.SetTidAddress -> 4252 + | LinuxSyscall.RestartSyscall -> 4253 + | LinuxSyscall.Fadvise64 -> 4254 + | LinuxSyscall.Statfs64 -> 4255 + | LinuxSyscall.Fstatfs64 -> 4256 + | LinuxSyscall.TimerCreate -> 4257 + | LinuxSyscall.TimerSettime -> 4258 + | LinuxSyscall.TimerGettime -> 4259 + | LinuxSyscall.TimerGetoverrun -> 4260 + | LinuxSyscall.TimerDelete -> 4261 + | LinuxSyscall.ClockSettime -> 4262 + | LinuxSyscall.ClockGettime -> 4263 + | LinuxSyscall.ClockGetres -> 4264 + | LinuxSyscall.ClockNanosleep -> 4265 + | LinuxSyscall.Tgkill -> 4266 + | LinuxSyscall.Utimes -> 4267 + | LinuxSyscall.Mbind -> 4268 + | LinuxSyscall.GetMempolicy -> 4269 + | LinuxSyscall.SetMempolicy -> 4270 + | LinuxSyscall.MqOpen -> 4271 + | LinuxSyscall.MqUnlink -> 4272 + | LinuxSyscall.MqTimedsend -> 4273 + | LinuxSyscall.MqTimedreceive -> 4274 + | LinuxSyscall.MqNotify -> 4275 + | LinuxSyscall.MqGetsetattr -> 4276 + | LinuxSyscall.Vserver -> 4277 + | LinuxSyscall.Waitid -> 4278 + | LinuxSyscall.AddKey -> 4280 + | LinuxSyscall.RequestKey -> 4281 + | LinuxSyscall.Keyctl -> 4282 + | LinuxSyscall.SetThreadArea -> 4283 + | LinuxSyscall.InotifyInit -> 4284 + | LinuxSyscall.InotifyAddWatch -> 4285 + | LinuxSyscall.InotifyRmWatch -> 4286 + | LinuxSyscall.MigratePages -> 4287 + | LinuxSyscall.Openat -> 4288 + | LinuxSyscall.Mkdirat -> 4289 + | LinuxSyscall.Mknodat -> 4290 + | LinuxSyscall.Fchownat -> 4291 + | LinuxSyscall.Futimesat -> 4292 + | LinuxSyscall.Fstatat64 -> 4293 + | LinuxSyscall.Unlinkat -> 4294 + | LinuxSyscall.Renameat -> 4295 + | LinuxSyscall.Linkat -> 4296 + | LinuxSyscall.Symlinkat -> 4297 + | LinuxSyscall.Readlinkat -> 4298 + | LinuxSyscall.Fchmodat -> 4299 + | LinuxSyscall.Faccessat -> 4300 + | LinuxSyscall.Pselect6 -> 4301 + | LinuxSyscall.Ppoll -> 4302 + | LinuxSyscall.Unshare -> 4303 + | LinuxSyscall.Splice -> 4304 + | LinuxSyscall.SyncFileRange -> 4305 + | LinuxSyscall.Tee -> 4306 + | LinuxSyscall.Vmsplice -> 4307 + | LinuxSyscall.MovePages -> 4308 + | LinuxSyscall.SetRobustList -> 4309 + | LinuxSyscall.GetRobustList -> 4310 + | LinuxSyscall.KexecLoad -> 4311 + | LinuxSyscall.Getcpu -> 4312 + | LinuxSyscall.EpollPwait -> 4313 + | LinuxSyscall.IoprioSet -> 4314 + | LinuxSyscall.IoprioGet -> 4315 + | LinuxSyscall.Utimensat -> 4316 + | LinuxSyscall.Signalfd -> 4317 + | LinuxSyscall.Eventfd -> 4319 + | LinuxSyscall.Fallocate -> 4320 + | LinuxSyscall.TimerfdCreate -> 4321 + | LinuxSyscall.TimerfdGettime -> 4322 + | LinuxSyscall.TimerfdSettime -> 4323 + | LinuxSyscall.Signalfd4 -> 4324 + | LinuxSyscall.Eventfd2 -> 4325 + | LinuxSyscall.EpollCreate1 -> 4326 + | LinuxSyscall.Dup3 -> 4327 + | LinuxSyscall.Pipe2 -> 4328 + | LinuxSyscall.InotifyInit1 -> 4329 + | LinuxSyscall.Preadv -> 4330 + | LinuxSyscall.Pwritev -> 4331 + | LinuxSyscall.RtTgsigqueueinfo -> 4332 + | LinuxSyscall.PerfEventOpen -> 4333 + | LinuxSyscall.Accept4 -> 4334 + | LinuxSyscall.Recvmmsg -> 4335 + | LinuxSyscall.FanotifyInit -> 4336 + | LinuxSyscall.FanotifyMark -> 4337 + | LinuxSyscall.Prlimit64 -> 4338 + | LinuxSyscall.NameToHandleAt -> 4339 + | LinuxSyscall.OpenByHandleAt -> 4340 + | LinuxSyscall.ClockAdjtime -> 4341 + | LinuxSyscall.Syncfs -> 4342 + | LinuxSyscall.Sendmmsg -> 4343 + | LinuxSyscall.Setns -> 4344 + | LinuxSyscall.ProcessVmReadv -> 4345 + | LinuxSyscall.ProcessVmWritev -> 4346 + | LinuxSyscall.Kcmp -> 4347 + | LinuxSyscall.FinitModule -> 4348 + | LinuxSyscall.SchedSetattr -> 4349 + | LinuxSyscall.SchedGetattr -> 4350 + | LinuxSyscall.Renameat2 -> 4351 + | LinuxSyscall.Seccomp -> 4352 + | LinuxSyscall.Getrandom -> 4353 + | LinuxSyscall.MemfdCreate -> 4354 + | LinuxSyscall.Bpf -> 4355 + | LinuxSyscall.Execveat -> 4356 + | LinuxSyscall.Userfaultfd -> 4357 + | LinuxSyscall.Membarrier -> 4358 + | LinuxSyscall.Mlock2 -> 4359 + | LinuxSyscall.CopyFileRange -> 4360 + | LinuxSyscall.Preadv2 -> 4361 + | LinuxSyscall.Pwritev2 -> 4362 + | LinuxSyscall.PkeyMprotect -> 4363 + | LinuxSyscall.PkeyAlloc -> 4364 + | LinuxSyscall.PkeyFree -> 4365 + | LinuxSyscall.Statx -> 4366 + | LinuxSyscall.Rseq -> 4367 + | LinuxSyscall.IoPgetevents -> 4368 + | LinuxSyscall.Semget -> 4393 + | LinuxSyscall.Semctl -> 4394 + | LinuxSyscall.Shmget -> 4395 + | LinuxSyscall.Shmctl -> 4396 + | LinuxSyscall.Shmat -> 4397 + | LinuxSyscall.Shmdt -> 4398 + | LinuxSyscall.Msgget -> 4399 + | LinuxSyscall.Msgsnd -> 4400 + | LinuxSyscall.Msgrcv -> 4401 + | LinuxSyscall.Msgctl -> 4402 + | LinuxSyscall.ClockGettime64 -> 4403 + | LinuxSyscall.ClockSettime64 -> 4404 + | LinuxSyscall.ClockAdjtime64 -> 4405 + | LinuxSyscall.ClockGetres64 -> 4406 + | LinuxSyscall.ClockNanosleep64 -> 4407 + | LinuxSyscall.TimerGettime64 -> 4408 + | LinuxSyscall.TimerSettime64 -> 4409 + | LinuxSyscall.TimerfdGettime64 -> 4410 + | LinuxSyscall.TimerfdSettime64 -> 4411 + | LinuxSyscall.Utimensat64 -> 4412 + | LinuxSyscall.Pselect6_64 -> 4413 + | LinuxSyscall.Ppoll64 -> 4414 + | LinuxSyscall.IoPgetevents64 -> 4416 + | LinuxSyscall.Recvmmsg64 -> 4417 + | LinuxSyscall.MqTimedsend64 -> 4418 + | LinuxSyscall.MqTimedreceive64 -> 4419 + | LinuxSyscall.Semtimedop64 -> 4420 + | LinuxSyscall.RtSigtimedwait64 -> 4421 + | LinuxSyscall.Futex64 -> 4422 + | LinuxSyscall.SchedRrGetInterval64 -> 4423 + | LinuxSyscall.PidfdSendSignal -> 4424 + | LinuxSyscall.IoUringSetup -> 4425 + | LinuxSyscall.IoUringEnter -> 4426 + | LinuxSyscall.IoUringRegister -> 4427 + | LinuxSyscall.OpenTree -> 4428 + | LinuxSyscall.MoveMount -> 4429 + | LinuxSyscall.Fsopen -> 4430 + | LinuxSyscall.Fsconfig -> 4431 + | LinuxSyscall.Fsmount -> 4432 + | LinuxSyscall.Fspick -> 4433 + | LinuxSyscall.PidfdOpen -> 4434 + | LinuxSyscall.Clone3 -> 4435 + | LinuxSyscall.Openat2 -> 4437 + | LinuxSyscall.PidfdGetfd -> 4438 + | _ -> raise UnhandledSyscallException + + let private getMIPSN64Number = function + | LinuxSyscall.Read -> 5000 + | LinuxSyscall.Write -> 5001 + | LinuxSyscall.Open -> 5002 + | LinuxSyscall.Close -> 5003 + | LinuxSyscall.Stat -> 5004 + | LinuxSyscall.Fstat -> 5005 + | LinuxSyscall.Lstat -> 5006 + | LinuxSyscall.Poll -> 5007 + | LinuxSyscall.Lseek -> 5008 + | LinuxSyscall.Mmap -> 5009 + | LinuxSyscall.Mprotect -> 5010 + | LinuxSyscall.Munmap -> 5011 + | LinuxSyscall.Brk -> 5012 + | LinuxSyscall.RtSigaction -> 5013 + | LinuxSyscall.RtSigprocmask -> 5014 + | LinuxSyscall.Ioctl -> 5015 + | LinuxSyscall.Pread64 -> 5016 + | LinuxSyscall.Pwrite64 -> 5017 + | LinuxSyscall.Readv -> 5018 + | LinuxSyscall.Writev -> 5019 + | LinuxSyscall.Access -> 5020 + | LinuxSyscall.Pipe -> 5021 + | LinuxSyscall.NewSelect -> 5022 + | LinuxSyscall.SchedYield -> 5023 + | LinuxSyscall.Mremap -> 5024 + | LinuxSyscall.Msync -> 5025 + | LinuxSyscall.Mincore -> 5026 + | LinuxSyscall.Madvise -> 5027 + | LinuxSyscall.Shmget -> 5028 + | LinuxSyscall.Shmat -> 5029 + | LinuxSyscall.Shmctl -> 5030 + | LinuxSyscall.Dup -> 5031 + | LinuxSyscall.Dup2 -> 5032 + | LinuxSyscall.Pause -> 5033 + | LinuxSyscall.Nanosleep -> 5034 + | LinuxSyscall.Getitimer -> 5035 + | LinuxSyscall.Setitimer -> 5036 + | LinuxSyscall.Alarm -> 5037 + | LinuxSyscall.Getpid -> 5038 + | LinuxSyscall.Sendfile -> 5039 + | LinuxSyscall.Socket -> 5040 + | LinuxSyscall.Connect -> 5041 + | LinuxSyscall.Accept -> 5042 + | LinuxSyscall.Sendto -> 5043 + | LinuxSyscall.Recvfrom -> 5044 + | LinuxSyscall.Sendmsg -> 5045 + | LinuxSyscall.Recvmsg -> 5046 + | LinuxSyscall.Shutdown -> 5047 + | LinuxSyscall.Bind -> 5048 + | LinuxSyscall.Listen -> 5049 + | LinuxSyscall.Getsockname -> 5050 + | LinuxSyscall.Getpeername -> 5051 + | LinuxSyscall.Socketpair -> 5052 + | LinuxSyscall.Setsockopt -> 5053 + | LinuxSyscall.Getsockopt -> 5054 + | LinuxSyscall.Clone -> 5055 + | LinuxSyscall.Fork -> 5056 + | LinuxSyscall.Execve -> 5057 + | LinuxSyscall.Exit -> 5058 + | LinuxSyscall.Wait4 -> 5059 + | LinuxSyscall.Kill -> 5060 + | LinuxSyscall.Uname -> 5061 + | LinuxSyscall.Semget -> 5062 + | LinuxSyscall.Semop -> 5063 + | LinuxSyscall.Semctl -> 5064 + | LinuxSyscall.Shmdt -> 5065 + | LinuxSyscall.Msgget -> 5066 + | LinuxSyscall.Msgsnd -> 5067 + | LinuxSyscall.Msgrcv -> 5068 + | LinuxSyscall.Msgctl -> 5069 + | LinuxSyscall.Fcntl -> 5070 + | LinuxSyscall.Flock -> 5071 + | LinuxSyscall.Fsync -> 5072 + | LinuxSyscall.Fdatasync -> 5073 + | LinuxSyscall.Truncate -> 5074 + | LinuxSyscall.Ftruncate -> 5075 + | LinuxSyscall.Getdents -> 5076 + | LinuxSyscall.Getcwd -> 5077 + | LinuxSyscall.Chdir -> 5078 + | LinuxSyscall.Fchdir -> 5079 + | LinuxSyscall.Rename -> 5080 + | LinuxSyscall.Mkdir -> 5081 + | LinuxSyscall.Rmdir -> 5082 + | LinuxSyscall.Creat -> 5083 + | LinuxSyscall.Link -> 5084 + | LinuxSyscall.Unlink -> 5085 + | LinuxSyscall.Symlink -> 5086 + | LinuxSyscall.Readlink -> 5087 + | LinuxSyscall.Chmod -> 5088 + | LinuxSyscall.Fchmod -> 5089 + | LinuxSyscall.Chown -> 5090 + | LinuxSyscall.Fchown -> 5091 + | LinuxSyscall.Lchown -> 5092 + | LinuxSyscall.Umask -> 5093 + | LinuxSyscall.Gettimeofday -> 5094 + | LinuxSyscall.Getrlimit -> 5095 + | LinuxSyscall.Getrusage -> 5096 + | LinuxSyscall.Sysinfo -> 5097 + | LinuxSyscall.Times -> 5098 + | LinuxSyscall.Ptrace -> 5099 + | LinuxSyscall.Getuid -> 5100 + | LinuxSyscall.Syslog -> 5101 + | LinuxSyscall.Getgid -> 5102 + | LinuxSyscall.Setuid -> 5103 + | LinuxSyscall.Setgid -> 5104 + | LinuxSyscall.Geteuid -> 5105 + | LinuxSyscall.Getegid -> 5106 + | LinuxSyscall.Setpgid -> 5107 + | LinuxSyscall.Getppid -> 5108 + | LinuxSyscall.Getpgrp -> 5109 + | LinuxSyscall.Setsid -> 5110 + | LinuxSyscall.Setreuid -> 5111 + | LinuxSyscall.Setregid -> 5112 + | LinuxSyscall.Getgroups -> 5113 + | LinuxSyscall.Setgroups -> 5114 + | LinuxSyscall.Setresuid -> 5115 + | LinuxSyscall.Getresuid -> 5116 + | LinuxSyscall.Setresgid -> 5117 + | LinuxSyscall.Getresgid -> 5118 + | LinuxSyscall.Getpgid -> 5119 + | LinuxSyscall.Setfsuid -> 5120 + | LinuxSyscall.Setfsgid -> 5121 + | LinuxSyscall.Getsid -> 5122 + | LinuxSyscall.CapGet -> 5123 + | LinuxSyscall.CapSet -> 5124 + | LinuxSyscall.RtSigpending -> 5125 + | LinuxSyscall.RtSigtimedwait -> 5126 + | LinuxSyscall.RtSigqueueinfo -> 5127 + | LinuxSyscall.RtSigsuspend -> 5128 + | LinuxSyscall.Sigaltstack -> 5129 + | LinuxSyscall.Utime -> 5130 + | LinuxSyscall.Mknod -> 5131 + | LinuxSyscall.Personality -> 5132 + | LinuxSyscall.Ustat -> 5133 + | LinuxSyscall.Statfs -> 5134 + | LinuxSyscall.Fstatfs -> 5135 + | LinuxSyscall.Sysfs -> 5136 + | LinuxSyscall.Getpriority -> 5137 + | LinuxSyscall.Setpriority -> 5138 + | LinuxSyscall.SchedSetparam -> 5139 + | LinuxSyscall.SchedGetparam -> 5140 + | LinuxSyscall.SchedSetscheduler -> 5141 + | LinuxSyscall.SchedGetscheduler -> 5142 + | LinuxSyscall.SchedGetPriorityMax -> 5143 + | LinuxSyscall.SchedGetPriorityMin -> 5144 + | LinuxSyscall.SchedRrGetInterval -> 5145 + | LinuxSyscall.Mlock -> 5146 + | LinuxSyscall.Munlock -> 5147 + | LinuxSyscall.Mlockall -> 5148 + | LinuxSyscall.Munlockall -> 5149 + | LinuxSyscall.Vhangup -> 5150 + | LinuxSyscall.PivotRoot -> 5151 + | LinuxSyscall.Sysctl -> 5152 + | LinuxSyscall.Prctl -> 5153 + | LinuxSyscall.AdjTimex -> 5154 + | LinuxSyscall.Setrlimit -> 5155 + | LinuxSyscall.Chroot -> 5156 + | LinuxSyscall.Sync -> 5157 + | LinuxSyscall.Acct -> 5158 + | LinuxSyscall.Settimeofday -> 5159 + | LinuxSyscall.Mount -> 5160 + | LinuxSyscall.Umount2 -> 5161 + | LinuxSyscall.Swapon -> 5162 + | LinuxSyscall.Swapoff -> 5163 + | LinuxSyscall.Reboot -> 5164 + | LinuxSyscall.Sethostname -> 5165 + | LinuxSyscall.Setdomainname -> 5166 + | LinuxSyscall.CreateModule -> 5167 + | LinuxSyscall.InitModule -> 5168 + | LinuxSyscall.DeleteModule -> 5169 + | LinuxSyscall.GetKernelSyms -> 5170 + | LinuxSyscall.QueryModule -> 5171 + | LinuxSyscall.Quotactl -> 5172 + | LinuxSyscall.Nfsservctl -> 5173 + | LinuxSyscall.Gettid -> 5178 + | LinuxSyscall.Readahead -> 5179 + | LinuxSyscall.Setxattr -> 5180 + | LinuxSyscall.Lsetxattr -> 5181 + | LinuxSyscall.Fsetxattr -> 5182 + | LinuxSyscall.Getxattr -> 5183 + | LinuxSyscall.Lgetxattr -> 5184 + | LinuxSyscall.Fgetxattr -> 5185 + | LinuxSyscall.Listxattr -> 5186 + | LinuxSyscall.Llistxattr -> 5187 + | LinuxSyscall.Flistxattr -> 5188 + | LinuxSyscall.Removexattr -> 5189 + | LinuxSyscall.Lremovexattr -> 5190 + | LinuxSyscall.Fremovexattr -> 5191 + | LinuxSyscall.Tkill -> 5192 + | LinuxSyscall.Futex -> 5194 + | LinuxSyscall.SchedSetaffinity -> 5195 + | LinuxSyscall.SchedGetaffinity -> 5196 + | LinuxSyscall.CacheFlush -> 5197 + | LinuxSyscall.CacheCtl -> 5198 + | LinuxSyscall.Sysmips -> 5199 + | LinuxSyscall.IoSetup -> 5200 + | LinuxSyscall.IoDestroy -> 5201 + | LinuxSyscall.IoGetevents -> 5202 + | LinuxSyscall.IoSubmit -> 5203 + | LinuxSyscall.IoCancel -> 5204 + | LinuxSyscall.ExitGroup -> 5205 + | LinuxSyscall.LookupDcookie -> 5206 + | LinuxSyscall.EpollCreate -> 5207 + | LinuxSyscall.EpollCtl -> 5208 + | LinuxSyscall.EpollWait -> 5209 + | LinuxSyscall.RemapFilePages -> 5210 + | LinuxSyscall.RtSigreturn -> 5211 + | LinuxSyscall.SetTidAddress -> 5212 + | LinuxSyscall.RestartSyscall -> 5213 + | LinuxSyscall.Semtimedop -> 5214 + | LinuxSyscall.Fadvise64 -> 5215 + | LinuxSyscall.TimerCreate -> 5216 + | LinuxSyscall.TimerSettime -> 5217 + | LinuxSyscall.TimerGettime -> 5218 + | LinuxSyscall.TimerGetoverrun -> 5219 + | LinuxSyscall.TimerDelete -> 5220 + | LinuxSyscall.ClockSettime -> 5221 + | LinuxSyscall.ClockGettime -> 5222 + | LinuxSyscall.ClockGetres -> 5223 + | LinuxSyscall.ClockNanosleep -> 5224 + | LinuxSyscall.Tgkill -> 5225 + | LinuxSyscall.Utimes -> 5226 + | LinuxSyscall.Mbind -> 5227 + | LinuxSyscall.GetMempolicy -> 5228 + | LinuxSyscall.SetMempolicy -> 5229 + | LinuxSyscall.MqOpen -> 5230 + | LinuxSyscall.MqUnlink -> 5231 + | LinuxSyscall.MqTimedsend -> 5232 + | LinuxSyscall.MqTimedreceive -> 5233 + | LinuxSyscall.MqNotify -> 5234 + | LinuxSyscall.MqGetsetattr -> 5235 + | LinuxSyscall.Vserver -> 5236 + | LinuxSyscall.Waitid -> 5237 + | LinuxSyscall.AddKey -> 5239 + | LinuxSyscall.RequestKey -> 5240 + | LinuxSyscall.Keyctl -> 5241 + | LinuxSyscall.SetThreadArea -> 5242 + | LinuxSyscall.InotifyInit -> 5243 + | LinuxSyscall.InotifyAddWatch -> 5244 + | LinuxSyscall.InotifyRmWatch -> 5245 + | LinuxSyscall.MigratePages -> 5246 + | LinuxSyscall.Openat -> 5247 + | LinuxSyscall.Mkdirat -> 5248 + | LinuxSyscall.Mknodat -> 5249 + | LinuxSyscall.Fchownat -> 5250 + | LinuxSyscall.Futimesat -> 5251 + | LinuxSyscall.Newfstatat -> 5252 + | LinuxSyscall.Unlinkat -> 5253 + | LinuxSyscall.Renameat -> 5254 + | LinuxSyscall.Linkat -> 5255 + | LinuxSyscall.Symlinkat -> 5256 + | LinuxSyscall.Readlinkat -> 5257 + | LinuxSyscall.Fchmodat -> 5258 + | LinuxSyscall.Faccessat -> 5259 + | LinuxSyscall.Pselect6 -> 5260 + | LinuxSyscall.Ppoll -> 5261 + | LinuxSyscall.Unshare -> 5262 + | LinuxSyscall.Splice -> 5263 + | LinuxSyscall.SyncFileRange -> 5264 + | LinuxSyscall.Tee -> 5265 + | LinuxSyscall.Vmsplice -> 5266 + | LinuxSyscall.MovePages -> 5267 + | LinuxSyscall.SetRobustList -> 5268 + | LinuxSyscall.GetRobustList -> 5269 + | LinuxSyscall.KexecLoad -> 5270 + | LinuxSyscall.Getcpu -> 5271 + | LinuxSyscall.EpollPwait -> 5272 + | LinuxSyscall.IoprioSet -> 5273 + | LinuxSyscall.IoprioGet -> 5274 + | LinuxSyscall.Utimensat -> 5275 + | LinuxSyscall.Signalfd -> 5276 + | LinuxSyscall.Timerfd -> 5277 + | LinuxSyscall.Eventfd -> 5278 + | LinuxSyscall.Fallocate -> 5279 + | LinuxSyscall.TimerfdCreate -> 5280 + | LinuxSyscall.TimerfdGettime -> 5281 + | LinuxSyscall.TimerfdSettime -> 5282 + | LinuxSyscall.Signalfd4 -> 5283 + | LinuxSyscall.Eventfd2 -> 5284 + | LinuxSyscall.EpollCreate1 -> 5285 + | LinuxSyscall.Dup3 -> 5286 + | LinuxSyscall.Pipe2 -> 5287 + | LinuxSyscall.InotifyInit1 -> 5288 + | LinuxSyscall.Preadv -> 5289 + | LinuxSyscall.Pwritev -> 5290 + | LinuxSyscall.RtTgsigqueueinfo -> 5291 + | LinuxSyscall.PerfEventOpen -> 5292 + | LinuxSyscall.Accept4 -> 5293 + | LinuxSyscall.Recvmmsg -> 5294 + | LinuxSyscall.FanotifyInit -> 5295 + | LinuxSyscall.FanotifyMark -> 5296 + | LinuxSyscall.Prlimit64 -> 5297 + | LinuxSyscall.NameToHandleAt -> 5298 + | LinuxSyscall.OpenByHandleAt -> 5299 + | LinuxSyscall.ClockAdjtime -> 5300 + | LinuxSyscall.Syncfs -> 5301 + | LinuxSyscall.Sendmmsg -> 5302 + | LinuxSyscall.Setns -> 5303 + | LinuxSyscall.ProcessVmReadv -> 5304 + | LinuxSyscall.ProcessVmWritev -> 5305 + | LinuxSyscall.Kcmp -> 5306 + | LinuxSyscall.FinitModule -> 5307 + | LinuxSyscall.Getdents64 -> 5308 + | LinuxSyscall.SchedSetattr -> 5309 + | LinuxSyscall.SchedGetattr -> 5310 + | LinuxSyscall.Renameat2 -> 5311 + | LinuxSyscall.Seccomp -> 5312 + | LinuxSyscall.Getrandom -> 5313 + | LinuxSyscall.MemfdCreate -> 5314 + | LinuxSyscall.Bpf -> 5315 + | LinuxSyscall.Execveat -> 5316 + | LinuxSyscall.Userfaultfd -> 5317 + | LinuxSyscall.Membarrier -> 5318 + | LinuxSyscall.Mlock2 -> 5319 + | LinuxSyscall.CopyFileRange -> 5320 + | LinuxSyscall.Preadv2 -> 5321 + | LinuxSyscall.Pwritev2 -> 5322 + | LinuxSyscall.PkeyMprotect -> 5323 + | LinuxSyscall.PkeyAlloc -> 5324 + | LinuxSyscall.PkeyFree -> 5325 + | LinuxSyscall.Statx -> 5326 + | LinuxSyscall.Rseq -> 5327 + | LinuxSyscall.IoPgetevents -> 5328 + | LinuxSyscall.PidfdSendSignal -> 5424 + | LinuxSyscall.IoUringSetup -> 5425 + | LinuxSyscall.IoUringEnter -> 5426 + | LinuxSyscall.IoUringRegister -> 5427 + | LinuxSyscall.OpenTree -> 5428 + | LinuxSyscall.MoveMount -> 5429 + | LinuxSyscall.Fsopen -> 5430 + | LinuxSyscall.Fsconfig -> 5431 + | LinuxSyscall.Fsmount -> 5432 + | LinuxSyscall.Fspick -> 5433 + | LinuxSyscall.PidfdOpen -> 5434 + | LinuxSyscall.Clone3 -> 5435 + | LinuxSyscall.CloseRange -> 5436 + | LinuxSyscall.Openat2 -> 5437 + | LinuxSyscall.PidfdGetfd -> 5438 + | _ -> raise UnhandledSyscallException + + let private getPPC32Number = function + | LinuxSyscall.RestartSyscall -> 0 + | LinuxSyscall.Exit -> 1 + | LinuxSyscall.Fork -> 2 + | LinuxSyscall.Read -> 3 + | LinuxSyscall.Write -> 4 + | LinuxSyscall.Open -> 5 + | LinuxSyscall.Close -> 6 + | LinuxSyscall.Waitpid -> 7 + | LinuxSyscall.Creat -> 8 + | LinuxSyscall.Link -> 9 + | LinuxSyscall.Unlink -> 10 + | LinuxSyscall.Execve -> 11 + | LinuxSyscall.Chdir -> 12 + | LinuxSyscall.Time -> 13 + | LinuxSyscall.Mknod -> 14 + | LinuxSyscall.Chmod -> 15 + | LinuxSyscall.Lchown -> 16 + | LinuxSyscall.Oldstat -> 18 + | LinuxSyscall.Lseek -> 19 + | LinuxSyscall.Getpid -> 20 + | LinuxSyscall.Mount -> 21 + | LinuxSyscall.Umount -> 22 + | LinuxSyscall.Setuid -> 23 + | LinuxSyscall.Getuid -> 24 + | LinuxSyscall.Stime -> 25 + | LinuxSyscall.Ptrace -> 26 + | LinuxSyscall.Alarm -> 27 + | LinuxSyscall.Oldfstat -> 28 + | LinuxSyscall.Pause -> 29 + | LinuxSyscall.Utime -> 30 + | LinuxSyscall.Access -> 33 + | LinuxSyscall.Nice -> 34 + | LinuxSyscall.Sync -> 36 + | LinuxSyscall.Kill -> 37 + | LinuxSyscall.Rename -> 38 + | LinuxSyscall.Mkdir -> 39 + | LinuxSyscall.Rmdir -> 40 + | LinuxSyscall.Dup -> 41 + | LinuxSyscall.Pipe -> 42 + | LinuxSyscall.Times -> 43 + | LinuxSyscall.Brk -> 45 + | LinuxSyscall.Setgid -> 46 + | LinuxSyscall.Getgid -> 47 + | LinuxSyscall.Signal -> 48 + | LinuxSyscall.Geteuid -> 49 + | LinuxSyscall.Getegid -> 50 + | LinuxSyscall.Acct -> 51 + | LinuxSyscall.Umount2 -> 52 + | LinuxSyscall.Ioctl -> 54 + | LinuxSyscall.Fcntl -> 55 + | LinuxSyscall.Setpgid -> 57 + | LinuxSyscall.Oldolduname -> 59 + | LinuxSyscall.Umask -> 60 + | LinuxSyscall.Chroot -> 61 + | LinuxSyscall.Ustat -> 62 + | LinuxSyscall.Dup2 -> 63 + | LinuxSyscall.Getppid -> 64 + | LinuxSyscall.Getpgrp -> 65 + | LinuxSyscall.Setsid -> 66 + | LinuxSyscall.Sigaction -> 67 + | LinuxSyscall.Sgetmask -> 68 + | LinuxSyscall.Ssetmask -> 69 + | LinuxSyscall.Setreuid -> 70 + | LinuxSyscall.Setregid -> 71 + | LinuxSyscall.Sigsuspend -> 72 + | LinuxSyscall.Sigpending -> 73 + | LinuxSyscall.Sethostname -> 74 + | LinuxSyscall.Setrlimit -> 75 + | LinuxSyscall.Getrlimit -> 76 + | LinuxSyscall.Getrusage -> 77 + | LinuxSyscall.Gettimeofday -> 78 + | LinuxSyscall.Settimeofday -> 79 + | LinuxSyscall.Getgroups -> 80 + | LinuxSyscall.Setgroups -> 81 + | LinuxSyscall.Select -> 82 + | LinuxSyscall.Symlink -> 83 + | LinuxSyscall.Oldlstat -> 84 + | LinuxSyscall.Readlink -> 85 + | LinuxSyscall.Uselib -> 86 + | LinuxSyscall.Swapon -> 87 + | LinuxSyscall.Reboot -> 88 + | LinuxSyscall.Readdir -> 89 + | LinuxSyscall.Mmap -> 90 + | LinuxSyscall.Munmap -> 91 + | LinuxSyscall.Truncate -> 92 + | LinuxSyscall.Ftruncate -> 93 + | LinuxSyscall.Fchmod -> 94 + | LinuxSyscall.Fchown -> 95 + | LinuxSyscall.Getpriority -> 96 + | LinuxSyscall.Setpriority -> 97 + | LinuxSyscall.Statfs -> 99 + | LinuxSyscall.Fstatfs -> 100 + | LinuxSyscall.Ioperm -> 101 + | LinuxSyscall.Socketcall -> 102 + | LinuxSyscall.Syslog -> 103 + | LinuxSyscall.Setitimer -> 104 + | LinuxSyscall.Getitimer -> 105 + | LinuxSyscall.Stat -> 106 + | LinuxSyscall.Lstat -> 107 + | LinuxSyscall.Fstat -> 108 + | LinuxSyscall.Olduname -> 109 + | LinuxSyscall.Iopl -> 110 + | LinuxSyscall.Vhangup -> 111 + | LinuxSyscall.Vm86 -> 113 + | LinuxSyscall.Wait4 -> 114 + | LinuxSyscall.Swapoff -> 115 + | LinuxSyscall.Sysinfo -> 116 + | LinuxSyscall.Ipc -> 117 + | LinuxSyscall.Fsync -> 118 + | LinuxSyscall.Sigreturn -> 119 + | LinuxSyscall.Clone -> 120 + | LinuxSyscall.Setdomainname -> 121 + | LinuxSyscall.Uname -> 122 + | LinuxSyscall.ModifyLdt -> 123 + | LinuxSyscall.AdjTimex -> 124 + | LinuxSyscall.Mprotect -> 125 + | LinuxSyscall.Sigprocmask -> 126 + | LinuxSyscall.CreateModule -> 127 + | LinuxSyscall.InitModule -> 128 + | LinuxSyscall.DeleteModule -> 129 + | LinuxSyscall.GetKernelSyms -> 130 + | LinuxSyscall.Quotactl -> 131 + | LinuxSyscall.Getpgid -> 132 + | LinuxSyscall.Fchdir -> 133 + | LinuxSyscall.Bdflush -> 134 + | LinuxSyscall.Sysfs -> 135 + | LinuxSyscall.Personality -> 136 + | LinuxSyscall.Setfsuid -> 138 + | LinuxSyscall.Setfsgid -> 139 + | LinuxSyscall.LLseek -> 140 + | LinuxSyscall.Getdents -> 141 + | LinuxSyscall.NewSelect -> 142 + | LinuxSyscall.Flock -> 143 + | LinuxSyscall.Msync -> 144 + | LinuxSyscall.Readv -> 145 + | LinuxSyscall.Writev -> 146 + | LinuxSyscall.Getsid -> 147 + | LinuxSyscall.Fdatasync -> 148 + | LinuxSyscall.Sysctl -> 149 + | LinuxSyscall.Mlock -> 150 + | LinuxSyscall.Munlock -> 151 + | LinuxSyscall.Mlockall -> 152 + | LinuxSyscall.Munlockall -> 153 + | LinuxSyscall.SchedSetparam -> 154 + | LinuxSyscall.SchedGetparam -> 155 + | LinuxSyscall.SchedSetscheduler -> 156 + | LinuxSyscall.SchedGetscheduler -> 157 + | LinuxSyscall.SchedYield -> 158 + | LinuxSyscall.SchedGetPriorityMax -> 159 + | LinuxSyscall.SchedGetPriorityMin -> 160 + | LinuxSyscall.SchedRrGetInterval -> 161 + | LinuxSyscall.Nanosleep -> 162 + | LinuxSyscall.Mremap -> 163 + | LinuxSyscall.Setresuid -> 164 + | LinuxSyscall.Getresuid -> 165 + | LinuxSyscall.QueryModule -> 166 + | LinuxSyscall.Poll -> 167 + | LinuxSyscall.Nfsservctl -> 168 + | LinuxSyscall.Setresgid -> 169 + | LinuxSyscall.Getresgid -> 170 + | LinuxSyscall.Prctl -> 171 + | LinuxSyscall.RtSigreturn -> 172 + | LinuxSyscall.RtSigaction -> 173 + | LinuxSyscall.RtSigprocmask -> 174 + | LinuxSyscall.RtSigpending -> 175 + | LinuxSyscall.RtSigtimedwait -> 176 + | LinuxSyscall.RtSigqueueinfo -> 177 + | LinuxSyscall.RtSigsuspend -> 178 + | LinuxSyscall.Pread64 -> 179 + | LinuxSyscall.Pwrite64 -> 180 + | LinuxSyscall.Chown -> 181 + | LinuxSyscall.Getcwd -> 182 + | LinuxSyscall.CapGet -> 183 + | LinuxSyscall.CapSet -> 184 + | LinuxSyscall.Sigaltstack -> 185 + | LinuxSyscall.Sendfile -> 186 + | LinuxSyscall.Vfork -> 189 + | LinuxSyscall.Ugetrlimit -> 190 + | LinuxSyscall.Readahead -> 191 + | LinuxSyscall.Mmap2 -> 192 + | LinuxSyscall.Truncate64 -> 193 + | LinuxSyscall.Ftruncate64 -> 194 + | LinuxSyscall.Stat64 -> 195 + | LinuxSyscall.Lstat64 -> 196 + | LinuxSyscall.Fstat64 -> 197 + | LinuxSyscall.PciconfigRead -> 198 + | LinuxSyscall.PciconfigWrite -> 199 + | LinuxSyscall.PciconfigIobase -> 200 + | LinuxSyscall.Getdents64 -> 202 + | LinuxSyscall.PivotRoot -> 203 + | LinuxSyscall.Fcntl64 -> 204 + | LinuxSyscall.Madvise -> 205 + | LinuxSyscall.Mincore -> 206 + | LinuxSyscall.Gettid -> 207 + | LinuxSyscall.Tkill -> 208 + | LinuxSyscall.Setxattr -> 209 + | LinuxSyscall.Lsetxattr -> 210 + | LinuxSyscall.Fsetxattr -> 211 + | LinuxSyscall.Getxattr -> 212 + | LinuxSyscall.Lgetxattr -> 213 + | LinuxSyscall.Fgetxattr -> 214 + | LinuxSyscall.Listxattr -> 215 + | LinuxSyscall.Llistxattr -> 216 + | LinuxSyscall.Flistxattr -> 217 + | LinuxSyscall.Removexattr -> 218 + | LinuxSyscall.Lremovexattr -> 219 + | LinuxSyscall.Fremovexattr -> 220 + | LinuxSyscall.Futex -> 221 + | LinuxSyscall.SchedSetaffinity -> 222 + | LinuxSyscall.SchedGetaffinity -> 223 + | LinuxSyscall.Sendfile64 -> 226 + | LinuxSyscall.IoSetup -> 227 + | LinuxSyscall.IoDestroy -> 228 + | LinuxSyscall.IoGetevents -> 229 + | LinuxSyscall.IoSubmit -> 230 + | LinuxSyscall.IoCancel -> 231 + | LinuxSyscall.SetTidAddress -> 232 + | LinuxSyscall.Fadvise64 -> 233 + | LinuxSyscall.ExitGroup -> 234 + | LinuxSyscall.LookupDcookie -> 235 + | LinuxSyscall.EpollCreate -> 236 + | LinuxSyscall.EpollCtl -> 237 + | LinuxSyscall.EpollWait -> 238 + | LinuxSyscall.RemapFilePages -> 239 + | LinuxSyscall.TimerCreate -> 240 + | LinuxSyscall.TimerSettime -> 241 + | LinuxSyscall.TimerGettime -> 242 + | LinuxSyscall.TimerGetoverrun -> 243 + | LinuxSyscall.TimerDelete -> 244 + | LinuxSyscall.ClockSettime -> 245 + | LinuxSyscall.ClockGettime -> 246 + | LinuxSyscall.ClockGetres -> 247 + | LinuxSyscall.ClockNanosleep -> 248 + | LinuxSyscall.Swapcontext -> 249 + | LinuxSyscall.Tgkill -> 250 + | LinuxSyscall.Utimes -> 251 + | LinuxSyscall.Statfs64 -> 252 + | LinuxSyscall.Fstatfs64 -> 253 + | LinuxSyscall.Fadvise64_64 -> 254 + | LinuxSyscall.Rtas -> 255 + | LinuxSyscall.SysDebugSetcontext -> 256 + | LinuxSyscall.MigratePages -> 258 + | LinuxSyscall.Mbind -> 259 + | LinuxSyscall.GetMempolicy -> 260 + | LinuxSyscall.SetMempolicy -> 261 + | LinuxSyscall.MqOpen -> 262 + | LinuxSyscall.MqUnlink -> 263 + | LinuxSyscall.MqTimedsend -> 264 + | LinuxSyscall.MqTimedreceive -> 265 + | LinuxSyscall.MqNotify -> 266 + | LinuxSyscall.MqGetsetattr -> 267 + | LinuxSyscall.KexecLoad -> 268 + | LinuxSyscall.AddKey -> 269 + | LinuxSyscall.RequestKey -> 270 + | LinuxSyscall.Keyctl -> 271 + | LinuxSyscall.Waitid -> 272 + | LinuxSyscall.IoprioSet -> 273 + | LinuxSyscall.IoprioGet -> 274 + | LinuxSyscall.InotifyInit -> 275 + | LinuxSyscall.InotifyAddWatch -> 276 + | LinuxSyscall.InotifyRmWatch -> 277 + | LinuxSyscall.SpuRun -> 278 + | LinuxSyscall.SpuCreate -> 279 + | LinuxSyscall.Pselect6 -> 280 + | LinuxSyscall.Ppoll -> 281 + | LinuxSyscall.Unshare -> 282 + | LinuxSyscall.Splice -> 283 + | LinuxSyscall.Tee -> 284 + | LinuxSyscall.Vmsplice -> 285 + | LinuxSyscall.Openat -> 286 + | LinuxSyscall.Mkdirat -> 287 + | LinuxSyscall.Mknodat -> 288 + | LinuxSyscall.Fchownat -> 289 + | LinuxSyscall.Futimesat -> 290 + | LinuxSyscall.Fstatat64 -> 291 + | LinuxSyscall.Unlinkat -> 292 + | LinuxSyscall.Renameat -> 293 + | LinuxSyscall.Linkat -> 294 + | LinuxSyscall.Symlinkat -> 295 + | LinuxSyscall.Readlinkat -> 296 + | LinuxSyscall.Fchmodat -> 297 + | LinuxSyscall.Faccessat -> 298 + | LinuxSyscall.GetRobustList -> 299 + | LinuxSyscall.SetRobustList -> 300 + | LinuxSyscall.MovePages -> 301 + | LinuxSyscall.Getcpu -> 302 + | LinuxSyscall.EpollPwait -> 303 + | LinuxSyscall.Utimensat -> 304 + | LinuxSyscall.Signalfd -> 305 + | LinuxSyscall.TimerfdCreate -> 306 + | LinuxSyscall.Eventfd -> 307 + | LinuxSyscall.SyncFileRange2 -> 308 + | LinuxSyscall.Fallocate -> 309 + | LinuxSyscall.SubpageProt -> 310 + | LinuxSyscall.TimerfdSettime -> 311 + | LinuxSyscall.TimerfdGettime -> 312 + | LinuxSyscall.Signalfd4 -> 313 + | LinuxSyscall.Eventfd2 -> 314 + | LinuxSyscall.EpollCreate1 -> 315 + | LinuxSyscall.Dup3 -> 316 + | LinuxSyscall.Pipe2 -> 317 + | LinuxSyscall.InotifyInit1 -> 318 + | LinuxSyscall.PerfEventOpen -> 319 + | LinuxSyscall.Preadv -> 320 + | LinuxSyscall.Pwritev -> 321 + | LinuxSyscall.RtTgsigqueueinfo -> 322 + | LinuxSyscall.FanotifyInit -> 323 + | LinuxSyscall.FanotifyMark -> 324 + | LinuxSyscall.Prlimit64 -> 325 + | LinuxSyscall.Socket -> 326 + | LinuxSyscall.Bind -> 327 + | LinuxSyscall.Connect -> 328 + | LinuxSyscall.Listen -> 329 + | LinuxSyscall.Accept -> 330 + | LinuxSyscall.Getsockname -> 331 + | LinuxSyscall.Getpeername -> 332 + | LinuxSyscall.Socketpair -> 333 + | LinuxSyscall.Send -> 334 + | LinuxSyscall.Sendto -> 335 + | LinuxSyscall.Recv -> 336 + | LinuxSyscall.Recvfrom -> 337 + | LinuxSyscall.Shutdown -> 338 + | LinuxSyscall.Setsockopt -> 339 + | LinuxSyscall.Getsockopt -> 340 + | LinuxSyscall.Sendmsg -> 341 + | LinuxSyscall.Recvmsg -> 342 + | LinuxSyscall.Recvmmsg -> 343 + | LinuxSyscall.Accept4 -> 344 + | LinuxSyscall.NameToHandleAt -> 345 + | LinuxSyscall.OpenByHandleAt -> 346 + | LinuxSyscall.ClockAdjtime -> 347 + | LinuxSyscall.Syncfs -> 348 + | LinuxSyscall.Sendmmsg -> 349 + | LinuxSyscall.Setns -> 350 + | LinuxSyscall.ProcessVmReadv -> 351 + | LinuxSyscall.ProcessVmWritev -> 352 + | LinuxSyscall.FinitModule -> 353 + | LinuxSyscall.Kcmp -> 354 + | LinuxSyscall.SchedSetattr -> 355 + | LinuxSyscall.SchedGetattr -> 356 + | LinuxSyscall.Renameat2 -> 357 + | LinuxSyscall.MemfdCreate -> 360 + | _ -> raise UnhandledSyscallException + + let private getRISCV64Number = function + | LinuxSyscall.IoSetup -> 0 + | LinuxSyscall.IoDestroy -> 1 + | LinuxSyscall.IoSubmit -> 2 + | LinuxSyscall.IoCancel -> 3 + | LinuxSyscall.IoGetevents -> 4 + | LinuxSyscall.Setxattr -> 5 + | LinuxSyscall.Lsetxattr -> 6 + | LinuxSyscall.Fsetxattr -> 7 + | LinuxSyscall.Getxattr -> 8 + | LinuxSyscall.Lgetxattr -> 9 + | LinuxSyscall.Fgetxattr -> 10 + | LinuxSyscall.Listxattr -> 11 + | LinuxSyscall.Llistxattr -> 12 + | LinuxSyscall.Flistxattr -> 13 + | LinuxSyscall.Removexattr -> 14 + | LinuxSyscall.Lremovexattr -> 15 + | LinuxSyscall.Fremovexattr -> 16 + | LinuxSyscall.Getcwd -> 17 + | LinuxSyscall.LookupDcookie -> 18 + | LinuxSyscall.Eventfd2 -> 19 + | LinuxSyscall.EpollCreate1 -> 20 + | LinuxSyscall.EpollCtl -> 21 + | LinuxSyscall.EpollPwait -> 22 + | LinuxSyscall.Dup -> 23 + | LinuxSyscall.Dup3 -> 24 + | LinuxSyscall.Fcntl -> 25 + | LinuxSyscall.InotifyInit1 -> 26 + | LinuxSyscall.InotifyAddWatch -> 27 + | LinuxSyscall.InotifyRmWatch -> 28 + | LinuxSyscall.Ioctl -> 29 + | LinuxSyscall.IoprioSet -> 30 + | LinuxSyscall.IoprioGet -> 31 + | LinuxSyscall.Flock -> 32 + | LinuxSyscall.Mknodat -> 33 + | LinuxSyscall.Mkdirat -> 34 + | LinuxSyscall.Unlinkat -> 35 + | LinuxSyscall.Symlinkat -> 36 + | LinuxSyscall.Linkat -> 37 + | LinuxSyscall.Renameat -> 38 + | LinuxSyscall.Umount2 -> 39 + | LinuxSyscall.Mount -> 40 + | LinuxSyscall.PivotRoot -> 41 + | LinuxSyscall.Nfsservctl -> 42 + | LinuxSyscall.Statfs -> 43 + | LinuxSyscall.Fstatfs -> 44 + | LinuxSyscall.Truncate -> 45 + | LinuxSyscall.Ftruncate -> 46 + | LinuxSyscall.Fallocate -> 47 + | LinuxSyscall.Faccessat -> 48 + | LinuxSyscall.Chdir -> 49 + | LinuxSyscall.Fchdir -> 50 + | LinuxSyscall.Chroot -> 51 + | LinuxSyscall.Fchmod -> 52 + | LinuxSyscall.Fchmodat -> 53 + | LinuxSyscall.Fchownat -> 54 + | LinuxSyscall.Fchown -> 55 + | LinuxSyscall.Openat -> 56 + | LinuxSyscall.Close -> 57 + | LinuxSyscall.Vhangup -> 58 + | LinuxSyscall.Pipe2 -> 59 + | LinuxSyscall.Quotactl -> 60 + | LinuxSyscall.Getdents64 -> 61 + | LinuxSyscall.Lseek -> 62 + | LinuxSyscall.Read -> 63 + | LinuxSyscall.Write -> 64 + | LinuxSyscall.Readv -> 65 + | LinuxSyscall.Writev -> 66 + | LinuxSyscall.Pread64 -> 67 + | LinuxSyscall.Pwrite64 -> 68 + | LinuxSyscall.Preadv -> 69 + | LinuxSyscall.Pwritev -> 70 + | LinuxSyscall.Sendfile -> 71 + | LinuxSyscall.Pselect6 -> 72 + | LinuxSyscall.Ppoll -> 73 + | LinuxSyscall.Signalfd4 -> 74 + | LinuxSyscall.Vmsplice -> 75 + | LinuxSyscall.Splice -> 76 + | LinuxSyscall.Tee -> 77 + | LinuxSyscall.Readlinkat -> 78 + | LinuxSyscall.Fstatat64 -> 79 + | LinuxSyscall.Fstat -> 80 + | LinuxSyscall.Sync -> 81 + | LinuxSyscall.Fsync -> 82 + | LinuxSyscall.Fdatasync -> 83 + | LinuxSyscall.SyncFileRange -> 84 + | LinuxSyscall.TimerfdCreate -> 85 + | LinuxSyscall.TimerfdSettime -> 86 + | LinuxSyscall.TimerfdGettime -> 87 + | LinuxSyscall.Utimensat -> 88 + | LinuxSyscall.Acct -> 89 + | LinuxSyscall.CapGet -> 90 + | LinuxSyscall.CapSet -> 91 + | LinuxSyscall.Personality -> 92 + | LinuxSyscall.Exit -> 93 + | LinuxSyscall.ExitGroup -> 94 + | LinuxSyscall.Waitid -> 95 + | LinuxSyscall.SetTidAddress -> 96 + | LinuxSyscall.Unshare -> 97 + | LinuxSyscall.Futex -> 98 + | LinuxSyscall.SetRobustList -> 99 + | LinuxSyscall.GetRobustList -> 100 + | LinuxSyscall.Nanosleep -> 101 + | LinuxSyscall.Getitimer -> 102 + | LinuxSyscall.Setitimer -> 103 + | LinuxSyscall.KexecLoad -> 104 + | LinuxSyscall.InitModule -> 105 + | LinuxSyscall.DeleteModule -> 106 + | LinuxSyscall.TimerCreate -> 107 + | LinuxSyscall.TimerGettime -> 108 + | LinuxSyscall.TimerGetoverrun -> 109 + | LinuxSyscall.TimerSettime -> 110 + | LinuxSyscall.TimerDelete -> 111 + | LinuxSyscall.ClockSettime -> 112 + | LinuxSyscall.ClockGettime -> 113 + | LinuxSyscall.ClockGetres -> 114 + | LinuxSyscall.ClockNanosleep -> 115 + | LinuxSyscall.Syslog -> 116 + | LinuxSyscall.Ptrace -> 117 + | LinuxSyscall.SchedSetparam -> 118 + | LinuxSyscall.SchedSetscheduler -> 119 + | LinuxSyscall.SchedGetscheduler -> 120 + | LinuxSyscall.SchedGetparam -> 121 + | LinuxSyscall.SchedSetaffinity -> 122 + | LinuxSyscall.SchedGetaffinity -> 123 + | LinuxSyscall.SchedYield -> 124 + | LinuxSyscall.SchedGetPriorityMax -> 125 + | LinuxSyscall.SchedGetPriorityMin -> 126 + | LinuxSyscall.SchedRrGetInterval -> 127 + | LinuxSyscall.RestartSyscall -> 128 + | LinuxSyscall.Kill -> 129 + | LinuxSyscall.Tkill -> 130 + | LinuxSyscall.Tgkill -> 131 + | LinuxSyscall.Sigaltstack -> 132 + | LinuxSyscall.RtSigsuspend -> 133 + | LinuxSyscall.RtSigaction -> 134 + | LinuxSyscall.RtSigprocmask -> 135 + | LinuxSyscall.RtSigpending -> 136 + | LinuxSyscall.RtSigtimedwait -> 137 + | LinuxSyscall.RtSigqueueinfo -> 138 + | LinuxSyscall.RtSigreturn -> 139 + | LinuxSyscall.Setpriority -> 140 + | LinuxSyscall.Getpriority -> 141 + | LinuxSyscall.Reboot -> 142 + | LinuxSyscall.Setregid -> 143 + | LinuxSyscall.Setgid -> 144 + | LinuxSyscall.Setreuid -> 145 + | LinuxSyscall.Setuid -> 146 + | LinuxSyscall.Setresuid -> 147 + | LinuxSyscall.Getresuid -> 148 + | LinuxSyscall.Setresgid -> 149 + | LinuxSyscall.Getresgid -> 150 + | LinuxSyscall.Setfsuid -> 151 + | LinuxSyscall.Setfsgid -> 152 + | LinuxSyscall.Times -> 153 + | LinuxSyscall.Setpgid -> 154 + | LinuxSyscall.Getpgid -> 155 + | LinuxSyscall.Getsid -> 156 + | LinuxSyscall.Setsid -> 157 + | LinuxSyscall.Getgroups -> 158 + | LinuxSyscall.Setgroups -> 159 + | LinuxSyscall.Uname -> 160 + | LinuxSyscall.Sethostname -> 161 + | LinuxSyscall.Setdomainname -> 162 + | LinuxSyscall.Getrlimit -> 163 + | LinuxSyscall.Setrlimit -> 164 + | LinuxSyscall.Getrusage -> 165 + | LinuxSyscall.Umask -> 166 + | LinuxSyscall.Prctl -> 167 + | LinuxSyscall.Getcpu -> 168 + | LinuxSyscall.Gettimeofday -> 169 + | LinuxSyscall.Settimeofday -> 170 + | LinuxSyscall.AdjTimex -> 171 + | LinuxSyscall.Getpid -> 172 + | LinuxSyscall.Getppid -> 173 + | LinuxSyscall.Getuid -> 174 + | LinuxSyscall.Geteuid -> 175 + | LinuxSyscall.Getgid -> 176 + | LinuxSyscall.Getegid -> 177 + | LinuxSyscall.Gettid -> 178 + | LinuxSyscall.Sysinfo -> 179 + | LinuxSyscall.MqOpen -> 180 + | LinuxSyscall.MqUnlink -> 181 + | LinuxSyscall.MqTimedsend -> 182 + | LinuxSyscall.MqTimedreceive -> 183 + | LinuxSyscall.MqNotify -> 184 + | LinuxSyscall.MqGetsetattr -> 185 + | LinuxSyscall.Msgget -> 186 + | LinuxSyscall.Msgctl -> 187 + | LinuxSyscall.Msgrcv -> 188 + | LinuxSyscall.Msgsnd -> 189 + | LinuxSyscall.Semget -> 190 + | LinuxSyscall.Semctl -> 191 + | LinuxSyscall.Semtimedop -> 192 + | LinuxSyscall.Semop -> 193 + | LinuxSyscall.Shmget -> 194 + | LinuxSyscall.Shmctl -> 195 + | LinuxSyscall.Shmat -> 196 + | LinuxSyscall.Shmdt -> 197 + | LinuxSyscall.Socket -> 198 + | LinuxSyscall.Socketpair -> 199 + | LinuxSyscall.Bind -> 200 + | LinuxSyscall.Listen -> 201 + | LinuxSyscall.Accept -> 202 + | LinuxSyscall.Connect -> 203 + | LinuxSyscall.Getsockname -> 204 + | LinuxSyscall.Getpeername -> 205 + | LinuxSyscall.Sendto -> 206 + | LinuxSyscall.Recvfrom -> 207 + | LinuxSyscall.Setsockopt -> 208 + | LinuxSyscall.Getsockopt -> 209 + | LinuxSyscall.Shutdown -> 210 + | LinuxSyscall.Sendmsg -> 211 + | LinuxSyscall.Recvmsg -> 212 + | LinuxSyscall.Readahead -> 213 + | LinuxSyscall.Brk -> 214 + | LinuxSyscall.Munmap -> 215 + | LinuxSyscall.Mremap -> 216 + | LinuxSyscall.AddKey -> 217 + | LinuxSyscall.RequestKey -> 218 + | LinuxSyscall.Keyctl -> 219 + | LinuxSyscall.Clone -> 220 + | LinuxSyscall.Execve -> 221 + | LinuxSyscall.Mmap -> 222 + | LinuxSyscall.Fadvise64 -> 223 + | LinuxSyscall.Swapon -> 224 + | LinuxSyscall.Swapoff -> 225 + | LinuxSyscall.Mprotect -> 226 + | LinuxSyscall.Msync -> 227 + | LinuxSyscall.Mlock -> 228 + | LinuxSyscall.Munlock -> 229 + | LinuxSyscall.Mlockall -> 230 + | LinuxSyscall.Munlockall -> 231 + | LinuxSyscall.Mincore -> 232 + | LinuxSyscall.Madvise -> 233 + | LinuxSyscall.RemapFilePages -> 234 + | LinuxSyscall.Mbind -> 235 + | LinuxSyscall.GetMempolicy -> 236 + | LinuxSyscall.SetMempolicy -> 237 + | LinuxSyscall.MigratePages -> 238 + | LinuxSyscall.MovePages -> 239 + | LinuxSyscall.RtTgsigqueueinfo -> 240 + | LinuxSyscall.PerfEventOpen -> 241 + | LinuxSyscall.Accept4 -> 242 + | LinuxSyscall.Recvmmsg -> 243 + | LinuxSyscall.Wait4 -> 260 + | LinuxSyscall.Prlimit64 -> 261 + | LinuxSyscall.FanotifyInit -> 262 + | LinuxSyscall.FanotifyMark -> 263 + | LinuxSyscall.NameToHandleAt -> 264 + | LinuxSyscall.OpenByHandleAt -> 265 + | LinuxSyscall.ClockAdjtime -> 266 + | LinuxSyscall.Syncfs -> 267 + | LinuxSyscall.Setns -> 268 + | LinuxSyscall.Sendmmsg -> 269 + | LinuxSyscall.ProcessVmReadv -> 270 + | LinuxSyscall.ProcessVmWritev -> 271 + | LinuxSyscall.Kcmp -> 272 + | LinuxSyscall.FinitModule -> 273 + | LinuxSyscall.SchedSetattr -> 274 + | LinuxSyscall.SchedGetattr -> 275 + | LinuxSyscall.Renameat2 -> 276 + | LinuxSyscall.Seccomp -> 277 + | LinuxSyscall.Getrandom -> 278 + | LinuxSyscall.MemfdCreate -> 279 + | LinuxSyscall.Bpf -> 280 + | LinuxSyscall.Execveat -> 281 + | LinuxSyscall.Userfaultfd -> 282 + | LinuxSyscall.Membarrier -> 283 + | LinuxSyscall.Mlock2 -> 284 + | LinuxSyscall.CopyFileRange -> 285 + | LinuxSyscall.Preadv2 -> 286 + | LinuxSyscall.Pwritev2 -> 287 + | LinuxSyscall.PkeyMprotect -> 288 + | LinuxSyscall.PkeyAlloc -> 289 + | LinuxSyscall.PkeyFree -> 290 + | LinuxSyscall.Statx -> 291 + | LinuxSyscall.IoPgetevents -> 292 + | LinuxSyscall.Rseq -> 293 + | LinuxSyscall.KexecFileLoad -> 294 + | LinuxSyscall.ClockGettime64 -> 403 + | LinuxSyscall.ClockSettime64 -> 404 + | LinuxSyscall.ClockAdjtime64 -> 405 + | LinuxSyscall.ClockGetres64 -> 406 + | LinuxSyscall.ClockNanosleep64 -> 407 + | LinuxSyscall.TimerGettime64 -> 408 + | LinuxSyscall.TimerSettime64 -> 409 + | LinuxSyscall.TimerfdGettime64 -> 410 + | LinuxSyscall.TimerfdSettime64 -> 411 + | LinuxSyscall.Utimensat64 -> 412 + | LinuxSyscall.Pselect6_64 -> 413 + | LinuxSyscall.Ppoll64 -> 414 + | LinuxSyscall.IoPgetevents64 -> 416 + | LinuxSyscall.Recvmmsg64 -> 417 + | LinuxSyscall.MqTimedsend64 -> 418 + | LinuxSyscall.MqTimedreceive64 -> 419 + | LinuxSyscall.Semtimedop64 -> 420 + | LinuxSyscall.RtSigtimedwait64 -> 421 + | LinuxSyscall.Futex64 -> 422 + | LinuxSyscall.SchedRrGetInterval64 -> 423 + | LinuxSyscall.PidfdSendSignal -> 424 + | LinuxSyscall.IoUringSetup -> 425 + | LinuxSyscall.IoUringEnter -> 426 + | LinuxSyscall.IoUringRegister -> 427 + | LinuxSyscall.OpenTree -> 428 + | LinuxSyscall.MoveMount -> 429 + | LinuxSyscall.Fsopen -> 430 + | LinuxSyscall.Fsconfig -> 431 + | LinuxSyscall.Fsmount -> 432 + | LinuxSyscall.Fspick -> 433 + | LinuxSyscall.PidfdOpen -> 434 + | LinuxSyscall.Clone3 -> 435 + | LinuxSyscall.CloseRange -> 436 + | LinuxSyscall.Openat2 -> 437 + | LinuxSyscall.PidfdGetfd -> 438 + | LinuxSyscall.Faccessat2 -> 439 + | _ -> raise UnhandledSyscallException + + /// Gets the syscall number for the given syscall at the given architecture. + [] let toNumber arch syscall = match arch with - | Arch.IntelX86 -> getX86Number syscall - | Arch.IntelX64 -> getX64Number syscall + | Architecture.IntelX86 -> getX86Number syscall + | Architecture.IntelX64 -> getX64Number syscall + | Architecture.ARMv7 | Architecture.AARCH32-> getARMEABINumber syscall + | Architecture.AARCH64 -> getAARCH64Number syscall + | Architecture.MIPS32 -> getMIPSO32Number syscall + | Architecture.MIPS64 -> getMIPSN64Number syscall + | Architecture.PPC32 -> getPPC32Number syscall + | Architecture.RISCV64 -> getRISCV64Number syscall | _ -> raise UnhandledSyscallException let private getX86Syscall = function @@ -1968,14 +4083,2137 @@ module LinuxSyscall = | 330 -> LinuxSyscall.PkeyAlloc | 331 -> LinuxSyscall.PkeyFree | 332 -> LinuxSyscall.Statx + | 333 -> LinuxSyscall.IoPgetevents + | 334 -> LinuxSyscall.Rseq + | _ -> raise UnhandledSyscallException + + let private getARMEABISyscall = function + | 0 -> LinuxSyscall.RestartSyscall + | 1 -> LinuxSyscall.Exit + | 2 -> LinuxSyscall.Fork + | 3 -> LinuxSyscall.Read + | 4 -> LinuxSyscall.Write + | 5 -> LinuxSyscall.Open + | 6 -> LinuxSyscall.Close + | 8 -> LinuxSyscall.Creat + | 9 -> LinuxSyscall.Link + | 10 -> LinuxSyscall.Unlink + | 11 -> LinuxSyscall.Execve + | 12 -> LinuxSyscall.Chdir + | 14 -> LinuxSyscall.Mknod + | 15 -> LinuxSyscall.Chmod + | 16 -> LinuxSyscall.Lchown + | 19 -> LinuxSyscall.Lseek + | 20 -> LinuxSyscall.Getpid + | 21 -> LinuxSyscall.Mount + | 23 -> LinuxSyscall.Setuid + | 24 -> LinuxSyscall.Getuid + | 26 -> LinuxSyscall.Ptrace + | 29 -> LinuxSyscall.Pause + | 33 -> LinuxSyscall.Access + | 34 -> LinuxSyscall.Nice + | 36 -> LinuxSyscall.Sync + | 37 -> LinuxSyscall.Kill + | 38 -> LinuxSyscall.Rename + | 39 -> LinuxSyscall.Mkdir + | 40 -> LinuxSyscall.Rmdir + | 41 -> LinuxSyscall.Dup + | 42 -> LinuxSyscall.Pipe + | 43 -> LinuxSyscall.Times + | 45 -> LinuxSyscall.Brk + | 46 -> LinuxSyscall.Setgid + | 47 -> LinuxSyscall.Getgid + | 49 -> LinuxSyscall.Geteuid + | 50 -> LinuxSyscall.Getegid + | 51 -> LinuxSyscall.Acct + | 52 -> LinuxSyscall.Umount2 + | 54 -> LinuxSyscall.Ioctl + | 55 -> LinuxSyscall.Fcntl + | 57 -> LinuxSyscall.Setpgid + | 60 -> LinuxSyscall.Umask + | 61 -> LinuxSyscall.Chroot + | 62 -> LinuxSyscall.Ustat + | 63 -> LinuxSyscall.Dup2 + | 64 -> LinuxSyscall.Getppid + | 65 -> LinuxSyscall.Getpgrp + | 66 -> LinuxSyscall.Setsid + | 67 -> LinuxSyscall.Sigaction + | 70 -> LinuxSyscall.Setreuid + | 71 -> LinuxSyscall.Setregid + | 72 -> LinuxSyscall.Sigsuspend + | 73 -> LinuxSyscall.Sigpending + | 74 -> LinuxSyscall.Sethostname + | 75 -> LinuxSyscall.Setrlimit + | 77 -> LinuxSyscall.Getrusage + | 78 -> LinuxSyscall.Gettimeofday + | 79 -> LinuxSyscall.Settimeofday + | 80 -> LinuxSyscall.Getgroups + | 81 -> LinuxSyscall.Setgroups + | 83 -> LinuxSyscall.Symlink + | 85 -> LinuxSyscall.Readlink + | 86 -> LinuxSyscall.Uselib + | 87 -> LinuxSyscall.Swapon + | 88 -> LinuxSyscall.Reboot + | 91 -> LinuxSyscall.Munmap + | 92 -> LinuxSyscall.Truncate + | 93 -> LinuxSyscall.Ftruncate + | 94 -> LinuxSyscall.Fchmod + | 95 -> LinuxSyscall.Fchown + | 96 -> LinuxSyscall.Getpriority + | 97 -> LinuxSyscall.Setpriority + | 99 -> LinuxSyscall.Statfs + | 100 -> LinuxSyscall.Fstatfs + | 103 -> LinuxSyscall.Syslog + | 104 -> LinuxSyscall.Setitimer + | 105 -> LinuxSyscall.Getitimer + | 106 -> LinuxSyscall.Stat + | 107 -> LinuxSyscall.Lstat + | 108 -> LinuxSyscall.Fstat + | 111 -> LinuxSyscall.Vhangup + | 114 -> LinuxSyscall.Wait4 + | 115 -> LinuxSyscall.Swapoff + | 116 -> LinuxSyscall.Sysinfo + | 118 -> LinuxSyscall.Fsync + | 119 -> LinuxSyscall.Sigreturn + | 120 -> LinuxSyscall.Clone + | 121 -> LinuxSyscall.Setdomainname + | 122 -> LinuxSyscall.Uname + | 124 -> LinuxSyscall.AdjTimex + | 125 -> LinuxSyscall.Mprotect + | 126 -> LinuxSyscall.Sigprocmask + | 128 -> LinuxSyscall.InitModule + | 129 -> LinuxSyscall.DeleteModule + | 131 -> LinuxSyscall.Quotactl + | 132 -> LinuxSyscall.Getpgid + | 133 -> LinuxSyscall.Fchdir + | 134 -> LinuxSyscall.Bdflush + | 135 -> LinuxSyscall.Sysfs + | 136 -> LinuxSyscall.Personality + | 138 -> LinuxSyscall.Setfsuid + | 139 -> LinuxSyscall.Setfsgid + | 140 -> LinuxSyscall.LLseek + | 141 -> LinuxSyscall.Getdents + | 142 -> LinuxSyscall.NewSelect + | 143 -> LinuxSyscall.Flock + | 144 -> LinuxSyscall.Msync + | 145 -> LinuxSyscall.Readv + | 146 -> LinuxSyscall.Writev + | 147 -> LinuxSyscall.Getsid + | 148 -> LinuxSyscall.Fdatasync + | 149 -> LinuxSyscall.Sysctl + | 150 -> LinuxSyscall.Mlock + | 151 -> LinuxSyscall.Munlock + | 152 -> LinuxSyscall.Mlockall + | 153 -> LinuxSyscall.Munlockall + | 154 -> LinuxSyscall.SchedSetparam + | 155 -> LinuxSyscall.SchedGetparam + | 156 -> LinuxSyscall.SchedSetscheduler + | 157 -> LinuxSyscall.SchedGetscheduler + | 158 -> LinuxSyscall.SchedYield + | 159 -> LinuxSyscall.SchedGetPriorityMax + | 160 -> LinuxSyscall.SchedGetPriorityMin + | 161 -> LinuxSyscall.SchedRrGetInterval + | 162 -> LinuxSyscall.Nanosleep + | 163 -> LinuxSyscall.Mremap + | 164 -> LinuxSyscall.Setresuid + | 165 -> LinuxSyscall.Getresuid + | 168 -> LinuxSyscall.Poll + | 169 -> LinuxSyscall.Nfsservctl + | 170 -> LinuxSyscall.Setresgid + | 171 -> LinuxSyscall.Getresgid + | 172 -> LinuxSyscall.Prctl + | 173 -> LinuxSyscall.RtSigreturn + | 174 -> LinuxSyscall.RtSigaction + | 175 -> LinuxSyscall.RtSigprocmask + | 176 -> LinuxSyscall.RtSigpending + | 177 -> LinuxSyscall.RtSigtimedwait + | 178 -> LinuxSyscall.RtSigqueueinfo + | 179 -> LinuxSyscall.RtSigsuspend + | 180 -> LinuxSyscall.Pread64 + | 181 -> LinuxSyscall.Pwrite64 + | 182 -> LinuxSyscall.Chown + | 183 -> LinuxSyscall.Getcwd + | 184 -> LinuxSyscall.CapGet + | 185 -> LinuxSyscall.CapSet + | 186 -> LinuxSyscall.Sigaltstack + | 187 -> LinuxSyscall.Sendfile + | 190 -> LinuxSyscall.Vfork + | 191 -> LinuxSyscall.Ugetrlimit + | 192 -> LinuxSyscall.Mmap2 + | 193 -> LinuxSyscall.Truncate64 + | 194 -> LinuxSyscall.Ftruncate64 + | 195 -> LinuxSyscall.Stat64 + | 196 -> LinuxSyscall.Lstat64 + | 197 -> LinuxSyscall.Fstat64 + | 198 -> LinuxSyscall.Lchown32 + | 199 -> LinuxSyscall.Getuid32 + | 200 -> LinuxSyscall.Getgid32 + | 201 -> LinuxSyscall.Geteuid32 + | 202 -> LinuxSyscall.Getegid32 + | 203 -> LinuxSyscall.Setreuid32 + | 204 -> LinuxSyscall.Setregid32 + | 205 -> LinuxSyscall.Getgroups32 + | 206 -> LinuxSyscall.Setgroups32 + | 207 -> LinuxSyscall.Fchown32 + | 208 -> LinuxSyscall.Setresuid32 + | 209 -> LinuxSyscall.Getresuid32 + | 210 -> LinuxSyscall.Setresgid32 + | 211 -> LinuxSyscall.Getresgid32 + | 212 -> LinuxSyscall.Chown32 + | 213 -> LinuxSyscall.Setuid32 + | 214 -> LinuxSyscall.Setgid32 + | 215 -> LinuxSyscall.Setfsuid32 + | 216 -> LinuxSyscall.Setfsgid32 + | 217 -> LinuxSyscall.Getdents64 + | 218 -> LinuxSyscall.PivotRoot + | 219 -> LinuxSyscall.Mincore + | 220 -> LinuxSyscall.Madvise + | 221 -> LinuxSyscall.Fcntl64 + | 224 -> LinuxSyscall.Gettid + | 225 -> LinuxSyscall.Readahead + | 226 -> LinuxSyscall.Setxattr + | 227 -> LinuxSyscall.Lsetxattr + | 228 -> LinuxSyscall.Fsetxattr + | 229 -> LinuxSyscall.Getxattr + | 230 -> LinuxSyscall.Lgetxattr + | 231 -> LinuxSyscall.Fgetxattr + | 232 -> LinuxSyscall.Listxattr + | 233 -> LinuxSyscall.Llistxattr + | 234 -> LinuxSyscall.Flistxattr + | 235 -> LinuxSyscall.Removexattr + | 236 -> LinuxSyscall.Lremovexattr + | 237 -> LinuxSyscall.Fremovexattr + | 238 -> LinuxSyscall.Tkill + | 239 -> LinuxSyscall.Sendfile64 + | 240 -> LinuxSyscall.Futex + | 241 -> LinuxSyscall.SchedSetaffinity + | 242 -> LinuxSyscall.SchedGetaffinity + | 243 -> LinuxSyscall.IoSetup + | 244 -> LinuxSyscall.IoDestroy + | 245 -> LinuxSyscall.IoGetevents + | 246 -> LinuxSyscall.IoSubmit + | 247 -> LinuxSyscall.IoCancel + | 248 -> LinuxSyscall.ExitGroup + | 249 -> LinuxSyscall.LookupDcookie + | 250 -> LinuxSyscall.EpollCreate + | 251 -> LinuxSyscall.EpollCtl + | 252 -> LinuxSyscall.EpollWait + | 253 -> LinuxSyscall.RemapFilePages + | 256 -> LinuxSyscall.SetTidAddress + | 257 -> LinuxSyscall.TimerCreate + | 258 -> LinuxSyscall.TimerSettime + | 259 -> LinuxSyscall.TimerGettime + | 260 -> LinuxSyscall.TimerGetoverrun + | 261 -> LinuxSyscall.TimerDelete + | 262 -> LinuxSyscall.ClockSettime + | 263 -> LinuxSyscall.ClockGettime + | 264 -> LinuxSyscall.ClockGetres + | 265 -> LinuxSyscall.ClockNanosleep + | 266 -> LinuxSyscall.Statfs64 + | 267 -> LinuxSyscall.Fstatfs64 + | 268 -> LinuxSyscall.Tgkill + | 269 -> LinuxSyscall.Utimes + | 270 -> LinuxSyscall.ArmFadvise64 + | 271 -> LinuxSyscall.PciconfigIobase + | 272 -> LinuxSyscall.PciconfigRead + | 273 -> LinuxSyscall.PciconfigWrite + | 274 -> LinuxSyscall.MqOpen + | 275 -> LinuxSyscall.MqUnlink + | 276 -> LinuxSyscall.MqTimedsend + | 277 -> LinuxSyscall.MqTimedreceive + | 278 -> LinuxSyscall.MqNotify + | 279 -> LinuxSyscall.MqGetsetattr + | 280 -> LinuxSyscall.Waitid + | 281 -> LinuxSyscall.Socket + | 282 -> LinuxSyscall.Bind + | 283 -> LinuxSyscall.Connect + | 284 -> LinuxSyscall.Listen + | 285 -> LinuxSyscall.Accept + | 286 -> LinuxSyscall.Getsockname + | 287 -> LinuxSyscall.Getpeername + | 288 -> LinuxSyscall.Socketpair + | 289 -> LinuxSyscall.Send + | 290 -> LinuxSyscall.Sendto + | 291 -> LinuxSyscall.Recv + | 292 -> LinuxSyscall.Recvfrom + | 293 -> LinuxSyscall.Shutdown + | 294 -> LinuxSyscall.Setsockopt + | 295 -> LinuxSyscall.Getsockopt + | 296 -> LinuxSyscall.Sendmsg + | 297 -> LinuxSyscall.Recvmsg + | 298 -> LinuxSyscall.Semop + | 299 -> LinuxSyscall.Semget + | 300 -> LinuxSyscall.Semctl + | 301 -> LinuxSyscall.Msgsnd + | 302 -> LinuxSyscall.Msgrcv + | 303 -> LinuxSyscall.Msgget + | 304 -> LinuxSyscall.Msgctl + | 305 -> LinuxSyscall.Shmat + | 306 -> LinuxSyscall.Shmdt + | 307 -> LinuxSyscall.Shmget + | 308 -> LinuxSyscall.Shmctl + | 309 -> LinuxSyscall.AddKey + | 310 -> LinuxSyscall.RequestKey + | 311 -> LinuxSyscall.Keyctl + | 312 -> LinuxSyscall.Semtimedop + | 313 -> LinuxSyscall.Vserver + | 314 -> LinuxSyscall.IoprioSet + | 315 -> LinuxSyscall.IoprioGet + | 316 -> LinuxSyscall.InotifyInit + | 317 -> LinuxSyscall.InotifyAddWatch + | 318 -> LinuxSyscall.InotifyRmWatch + | 319 -> LinuxSyscall.Mbind + | 320 -> LinuxSyscall.GetMempolicy + | 321 -> LinuxSyscall.SetMempolicy + | 322 -> LinuxSyscall.Openat + | 323 -> LinuxSyscall.Mkdirat + | 324 -> LinuxSyscall.Mknodat + | 325 -> LinuxSyscall.Fchownat + | 326 -> LinuxSyscall.Futimesat + | 327 -> LinuxSyscall.Fstatat64 + | 328 -> LinuxSyscall.Unlinkat + | 329 -> LinuxSyscall.Renameat + | 330 -> LinuxSyscall.Linkat + | 331 -> LinuxSyscall.Symlinkat + | 332 -> LinuxSyscall.Readlinkat + | 333 -> LinuxSyscall.Fchmodat + | 334 -> LinuxSyscall.Faccessat + | 335 -> LinuxSyscall.Pselect6 + | 336 -> LinuxSyscall.Ppoll + | 337 -> LinuxSyscall.Unshare + | 338 -> LinuxSyscall.SetRobustList + | 339 -> LinuxSyscall.GetRobustList + | 340 -> LinuxSyscall.Splice + | 341 -> LinuxSyscall.ArmSyncFileRange + | 342 -> LinuxSyscall.Tee + | 343 -> LinuxSyscall.Vmsplice + | 344 -> LinuxSyscall.MovePages + | 345 -> LinuxSyscall.Getcpu + | 346 -> LinuxSyscall.EpollPwait + | 347 -> LinuxSyscall.KexecLoad + | 348 -> LinuxSyscall.Utimensat + | 349 -> LinuxSyscall.Signalfd + | 350 -> LinuxSyscall.TimerfdCreate + | 351 -> LinuxSyscall.Eventfd + | 352 -> LinuxSyscall.Fallocate + | 353 -> LinuxSyscall.TimerfdSettime + | 354 -> LinuxSyscall.TimerfdGettime + | 355 -> LinuxSyscall.Signalfd4 + | 356 -> LinuxSyscall.Eventfd2 + | 357 -> LinuxSyscall.EpollCreate1 + | 358 -> LinuxSyscall.Dup3 + | 359 -> LinuxSyscall.Pipe2 + | 360 -> LinuxSyscall.InotifyInit1 + | 361 -> LinuxSyscall.Preadv + | 362 -> LinuxSyscall.Pwritev + | 363 -> LinuxSyscall.RtTgsigqueueinfo + | 364 -> LinuxSyscall.PerfEventOpen + | 365 -> LinuxSyscall.Recvmmsg + | 366 -> LinuxSyscall.Accept4 + | 367 -> LinuxSyscall.FanotifyInit + | 368 -> LinuxSyscall.FanotifyMark + | 369 -> LinuxSyscall.Prlimit64 + | 370 -> LinuxSyscall.NameToHandleAt + | 371 -> LinuxSyscall.OpenByHandleAt + | 372 -> LinuxSyscall.ClockAdjtime + | 373 -> LinuxSyscall.Syncfs + | 374 -> LinuxSyscall.Sendmmsg + | 375 -> LinuxSyscall.Setns + | 376 -> LinuxSyscall.ProcessVmReadv + | 377 -> LinuxSyscall.ProcessVmWritev + | 378 -> LinuxSyscall.Kcmp + | 379 -> LinuxSyscall.FinitModule + | 380 -> LinuxSyscall.SchedSetattr + | 381 -> LinuxSyscall.SchedGetattr + | 382 -> LinuxSyscall.Renameat2 + | 383 -> LinuxSyscall.Seccomp + | 384 -> LinuxSyscall.Getrandom + | 385 -> LinuxSyscall.MemfdCreate + | 386 -> LinuxSyscall.Bpf + | 387 -> LinuxSyscall.Execveat + | 388 -> LinuxSyscall.Userfaultfd + | 389 -> LinuxSyscall.Membarrier + | 390 -> LinuxSyscall.Mlock2 + | 391 -> LinuxSyscall.CopyFileRange + | 392 -> LinuxSyscall.Preadv2 + | 393 -> LinuxSyscall.Pwritev2 + | 394 -> LinuxSyscall.PkeyMprotect + | 395 -> LinuxSyscall.PkeyAlloc + | 396 -> LinuxSyscall.PkeyFree + | 397 -> LinuxSyscall.Statx + | 398 -> LinuxSyscall.Rseq + | 399 -> LinuxSyscall.IoPgetevents + | 400 -> LinuxSyscall.MigratePages + | 401 -> LinuxSyscall.KexecFileLoad + | 403 -> LinuxSyscall.ClockGettime64 + | 404 -> LinuxSyscall.ClockSettime64 + | 405 -> LinuxSyscall.ClockAdjtime64 + | 408 -> LinuxSyscall.TimerGettime64 + | 409 -> LinuxSyscall.TimerSettime64 + | 410 -> LinuxSyscall.TimerfdGettime64 + | 411 -> LinuxSyscall.TimerfdSettime64 + | 412 -> LinuxSyscall.Utimensat64 + | 413 -> LinuxSyscall.Pselect6_64 + | 414 -> LinuxSyscall.Ppoll64 + | 416 -> LinuxSyscall.IoPgetevents64 + | 417 -> LinuxSyscall.Recvmmsg64 + | 418 -> LinuxSyscall.MqTimedsend64 + | 419 -> LinuxSyscall.MqTimedreceive64 + | 420 -> LinuxSyscall.Semtimedop64 + | 421 -> LinuxSyscall.RtSigtimedwait64 + | 422 -> LinuxSyscall.Futex64 + | 423 -> LinuxSyscall.SchedRrGetInterval64 + | 424 -> LinuxSyscall.PidfdSendSignal + | 425 -> LinuxSyscall.IoUringSetup + | 426 -> LinuxSyscall.IoUringEnter + | 427 -> LinuxSyscall.IoUringRegister + | 428 -> LinuxSyscall.OpenTree + | 429 -> LinuxSyscall.MoveMount + | 430 -> LinuxSyscall.Fsopen + | 431 -> LinuxSyscall.Fsconfig + | 432 -> LinuxSyscall.Fsmount + | 433 -> LinuxSyscall.Fspick + | 434 -> LinuxSyscall.PidfdOpen + | 435 -> LinuxSyscall.Clone3 + | 437 -> LinuxSyscall.Openat2 + | 438 -> LinuxSyscall.PidfdGetfd + | 0x0f0001 -> LinuxSyscall.Breakpoint (* __ARM_NR_breakpoint *) + | 0x0f0002 -> LinuxSyscall.CacheFlush (* __ARM_NR_cacheflush *) + | 0x0f0003 -> LinuxSyscall.Usr26 (* __ARM_NR_usr26 *) + | 0x0f0004 -> LinuxSyscall.Usr32 (* __ARM_NR_usr32 *) + | 0x0f0005 -> LinuxSyscall.SetTLS (* __ARM_NR_set_tls *) + | 0x0f0006 -> LinuxSyscall.GetTLS (* __ARM_NR_get_tls *) + | _ -> raise UnhandledSyscallException + + let private getAARCH64Syscall = function + | 0 -> LinuxSyscall.IoSetup + | 1 -> LinuxSyscall.IoDestroy + | 2 -> LinuxSyscall.IoSubmit + | 3 -> LinuxSyscall.IoCancel + | 4 -> LinuxSyscall.IoGetevents + | 5 -> LinuxSyscall.Setxattr + | 6 -> LinuxSyscall.Lsetxattr + | 7 -> LinuxSyscall.Fsetxattr + | 8 -> LinuxSyscall.Getxattr + | 9 -> LinuxSyscall.Lgetxattr + | 10 -> LinuxSyscall.Fgetxattr + | 11 -> LinuxSyscall.Listxattr + | 12 -> LinuxSyscall.Llistxattr + | 13 -> LinuxSyscall.Flistxattr + | 14 -> LinuxSyscall.Removexattr + | 15 -> LinuxSyscall.Lremovexattr + | 16 -> LinuxSyscall.Fremovexattr + | 17 -> LinuxSyscall.Getcwd + | 18 -> LinuxSyscall.LookupDcookie + | 19 -> LinuxSyscall.Eventfd2 + | 20 -> LinuxSyscall.EpollCreate1 + | 21 -> LinuxSyscall.EpollCtl + | 22 -> LinuxSyscall.EpollPwait + | 23 -> LinuxSyscall.Dup + | 24 -> LinuxSyscall.Dup3 + | 25 -> LinuxSyscall.Fcntl + | 26 -> LinuxSyscall.InotifyInit1 + | 27 -> LinuxSyscall.InotifyAddWatch + | 28 -> LinuxSyscall.InotifyRmWatch + | 29 -> LinuxSyscall.Ioctl + | 30 -> LinuxSyscall.IoprioSet + | 31 -> LinuxSyscall.IoprioGet + | 32 -> LinuxSyscall.Flock + | 33 -> LinuxSyscall.Mknodat + | 34 -> LinuxSyscall.Mkdirat + | 35 -> LinuxSyscall.Unlinkat + | 36 -> LinuxSyscall.Symlinkat + | 37 -> LinuxSyscall.Linkat + | 38 -> LinuxSyscall.Renameat + | 39 -> LinuxSyscall.Umount2 + | 40 -> LinuxSyscall.Mount + | 41 -> LinuxSyscall.PivotRoot + | 42 -> LinuxSyscall.Nfsservctl + | 43 -> LinuxSyscall.Statfs + | 44 -> LinuxSyscall.Fstatfs + | 45 -> LinuxSyscall.Truncate + | 46 -> LinuxSyscall.Ftruncate + | 47 -> LinuxSyscall.Fallocate + | 48 -> LinuxSyscall.Faccessat + | 49 -> LinuxSyscall.Chdir + | 50 -> LinuxSyscall.Fchdir + | 51 -> LinuxSyscall.Chroot + | 52 -> LinuxSyscall.Fchmod + | 53 -> LinuxSyscall.Fchmodat + | 54 -> LinuxSyscall.Fchownat + | 55 -> LinuxSyscall.Fchown + | 56 -> LinuxSyscall.Openat + | 57 -> LinuxSyscall.Close + | 58 -> LinuxSyscall.Vhangup + | 59 -> LinuxSyscall.Pipe2 + | 60 -> LinuxSyscall.Quotactl + | 61 -> LinuxSyscall.Getdents64 + | 62 -> LinuxSyscall.Lseek + | 63 -> LinuxSyscall.Read + | 64 -> LinuxSyscall.Write + | 65 -> LinuxSyscall.Readv + | 66 -> LinuxSyscall.Writev + | 67 -> LinuxSyscall.Pread64 + | 68 -> LinuxSyscall.Pwrite64 + | 69 -> LinuxSyscall.Preadv + | 70 -> LinuxSyscall.Pwritev + | 71 -> LinuxSyscall.Sendfile + | 72 -> LinuxSyscall.Pselect6 + | 73 -> LinuxSyscall.Ppoll + | 74 -> LinuxSyscall.Signalfd4 + | 75 -> LinuxSyscall.Vmsplice + | 76 -> LinuxSyscall.Splice + | 77 -> LinuxSyscall.Tee + | 78 -> LinuxSyscall.Readlinkat + | 79 -> LinuxSyscall.Newfstatat + | 80 -> LinuxSyscall.Fstat + | 81 -> LinuxSyscall.Sync + | 82 -> LinuxSyscall.Fsync + | 83 -> LinuxSyscall.Fdatasync + | 84 -> LinuxSyscall.SyncFileRange + | 85 -> LinuxSyscall.TimerfdCreate + | 86 -> LinuxSyscall.TimerfdSettime + | 87 -> LinuxSyscall.TimerfdGettime + | 88 -> LinuxSyscall.Utimensat + | 89 -> LinuxSyscall.Acct + | 90 -> LinuxSyscall.CapGet + | 91 -> LinuxSyscall.CapSet + | 92 -> LinuxSyscall.Personality + | 93 -> LinuxSyscall.Exit + | 94 -> LinuxSyscall.ExitGroup + | 95 -> LinuxSyscall.Waitid + | 96 -> LinuxSyscall.SetTidAddress + | 97 -> LinuxSyscall.Unshare + | 98 -> LinuxSyscall.Futex + | 99 -> LinuxSyscall.SetRobustList + | 100 -> LinuxSyscall.GetRobustList + | 101 -> LinuxSyscall.Nanosleep + | 102 -> LinuxSyscall.Getitimer + | 103 -> LinuxSyscall.Setitimer + | 104 -> LinuxSyscall.KexecLoad + | 105 -> LinuxSyscall.InitModule + | 106 -> LinuxSyscall.DeleteModule + | 107 -> LinuxSyscall.TimerCreate + | 108 -> LinuxSyscall.TimerGettime + | 109 -> LinuxSyscall.TimerGetoverrun + | 110 -> LinuxSyscall.TimerSettime + | 111 -> LinuxSyscall.TimerDelete + | 112 -> LinuxSyscall.ClockSettime + | 113 -> LinuxSyscall.ClockGettime + | 114 -> LinuxSyscall.ClockGetres + | 115 -> LinuxSyscall.ClockNanosleep + | 116 -> LinuxSyscall.Syslog + | 117 -> LinuxSyscall.Ptrace + | 118 -> LinuxSyscall.SchedSetparam + | 119 -> LinuxSyscall.SchedSetscheduler + | 120 -> LinuxSyscall.SchedGetscheduler + | 121 -> LinuxSyscall.SchedGetparam + | 122 -> LinuxSyscall.SchedSetaffinity + | 123 -> LinuxSyscall.SchedGetaffinity + | 124 -> LinuxSyscall.SchedYield + | 125 -> LinuxSyscall.SchedGetPriorityMax + | 126 -> LinuxSyscall.SchedGetPriorityMin + | 127 -> LinuxSyscall.SchedRrGetInterval + | 128 -> LinuxSyscall.RestartSyscall + | 129 -> LinuxSyscall.Kill + | 130 -> LinuxSyscall.Tkill + | 131 -> LinuxSyscall.Tgkill + | 132 -> LinuxSyscall.Sigaltstack + | 133 -> LinuxSyscall.RtSigsuspend + | 134 -> LinuxSyscall.RtSigaction + | 135 -> LinuxSyscall.RtSigprocmask + | 136 -> LinuxSyscall.RtSigpending + | 137 -> LinuxSyscall.RtSigtimedwait + | 138 -> LinuxSyscall.RtSigqueueinfo + | 139 -> LinuxSyscall.RtSigreturn + | 140 -> LinuxSyscall.Setpriority + | 141 -> LinuxSyscall.Getpriority + | 142 -> LinuxSyscall.Reboot + | 143 -> LinuxSyscall.Setregid + | 144 -> LinuxSyscall.Setgid + | 145 -> LinuxSyscall.Setreuid + | 146 -> LinuxSyscall.Setuid + | 147 -> LinuxSyscall.Setresuid + | 148 -> LinuxSyscall.Getresuid + | 149 -> LinuxSyscall.Setresgid + | 150 -> LinuxSyscall.Getresgid + | 151 -> LinuxSyscall.Setfsuid + | 152 -> LinuxSyscall.Setfsgid + | 153 -> LinuxSyscall.Times + | 154 -> LinuxSyscall.Setpgid + | 155 -> LinuxSyscall.Getpgid + | 156 -> LinuxSyscall.Getsid + | 157 -> LinuxSyscall.Setsid + | 158 -> LinuxSyscall.Getgroups + | 159 -> LinuxSyscall.Setgroups + | 160 -> LinuxSyscall.Uname + | 161 -> LinuxSyscall.Sethostname + | 162 -> LinuxSyscall.Setdomainname + | 163 -> LinuxSyscall.Getrlimit + | 164 -> LinuxSyscall.Setrlimit + | 165 -> LinuxSyscall.Getrusage + | 166 -> LinuxSyscall.Umask + | 167 -> LinuxSyscall.Prctl + | 168 -> LinuxSyscall.Getcpu + | 169 -> LinuxSyscall.Gettimeofday + | 170 -> LinuxSyscall.Settimeofday + | 171 -> LinuxSyscall.AdjTimex + | 172 -> LinuxSyscall.Getpid + | 173 -> LinuxSyscall.Getppid + | 174 -> LinuxSyscall.Getuid + | 175 -> LinuxSyscall.Geteuid + | 176 -> LinuxSyscall.Getgid + | 177 -> LinuxSyscall.Getegid + | 178 -> LinuxSyscall.Gettid + | 179 -> LinuxSyscall.Sysinfo + | 180 -> LinuxSyscall.MqOpen + | 181 -> LinuxSyscall.MqUnlink + | 182 -> LinuxSyscall.MqTimedsend + | 183 -> LinuxSyscall.MqTimedreceive + | 184 -> LinuxSyscall.MqNotify + | 185 -> LinuxSyscall.MqGetsetattr + | 186 -> LinuxSyscall.Msgget + | 187 -> LinuxSyscall.Msgctl + | 188 -> LinuxSyscall.Msgrcv + | 189 -> LinuxSyscall.Msgsnd + | 190 -> LinuxSyscall.Semget + | 191 -> LinuxSyscall.Semctl + | 192 -> LinuxSyscall.Semtimedop + | 193 -> LinuxSyscall.Semop + | 194 -> LinuxSyscall.Shmget + | 195 -> LinuxSyscall.Shmctl + | 196 -> LinuxSyscall.Shmat + | 197 -> LinuxSyscall.Shmdt + | 198 -> LinuxSyscall.Socket + | 199 -> LinuxSyscall.Socketpair + | 200 -> LinuxSyscall.Bind + | 201 -> LinuxSyscall.Listen + | 202 -> LinuxSyscall.Accept + | 203 -> LinuxSyscall.Connect + | 204 -> LinuxSyscall.Getsockname + | 205 -> LinuxSyscall.Getpeername + | 206 -> LinuxSyscall.Sendto + | 207 -> LinuxSyscall.Recvfrom + | 208 -> LinuxSyscall.Setsockopt + | 209 -> LinuxSyscall.Getsockopt + | 210 -> LinuxSyscall.Shutdown + | 211 -> LinuxSyscall.Sendmsg + | 212 -> LinuxSyscall.Recvmsg + | 213 -> LinuxSyscall.Readahead + | 214 -> LinuxSyscall.Brk + | 215 -> LinuxSyscall.Munmap + | 216 -> LinuxSyscall.Mremap + | 217 -> LinuxSyscall.AddKey + | 218 -> LinuxSyscall.RequestKey + | 219 -> LinuxSyscall.Keyctl + | 220 -> LinuxSyscall.Clone + | 221 -> LinuxSyscall.Execve + | 222 -> LinuxSyscall.Mmap + | 223 -> LinuxSyscall.Fadvise64 + | 224 -> LinuxSyscall.Swapon + | 225 -> LinuxSyscall.Swapoff + | 226 -> LinuxSyscall.Mprotect + | 227 -> LinuxSyscall.Msync + | 228 -> LinuxSyscall.Mlock + | 229 -> LinuxSyscall.Munlock + | 230 -> LinuxSyscall.Mlockall + | 231 -> LinuxSyscall.Munlockall + | 232 -> LinuxSyscall.Mincore + | 233 -> LinuxSyscall.Madvise + | 234 -> LinuxSyscall.RemapFilePages + | 235 -> LinuxSyscall.Mbind + | 236 -> LinuxSyscall.GetMempolicy + | 237 -> LinuxSyscall.SetMempolicy + | 238 -> LinuxSyscall.MigratePages + | 239 -> LinuxSyscall.MovePages + | 240 -> LinuxSyscall.RtTgsigqueueinfo + | 241 -> LinuxSyscall.PerfEventOpen + | 242 -> LinuxSyscall.Accept4 + | 243 -> LinuxSyscall.Recvmmsg + | 260 -> LinuxSyscall.Wait4 + | 261 -> LinuxSyscall.Prlimit64 + | 262 -> LinuxSyscall.FanotifyInit + | 263 -> LinuxSyscall.FanotifyMark + | 264 -> LinuxSyscall.NameToHandleAt + | 265 -> LinuxSyscall.OpenByHandleAt + | 266 -> LinuxSyscall.ClockAdjtime + | 267 -> LinuxSyscall.Syncfs + | 268 -> LinuxSyscall.Setns + | 269 -> LinuxSyscall.Sendmmsg + | 270 -> LinuxSyscall.ProcessVmReadv + | 271 -> LinuxSyscall.ProcessVmWritev + | 272 -> LinuxSyscall.Kcmp + | 273 -> LinuxSyscall.FinitModule + | 274 -> LinuxSyscall.SchedSetattr + | 275 -> LinuxSyscall.SchedGetattr + | 276 -> LinuxSyscall.Renameat2 + | 277 -> LinuxSyscall.Seccomp + | 278 -> LinuxSyscall.Getrandom + | 279 -> LinuxSyscall.MemfdCreate + | 280 -> LinuxSyscall.Bpf + | 281 -> LinuxSyscall.Execveat + | 282 -> LinuxSyscall.Userfaultfd + | 283 -> LinuxSyscall.Membarrier + | 284 -> LinuxSyscall.Mlock2 + | 285 -> LinuxSyscall.CopyFileRange + | 286 -> LinuxSyscall.Preadv2 + | 287 -> LinuxSyscall.Pwritev2 + | 288 -> LinuxSyscall.PkeyMprotect + | 289 -> LinuxSyscall.PkeyAlloc + | 290 -> LinuxSyscall.PkeyFree + | 291 -> LinuxSyscall.Statx + | 292 -> LinuxSyscall.IoPgetevents + | 293 -> LinuxSyscall.Rseq + | 294 -> LinuxSyscall.KexecFileLoad + | 403 -> LinuxSyscall.ClockGettime64 + | 404 -> LinuxSyscall.ClockSettime64 + | 405 -> LinuxSyscall.ClockAdjtime64 + | 406 -> LinuxSyscall.ClockGetres64 + | 407 -> LinuxSyscall.ClockNanosleep64 + | 408 -> LinuxSyscall.TimerGettime64 + | 409 -> LinuxSyscall.TimerSettime64 + | 410 -> LinuxSyscall.TimerfdGettime64 + | 411 -> LinuxSyscall.TimerfdSettime64 + | 412 -> LinuxSyscall.Utimensat64 + | 413 -> LinuxSyscall.Pselect6_64 + | 414 -> LinuxSyscall.Ppoll64 + | 416 -> LinuxSyscall.IoPgetevents64 + | 417 -> LinuxSyscall.Recvmmsg64 + | 418 -> LinuxSyscall.MqTimedsend64 + | 419 -> LinuxSyscall.MqTimedreceive64 + | 420 -> LinuxSyscall.Semtimedop64 + | 421 -> LinuxSyscall.RtSigtimedwait64 + | 422 -> LinuxSyscall.Futex64 + | 423 -> LinuxSyscall.SchedRrGetInterval64 + | 424 -> LinuxSyscall.PidfdSendSignal + | 425 -> LinuxSyscall.IoUringSetup + | 426 -> LinuxSyscall.IoUringEnter + | 427 -> LinuxSyscall.IoUringRegister + | 428 -> LinuxSyscall.OpenTree + | 429 -> LinuxSyscall.MoveMount + | 430 -> LinuxSyscall.Fsopen + | 431 -> LinuxSyscall.Fsconfig + | 432 -> LinuxSyscall.Fsmount + | 433 -> LinuxSyscall.Fspick + | 434 -> LinuxSyscall.PidfdOpen + | 435 -> LinuxSyscall.Clone3 + | 437 -> LinuxSyscall.Openat2 + | 438 -> LinuxSyscall.PidfdGetfd + | 439 -> LinuxSyscall.Faccessat + | _ -> raise UnhandledSyscallException + + let private getMIPSO32Syscall = function + | 4001 -> LinuxSyscall.Exit + | 4002 -> LinuxSyscall.Fork + | 4003 -> LinuxSyscall.Read + | 4004 -> LinuxSyscall.Write + | 4005 -> LinuxSyscall.Open + | 4006 -> LinuxSyscall.Close + | 4007 -> LinuxSyscall.Waitpid + | 4008 -> LinuxSyscall.Creat + | 4009 -> LinuxSyscall.Link + | 4010 -> LinuxSyscall.Unlink + | 4011 -> LinuxSyscall.Execve + | 4012 -> LinuxSyscall.Chdir + | 4013 -> LinuxSyscall.Time + | 4014 -> LinuxSyscall.Mknod + | 4015 -> LinuxSyscall.Chmod + | 4016 -> LinuxSyscall.Lchown + | 4017 -> LinuxSyscall.Breakpoint + | 4019 -> LinuxSyscall.Lseek + | 4020 -> LinuxSyscall.Getpid + | 4021 -> LinuxSyscall.Mount + | 4022 -> LinuxSyscall.Umount + | 4023 -> LinuxSyscall.Setuid + | 4024 -> LinuxSyscall.Getuid + | 4025 -> LinuxSyscall.Stime + | 4026 -> LinuxSyscall.Ptrace + | 4027 -> LinuxSyscall.Alarm + | 4029 -> LinuxSyscall.Pause + | 4030 -> LinuxSyscall.Utime + | 4033 -> LinuxSyscall.Access + | 4034 -> LinuxSyscall.Nice + | 4036 -> LinuxSyscall.Sync + | 4037 -> LinuxSyscall.Kill + | 4038 -> LinuxSyscall.Rename + | 4039 -> LinuxSyscall.Mkdir + | 4040 -> LinuxSyscall.Rmdir + | 4041 -> LinuxSyscall.Dup + | 4042 -> LinuxSyscall.Pipe + | 4043 -> LinuxSyscall.Times + | 4045 -> LinuxSyscall.Brk + | 4046 -> LinuxSyscall.Setgid + | 4047 -> LinuxSyscall.Getgid + | 4048 -> LinuxSyscall.Signal + | 4049 -> LinuxSyscall.Geteuid + | 4050 -> LinuxSyscall.Getegid + | 4051 -> LinuxSyscall.Acct + | 4052 -> LinuxSyscall.Umount2 + | 4054 -> LinuxSyscall.Ioctl + | 4055 -> LinuxSyscall.Fcntl + | 4057 -> LinuxSyscall.Setpgid + | 4060 -> LinuxSyscall.Umask + | 4061 -> LinuxSyscall.Chroot + | 4062 -> LinuxSyscall.Ustat + | 4063 -> LinuxSyscall.Dup2 + | 4064 -> LinuxSyscall.Getppid + | 4065 -> LinuxSyscall.Getpgrp + | 4066 -> LinuxSyscall.Setsid + | 4067 -> LinuxSyscall.Sigaction + | 4068 -> LinuxSyscall.Sgetmask + | 4069 -> LinuxSyscall.Ssetmask + | 4070 -> LinuxSyscall.Setreuid + | 4071 -> LinuxSyscall.Setregid + | 4072 -> LinuxSyscall.Sigsuspend + | 4073 -> LinuxSyscall.Sigpending + | 4074 -> LinuxSyscall.Sethostname + | 4075 -> LinuxSyscall.Setrlimit + | 4076 -> LinuxSyscall.Getrlimit + | 4077 -> LinuxSyscall.Getrusage + | 4078 -> LinuxSyscall.Gettimeofday + | 4079 -> LinuxSyscall.Settimeofday + | 4080 -> LinuxSyscall.Getgroups + | 4081 -> LinuxSyscall.Setgroups + | 4083 -> LinuxSyscall.Symlink + | 4085 -> LinuxSyscall.Readlink + | 4086 -> LinuxSyscall.Uselib + | 4087 -> LinuxSyscall.Swapon + | 4088 -> LinuxSyscall.Reboot + | 4089 -> LinuxSyscall.Readdir + | 4090 -> LinuxSyscall.Mmap + | 4091 -> LinuxSyscall.Munmap + | 4092 -> LinuxSyscall.Truncate + | 4093 -> LinuxSyscall.Ftruncate + | 4094 -> LinuxSyscall.Fchmod + | 4095 -> LinuxSyscall.Fchown + | 4096 -> LinuxSyscall.Getpriority + | 4097 -> LinuxSyscall.Setpriority + | 4099 -> LinuxSyscall.Statfs + | 4100 -> LinuxSyscall.Fstatfs + | 4101 -> LinuxSyscall.Ioperm + | 4102 -> LinuxSyscall.Socketcall + | 4103 -> LinuxSyscall.Syslog + | 4104 -> LinuxSyscall.Setitimer + | 4105 -> LinuxSyscall.Getitimer + | 4106 -> LinuxSyscall.Stat + | 4107 -> LinuxSyscall.Lstat + | 4108 -> LinuxSyscall.Fstat + | 4110 -> LinuxSyscall.Iopl + | 4111 -> LinuxSyscall.Vhangup + | 4113 -> LinuxSyscall.Vm86 + | 4114 -> LinuxSyscall.Wait4 + | 4115 -> LinuxSyscall.Swapoff + | 4116 -> LinuxSyscall.Sysinfo + | 4117 -> LinuxSyscall.Ipc + | 4118 -> LinuxSyscall.Fsync + | 4119 -> LinuxSyscall.Sigreturn + | 4120 -> LinuxSyscall.Clone + | 4121 -> LinuxSyscall.Setdomainname + | 4122 -> LinuxSyscall.Uname + | 4123 -> LinuxSyscall.ModifyLdt + | 4124 -> LinuxSyscall.OldAdjtimex + | 4125 -> LinuxSyscall.Mprotect + | 4126 -> LinuxSyscall.Sigprocmask + | 4127 -> LinuxSyscall.CreateModule + | 4128 -> LinuxSyscall.InitModule + | 4129 -> LinuxSyscall.DeleteModule + | 4130 -> LinuxSyscall.GetKernelSyms + | 4131 -> LinuxSyscall.Quotactl + | 4132 -> LinuxSyscall.Getpgid + | 4133 -> LinuxSyscall.Fchdir + | 4134 -> LinuxSyscall.Bdflush + | 4135 -> LinuxSyscall.Sysfs + | 4136 -> LinuxSyscall.Personality + | 4138 -> LinuxSyscall.Setfsuid + | 4139 -> LinuxSyscall.Setfsgid + | 4140 -> LinuxSyscall.LLseek + | 4141 -> LinuxSyscall.Getdents + | 4142 -> LinuxSyscall.NewSelect + | 4143 -> LinuxSyscall.Flock + | 4144 -> LinuxSyscall.Msync + | 4145 -> LinuxSyscall.Readv + | 4146 -> LinuxSyscall.Writev + | 4147 -> LinuxSyscall.CacheFlush + | 4149 -> LinuxSyscall.Sysmips + | 4151 -> LinuxSyscall.Getsid + | 4152 -> LinuxSyscall.Fdatasync + | 4154 -> LinuxSyscall.Mlock + | 4155 -> LinuxSyscall.Munlock + | 4156 -> LinuxSyscall.Mlockall + | 4157 -> LinuxSyscall.Munlockall + | 4158 -> LinuxSyscall.SchedSetparam + | 4159 -> LinuxSyscall.SchedGetparam + | 4160 -> LinuxSyscall.SchedSetscheduler + | 4161 -> LinuxSyscall.SchedGetscheduler + | 4162 -> LinuxSyscall.SchedYield + | 4163 -> LinuxSyscall.SchedGetPriorityMax + | 4164 -> LinuxSyscall.SchedGetPriorityMin + | 4165 -> LinuxSyscall.SchedRrGetInterval + | 4166 -> LinuxSyscall.Nanosleep + | 4167 -> LinuxSyscall.Mremap + | 4168 -> LinuxSyscall.Accept + | 4169 -> LinuxSyscall.Bind + | 4170 -> LinuxSyscall.Connect + | 4171 -> LinuxSyscall.Getpeername + | 4172 -> LinuxSyscall.Getsockname + | 4173 -> LinuxSyscall.Getsockopt + | 4174 -> LinuxSyscall.Listen + | 4175 -> LinuxSyscall.Recv + | 4176 -> LinuxSyscall.Recvfrom + | 4177 -> LinuxSyscall.Recvmsg + | 4178 -> LinuxSyscall.Send + | 4179 -> LinuxSyscall.Sendmsg + | 4180 -> LinuxSyscall.Sendto + | 4181 -> LinuxSyscall.Setsockopt + | 4182 -> LinuxSyscall.Shutdown + | 4183 -> LinuxSyscall.Socket + | 4184 -> LinuxSyscall.Socketpair + | 4185 -> LinuxSyscall.Setresuid + | 4186 -> LinuxSyscall.Getresuid + | 4187 -> LinuxSyscall.QueryModule + | 4188 -> LinuxSyscall.Poll + | 4189 -> LinuxSyscall.Nfsservctl + | 4190 -> LinuxSyscall.Setresgid + | 4191 -> LinuxSyscall.Getresgid + | 4192 -> LinuxSyscall.Prctl + | 4193 -> LinuxSyscall.RtSigreturn + | 4194 -> LinuxSyscall.RtSigaction + | 4195 -> LinuxSyscall.RtSigprocmask + | 4196 -> LinuxSyscall.RtSigpending + | 4197 -> LinuxSyscall.RtSigtimedwait + | 4198 -> LinuxSyscall.RtSigqueueinfo + | 4199 -> LinuxSyscall.RtSigsuspend + | 4200 -> LinuxSyscall.Pread64 + | 4201 -> LinuxSyscall.Pwrite64 + | 4202 -> LinuxSyscall.Chown + | 4203 -> LinuxSyscall.Getcwd + | 4204 -> LinuxSyscall.CapGet + | 4205 -> LinuxSyscall.CapSet + | 4206 -> LinuxSyscall.Sigaltstack + | 4207 -> LinuxSyscall.Sendfile + | 4210 -> LinuxSyscall.Mmap2 + | 4211 -> LinuxSyscall.Truncate64 + | 4212 -> LinuxSyscall.Ftruncate64 + | 4213 -> LinuxSyscall.Stat64 + | 4214 -> LinuxSyscall.Lstat64 + | 4215 -> LinuxSyscall.Fstat64 + | 4216 -> LinuxSyscall.PivotRoot + | 4217 -> LinuxSyscall.Mincore + | 4218 -> LinuxSyscall.Madvise + | 4219 -> LinuxSyscall.Getdents64 + | 4220 -> LinuxSyscall.Fcntl64 + | 4222 -> LinuxSyscall.Gettid + | 4223 -> LinuxSyscall.Readahead + | 4224 -> LinuxSyscall.Setxattr + | 4225 -> LinuxSyscall.Lsetxattr + | 4226 -> LinuxSyscall.Fsetxattr + | 4227 -> LinuxSyscall.Getxattr + | 4228 -> LinuxSyscall.Lgetxattr + | 4229 -> LinuxSyscall.Fgetxattr + | 4230 -> LinuxSyscall.Listxattr + | 4231 -> LinuxSyscall.Llistxattr + | 4232 -> LinuxSyscall.Flistxattr + | 4233 -> LinuxSyscall.Removexattr + | 4234 -> LinuxSyscall.Lremovexattr + | 4235 -> LinuxSyscall.Fremovexattr + | 4236 -> LinuxSyscall.Tkill + | 4237 -> LinuxSyscall.Sendfile64 + | 4238 -> LinuxSyscall.Futex + | 4239 -> LinuxSyscall.SchedSetaffinity + | 4240 -> LinuxSyscall.SchedGetaffinity + | 4241 -> LinuxSyscall.IoSetup + | 4242 -> LinuxSyscall.IoDestroy + | 4243 -> LinuxSyscall.IoGetevents + | 4244 -> LinuxSyscall.IoSubmit + | 4245 -> LinuxSyscall.IoCancel + | 4246 -> LinuxSyscall.ExitGroup + | 4247 -> LinuxSyscall.LookupDcookie + | 4248 -> LinuxSyscall.EpollCreate + | 4249 -> LinuxSyscall.EpollCtl + | 4250 -> LinuxSyscall.EpollWait + | 4251 -> LinuxSyscall.RemapFilePages + | 4252 -> LinuxSyscall.SetTidAddress + | 4253 -> LinuxSyscall.RestartSyscall + | 4254 -> LinuxSyscall.Fadvise64 + | 4255 -> LinuxSyscall.Statfs64 + | 4256 -> LinuxSyscall.Fstatfs64 + | 4257 -> LinuxSyscall.TimerCreate + | 4258 -> LinuxSyscall.TimerSettime + | 4259 -> LinuxSyscall.TimerGettime + | 4260 -> LinuxSyscall.TimerGetoverrun + | 4261 -> LinuxSyscall.TimerDelete + | 4262 -> LinuxSyscall.ClockSettime + | 4263 -> LinuxSyscall.ClockGettime + | 4264 -> LinuxSyscall.ClockGetres + | 4265 -> LinuxSyscall.ClockNanosleep + | 4266 -> LinuxSyscall.Tgkill + | 4267 -> LinuxSyscall.Utimes + | 4268 -> LinuxSyscall.Mbind + | 4269 -> LinuxSyscall.GetMempolicy + | 4270 -> LinuxSyscall.SetMempolicy + | 4271 -> LinuxSyscall.MqOpen + | 4272 -> LinuxSyscall.MqUnlink + | 4273 -> LinuxSyscall.MqTimedsend + | 4274 -> LinuxSyscall.MqTimedreceive + | 4275 -> LinuxSyscall.MqNotify + | 4276 -> LinuxSyscall.MqGetsetattr + | 4277 -> LinuxSyscall.Vserver + | 4278 -> LinuxSyscall.Waitid + | 4280 -> LinuxSyscall.AddKey + | 4281 -> LinuxSyscall.RequestKey + | 4282 -> LinuxSyscall.Keyctl + | 4283 -> LinuxSyscall.SetThreadArea + | 4284 -> LinuxSyscall.InotifyInit + | 4285 -> LinuxSyscall.InotifyAddWatch + | 4286 -> LinuxSyscall.InotifyRmWatch + | 4287 -> LinuxSyscall.MigratePages + | 4288 -> LinuxSyscall.Openat + | 4289 -> LinuxSyscall.Mkdirat + | 4290 -> LinuxSyscall.Mknodat + | 4291 -> LinuxSyscall.Fchownat + | 4292 -> LinuxSyscall.Futimesat + | 4293 -> LinuxSyscall.Fstatat64 + | 4294 -> LinuxSyscall.Unlinkat + | 4295 -> LinuxSyscall.Renameat + | 4296 -> LinuxSyscall.Linkat + | 4297 -> LinuxSyscall.Symlinkat + | 4298 -> LinuxSyscall.Readlinkat + | 4299 -> LinuxSyscall.Fchmodat + | 4300 -> LinuxSyscall.Faccessat + | 4301 -> LinuxSyscall.Pselect6 + | 4302 -> LinuxSyscall.Ppoll + | 4303 -> LinuxSyscall.Unshare + | 4304 -> LinuxSyscall.Splice + | 4305 -> LinuxSyscall.SyncFileRange + | 4306 -> LinuxSyscall.Tee + | 4307 -> LinuxSyscall.Vmsplice + | 4308 -> LinuxSyscall.MovePages + | 4309 -> LinuxSyscall.SetRobustList + | 4310 -> LinuxSyscall.GetRobustList + | 4311 -> LinuxSyscall.KexecLoad + | 4312 -> LinuxSyscall.Getcpu + | 4313 -> LinuxSyscall.EpollPwait + | 4314 -> LinuxSyscall.IoprioSet + | 4315 -> LinuxSyscall.IoprioGet + | 4316 -> LinuxSyscall.Utimensat + | 4317 -> LinuxSyscall.Signalfd + | 4319 -> LinuxSyscall.Eventfd + | 4320 -> LinuxSyscall.Fallocate + | 4321 -> LinuxSyscall.TimerfdCreate + | 4322 -> LinuxSyscall.TimerfdGettime + | 4323 -> LinuxSyscall.TimerfdSettime + | 4324 -> LinuxSyscall.Signalfd4 + | 4325 -> LinuxSyscall.Eventfd2 + | 4326 -> LinuxSyscall.EpollCreate1 + | 4327 -> LinuxSyscall.Dup3 + | 4328 -> LinuxSyscall.Pipe2 + | 4329 -> LinuxSyscall.InotifyInit1 + | 4330 -> LinuxSyscall.Preadv + | 4331 -> LinuxSyscall.Pwritev + | 4332 -> LinuxSyscall.RtTgsigqueueinfo + | 4333 -> LinuxSyscall.PerfEventOpen + | 4334 -> LinuxSyscall.Accept4 + | 4335 -> LinuxSyscall.Recvmmsg + | 4336 -> LinuxSyscall.FanotifyInit + | 4337 -> LinuxSyscall.FanotifyMark + | 4338 -> LinuxSyscall.Prlimit64 + | 4339 -> LinuxSyscall.NameToHandleAt + | 4340 -> LinuxSyscall.OpenByHandleAt + | 4341 -> LinuxSyscall.ClockAdjtime + | 4342 -> LinuxSyscall.Syncfs + | 4343 -> LinuxSyscall.Sendmmsg + | 4344 -> LinuxSyscall.Setns + | 4345 -> LinuxSyscall.ProcessVmReadv + | 4346 -> LinuxSyscall.ProcessVmWritev + | 4347 -> LinuxSyscall.Kcmp + | 4348 -> LinuxSyscall.FinitModule + | 4349 -> LinuxSyscall.SchedSetattr + | 4350 -> LinuxSyscall.SchedGetattr + | 4351 -> LinuxSyscall.Renameat2 + | 4352 -> LinuxSyscall.Seccomp + | 4353 -> LinuxSyscall.Getrandom + | 4354 -> LinuxSyscall.MemfdCreate + | 4355 -> LinuxSyscall.Bpf + | 4356 -> LinuxSyscall.Execveat + | 4357 -> LinuxSyscall.Userfaultfd + | 4358 -> LinuxSyscall.Membarrier + | 4359 -> LinuxSyscall.Mlock2 + | 4360 -> LinuxSyscall.CopyFileRange + | 4361 -> LinuxSyscall.Preadv2 + | 4362 -> LinuxSyscall.Pwritev2 + | 4363 -> LinuxSyscall.PkeyMprotect + | 4364 -> LinuxSyscall.PkeyAlloc + | 4365 -> LinuxSyscall.PkeyFree + | 4366 -> LinuxSyscall.Statx + | 4367 -> LinuxSyscall.Rseq + | 4368 -> LinuxSyscall.IoPgetevents + | 4393 -> LinuxSyscall.Semget + | 4394 -> LinuxSyscall.Semctl + | 4395 -> LinuxSyscall.Shmget + | 4396 -> LinuxSyscall.Shmctl + | 4397 -> LinuxSyscall.Shmat + | 4398 -> LinuxSyscall.Shmdt + | 4399 -> LinuxSyscall.Msgget + | 4400 -> LinuxSyscall.Msgsnd + | 4401 -> LinuxSyscall.Msgrcv + | 4402 -> LinuxSyscall.Msgctl + | 4403 -> LinuxSyscall.ClockGettime64 + | 4404 -> LinuxSyscall.ClockSettime64 + | 4405 -> LinuxSyscall.ClockAdjtime64 + | 4406 -> LinuxSyscall.ClockGetres64 + | 4407 -> LinuxSyscall.ClockNanosleep64 + | 4408 -> LinuxSyscall.TimerGettime64 + | 4409 -> LinuxSyscall.TimerSettime64 + | 4410 -> LinuxSyscall.TimerfdGettime64 + | 4411 -> LinuxSyscall.TimerfdSettime64 + | 4412 -> LinuxSyscall.Utimensat64 + | 4413 -> LinuxSyscall.Pselect6_64 + | 4414 -> LinuxSyscall.Ppoll64 + | 4416 -> LinuxSyscall.IoPgetevents64 + | 4417 -> LinuxSyscall.Recvmmsg64 + | 4418 -> LinuxSyscall.MqTimedsend64 + | 4419 -> LinuxSyscall.MqTimedreceive64 + | 4420 -> LinuxSyscall.Semtimedop64 + | 4421 -> LinuxSyscall.RtSigtimedwait64 + | 4422 -> LinuxSyscall.Futex64 + | 4423 -> LinuxSyscall.SchedRrGetInterval64 + | 4424 -> LinuxSyscall.PidfdSendSignal + | 4425 -> LinuxSyscall.IoUringSetup + | 4426 -> LinuxSyscall.IoUringEnter + | 4427 -> LinuxSyscall.IoUringRegister + | 4428 -> LinuxSyscall.OpenTree + | 4429 -> LinuxSyscall.MoveMount + | 4430 -> LinuxSyscall.Fsopen + | 4431 -> LinuxSyscall.Fsconfig + | 4432 -> LinuxSyscall.Fsmount + | 4433 -> LinuxSyscall.Fspick + | 4434 -> LinuxSyscall.PidfdOpen + | 4435 -> LinuxSyscall.Clone3 + | 4437 -> LinuxSyscall.Openat2 + | 4438 -> LinuxSyscall.PidfdGetfd + | _ -> raise UnhandledSyscallException + + let private getMIPSN64Syscall = function + | 5000 -> LinuxSyscall.Read + | 5001 -> LinuxSyscall.Write + | 5002 -> LinuxSyscall.Open + | 5003 -> LinuxSyscall.Close + | 5004 -> LinuxSyscall.Stat + | 5005 -> LinuxSyscall.Fstat + | 5006 -> LinuxSyscall.Lstat + | 5007 -> LinuxSyscall.Poll + | 5008 -> LinuxSyscall.Lseek + | 5009 -> LinuxSyscall.Mmap + | 5010 -> LinuxSyscall.Mprotect + | 5011 -> LinuxSyscall.Munmap + | 5012 -> LinuxSyscall.Brk + | 5013 -> LinuxSyscall.RtSigaction + | 5014 -> LinuxSyscall.RtSigprocmask + | 5015 -> LinuxSyscall.Ioctl + | 5016 -> LinuxSyscall.Pread64 + | 5017 -> LinuxSyscall.Pwrite64 + | 5018 -> LinuxSyscall.Readv + | 5019 -> LinuxSyscall.Writev + | 5020 -> LinuxSyscall.Access + | 5021 -> LinuxSyscall.Pipe + | 5022 -> LinuxSyscall.NewSelect + | 5023 -> LinuxSyscall.SchedYield + | 5024 -> LinuxSyscall.Mremap + | 5025 -> LinuxSyscall.Msync + | 5026 -> LinuxSyscall.Mincore + | 5027 -> LinuxSyscall.Madvise + | 5028 -> LinuxSyscall.Shmget + | 5029 -> LinuxSyscall.Shmat + | 5030 -> LinuxSyscall.Shmctl + | 5031 -> LinuxSyscall.Dup + | 5032 -> LinuxSyscall.Dup2 + | 5033 -> LinuxSyscall.Pause + | 5034 -> LinuxSyscall.Nanosleep + | 5035 -> LinuxSyscall.Getitimer + | 5036 -> LinuxSyscall.Setitimer + | 5037 -> LinuxSyscall.Alarm + | 5038 -> LinuxSyscall.Getpid + | 5039 -> LinuxSyscall.Sendfile + | 5040 -> LinuxSyscall.Socket + | 5041 -> LinuxSyscall.Connect + | 5042 -> LinuxSyscall.Accept + | 5043 -> LinuxSyscall.Sendto + | 5044 -> LinuxSyscall.Recvfrom + | 5045 -> LinuxSyscall.Sendmsg + | 5046 -> LinuxSyscall.Recvmsg + | 5047 -> LinuxSyscall.Shutdown + | 5048 -> LinuxSyscall.Bind + | 5049 -> LinuxSyscall.Listen + | 5050 -> LinuxSyscall.Getsockname + | 5051 -> LinuxSyscall.Getpeername + | 5052 -> LinuxSyscall.Socketpair + | 5053 -> LinuxSyscall.Setsockopt + | 5054 -> LinuxSyscall.Getsockopt + | 5055 -> LinuxSyscall.Clone + | 5056 -> LinuxSyscall.Fork + | 5057 -> LinuxSyscall.Execve + | 5058 -> LinuxSyscall.Exit + | 5059 -> LinuxSyscall.Wait4 + | 5060 -> LinuxSyscall.Kill + | 5061 -> LinuxSyscall.Uname + | 5062 -> LinuxSyscall.Semget + | 5063 -> LinuxSyscall.Semop + | 5064 -> LinuxSyscall.Semctl + | 5065 -> LinuxSyscall.Shmdt + | 5066 -> LinuxSyscall.Msgget + | 5067 -> LinuxSyscall.Msgsnd + | 5068 -> LinuxSyscall.Msgrcv + | 5069 -> LinuxSyscall.Msgctl + | 5070 -> LinuxSyscall.Fcntl + | 5071 -> LinuxSyscall.Flock + | 5072 -> LinuxSyscall.Fsync + | 5073 -> LinuxSyscall.Fdatasync + | 5074 -> LinuxSyscall.Truncate + | 5075 -> LinuxSyscall.Ftruncate + | 5076 -> LinuxSyscall.Getdents + | 5077 -> LinuxSyscall.Getcwd + | 5078 -> LinuxSyscall.Chdir + | 5079 -> LinuxSyscall.Fchdir + | 5080 -> LinuxSyscall.Rename + | 5081 -> LinuxSyscall.Mkdir + | 5082 -> LinuxSyscall.Rmdir + | 5083 -> LinuxSyscall.Creat + | 5084 -> LinuxSyscall.Link + | 5085 -> LinuxSyscall.Unlink + | 5086 -> LinuxSyscall.Symlink + | 5087 -> LinuxSyscall.Readlink + | 5088 -> LinuxSyscall.Chmod + | 5089 -> LinuxSyscall.Fchmod + | 5090 -> LinuxSyscall.Chown + | 5091 -> LinuxSyscall.Fchown + | 5092 -> LinuxSyscall.Lchown + | 5093 -> LinuxSyscall.Umask + | 5094 -> LinuxSyscall.Gettimeofday + | 5095 -> LinuxSyscall.Getrlimit + | 5096 -> LinuxSyscall.Getrusage + | 5097 -> LinuxSyscall.Sysinfo + | 5098 -> LinuxSyscall.Times + | 5099 -> LinuxSyscall.Ptrace + | 5100 -> LinuxSyscall.Getuid + | 5101 -> LinuxSyscall.Syslog + | 5102 -> LinuxSyscall.Getgid + | 5103 -> LinuxSyscall.Setuid + | 5104 -> LinuxSyscall.Setgid + | 5105 -> LinuxSyscall.Geteuid + | 5106 -> LinuxSyscall.Getegid + | 5107 -> LinuxSyscall.Setpgid + | 5108 -> LinuxSyscall.Getppid + | 5109 -> LinuxSyscall.Getpgrp + | 5110 -> LinuxSyscall.Setsid + | 5111 -> LinuxSyscall.Setreuid + | 5112 -> LinuxSyscall.Setregid + | 5113 -> LinuxSyscall.Getgroups + | 5114 -> LinuxSyscall.Setgroups + | 5115 -> LinuxSyscall.Setresuid + | 5116 -> LinuxSyscall.Getresuid + | 5117 -> LinuxSyscall.Setresgid + | 5118 -> LinuxSyscall.Getresgid + | 5119 -> LinuxSyscall.Getpgid + | 5120 -> LinuxSyscall.Setfsuid + | 5121 -> LinuxSyscall.Setfsgid + | 5122 -> LinuxSyscall.Getsid + | 5123 -> LinuxSyscall.CapGet + | 5124 -> LinuxSyscall.CapSet + | 5125 -> LinuxSyscall.RtSigpending + | 5126 -> LinuxSyscall.RtSigtimedwait + | 5127 -> LinuxSyscall.RtSigqueueinfo + | 5128 -> LinuxSyscall.RtSigsuspend + | 5129 -> LinuxSyscall.Sigaltstack + | 5130 -> LinuxSyscall.Utime + | 5131 -> LinuxSyscall.Mknod + | 5132 -> LinuxSyscall.Personality + | 5133 -> LinuxSyscall.Ustat + | 5134 -> LinuxSyscall.Statfs + | 5135 -> LinuxSyscall.Fstatfs + | 5136 -> LinuxSyscall.Sysfs + | 5137 -> LinuxSyscall.Getpriority + | 5138 -> LinuxSyscall.Setpriority + | 5139 -> LinuxSyscall.SchedSetparam + | 5140 -> LinuxSyscall.SchedGetparam + | 5141 -> LinuxSyscall.SchedSetscheduler + | 5142 -> LinuxSyscall.SchedGetscheduler + | 5143 -> LinuxSyscall.SchedGetPriorityMax + | 5144 -> LinuxSyscall.SchedGetPriorityMin + | 5145 -> LinuxSyscall.SchedRrGetInterval + | 5146 -> LinuxSyscall.Mlock + | 5147 -> LinuxSyscall.Munlock + | 5148 -> LinuxSyscall.Mlockall + | 5149 -> LinuxSyscall.Munlockall + | 5150 -> LinuxSyscall.Vhangup + | 5151 -> LinuxSyscall.PivotRoot + | 5152 -> LinuxSyscall.Sysctl + | 5153 -> LinuxSyscall.Prctl + | 5154 -> LinuxSyscall.AdjTimex + | 5155 -> LinuxSyscall.Setrlimit + | 5156 -> LinuxSyscall.Chroot + | 5157 -> LinuxSyscall.Sync + | 5158 -> LinuxSyscall.Acct + | 5159 -> LinuxSyscall.Settimeofday + | 5160 -> LinuxSyscall.Mount + | 5161 -> LinuxSyscall.Umount2 + | 5162 -> LinuxSyscall.Swapon + | 5163 -> LinuxSyscall.Swapoff + | 5164 -> LinuxSyscall.Reboot + | 5165 -> LinuxSyscall.Sethostname + | 5166 -> LinuxSyscall.Setdomainname + | 5167 -> LinuxSyscall.CreateModule + | 5168 -> LinuxSyscall.InitModule + | 5169 -> LinuxSyscall.DeleteModule + | 5170 -> LinuxSyscall.GetKernelSyms + | 5171 -> LinuxSyscall.QueryModule + | 5172 -> LinuxSyscall.Quotactl + | 5173 -> LinuxSyscall.Nfsservctl + | 5178 -> LinuxSyscall.Gettid + | 5179 -> LinuxSyscall.Readahead + | 5180 -> LinuxSyscall.Setxattr + | 5181 -> LinuxSyscall.Lsetxattr + | 5182 -> LinuxSyscall.Fsetxattr + | 5183 -> LinuxSyscall.Getxattr + | 5184 -> LinuxSyscall.Lgetxattr + | 5185 -> LinuxSyscall.Fgetxattr + | 5186 -> LinuxSyscall.Listxattr + | 5187 -> LinuxSyscall.Llistxattr + | 5188 -> LinuxSyscall.Flistxattr + | 5189 -> LinuxSyscall.Removexattr + | 5190 -> LinuxSyscall.Lremovexattr + | 5191 -> LinuxSyscall.Fremovexattr + | 5192 -> LinuxSyscall.Tkill + | 5194 -> LinuxSyscall.Futex + | 5195 -> LinuxSyscall.SchedSetaffinity + | 5196 -> LinuxSyscall.SchedGetaffinity + | 5197 -> LinuxSyscall.CacheFlush + | 5198 -> LinuxSyscall.CacheCtl + | 5199 -> LinuxSyscall.Sysmips + | 5200 -> LinuxSyscall.IoSetup + | 5201 -> LinuxSyscall.IoDestroy + | 5202 -> LinuxSyscall.IoGetevents + | 5203 -> LinuxSyscall.IoSubmit + | 5204 -> LinuxSyscall.IoCancel + | 5205 -> LinuxSyscall.ExitGroup + | 5206 -> LinuxSyscall.LookupDcookie + | 5207 -> LinuxSyscall.EpollCreate + | 5208 -> LinuxSyscall.EpollCtl + | 5209 -> LinuxSyscall.EpollWait + | 5210 -> LinuxSyscall.RemapFilePages + | 5211 -> LinuxSyscall.RtSigreturn + | 5212 -> LinuxSyscall.SetTidAddress + | 5213 -> LinuxSyscall.RestartSyscall + | 5214 -> LinuxSyscall.Semtimedop + | 5215 -> LinuxSyscall.Fadvise64 + | 5216 -> LinuxSyscall.TimerCreate + | 5217 -> LinuxSyscall.TimerSettime + | 5218 -> LinuxSyscall.TimerGettime + | 5219 -> LinuxSyscall.TimerGetoverrun + | 5220 -> LinuxSyscall.TimerDelete + | 5221 -> LinuxSyscall.ClockSettime + | 5222 -> LinuxSyscall.ClockGettime + | 5223 -> LinuxSyscall.ClockGetres + | 5224 -> LinuxSyscall.ClockNanosleep + | 5225 -> LinuxSyscall.Tgkill + | 5226 -> LinuxSyscall.Utimes + | 5227 -> LinuxSyscall.Mbind + | 5228 -> LinuxSyscall.GetMempolicy + | 5229 -> LinuxSyscall.SetMempolicy + | 5230 -> LinuxSyscall.MqOpen + | 5231 -> LinuxSyscall.MqUnlink + | 5232 -> LinuxSyscall.MqTimedsend + | 5233 -> LinuxSyscall.MqTimedreceive + | 5234 -> LinuxSyscall.MqNotify + | 5235 -> LinuxSyscall.MqGetsetattr + | 5236 -> LinuxSyscall.Vserver + | 5237 -> LinuxSyscall.Waitid + | 5239 -> LinuxSyscall.AddKey + | 5240 -> LinuxSyscall.RequestKey + | 5241 -> LinuxSyscall.Keyctl + | 5242 -> LinuxSyscall.SetThreadArea + | 5243 -> LinuxSyscall.InotifyInit + | 5244 -> LinuxSyscall.InotifyAddWatch + | 5245 -> LinuxSyscall.InotifyRmWatch + | 5246 -> LinuxSyscall.MigratePages + | 5247 -> LinuxSyscall.Openat + | 5248 -> LinuxSyscall.Mkdirat + | 5249 -> LinuxSyscall.Mknodat + | 5250 -> LinuxSyscall.Fchownat + | 5251 -> LinuxSyscall.Futimesat + | 5252 -> LinuxSyscall.Newfstatat + | 5253 -> LinuxSyscall.Unlinkat + | 5254 -> LinuxSyscall.Renameat + | 5255 -> LinuxSyscall.Linkat + | 5256 -> LinuxSyscall.Symlinkat + | 5257 -> LinuxSyscall.Readlinkat + | 5258 -> LinuxSyscall.Fchmodat + | 5259 -> LinuxSyscall.Faccessat + | 5260 -> LinuxSyscall.Pselect6 + | 5261 -> LinuxSyscall.Ppoll + | 5262 -> LinuxSyscall.Unshare + | 5263 -> LinuxSyscall.Splice + | 5264 -> LinuxSyscall.SyncFileRange + | 5265 -> LinuxSyscall.Tee + | 5266 -> LinuxSyscall.Vmsplice + | 5267 -> LinuxSyscall.MovePages + | 5268 -> LinuxSyscall.SetRobustList + | 5269 -> LinuxSyscall.GetRobustList + | 5270 -> LinuxSyscall.KexecLoad + | 5271 -> LinuxSyscall.Getcpu + | 5272 -> LinuxSyscall.EpollPwait + | 5273 -> LinuxSyscall.IoprioSet + | 5274 -> LinuxSyscall.IoprioGet + | 5275 -> LinuxSyscall.Utimensat + | 5276 -> LinuxSyscall.Signalfd + | 5277 -> LinuxSyscall.Timerfd + | 5278 -> LinuxSyscall.Eventfd + | 5279 -> LinuxSyscall.Fallocate + | 5280 -> LinuxSyscall.TimerfdCreate + | 5281 -> LinuxSyscall.TimerfdGettime + | 5282 -> LinuxSyscall.TimerfdSettime + | 5283 -> LinuxSyscall.Signalfd4 + | 5284 -> LinuxSyscall.Eventfd2 + | 5285 -> LinuxSyscall.EpollCreate1 + | 5286 -> LinuxSyscall.Dup3 + | 5287 -> LinuxSyscall.Pipe2 + | 5288 -> LinuxSyscall.InotifyInit1 + | 5289 -> LinuxSyscall.Preadv + | 5290 -> LinuxSyscall.Pwritev + | 5291 -> LinuxSyscall.RtTgsigqueueinfo + | 5292 -> LinuxSyscall.PerfEventOpen + | 5293 -> LinuxSyscall.Accept4 + | 5294 -> LinuxSyscall.Recvmmsg + | 5295 -> LinuxSyscall.FanotifyInit + | 5296 -> LinuxSyscall.FanotifyMark + | 5297 -> LinuxSyscall.Prlimit64 + | 5298 -> LinuxSyscall.NameToHandleAt + | 5299 -> LinuxSyscall.OpenByHandleAt + | 5300 -> LinuxSyscall.ClockAdjtime + | 5301 -> LinuxSyscall.Syncfs + | 5302 -> LinuxSyscall.Sendmmsg + | 5303 -> LinuxSyscall.Setns + | 5304 -> LinuxSyscall.ProcessVmReadv + | 5305 -> LinuxSyscall.ProcessVmWritev + | 5306 -> LinuxSyscall.Kcmp + | 5307 -> LinuxSyscall.FinitModule + | 5308 -> LinuxSyscall.Getdents64 + | 5309 -> LinuxSyscall.SchedSetattr + | 5310 -> LinuxSyscall.SchedGetattr + | 5311 -> LinuxSyscall.Renameat2 + | 5312 -> LinuxSyscall.Seccomp + | 5313 -> LinuxSyscall.Getrandom + | 5314 -> LinuxSyscall.MemfdCreate + | 5315 -> LinuxSyscall.Bpf + | 5316 -> LinuxSyscall.Execveat + | 5317 -> LinuxSyscall.Userfaultfd + | 5318 -> LinuxSyscall.Membarrier + | 5319 -> LinuxSyscall.Mlock2 + | 5320 -> LinuxSyscall.CopyFileRange + | 5321 -> LinuxSyscall.Preadv2 + | 5322 -> LinuxSyscall.Pwritev2 + | 5323 -> LinuxSyscall.PkeyMprotect + | 5324 -> LinuxSyscall.PkeyAlloc + | 5325 -> LinuxSyscall.PkeyFree + | 5326 -> LinuxSyscall.Statx + | 5327 -> LinuxSyscall.Rseq + | 5328 -> LinuxSyscall.IoPgetevents + | 5424 -> LinuxSyscall.PidfdSendSignal + | 5425 -> LinuxSyscall.IoUringSetup + | 5426 -> LinuxSyscall.IoUringEnter + | 5427 -> LinuxSyscall.IoUringRegister + | 5428 -> LinuxSyscall.OpenTree + | 5429 -> LinuxSyscall.MoveMount + | 5430 -> LinuxSyscall.Fsopen + | 5431 -> LinuxSyscall.Fsconfig + | 5432 -> LinuxSyscall.Fsmount + | 5433 -> LinuxSyscall.Fspick + | 5434 -> LinuxSyscall.PidfdOpen + | 5435 -> LinuxSyscall.Clone3 + | 5436 -> LinuxSyscall.CloseRange + | 5437 -> LinuxSyscall.Openat2 + | 5438 -> LinuxSyscall.PidfdGetfd + | _ -> raise UnhandledSyscallException + + let private getPPC32Syscall = function + | 0 -> LinuxSyscall.RestartSyscall + | 1 -> LinuxSyscall.Exit + | 2 -> LinuxSyscall.Fork + | 3 -> LinuxSyscall.Read + | 4 -> LinuxSyscall.Write + | 5 -> LinuxSyscall.Open + | 6 -> LinuxSyscall.Close + | 7 -> LinuxSyscall.Waitpid + | 8 -> LinuxSyscall.Creat + | 9 -> LinuxSyscall.Link + | 10 -> LinuxSyscall.Unlink + | 11 -> LinuxSyscall.Execve + | 12 -> LinuxSyscall.Chdir + | 13 -> LinuxSyscall.Time + | 14 -> LinuxSyscall.Mknod + | 15 -> LinuxSyscall.Chmod + | 16 -> LinuxSyscall.Lchown + | 18 -> LinuxSyscall.Oldstat + | 19 -> LinuxSyscall.Lseek + | 20 -> LinuxSyscall.Getpid + | 21 -> LinuxSyscall.Mount + | 22 -> LinuxSyscall.Umount + | 23 -> LinuxSyscall.Setuid + | 24 -> LinuxSyscall.Getuid + | 25 -> LinuxSyscall.Stime + | 26 -> LinuxSyscall.Ptrace + | 27 -> LinuxSyscall.Alarm + | 28 -> LinuxSyscall.Oldfstat + | 29 -> LinuxSyscall.Pause + | 30 -> LinuxSyscall.Utime + | 33 -> LinuxSyscall.Access + | 34 -> LinuxSyscall.Nice + | 36 -> LinuxSyscall.Sync + | 37 -> LinuxSyscall.Kill + | 38 -> LinuxSyscall.Rename + | 39 -> LinuxSyscall.Mkdir + | 40 -> LinuxSyscall.Rmdir + | 41 -> LinuxSyscall.Dup + | 42 -> LinuxSyscall.Pipe + | 43 -> LinuxSyscall.Times + | 45 -> LinuxSyscall.Brk + | 46 -> LinuxSyscall.Setgid + | 47 -> LinuxSyscall.Getgid + | 48 -> LinuxSyscall.Signal + | 49 -> LinuxSyscall.Geteuid + | 50 -> LinuxSyscall.Getegid + | 51 -> LinuxSyscall.Acct + | 52 -> LinuxSyscall.Umount2 + | 54 -> LinuxSyscall.Ioctl + | 55 -> LinuxSyscall.Fcntl + | 57 -> LinuxSyscall.Setpgid + | 59 -> LinuxSyscall.Oldolduname + | 60 -> LinuxSyscall.Umask + | 61 -> LinuxSyscall.Chroot + | 62 -> LinuxSyscall.Ustat + | 63 -> LinuxSyscall.Dup2 + | 64 -> LinuxSyscall.Getppid + | 65 -> LinuxSyscall.Getpgrp + | 66 -> LinuxSyscall.Setsid + | 67 -> LinuxSyscall.Sigaction + | 68 -> LinuxSyscall.Sgetmask + | 69 -> LinuxSyscall.Ssetmask + | 70 -> LinuxSyscall.Setreuid + | 71 -> LinuxSyscall.Setregid + | 72 -> LinuxSyscall.Sigsuspend + | 73 -> LinuxSyscall.Sigpending + | 74 -> LinuxSyscall.Sethostname + | 75 -> LinuxSyscall.Setrlimit + | 76 -> LinuxSyscall.Getrlimit + | 77 -> LinuxSyscall.Getrusage + | 78 -> LinuxSyscall.Gettimeofday + | 79 -> LinuxSyscall.Settimeofday + | 80 -> LinuxSyscall.Getgroups + | 81 -> LinuxSyscall.Setgroups + | 82 -> LinuxSyscall.Select + | 83 -> LinuxSyscall.Symlink + | 84 -> LinuxSyscall.Oldlstat + | 85 -> LinuxSyscall.Readlink + | 86 -> LinuxSyscall.Uselib + | 87 -> LinuxSyscall.Swapon + | 88 -> LinuxSyscall.Reboot + | 89 -> LinuxSyscall.Readdir + | 90 -> LinuxSyscall.Mmap + | 91 -> LinuxSyscall.Munmap + | 92 -> LinuxSyscall.Truncate + | 93 -> LinuxSyscall.Ftruncate + | 94 -> LinuxSyscall.Fchmod + | 95 -> LinuxSyscall.Fchown + | 96 -> LinuxSyscall.Getpriority + | 97 -> LinuxSyscall.Setpriority + | 99 -> LinuxSyscall.Statfs + | 100 -> LinuxSyscall.Fstatfs + | 101 -> LinuxSyscall.Ioperm + | 102 -> LinuxSyscall.Socketcall + | 103 -> LinuxSyscall.Syslog + | 104 -> LinuxSyscall.Setitimer + | 105 -> LinuxSyscall.Getitimer + | 106 -> LinuxSyscall.Stat + | 107 -> LinuxSyscall.Lstat + | 108 -> LinuxSyscall.Fstat + | 109 -> LinuxSyscall.Olduname + | 110 -> LinuxSyscall.Iopl + | 111 -> LinuxSyscall.Vhangup + | 113 -> LinuxSyscall.Vm86 + | 114 -> LinuxSyscall.Wait4 + | 115 -> LinuxSyscall.Swapoff + | 116 -> LinuxSyscall.Sysinfo + | 117 -> LinuxSyscall.Ipc + | 118 -> LinuxSyscall.Fsync + | 119 -> LinuxSyscall.Sigreturn + | 120 -> LinuxSyscall.Clone + | 121 -> LinuxSyscall.Setdomainname + | 122 -> LinuxSyscall.Uname + | 123 -> LinuxSyscall.ModifyLdt + | 124 -> LinuxSyscall.AdjTimex + | 125 -> LinuxSyscall.Mprotect + | 126 -> LinuxSyscall.Sigprocmask + | 127 -> LinuxSyscall.CreateModule + | 128 -> LinuxSyscall.InitModule + | 129 -> LinuxSyscall.DeleteModule + | 130 -> LinuxSyscall.GetKernelSyms + | 131 -> LinuxSyscall.Quotactl + | 132 -> LinuxSyscall.Getpgid + | 133 -> LinuxSyscall.Fchdir + | 134 -> LinuxSyscall.Bdflush + | 135 -> LinuxSyscall.Sysfs + | 136 -> LinuxSyscall.Personality + | 138 -> LinuxSyscall.Setfsuid + | 139 -> LinuxSyscall.Setfsgid + | 140 -> LinuxSyscall.LLseek + | 141 -> LinuxSyscall.Getdents + | 142 -> LinuxSyscall.NewSelect + | 143 -> LinuxSyscall.Flock + | 144 -> LinuxSyscall.Msync + | 145 -> LinuxSyscall.Readv + | 146 -> LinuxSyscall.Writev + | 147 -> LinuxSyscall.Getsid + | 148 -> LinuxSyscall.Fdatasync + | 149 -> LinuxSyscall.Sysctl + | 150 -> LinuxSyscall.Mlock + | 151 -> LinuxSyscall.Munlock + | 152 -> LinuxSyscall.Mlockall + | 153 -> LinuxSyscall.Munlockall + | 154 -> LinuxSyscall.SchedSetparam + | 155 -> LinuxSyscall.SchedGetparam + | 156 -> LinuxSyscall.SchedSetscheduler + | 157 -> LinuxSyscall.SchedGetscheduler + | 158 -> LinuxSyscall.SchedYield + | 159 -> LinuxSyscall.SchedGetPriorityMax + | 160 -> LinuxSyscall.SchedGetPriorityMin + | 161 -> LinuxSyscall.SchedRrGetInterval + | 162 -> LinuxSyscall.Nanosleep + | 163 -> LinuxSyscall.Mremap + | 164 -> LinuxSyscall.Setresuid + | 165 -> LinuxSyscall.Getresuid + | 166 -> LinuxSyscall.QueryModule + | 167 -> LinuxSyscall.Poll + | 168 -> LinuxSyscall.Nfsservctl + | 169 -> LinuxSyscall.Setresgid + | 170 -> LinuxSyscall.Getresgid + | 171 -> LinuxSyscall.Prctl + | 172 -> LinuxSyscall.RtSigreturn + | 173 -> LinuxSyscall.RtSigaction + | 174 -> LinuxSyscall.RtSigprocmask + | 175 -> LinuxSyscall.RtSigpending + | 176 -> LinuxSyscall.RtSigtimedwait + | 177 -> LinuxSyscall.RtSigqueueinfo + | 178 -> LinuxSyscall.RtSigsuspend + | 179 -> LinuxSyscall.Pread64 + | 180 -> LinuxSyscall.Pwrite64 + | 181 -> LinuxSyscall.Chown + | 182 -> LinuxSyscall.Getcwd + | 183 -> LinuxSyscall.CapGet + | 184 -> LinuxSyscall.CapSet + | 185 -> LinuxSyscall.Sigaltstack + | 186 -> LinuxSyscall.Sendfile + | 189 -> LinuxSyscall.Vfork + | 190 -> LinuxSyscall.Ugetrlimit + | 191 -> LinuxSyscall.Readahead + | 192 -> LinuxSyscall.Mmap2 + | 193 -> LinuxSyscall.Truncate64 + | 194 -> LinuxSyscall.Ftruncate64 + | 195 -> LinuxSyscall.Stat64 + | 196 -> LinuxSyscall.Lstat64 + | 197 -> LinuxSyscall.Fstat64 + | 198 -> LinuxSyscall.PciconfigRead + | 199 -> LinuxSyscall.PciconfigWrite + | 200 -> LinuxSyscall.PciconfigIobase + | 202 -> LinuxSyscall.Getdents64 + | 203 -> LinuxSyscall.PivotRoot + | 204 -> LinuxSyscall.Fcntl64 + | 205 -> LinuxSyscall.Madvise + | 206 -> LinuxSyscall.Mincore + | 207 -> LinuxSyscall.Gettid + | 208 -> LinuxSyscall.Tkill + | 209 -> LinuxSyscall.Setxattr + | 210 -> LinuxSyscall.Lsetxattr + | 211 -> LinuxSyscall.Fsetxattr + | 212 -> LinuxSyscall.Getxattr + | 213 -> LinuxSyscall.Lgetxattr + | 214 -> LinuxSyscall.Fgetxattr + | 215 -> LinuxSyscall.Listxattr + | 216 -> LinuxSyscall.Llistxattr + | 217 -> LinuxSyscall.Flistxattr + | 218 -> LinuxSyscall.Removexattr + | 219 -> LinuxSyscall.Lremovexattr + | 220 -> LinuxSyscall.Fremovexattr + | 221 -> LinuxSyscall.Futex + | 222 -> LinuxSyscall.SchedSetaffinity + | 223 -> LinuxSyscall.SchedGetaffinity + | 226 -> LinuxSyscall.Sendfile64 + | 227 -> LinuxSyscall.IoSetup + | 228 -> LinuxSyscall.IoDestroy + | 229 -> LinuxSyscall.IoGetevents + | 230 -> LinuxSyscall.IoSubmit + | 231 -> LinuxSyscall.IoCancel + | 232 -> LinuxSyscall.SetTidAddress + | 233 -> LinuxSyscall.Fadvise64 + | 234 -> LinuxSyscall.ExitGroup + | 235 -> LinuxSyscall.LookupDcookie + | 236 -> LinuxSyscall.EpollCreate + | 237 -> LinuxSyscall.EpollCtl + | 238 -> LinuxSyscall.EpollWait + | 239 -> LinuxSyscall.RemapFilePages + | 240 -> LinuxSyscall.TimerCreate + | 241 -> LinuxSyscall.TimerSettime + | 242 -> LinuxSyscall.TimerGettime + | 243 -> LinuxSyscall.TimerGetoverrun + | 244 -> LinuxSyscall.TimerDelete + | 245 -> LinuxSyscall.ClockSettime + | 246 -> LinuxSyscall.ClockGettime + | 247 -> LinuxSyscall.ClockGetres + | 248 -> LinuxSyscall.ClockNanosleep + | 249 -> LinuxSyscall.Swapcontext + | 250 -> LinuxSyscall.Tgkill + | 251 -> LinuxSyscall.Utimes + | 252 -> LinuxSyscall.Statfs64 + | 253 -> LinuxSyscall.Fstatfs64 + | 254 -> LinuxSyscall.Fadvise64_64 + | 255 -> LinuxSyscall.Rtas + | 256 -> LinuxSyscall.SysDebugSetcontext + | 258 -> LinuxSyscall.MigratePages + | 259 -> LinuxSyscall.Mbind + | 260 -> LinuxSyscall.GetMempolicy + | 261 -> LinuxSyscall.SetMempolicy + | 262 -> LinuxSyscall.MqOpen + | 263 -> LinuxSyscall.MqUnlink + | 264 -> LinuxSyscall.MqTimedsend + | 265 -> LinuxSyscall.MqTimedreceive + | 266 -> LinuxSyscall.MqNotify + | 267 -> LinuxSyscall.MqGetsetattr + | 268 -> LinuxSyscall.KexecLoad + | 269 -> LinuxSyscall.AddKey + | 270 -> LinuxSyscall.RequestKey + | 271 -> LinuxSyscall.Keyctl + | 272 -> LinuxSyscall.Waitid + | 273 -> LinuxSyscall.IoprioSet + | 274 -> LinuxSyscall.IoprioGet + | 275 -> LinuxSyscall.InotifyInit + | 276 -> LinuxSyscall.InotifyAddWatch + | 277 -> LinuxSyscall.InotifyRmWatch + | 278 -> LinuxSyscall.SpuRun + | 279 -> LinuxSyscall.SpuCreate + | 280 -> LinuxSyscall.Pselect6 + | 281 -> LinuxSyscall.Ppoll + | 282 -> LinuxSyscall.Unshare + | 283 -> LinuxSyscall.Splice + | 284 -> LinuxSyscall.Tee + | 285 -> LinuxSyscall.Vmsplice + | 286 -> LinuxSyscall.Openat + | 287 -> LinuxSyscall.Mkdirat + | 288 -> LinuxSyscall.Mknodat + | 289 -> LinuxSyscall.Fchownat + | 290 -> LinuxSyscall.Futimesat + | 291 -> LinuxSyscall.Fstatat64 + | 292 -> LinuxSyscall.Unlinkat + | 293 -> LinuxSyscall.Renameat + | 294 -> LinuxSyscall.Linkat + | 295 -> LinuxSyscall.Symlinkat + | 296 -> LinuxSyscall.Readlinkat + | 297 -> LinuxSyscall.Fchmodat + | 298 -> LinuxSyscall.Faccessat + | 299 -> LinuxSyscall.GetRobustList + | 300 -> LinuxSyscall.SetRobustList + | 301 -> LinuxSyscall.MovePages + | 302 -> LinuxSyscall.Getcpu + | 303 -> LinuxSyscall.EpollPwait + | 304 -> LinuxSyscall.Utimensat + | 305 -> LinuxSyscall.Signalfd + | 306 -> LinuxSyscall.TimerfdCreate + | 307 -> LinuxSyscall.Eventfd + | 308 -> LinuxSyscall.SyncFileRange2 + | 309 -> LinuxSyscall.Fallocate + | 310 -> LinuxSyscall.SubpageProt + | 311 -> LinuxSyscall.TimerfdSettime + | 312 -> LinuxSyscall.TimerfdGettime + | 313 -> LinuxSyscall.Signalfd4 + | 314 -> LinuxSyscall.Eventfd2 + | 315 -> LinuxSyscall.EpollCreate1 + | 316 -> LinuxSyscall.Dup3 + | 317 -> LinuxSyscall.Pipe2 + | 318 -> LinuxSyscall.InotifyInit1 + | 319 -> LinuxSyscall.PerfEventOpen + | 320 -> LinuxSyscall.Preadv + | 321 -> LinuxSyscall.Pwritev + | 322 -> LinuxSyscall.RtTgsigqueueinfo + | 323 -> LinuxSyscall.FanotifyInit + | 324 -> LinuxSyscall.FanotifyMark + | 325 -> LinuxSyscall.Prlimit64 + | 326 -> LinuxSyscall.Socket + | 327 -> LinuxSyscall.Bind + | 328 -> LinuxSyscall.Connect + | 329 -> LinuxSyscall.Listen + | 330 -> LinuxSyscall.Accept + | 331 -> LinuxSyscall.Getsockname + | 332 -> LinuxSyscall.Getpeername + | 333 -> LinuxSyscall.Socketpair + | 334 -> LinuxSyscall.Send + | 335 -> LinuxSyscall.Sendto + | 336 -> LinuxSyscall.Recv + | 337 -> LinuxSyscall.Recvfrom + | 338 -> LinuxSyscall.Shutdown + | 339 -> LinuxSyscall.Setsockopt + | 340 -> LinuxSyscall.Getsockopt + | 341 -> LinuxSyscall.Sendmsg + | 342 -> LinuxSyscall.Recvmsg + | 343 -> LinuxSyscall.Recvmmsg + | 344 -> LinuxSyscall.Accept4 + | 345 -> LinuxSyscall.NameToHandleAt + | 346 -> LinuxSyscall.OpenByHandleAt + | 347 -> LinuxSyscall.ClockAdjtime + | 348 -> LinuxSyscall.Syncfs + | 349 -> LinuxSyscall.Sendmmsg + | 350 -> LinuxSyscall.Setns + | 351 -> LinuxSyscall.ProcessVmReadv + | 352 -> LinuxSyscall.ProcessVmWritev + | 353 -> LinuxSyscall.FinitModule + | 354 -> LinuxSyscall.Kcmp + | 355 -> LinuxSyscall.SchedSetattr + | 356 -> LinuxSyscall.SchedGetattr + | 357 -> LinuxSyscall.Renameat2 + | 360 -> LinuxSyscall.MemfdCreate + | _ -> raise UnhandledSyscallException + + let private getRISCV64Syscall = function + | 0 -> LinuxSyscall.IoSetup + | 1 -> LinuxSyscall.IoDestroy + | 2 -> LinuxSyscall.IoSubmit + | 3 -> LinuxSyscall.IoCancel + | 4 -> LinuxSyscall.IoGetevents + | 5 -> LinuxSyscall.Setxattr + | 6 -> LinuxSyscall.Lsetxattr + | 7 -> LinuxSyscall.Fsetxattr + | 8 -> LinuxSyscall.Getxattr + | 9 -> LinuxSyscall.Lgetxattr + | 10 -> LinuxSyscall.Fgetxattr + | 11 -> LinuxSyscall.Listxattr + | 12 -> LinuxSyscall.Llistxattr + | 13 -> LinuxSyscall.Flistxattr + | 14 -> LinuxSyscall.Removexattr + | 15 -> LinuxSyscall.Lremovexattr + | 16 -> LinuxSyscall.Fremovexattr + | 17 -> LinuxSyscall.Getcwd + | 18 -> LinuxSyscall.LookupDcookie + | 19 -> LinuxSyscall.Eventfd2 + | 20 -> LinuxSyscall.EpollCreate1 + | 21 -> LinuxSyscall.EpollCtl + | 22 -> LinuxSyscall.EpollPwait + | 23 -> LinuxSyscall.Dup + | 24 -> LinuxSyscall.Dup3 + | 25 -> LinuxSyscall.Fcntl + | 26 -> LinuxSyscall.InotifyInit1 + | 27 -> LinuxSyscall.InotifyAddWatch + | 28 -> LinuxSyscall.InotifyRmWatch + | 29 -> LinuxSyscall.Ioctl + | 30 -> LinuxSyscall.IoprioSet + | 31 -> LinuxSyscall.IoprioGet + | 32 -> LinuxSyscall.Flock + | 33 -> LinuxSyscall.Mknodat + | 34 -> LinuxSyscall.Mkdirat + | 35 -> LinuxSyscall.Unlinkat + | 36 -> LinuxSyscall.Symlinkat + | 37 -> LinuxSyscall.Linkat + | 38 -> LinuxSyscall.Renameat + | 39 -> LinuxSyscall.Umount2 + | 40 -> LinuxSyscall.Mount + | 41 -> LinuxSyscall.PivotRoot + | 42 -> LinuxSyscall.Nfsservctl + | 43 -> LinuxSyscall.Statfs + | 44 -> LinuxSyscall.Fstatfs + | 45 -> LinuxSyscall.Truncate + | 46 -> LinuxSyscall.Ftruncate + | 47 -> LinuxSyscall.Fallocate + | 48 -> LinuxSyscall.Faccessat + | 49 -> LinuxSyscall.Chdir + | 50 -> LinuxSyscall.Fchdir + | 51 -> LinuxSyscall.Chroot + | 52 -> LinuxSyscall.Fchmod + | 53 -> LinuxSyscall.Fchmodat + | 54 -> LinuxSyscall.Fchownat + | 55 -> LinuxSyscall.Fchown + | 56 -> LinuxSyscall.Openat + | 57 -> LinuxSyscall.Close + | 58 -> LinuxSyscall.Vhangup + | 59 -> LinuxSyscall.Pipe2 + | 60 -> LinuxSyscall.Quotactl + | 61 -> LinuxSyscall.Getdents64 + | 62 -> LinuxSyscall.Lseek + | 63 -> LinuxSyscall.Read + | 64 -> LinuxSyscall.Write + | 65 -> LinuxSyscall.Readv + | 66 -> LinuxSyscall.Writev + | 67 -> LinuxSyscall.Pread64 + | 68 -> LinuxSyscall.Pwrite64 + | 69 -> LinuxSyscall.Preadv + | 70 -> LinuxSyscall.Pwritev + | 71 -> LinuxSyscall.Sendfile + | 72 -> LinuxSyscall.Pselect6 + | 73 -> LinuxSyscall.Ppoll + | 74 -> LinuxSyscall.Signalfd4 + | 75 -> LinuxSyscall.Vmsplice + | 76 -> LinuxSyscall.Splice + | 77 -> LinuxSyscall.Tee + | 78 -> LinuxSyscall.Readlinkat + | 79 -> LinuxSyscall.Fstatat64 + | 80 -> LinuxSyscall.Fstat + | 81 -> LinuxSyscall.Sync + | 82 -> LinuxSyscall.Fsync + | 83 -> LinuxSyscall.Fdatasync + | 84 -> LinuxSyscall.SyncFileRange + | 85 -> LinuxSyscall.TimerfdCreate + | 86 -> LinuxSyscall.TimerfdSettime + | 87 -> LinuxSyscall.TimerfdGettime + | 88 -> LinuxSyscall.Utimensat + | 89 -> LinuxSyscall.Acct + | 90 -> LinuxSyscall.CapGet + | 91 -> LinuxSyscall.CapSet + | 92 -> LinuxSyscall.Personality + | 93 -> LinuxSyscall.Exit + | 94 -> LinuxSyscall.ExitGroup + | 95 -> LinuxSyscall.Waitid + | 96 -> LinuxSyscall.SetTidAddress + | 97 -> LinuxSyscall.Unshare + | 98 -> LinuxSyscall.Futex + | 99 -> LinuxSyscall.SetRobustList + | 100 -> LinuxSyscall.GetRobustList + | 101 -> LinuxSyscall.Nanosleep + | 102 -> LinuxSyscall.Getitimer + | 103 -> LinuxSyscall.Setitimer + | 104 -> LinuxSyscall.KexecLoad + | 105 -> LinuxSyscall.InitModule + | 106 -> LinuxSyscall.DeleteModule + | 107 -> LinuxSyscall.TimerCreate + | 108 -> LinuxSyscall.TimerGettime + | 109 -> LinuxSyscall.TimerGetoverrun + | 110 -> LinuxSyscall.TimerSettime + | 111 -> LinuxSyscall.TimerDelete + | 112 -> LinuxSyscall.ClockSettime + | 113 -> LinuxSyscall.ClockGettime + | 114 -> LinuxSyscall.ClockGetres + | 115 -> LinuxSyscall.ClockNanosleep + | 116 -> LinuxSyscall.Syslog + | 117 -> LinuxSyscall.Ptrace + | 118 -> LinuxSyscall.SchedSetparam + | 119 -> LinuxSyscall.SchedSetscheduler + | 120 -> LinuxSyscall.SchedGetscheduler + | 121 -> LinuxSyscall.SchedGetparam + | 122 -> LinuxSyscall.SchedSetaffinity + | 123 -> LinuxSyscall.SchedGetaffinity + | 124 -> LinuxSyscall.SchedYield + | 125 -> LinuxSyscall.SchedGetPriorityMax + | 126 -> LinuxSyscall.SchedGetPriorityMin + | 127 -> LinuxSyscall.SchedRrGetInterval + | 128 -> LinuxSyscall.RestartSyscall + | 129 -> LinuxSyscall.Kill + | 130 -> LinuxSyscall.Tkill + | 131 -> LinuxSyscall.Tgkill + | 132 -> LinuxSyscall.Sigaltstack + | 133 -> LinuxSyscall.RtSigsuspend + | 134 -> LinuxSyscall.RtSigaction + | 135 -> LinuxSyscall.RtSigprocmask + | 136 -> LinuxSyscall.RtSigpending + | 137 -> LinuxSyscall.RtSigtimedwait + | 138 -> LinuxSyscall.RtSigqueueinfo + | 139 -> LinuxSyscall.RtSigreturn + | 140 -> LinuxSyscall.Setpriority + | 141 -> LinuxSyscall.Getpriority + | 142 -> LinuxSyscall.Reboot + | 143 -> LinuxSyscall.Setregid + | 144 -> LinuxSyscall.Setgid + | 145 -> LinuxSyscall.Setreuid + | 146 -> LinuxSyscall.Setuid + | 147 -> LinuxSyscall.Setresuid + | 148 -> LinuxSyscall.Getresuid + | 149 -> LinuxSyscall.Setresgid + | 150 -> LinuxSyscall.Getresgid + | 151 -> LinuxSyscall.Setfsuid + | 152 -> LinuxSyscall.Setfsgid + | 153 -> LinuxSyscall.Times + | 154 -> LinuxSyscall.Setpgid + | 155 -> LinuxSyscall.Getpgid + | 156 -> LinuxSyscall.Getsid + | 157 -> LinuxSyscall.Setsid + | 158 -> LinuxSyscall.Getgroups + | 159 -> LinuxSyscall.Setgroups + | 160 -> LinuxSyscall.Uname + | 161 -> LinuxSyscall.Sethostname + | 162 -> LinuxSyscall.Setdomainname + | 163 -> LinuxSyscall.Getrlimit + | 164 -> LinuxSyscall.Setrlimit + | 165 -> LinuxSyscall.Getrusage + | 166 -> LinuxSyscall.Umask + | 167 -> LinuxSyscall.Prctl + | 168 -> LinuxSyscall.Getcpu + | 169 -> LinuxSyscall.Gettimeofday + | 170 -> LinuxSyscall.Settimeofday + | 171 -> LinuxSyscall.AdjTimex + | 172 -> LinuxSyscall.Getpid + | 173 -> LinuxSyscall.Getppid + | 174 -> LinuxSyscall.Getuid + | 175 -> LinuxSyscall.Geteuid + | 176 -> LinuxSyscall.Getgid + | 177 -> LinuxSyscall.Getegid + | 178 -> LinuxSyscall.Gettid + | 179 -> LinuxSyscall.Sysinfo + | 180 -> LinuxSyscall.MqOpen + | 181 -> LinuxSyscall.MqUnlink + | 182 -> LinuxSyscall.MqTimedsend + | 183 -> LinuxSyscall.MqTimedreceive + | 184 -> LinuxSyscall.MqNotify + | 185 -> LinuxSyscall.MqGetsetattr + | 186 -> LinuxSyscall.Msgget + | 187 -> LinuxSyscall.Msgctl + | 188 -> LinuxSyscall.Msgrcv + | 189 -> LinuxSyscall.Msgsnd + | 190 -> LinuxSyscall.Semget + | 191 -> LinuxSyscall.Semctl + | 192 -> LinuxSyscall.Semtimedop + | 193 -> LinuxSyscall.Semop + | 194 -> LinuxSyscall.Shmget + | 195 -> LinuxSyscall.Shmctl + | 196 -> LinuxSyscall.Shmat + | 197 -> LinuxSyscall.Shmdt + | 198 -> LinuxSyscall.Socket + | 199 -> LinuxSyscall.Socketpair + | 200 -> LinuxSyscall.Bind + | 201 -> LinuxSyscall.Listen + | 202 -> LinuxSyscall.Accept + | 203 -> LinuxSyscall.Connect + | 204 -> LinuxSyscall.Getsockname + | 205 -> LinuxSyscall.Getpeername + | 206 -> LinuxSyscall.Sendto + | 207 -> LinuxSyscall.Recvfrom + | 208 -> LinuxSyscall.Setsockopt + | 209 -> LinuxSyscall.Getsockopt + | 210 -> LinuxSyscall.Shutdown + | 211 -> LinuxSyscall.Sendmsg + | 212 -> LinuxSyscall.Recvmsg + | 213 -> LinuxSyscall.Readahead + | 214 -> LinuxSyscall.Brk + | 215 -> LinuxSyscall.Munmap + | 216 -> LinuxSyscall.Mremap + | 217 -> LinuxSyscall.AddKey + | 218 -> LinuxSyscall.RequestKey + | 219 -> LinuxSyscall.Keyctl + | 220 -> LinuxSyscall.Clone + | 221 -> LinuxSyscall.Execve + | 222 -> LinuxSyscall.Mmap + | 223 -> LinuxSyscall.Fadvise64 + | 224 -> LinuxSyscall.Swapon + | 225 -> LinuxSyscall.Swapoff + | 226 -> LinuxSyscall.Mprotect + | 227 -> LinuxSyscall.Msync + | 228 -> LinuxSyscall.Mlock + | 229 -> LinuxSyscall.Munlock + | 230 -> LinuxSyscall.Mlockall + | 231 -> LinuxSyscall.Munlockall + | 232 -> LinuxSyscall.Mincore + | 233 -> LinuxSyscall.Madvise + | 234 -> LinuxSyscall.RemapFilePages + | 235 -> LinuxSyscall.Mbind + | 236 -> LinuxSyscall.GetMempolicy + | 237 -> LinuxSyscall.SetMempolicy + | 238 -> LinuxSyscall.MigratePages + | 239 -> LinuxSyscall.MovePages + | 240 -> LinuxSyscall.RtTgsigqueueinfo + | 241 -> LinuxSyscall.PerfEventOpen + | 242 -> LinuxSyscall.Accept4 + | 243 -> LinuxSyscall.Recvmmsg + | 260 -> LinuxSyscall.Wait4 + | 261 -> LinuxSyscall.Prlimit64 + | 262 -> LinuxSyscall.FanotifyInit + | 263 -> LinuxSyscall.FanotifyMark + | 264 -> LinuxSyscall.NameToHandleAt + | 265 -> LinuxSyscall.OpenByHandleAt + | 266 -> LinuxSyscall.ClockAdjtime + | 267 -> LinuxSyscall.Syncfs + | 268 -> LinuxSyscall.Setns + | 269 -> LinuxSyscall.Sendmmsg + | 270 -> LinuxSyscall.ProcessVmReadv + | 271 -> LinuxSyscall.ProcessVmWritev + | 272 -> LinuxSyscall.Kcmp + | 273 -> LinuxSyscall.FinitModule + | 274 -> LinuxSyscall.SchedSetattr + | 275 -> LinuxSyscall.SchedGetattr + | 276 -> LinuxSyscall.Renameat2 + | 277 -> LinuxSyscall.Seccomp + | 278 -> LinuxSyscall.Getrandom + | 279 -> LinuxSyscall.MemfdCreate + | 280 -> LinuxSyscall.Bpf + | 281 -> LinuxSyscall.Execveat + | 282 -> LinuxSyscall.Userfaultfd + | 283 -> LinuxSyscall.Membarrier + | 284 -> LinuxSyscall.Mlock2 + | 285 -> LinuxSyscall.CopyFileRange + | 286 -> LinuxSyscall.Preadv2 + | 287 -> LinuxSyscall.Pwritev2 + | 288 -> LinuxSyscall.PkeyMprotect + | 289 -> LinuxSyscall.PkeyAlloc + | 290 -> LinuxSyscall.PkeyFree + | 291 -> LinuxSyscall.Statx + | 292 -> LinuxSyscall.IoPgetevents + | 293 -> LinuxSyscall.Rseq + | 294 -> LinuxSyscall.KexecFileLoad + | 403 -> LinuxSyscall.ClockGettime64 + | 404 -> LinuxSyscall.ClockSettime64 + | 405 -> LinuxSyscall.ClockAdjtime64 + | 406 -> LinuxSyscall.ClockGetres64 + | 407 -> LinuxSyscall.ClockNanosleep64 + | 408 -> LinuxSyscall.TimerGettime64 + | 409 -> LinuxSyscall.TimerSettime64 + | 410 -> LinuxSyscall.TimerfdGettime64 + | 411 -> LinuxSyscall.TimerfdSettime64 + | 412 -> LinuxSyscall.Utimensat64 + | 413 -> LinuxSyscall.Pselect6_64 + | 414 -> LinuxSyscall.Ppoll64 + | 416 -> LinuxSyscall.IoPgetevents64 + | 417 -> LinuxSyscall.Recvmmsg64 + | 418 -> LinuxSyscall.MqTimedsend64 + | 419 -> LinuxSyscall.MqTimedreceive64 + | 420 -> LinuxSyscall.Semtimedop64 + | 421 -> LinuxSyscall.RtSigtimedwait64 + | 422 -> LinuxSyscall.Futex64 + | 423 -> LinuxSyscall.SchedRrGetInterval64 + | 424 -> LinuxSyscall.PidfdSendSignal + | 425 -> LinuxSyscall.IoUringSetup + | 426 -> LinuxSyscall.IoUringEnter + | 427 -> LinuxSyscall.IoUringRegister + | 428 -> LinuxSyscall.OpenTree + | 429 -> LinuxSyscall.MoveMount + | 430 -> LinuxSyscall.Fsopen + | 431 -> LinuxSyscall.Fsconfig + | 432 -> LinuxSyscall.Fsmount + | 433 -> LinuxSyscall.Fspick + | 434 -> LinuxSyscall.PidfdOpen + | 435 -> LinuxSyscall.Clone3 + | 436 -> LinuxSyscall.CloseRange + | 437 -> LinuxSyscall.Openat2 + | 438 -> LinuxSyscall.PidfdGetfd + | 439 -> LinuxSyscall.Faccessat2 + | 441 -> LinuxSyscall.EpollPwait | _ -> raise UnhandledSyscallException + /// Return a LinuxSyscall from a given number and architecture. + [] let ofNumber arch num = match arch with - | Arch.IntelX86 -> getX86Syscall num - | Arch.IntelX64 -> getX64Syscall num + | Architecture.IntelX86 -> getX86Syscall num + | Architecture.IntelX64 -> getX64Syscall num + | Architecture.ARMv7 | Architecture.AARCH32 -> getARMEABISyscall num + | Architecture.AARCH64 -> getAARCH64Syscall num + | Architecture.MIPS32 -> getMIPSO32Syscall num + | Architecture.MIPS64 -> getMIPSN64Syscall num + | Architecture.PPC32 -> getPPC32Syscall num + | Architecture.RISCV64 -> getRISCV64Syscall num | _ -> raise UnhandledSyscallException + /// Transform a LinuxSyscall to a string. + [] let toString = function | LinuxSyscall.Accept -> "accept" | LinuxSyscall.Accept4 -> "accept4" @@ -1989,6 +6227,8 @@ module LinuxSyscall = | LinuxSyscall.ArcSetTLS -> "arc_settls" | LinuxSyscall.ArcUsrCmpxchg -> "arc_usr_cmpxchg" | LinuxSyscall.ArchPrctl -> "arch_prctl" + | LinuxSyscall.ArmFadvise64 -> "arm_fadvise64_64" + | LinuxSyscall.ArmSyncFileRange -> "arm_sync_file_range" | LinuxSyscall.AtomicBarrier -> "atomic_barrier" | LinuxSyscall.AtomicCmpxchg32 -> "atomic_cmpxchg_32" | LinuxSyscall.Bdflush -> "bdflush" @@ -1997,6 +6237,7 @@ module LinuxSyscall = | LinuxSyscall.Bpf -> "bpf" | LinuxSyscall.Brk -> "brk" | LinuxSyscall.Breakpoint -> "breakpoint" + | LinuxSyscall.CacheCtl -> "cachectl" | LinuxSyscall.CacheFlush -> "cacheflush" | LinuxSyscall.CapGet -> "capget" | LinuxSyscall.CapSet -> "capset" @@ -2019,6 +6260,7 @@ module LinuxSyscall = | LinuxSyscall.Clone -> "clone" | LinuxSyscall.Clone3 -> "clone3" | LinuxSyscall.Close -> "close" + | LinuxSyscall.CloseRange -> "close_range" | LinuxSyscall.CmpxchgBadaddr -> "cmpxchg_badaddr" | LinuxSyscall.Connect -> "connect" | LinuxSyscall.CopyFileRange -> "copy_file_range" @@ -2428,6 +6670,7 @@ module LinuxSyscall = | LinuxSyscall.TimerGettime64 -> "timer_gettime64" | LinuxSyscall.TimerSettime -> "timer_settime" | LinuxSyscall.TimerSettime64 -> "timer_settime64" + | LinuxSyscall.Timerfd -> "timerfd" | LinuxSyscall.TimerfdCreate -> "timerfd_create" | LinuxSyscall.TimerfdGettime -> "timerfd_gettime" | LinuxSyscall.TimerfdGettime64 -> "timerfd_gettime64" @@ -2468,3 +6711,503 @@ module LinuxSyscall = | LinuxSyscall.Writev -> "writev" | LinuxSyscall.Xtensa -> "xtensa" | _ -> raise UnhandledSyscallException + + /// Convert a string to a LinuxSyscall. + [] + let ofString = function + | "accept" -> LinuxSyscall.Accept + | "accept4" -> LinuxSyscall.Accept4 + | "access" -> LinuxSyscall.Access + | "acct" -> LinuxSyscall.Acct + | "add_key" -> LinuxSyscall.AddKey + | "adjtimex" -> LinuxSyscall.AdjTimex + | "alarm" -> LinuxSyscall.Alarm + | "alloc_hugepages" -> LinuxSyscall.AllocHugePages + | "arc_gettls" -> LinuxSyscall.ArcGetTLS + | "arc_settls" -> LinuxSyscall.ArcSetTLS + | "arc_usr_cmpxchg" -> LinuxSyscall.ArcUsrCmpxchg + | "arch_prctl" -> LinuxSyscall.ArchPrctl + | "arm_fadvise64_64" -> LinuxSyscall.ArmFadvise64 + | "arm_sync_file_range" -> LinuxSyscall.ArmSyncFileRange + | "atomic_barrier" -> LinuxSyscall.AtomicBarrier + | "atomic_cmpxchg_32" -> LinuxSyscall.AtomicCmpxchg32 + | "bdflush" -> LinuxSyscall.Bdflush + | "bfin_spinlock" -> LinuxSyscall.BfinSpinlock + | "bind" -> LinuxSyscall.Bind + | "bpf" -> LinuxSyscall.Bpf + | "brk" -> LinuxSyscall.Brk + | "breakpoint" -> LinuxSyscall.Breakpoint + | "cachectl" -> LinuxSyscall.CacheCtl + | "cacheflush" -> LinuxSyscall.CacheFlush + | "capget" -> LinuxSyscall.CapGet + | "capset" -> LinuxSyscall.CapSet + | "chdir" -> LinuxSyscall.Chdir + | "chmod" -> LinuxSyscall.Chmod + | "chown" -> LinuxSyscall.Chown + | "chown32" -> LinuxSyscall.Chown32 + | "chroot" -> LinuxSyscall.Chroot + | "clock_adjtime" -> LinuxSyscall.ClockAdjtime + | "clock_adjtime64" -> LinuxSyscall.ClockAdjtime64 + | "clock_getres" -> LinuxSyscall.ClockGetres + | "clock_getres64" -> LinuxSyscall.ClockGetres64 + | "clock_gettime" -> LinuxSyscall.ClockGettime + | "clock_gettime64" -> LinuxSyscall.ClockGettime64 + | "clock_nanosleep" -> LinuxSyscall.ClockNanosleep + | "clock_settime" -> LinuxSyscall.ClockSettime + | "clock_settime64" -> LinuxSyscall.ClockSettime64 + | "clock_nanosleep64" -> LinuxSyscall.ClockNanosleep64 + | "clone2" -> LinuxSyscall.Clone2 + | "clone" -> LinuxSyscall.Clone + | "clone3" -> LinuxSyscall.Clone3 + | "close" -> LinuxSyscall.Close + | "close_range" -> LinuxSyscall.CloseRange + | "cmpxchg_badaddr" -> LinuxSyscall.CmpxchgBadaddr + | "connect" -> LinuxSyscall.Connect + | "copy_file_range" -> LinuxSyscall.CopyFileRange + | "creat" -> LinuxSyscall.Creat + | "create_module" -> LinuxSyscall.CreateModule + | "delete_module" -> LinuxSyscall.DeleteModule + | "dma_memcpy" -> LinuxSyscall.DmaMemcpy + | "dup" -> LinuxSyscall.Dup + | "dup2" -> LinuxSyscall.Dup2 + | "dup3" -> LinuxSyscall.Dup3 + | "epoll_create" -> LinuxSyscall.EpollCreate + | "epoll_create1" -> LinuxSyscall.EpollCreate1 + | "epoll_ctl" -> LinuxSyscall.EpollCtl + | "epoll_pwait" -> LinuxSyscall.EpollPwait + | "epoll_wait" -> LinuxSyscall.EpollWait + | "eventfd" -> LinuxSyscall.Eventfd + | "eventfd2" -> LinuxSyscall.Eventfd2 + | "execv" -> LinuxSyscall.Execv + | "execve" -> LinuxSyscall.Execve + | "execveat" -> LinuxSyscall.Execveat + | "exit" -> LinuxSyscall.Exit + | "exit_group" -> LinuxSyscall.ExitGroup + | "faccessat" -> LinuxSyscall.Faccessat + | "fadvise64" -> LinuxSyscall.Fadvise64 + | "fadvise64_64" -> LinuxSyscall.Fadvise64_64 + | "fallocate" -> LinuxSyscall.Fallocate + | "fanotify_init" -> LinuxSyscall.FanotifyInit + | "fanotify_mark" -> LinuxSyscall.FanotifyMark + | "fchdir" -> LinuxSyscall.Fchdir + | "fchmod" -> LinuxSyscall.Fchmod + | "fchmodat" -> LinuxSyscall.Fchmodat + | "fchown" -> LinuxSyscall.Fchown + | "fchown32" -> LinuxSyscall.Fchown32 + | "fchownat" -> LinuxSyscall.Fchownat + | "fcntl" -> LinuxSyscall.Fcntl + | "fcntl64" -> LinuxSyscall.Fcntl64 + | "fdatasync" -> LinuxSyscall.Fdatasync + | "fgetxattr" -> LinuxSyscall.Fgetxattr + | "finit_module" -> LinuxSyscall.FinitModule + | "flistxattr" -> LinuxSyscall.Flistxattr + | "flock" -> LinuxSyscall.Flock + | "fork" -> LinuxSyscall.Fork + | "free_hugepages" -> LinuxSyscall.FreeHugepages + | "fremovexattr" -> LinuxSyscall.Fremovexattr + | "fsconfig" -> LinuxSyscall.Fsconfig + | "fsetxattr" -> LinuxSyscall.Fsetxattr + | "fsmount" -> LinuxSyscall.Fsmount + | "fsopen" -> LinuxSyscall.Fsopen + | "fspick" -> LinuxSyscall.Fspick + | "fstat" -> LinuxSyscall.Fstat + | "fstat64" -> LinuxSyscall.Fstat64 + | "fstatat64" -> LinuxSyscall.Fstatat64 + | "fstatfs" -> LinuxSyscall.Fstatfs + | "fstatfs64" -> LinuxSyscall.Fstatfs64 + | "fsync" -> LinuxSyscall.Fsync + | "ftruncate" -> LinuxSyscall.Ftruncate + | "ftruncate64" -> LinuxSyscall.Ftruncate64 + | "futex" -> LinuxSyscall.Futex + | "futex64" -> LinuxSyscall.Futex64 + | "futimesat" -> LinuxSyscall.Futimesat + | "get_kernel_syms" -> LinuxSyscall.GetKernelSyms + | "get_mempolicy" -> LinuxSyscall.GetMempolicy + | "get_robust_list" -> LinuxSyscall.GetRobustList + | "get_thread_area" -> LinuxSyscall.GetThreadArea + | "get_tls" -> LinuxSyscall.GetTLS + | "getcpu" -> LinuxSyscall.Getcpu + | "getcwd" -> LinuxSyscall.Getcwd + | "getdents" -> LinuxSyscall.Getdents + | "getdents64" -> LinuxSyscall.Getdents64 + | "getdomainname" -> LinuxSyscall.Getdomainname + | "getdtablesize" -> LinuxSyscall.Getdtablesize + | "getegid" -> LinuxSyscall.Getegid + | "getegid32" -> LinuxSyscall.Getegid32 + | "geteuid" -> LinuxSyscall.Geteuid + | "geteuid32" -> LinuxSyscall.Geteuid32 + | "getgid" -> LinuxSyscall.Getgid + | "getgid32" -> LinuxSyscall.Getgid32 + | "getgroups" -> LinuxSyscall.Getgroups + | "getgroups32" -> LinuxSyscall.Getgroups32 + | "gethostname" -> LinuxSyscall.Gethostname + | "getitimer" -> LinuxSyscall.Getitimer + | "getpeername" -> LinuxSyscall.Getpeername + | "getpagesize" -> LinuxSyscall.Getpagesize + | "getpgid" -> LinuxSyscall.Getpgid + | "getpgrp" -> LinuxSyscall.Getpgrp + | "getpid" -> LinuxSyscall.Getpid + | "getppid" -> LinuxSyscall.Getppid + | "getpriority" -> LinuxSyscall.Getpriority + | "getrandom" -> LinuxSyscall.Getrandom + | "getresgid" -> LinuxSyscall.Getresgid + | "getresgid32" -> LinuxSyscall.Getresgid32 + | "getresuid" -> LinuxSyscall.Getresuid + | "getresuid32" -> LinuxSyscall.Getresuid32 + | "getrlimit" -> LinuxSyscall.Getrlimit + | "getrusage" -> LinuxSyscall.Getrusage + | "getsid" -> LinuxSyscall.Getsid + | "getsockname" -> LinuxSyscall.Getsockname + | "getsockopt" -> LinuxSyscall.Getsockopt + | "gettid" -> LinuxSyscall.Gettid + | "gettimeofday" -> LinuxSyscall.Gettimeofday + | "getuid" -> LinuxSyscall.Getuid + | "getuid32" -> LinuxSyscall.Getuid32 + | "getunwind" -> LinuxSyscall.Getunwind + | "getxattr" -> LinuxSyscall.Getxattr + | "getxgid" -> LinuxSyscall.Getxgid + | "getxpid" -> LinuxSyscall.Getxpid + | "getxuid" -> LinuxSyscall.Getxuid + | "init_module" -> LinuxSyscall.InitModule + | "inotify_add_watch" -> LinuxSyscall.InotifyAddWatch + | "inotify_init" -> LinuxSyscall.InotifyInit + | "inotify_init1" -> LinuxSyscall.InotifyInit1 + | "inotify_rm_watch" -> LinuxSyscall.InotifyRmWatch + | "io_cancel" -> LinuxSyscall.IoCancel + | "io_destroy" -> LinuxSyscall.IoDestroy + | "io_getevents" -> LinuxSyscall.IoGetevents + | "io_pgetevents" -> LinuxSyscall.IoPgetevents + | "io_pgetevents64" -> LinuxSyscall.IoPgetevents64 + | "io_setup" -> LinuxSyscall.IoSetup + | "io_submit" -> LinuxSyscall.IoSubmit + | "io_uring_enter" -> LinuxSyscall.IoUringEnter + | "io_uring_register" -> LinuxSyscall.IoUringRegister + | "io_uring_setup" -> LinuxSyscall.IoUringSetup + | "ioctl" -> LinuxSyscall.Ioctl + | "ioperm" -> LinuxSyscall.Ioperm + | "iopl" -> LinuxSyscall.Iopl + | "ioprio_get" -> LinuxSyscall.IoprioGet + | "ioprio_set" -> LinuxSyscall.IoprioSet + | "ipc" -> LinuxSyscall.Ipc + | "kcmp" -> LinuxSyscall.Kcmp + | "kern_features" -> LinuxSyscall.KernFeatures + | "kexec_file_load" -> LinuxSyscall.KexecFileLoad + | "kexec_load" -> LinuxSyscall.KexecLoad + | "keyctl" -> LinuxSyscall.Keyctl + | "kill" -> LinuxSyscall.Kill + | "lchown" -> LinuxSyscall.Lchown + | "lchown32" -> LinuxSyscall.Lchown32 + | "lgetxattr" -> LinuxSyscall.Lgetxattr + | "link" -> LinuxSyscall.Link + | "linkat" -> LinuxSyscall.Linkat + | "listen" -> LinuxSyscall.Listen + | "listxattr" -> LinuxSyscall.Listxattr + | "llistxattr" -> LinuxSyscall.Llistxattr + | "lookup_dcookie" -> LinuxSyscall.LookupDcookie + | "lremovexattr" -> LinuxSyscall.Lremovexattr + | "lseek" -> LinuxSyscall.Lseek + | "_llseek" -> LinuxSyscall.LLseek + | "lsetxattr" -> LinuxSyscall.Lsetxattr + | "lstat" -> LinuxSyscall.Lstat + | "lstat64" -> LinuxSyscall.Lstat64 + | "madvise" -> LinuxSyscall.Madvise + | "mbind" -> LinuxSyscall.Mbind + | "memory_ordering" -> LinuxSyscall.MemoryOrdering + | "metag_get_tls" -> LinuxSyscall.MetagGetTLS + | "metag_set_fpu_flags" -> LinuxSyscall.MetagSetFpuFlags + | "metag_set_tls" -> LinuxSyscall.MetagSetTLS + | "metag_setglobalbit" -> LinuxSyscall.MetagSetglobalbit + | "membarrier" -> LinuxSyscall.Membarrier + | "memfd_create" -> LinuxSyscall.MemfdCreate + | "migrate_pages" -> LinuxSyscall.MigratePages + | "mincore" -> LinuxSyscall.Mincore + | "mkdir" -> LinuxSyscall.Mkdir + | "mkdirat" -> LinuxSyscall.Mkdirat + | "mknod" -> LinuxSyscall.Mknod + | "mknodat" -> LinuxSyscall.Mknodat + | "mlock" -> LinuxSyscall.Mlock + | "mlock2" -> LinuxSyscall.Mlock2 + | "mlockall" -> LinuxSyscall.Mlockall + | "mmap" -> LinuxSyscall.Mmap + | "mmap2" -> LinuxSyscall.Mmap2 + | "modify_ldt" -> LinuxSyscall.ModifyLdt + | "mount" -> LinuxSyscall.Mount + | "move_mount" -> LinuxSyscall.MoveMount + | "move_pages" -> LinuxSyscall.MovePages + | "mprotect" -> LinuxSyscall.Mprotect + | "mq_getsetattr" -> LinuxSyscall.MqGetsetattr + | "mq_notify" -> LinuxSyscall.MqNotify + | "mq_open" -> LinuxSyscall.MqOpen + | "mq_timedreceive" -> LinuxSyscall.MqTimedreceive + | "mq_timedreceive64" -> LinuxSyscall.MqTimedreceive64 + | "mq_timedsend" -> LinuxSyscall.MqTimedsend + | "mq_timedsend64" -> LinuxSyscall.MqTimedsend64 + | "mq_unlink" -> LinuxSyscall.MqUnlink + | "mremap" -> LinuxSyscall.Mremap + | "msgctl" -> LinuxSyscall.Msgctl + | "msgget" -> LinuxSyscall.Msgget + | "msgrcv" -> LinuxSyscall.Msgrcv + | "msgsnd" -> LinuxSyscall.Msgsnd + | "msync" -> LinuxSyscall.Msync + | "munlock" -> LinuxSyscall.Munlock + | "munlockall" -> LinuxSyscall.Munlockall + | "munmap" -> LinuxSyscall.Munmap + | "name_to_handle_at" -> LinuxSyscall.NameToHandleAt + | "nanosleep" -> LinuxSyscall.Nanosleep + | "newfstatat" -> LinuxSyscall.Newfstatat + | "_newselect" -> LinuxSyscall.NewSelect + | "nfsservctl" -> LinuxSyscall.Nfsservctl + | "nice" -> LinuxSyscall.Nice + | "old_adjtimex" -> LinuxSyscall.OldAdjtimex + | "old_getrlimit" -> LinuxSyscall.OldGetrlimit + | "oldfstat" -> LinuxSyscall.Oldfstat + | "oldlstat" -> LinuxSyscall.Oldlstat + | "oldolduname" -> LinuxSyscall.Oldolduname + | "oldstat" -> LinuxSyscall.Oldstat + | "oldumount" -> LinuxSyscall.Oldumount + | "olduname" -> LinuxSyscall.Olduname + | "open" -> LinuxSyscall.Open + | "open_by_handle_at" -> LinuxSyscall.OpenByHandleAt + | "open_tree" -> LinuxSyscall.OpenTree + | "openat" -> LinuxSyscall.Openat + | "openat2" -> LinuxSyscall.Openat2 + | "or1k_atomic" -> LinuxSyscall.Or1kAtomic + | "pause" -> LinuxSyscall.Pause + | "pciconfig_iobase" -> LinuxSyscall.PciconfigIobase + | "pciconfig_read" -> LinuxSyscall.PciconfigRead + | "pciconfig_write" -> LinuxSyscall.PciconfigWrite + | "perf_event_open" -> LinuxSyscall.PerfEventOpen + | "personality" -> LinuxSyscall.Personality + | "perfctr" -> LinuxSyscall.Perfctr + | "perfmonctl" -> LinuxSyscall.Perfmonctl + | "pidfd_getfd" -> LinuxSyscall.PidfdGetfd + | "pidfd_send_signal" -> LinuxSyscall.PidfdSendSignal + | "pidfd_open" -> LinuxSyscall.PidfdOpen + | "pipe" -> LinuxSyscall.Pipe + | "pipe2" -> LinuxSyscall.Pipe2 + | "pivot_root" -> LinuxSyscall.PivotRoot + | "pkey_alloc" -> LinuxSyscall.PkeyAlloc + | "pkey_free" -> LinuxSyscall.PkeyFree + | "pkey_mprotect" -> LinuxSyscall.PkeyMprotect + | "poll" -> LinuxSyscall.Poll + | "ppoll" -> LinuxSyscall.Ppoll + | "ppoll64" -> LinuxSyscall.Ppoll64 + | "prctl" -> LinuxSyscall.Prctl + | "pread" -> LinuxSyscall.Pread + | "pread64" -> LinuxSyscall.Pread64 + | "preadv" -> LinuxSyscall.Preadv + | "preadv2" -> LinuxSyscall.Preadv2 + | "prlimit64" -> LinuxSyscall.Prlimit64 + | "process_vm_readv" -> LinuxSyscall.ProcessVmReadv + | "process_vm_writev" -> LinuxSyscall.ProcessVmWritev + | "pselect6" -> LinuxSyscall.Pselect6 + | "pselect6_64" -> LinuxSyscall.Pselect6_64 + | "ptrace" -> LinuxSyscall.Ptrace + | "pwrite" -> LinuxSyscall.Pwrite + | "pwrite64" -> LinuxSyscall.Pwrite64 + | "pwritev" -> LinuxSyscall.Pwritev + | "pwritev2" -> LinuxSyscall.Pwritev2 + | "query_module" -> LinuxSyscall.QueryModule + | "quotactl" -> LinuxSyscall.Quotactl + | "read" -> LinuxSyscall.Read + | "readahead" -> LinuxSyscall.Readahead + | "readdir" -> LinuxSyscall.Readdir + | "readlink" -> LinuxSyscall.Readlink + | "readlinkat" -> LinuxSyscall.Readlinkat + | "readv" -> LinuxSyscall.Readv + | "reboot" -> LinuxSyscall.Reboot + | "recv" -> LinuxSyscall.Recv + | "recvfrom" -> LinuxSyscall.Recvfrom + | "recvmsg" -> LinuxSyscall.Recvmsg + | "recvmmsg" -> LinuxSyscall.Recvmmsg + | "recvmmsg64" -> LinuxSyscall.Recvmmsg64 + | "remap_file_pages" -> LinuxSyscall.RemapFilePages + | "removexattr" -> LinuxSyscall.Removexattr + | "rename" -> LinuxSyscall.Rename + | "renameat" -> LinuxSyscall.Renameat + | "renameat2" -> LinuxSyscall.Renameat2 + | "request_key" -> LinuxSyscall.RequestKey + | "restart_syscall" -> LinuxSyscall.RestartSyscall + | "riscv_flush_icache" -> LinuxSyscall.RiscvFlushIcache + | "rmdir" -> LinuxSyscall.Rmdir + | "rseq" -> LinuxSyscall.Rseq + | "rt_sigaction" -> LinuxSyscall.RtSigaction + | "rt_sigpending" -> LinuxSyscall.RtSigpending + | "rt_sigprocmask" -> LinuxSyscall.RtSigprocmask + | "rt_sigqueueinfo" -> LinuxSyscall.RtSigqueueinfo + | "rt_sigreturn" -> LinuxSyscall.RtSigreturn + | "rt_sigsuspend" -> LinuxSyscall.RtSigsuspend + | "rt_sigtimedwait" -> LinuxSyscall.RtSigtimedwait + | "rt_sigtimedwait64" -> LinuxSyscall.RtSigtimedwait64 + | "rt_tgsigqueueinfo" -> LinuxSyscall.RtTgsigqueueinfo + | "rtas" -> LinuxSyscall.Rtas + | "s390_runtime_instr" -> LinuxSyscall.S390RuntimeInstr + | "s390_pci_mmio_read" -> LinuxSyscall.S390PciMmioRead + | "s390_pci_mmio_write" -> LinuxSyscall.S390PciMmioWrite + | "s390_sthyi" -> LinuxSyscall.S390Sthyi + | "s390_guarded_storage" -> LinuxSyscall.S390GuardedStorage + | "sched_get_affinity" -> LinuxSyscall.SchedGetAffinity + | "sched_get_priority_max" -> LinuxSyscall.SchedGetPriorityMax + | "sched_get_priority_min" -> LinuxSyscall.SchedGetPriorityMin + | "sched_getaffinity" -> LinuxSyscall.SchedGetaffinity + | "sched_getattr" -> LinuxSyscall.SchedGetattr + | "sched_getparam" -> LinuxSyscall.SchedGetparam + | "sched_getscheduler" -> LinuxSyscall.SchedGetscheduler + | "sched_rr_get_interval" -> LinuxSyscall.SchedRrGetInterval + | "sched_rr_get_interval64" -> LinuxSyscall.SchedRrGetInterval64 + | "sched_set_affinity" -> LinuxSyscall.SchedSetAffinity + | "sched_setaffinity" -> LinuxSyscall.SchedSetaffinity + | "sched_setattr" -> LinuxSyscall.SchedSetattr + | "sched_setparam" -> LinuxSyscall.SchedSetparam + | "sched_setscheduler" -> LinuxSyscall.SchedSetscheduler + | "sched_yield" -> LinuxSyscall.SchedYield + | "seccomp" -> LinuxSyscall.Seccomp + | "select" -> LinuxSyscall.Select + | "semctl" -> LinuxSyscall.Semctl + | "semget" -> LinuxSyscall.Semget + | "semop" -> LinuxSyscall.Semop + | "semtimedop" -> LinuxSyscall.Semtimedop + | "semtimedop64" -> LinuxSyscall.Semtimedop64 + | "send" -> LinuxSyscall.Send + | "sendfile" -> LinuxSyscall.Sendfile + | "sendfile64" -> LinuxSyscall.Sendfile64 + | "sendmmsg" -> LinuxSyscall.Sendmmsg + | "sendmsg" -> LinuxSyscall.Sendmsg + | "sendto" -> LinuxSyscall.Sendto + | "set_mempolicy" -> LinuxSyscall.SetMempolicy + | "set_robust_list" -> LinuxSyscall.SetRobustList + | "set_thread_area" -> LinuxSyscall.SetThreadArea + | "set_tid_address" -> LinuxSyscall.SetTidAddress + | "set_tls" -> LinuxSyscall.SetTLS + | "setdomainname" -> LinuxSyscall.Setdomainname + | "setfsgid" -> LinuxSyscall.Setfsgid + | "setfsgid32" -> LinuxSyscall.Setfsgid32 + | "setfsuid" -> LinuxSyscall.Setfsuid + | "setfsuid32" -> LinuxSyscall.Setfsuid32 + | "setgid" -> LinuxSyscall.Setgid + | "setgid32" -> LinuxSyscall.Setgid32 + | "setgroups" -> LinuxSyscall.Setgroups + | "setgroups32" -> LinuxSyscall.Setgroups32 + | "sethae" -> LinuxSyscall.Sethae + | "sethostname" -> LinuxSyscall.Sethostname + | "setitimer" -> LinuxSyscall.Setitimer + | "setns" -> LinuxSyscall.Setns + | "setpgid" -> LinuxSyscall.Setpgid + | "setpgrp" -> LinuxSyscall.Setpgrp + | "setpriority" -> LinuxSyscall.Setpriority + | "setregid" -> LinuxSyscall.Setregid + | "setregid32" -> LinuxSyscall.Setregid32 + | "setresgid" -> LinuxSyscall.Setresgid + | "setresgid32" -> LinuxSyscall.Setresgid32 + | "setresuid" -> LinuxSyscall.Setresuid + | "setresuid32" -> LinuxSyscall.Setresuid32 + | "setreuid" -> LinuxSyscall.Setreuid + | "setreuid32" -> LinuxSyscall.Setreuid32 + | "setrlimit" -> LinuxSyscall.Setrlimit + | "setsid" -> LinuxSyscall.Setsid + | "setsockopt" -> LinuxSyscall.Setsockopt + | "settimeofday" -> LinuxSyscall.Settimeofday + | "setuid" -> LinuxSyscall.Setuid + | "setuid32" -> LinuxSyscall.Setuid32 + | "setup" -> LinuxSyscall.Setup + | "setxattr" -> LinuxSyscall.Setxattr + | "sgetmask" -> LinuxSyscall.Sgetmask + | "shmat" -> LinuxSyscall.Shmat + | "shmctl" -> LinuxSyscall.Shmctl + | "shmdt" -> LinuxSyscall.Shmdt + | "shmget" -> LinuxSyscall.Shmget + | "shutdown" -> LinuxSyscall.Shutdown + | "sigaction" -> LinuxSyscall.Sigaction + | "sigaltstack" -> LinuxSyscall.Sigaltstack + | "signal" -> LinuxSyscall.Signal + | "signalfd" -> LinuxSyscall.Signalfd + | "signalfd4" -> LinuxSyscall.Signalfd4 + | "sigpending" -> LinuxSyscall.Sigpending + | "sigprocmask" -> LinuxSyscall.Sigprocmask + | "sigreturn" -> LinuxSyscall.Sigreturn + | "sigsuspend" -> LinuxSyscall.Sigsuspend + | "socket" -> LinuxSyscall.Socket + | "socketcall" -> LinuxSyscall.Socketcall + | "socketpair" -> LinuxSyscall.Socketpair + | "spill" -> LinuxSyscall.Spill + | "splice" -> LinuxSyscall.Splice + | "spu_create" -> LinuxSyscall.SpuCreate + | "spu_run" -> LinuxSyscall.SpuRun + | "sram_alloc" -> LinuxSyscall.SramAlloc + | "sram_free" -> LinuxSyscall.SramFree + | "ssetmask" -> LinuxSyscall.Ssetmask + | "stat" -> LinuxSyscall.Stat + | "stat64" -> LinuxSyscall.Stat64 + | "statfs" -> LinuxSyscall.Statfs + | "statfs64" -> LinuxSyscall.Statfs64 + | "statx" -> LinuxSyscall.Statx + | "stime" -> LinuxSyscall.Stime + | "subpage_prot" -> LinuxSyscall.SubpageProt + | "swapcontext" -> LinuxSyscall.SwitchEndian + | "switch_endian" -> LinuxSyscall.Swapcontext + | "swapoff" -> LinuxSyscall.Swapoff + | "swapon" -> LinuxSyscall.Swapon + | "symlink" -> LinuxSyscall.Symlink + | "symlinkat" -> LinuxSyscall.Symlinkat + | "sync" -> LinuxSyscall.Sync + | "sync_file_range" -> LinuxSyscall.SyncFileRange + | "sync_file_range2" -> LinuxSyscall.SyncFileRange2 + | "syncfs" -> LinuxSyscall.Syncfs + | "sys_debug_setcontext" -> LinuxSyscall.SysDebugSetcontext + | "syscall" -> LinuxSyscall.Syscall + | "_sysctl" -> LinuxSyscall.Sysctl + | "sysfs" -> LinuxSyscall.Sysfs + | "sysinfo" -> LinuxSyscall.Sysinfo + | "syslog" -> LinuxSyscall.Syslog + | "sysmips" -> LinuxSyscall.Sysmips + | "tee" -> LinuxSyscall.Tee + | "tgkill" -> LinuxSyscall.Tgkill + | "time" -> LinuxSyscall.Time + | "timer_create" -> LinuxSyscall.TimerCreate + | "timer_delete" -> LinuxSyscall.TimerDelete + | "timer_getoverrun" -> LinuxSyscall.TimerGetoverrun + | "timer_gettime" -> LinuxSyscall.TimerGettime + | "timer_gettime64" -> LinuxSyscall.TimerGettime64 + | "timer_settime" -> LinuxSyscall.TimerSettime + | "timer_settime64" -> LinuxSyscall.TimerSettime64 + | "timerfd" -> LinuxSyscall.Timerfd + | "timerfd_create" -> LinuxSyscall.TimerfdCreate + | "timerfd_gettime" -> LinuxSyscall.TimerfdGettime + | "timerfd_gettime64" -> LinuxSyscall.TimerfdGettime64 + | "timerfd_settime" -> LinuxSyscall.TimerfdSettime + | "timerfd_settime64" -> LinuxSyscall.TimerfdSettime64 + | "times" -> LinuxSyscall.Times + | "tkill" -> LinuxSyscall.Tkill + | "truncate" -> LinuxSyscall.Truncate + | "truncate64" -> LinuxSyscall.Truncate64 + | "ugetrlimit" -> LinuxSyscall.Ugetrlimit + | "umask" -> LinuxSyscall.Umask + | "umount" -> LinuxSyscall.Umount + | "umount2" -> LinuxSyscall.Umount2 + | "uname" -> LinuxSyscall.Uname + | "unlink" -> LinuxSyscall.Unlink + | "unlinkat" -> LinuxSyscall.Unlinkat + | "unshare" -> LinuxSyscall.Unshare + | "uselib" -> LinuxSyscall.Uselib + | "ustat" -> LinuxSyscall.Ustat + | "userfaultfd" -> LinuxSyscall.Userfaultfd + | "usr26" -> LinuxSyscall.Usr26 + | "usr32" -> LinuxSyscall.Usr32 + | "utime" -> LinuxSyscall.Utime + | "utimensat" -> LinuxSyscall.Utimensat + | "utimensat64" -> LinuxSyscall.Utimensat64 + | "utimes" -> LinuxSyscall.Utimes + | "utrap_install" -> LinuxSyscall.UtrapInstall + | "vfork" -> LinuxSyscall.Vfork + | "vhangup" -> LinuxSyscall.Vhangup + | "vm86old" -> LinuxSyscall.Vm86old + | "vm86" -> LinuxSyscall.Vm86 + | "vmsplice" -> LinuxSyscall.Vmsplice + | "vserver" -> LinuxSyscall.Vserver + | "wait4" -> LinuxSyscall.Wait4 + | "waitid" -> LinuxSyscall.Waitid + | "waitpid" -> LinuxSyscall.Waitpid + | "write" -> LinuxSyscall.Write + | "writev" -> LinuxSyscall.Writev + | "xtensa" -> LinuxSyscall.Xtensa + | _ -> raise UnhandledSyscallException \ No newline at end of file diff --git a/src/Core/TypeExtensions.fs b/src/Core/TypeExtensions.fs index a300411c..3b633f38 100644 --- a/src/Core/TypeExtensions.fs +++ b/src/Core/TypeExtensions.fs @@ -29,6 +29,7 @@ open System.Collections.Generic /// Extended Array. [] module Array = + /// Applies a function to each element of the array with its index. let inline foldi ([] folder) acc arr = Array.fold (fun (acc, idx) elt -> (folder acc idx elt, idx + 1)) (acc, 0) arr @@ -42,44 +43,28 @@ module String = explode str |> List.fold folder acc /// Convert a string to a byte array. + [] let toBytes (str: string) = str.ToCharArray () |> Array.map byte /// Convert a byte array to a string. + [] let fromBytes (bs: byte []) = Array.map char bs |> System.String + /// Wrap a string with a pair of parentheses. + [] let wrapParen s = "(" + s + ")" + /// Wrap a string with a pair of square brackets. + [] let wrapSqrdBracket s = "[" + s + "]" + /// Wrap a string with a pair of curly brackets. + [] let wrapAngleBracket s = "<" + s + ">" - let i32ToHex (v: int32) = - "0x" + v.ToString ("x") - - let u32ToHex (v: uint32) = - "0x" + v.ToString ("x") - - let u64ToHex (v: uint64) = - "0x" + v.ToString ("x") - - let i64ToHex (v: int64) = - "0x" + v.ToString ("x") - - let inline i32ToHexNoPrefix (v: int32) = - v.ToString ("x") - - let inline u32ToHexNoPrefix (v: uint32) = - v.ToString ("x") - - let inline u64ToHexNoPrefix (v: uint64) = - v.ToString ("x") - - let inline i64ToHexNoPrefix (v: int64) = - v.ToString ("x") - /// Extended BigInteger. [] module BigInteger = @@ -95,6 +80,37 @@ module BigInteger = /// Get a bitmask of size n. let getMask n = bigint.Pow (2I, n) - 1I +[] +module Byte = + /// Check if a byte is null. + [] + let isNull b = b = 0uy + + /// Check if a byte is printable. + [] + let isPrintable b = b >= 33uy && b <= 126uy + + /// Check if a byte is a whitespace. + [] + let isWhitespace b = b = 32uy || (b >= 9uy && b <= 13uy) + + /// Check if a byte is a control character. + [] + let isControl b = + b = 127uy || (b >= 1uy && b <= 8uy) || (b >= 14uy && b <= 31uy) + + /// Get a string representation of a byte used in B2R2. A null byte is + /// represented as a dot, a printable byte is represented as an ASCII + /// character, a whitespace is represented as an underscore, and a control + /// character is represented as an asterisk. + [] + let getRepresentation (b: byte) = + if isNull b then "." + elif isPrintable b then (char b).ToString () + elif isWhitespace b then "_" + elif isControl b then "*" + else "." + /// Extended Int64. [] module Int64 = @@ -107,15 +123,6 @@ module Int64 = if (power = 0L) then 1L else loop value (power - 1L) -/// Extended Option. -[] -module Option = - /// Unwrap an option type. If the value is None, throw the exception (exn). - let getWithExn (value: 'a option) exn = - match value with - | Some v -> v - | None -> raise exn - /// Extended Result. [] module Result = @@ -125,12 +132,6 @@ module Result = | Ok (r) -> r | Error _ -> invalidOp "The Result type had an Error, but not handled." - /// Is the result Ok? - let inline isOk res = - match res with - | Ok _ -> true - | _ -> false - [] module SortedList = let rec private binSearch value lo hi (keys: IList<_>) (comp: Comparer<_>) = diff --git a/src/Core/Utils.fs b/src/Core/Utils.fs index 2bbcc83d..b94e5a35 100644 --- a/src/Core/Utils.fs +++ b/src/Core/Utils.fs @@ -27,10 +27,6 @@ module B2R2.Utils open System open System.Diagnostics -let assertEqual a b exn = if a = b then () else raise exn - -let assertByCond condition exn = if condition then () else raise exn - [] let futureFeature () = let trace = StackTrace (true) @@ -45,22 +41,15 @@ let impossible () = trace.ToString () |> printfn "%s" raise <| InvalidOperationException () -let inline tap (f: 'a -> unit) (v: 'a) : 'a = - f v; v - -let inline curry f a b = f (a, b) - -let inline uncurry f (a, b) = f a b - let inline (===) a b = LanguagePrimitives.PhysicalEquality a b -let inline tupleToOpt result = +let inline tupleResultToOpt result = match result with | false, _ -> None | true, a -> Some a -let inline tripleFst (a, _, _) = a +let inline fstOfTriple (a, _, _) = a -let inline tripleSnd (_, a, _) = a +let inline sndOfTriple (_, a, _) = a -let inline tripleThd (_, _, a) = a +let inline thdOfTriple (_, _, a) = a diff --git a/src/Core/Utils.fsi b/src/Core/Utils.fsi index d3ea56cd..828632b6 100644 --- a/src/Core/Utils.fsi +++ b/src/Core/Utils.fsi @@ -25,39 +25,24 @@ /// A set of convenient misc. functions. module B2R2.Utils -/// Assert two values are equal. If not, raise an exception (exn). -val assertEqual<'a when 'a : equality> : 'a -> 'a -> exn -> unit - -/// Assert check condition. If not, raise an exception (exn). -val assertByCond: condition: bool -> exn -> unit - /// Not implemented features encountered, so raise an exception and die. val futureFeature: unit -> 'a /// Fatal error. This should never happen. val impossible: unit -> 'a -/// Apply a procedure in the middle of function pipes. -val inline tap : ('a -> unit) -> 'a -> 'a - -/// Curry a pair of arguments. -val inline curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c - -/// Uncurry a pair of arguments. -val inline uncurry : ('a -> 'b -> 'c) -> 'a * 'b -> 'c - /// Physical equality. val inline (===) : 'a -> 'a -> bool when 'a : not struct /// Convert a tuple result to an option type. The tuple result is obtained from -/// the TryGetValue pattern, e.g., IDictionary. -val inline tupleToOpt: bool * 'a -> 'a option +/// TryGetValue methods, e.g., from IDictionary. +val inline tupleResultToOpt: bool * 'a -> 'a option /// Return the first item of a triple. -val inline tripleFst: ('a * 'b * 'c) -> 'a +val inline fstOfTriple: ('a * 'b * 'c) -> 'a /// Return the second item of a triple. -val inline tripleSnd: ('a * 'b * 'c) -> 'b +val inline sndOfTriple: ('a * 'b * 'c) -> 'b /// Return the third item of a triple. -val inline tripleThd: ('a * 'b * 'c) -> 'c +val inline thdOfTriple: ('a * 'b * 'c) -> 'c diff --git a/src/Core/WordSize.fs b/src/Core/WordSize.fs index 543e5242..5a078c9b 100644 --- a/src/Core/WordSize.fs +++ b/src/Core/WordSize.fs @@ -24,8 +24,10 @@ namespace B2R2 -/// B2R2 represents the word size of a CPU with WordSize, which can be either -/// 32- or 64-bit. +/// This exception is raised when an invalid WordSize is encountered. +exception InvalidWordSizeException + +/// B2R2 represents the word size of a CPU with WordSize. type WordSize = | Bit8 = 8 | Bit16 = 16 @@ -34,25 +36,26 @@ type WordSize = | Bit128 = 128 | Bit256 = 256 -/// This exception is raised when an invalid WordSize is encountered. -exception InvalidWordSizeException - /// A helper module for the WordSize type. +[] module WordSize = - - let bitTypeOfString = function + /// Transform a string into a word size. + [] + let ofString = function | "8" -> WordSize.Bit8 | "16" -> WordSize.Bit16 | "32" -> WordSize.Bit32 | "64" -> WordSize.Bit64 | "128" -> WordSize.Bit128 | "256" -> WordSize.Bit256 - | _ -> failwith "Unknown WordSize." + | _ -> raise InvalidWordSizeException /// Transform a word size into a byte length. + [] let toByteWidth (wordSize: WordSize) = int32 wordSize / 8 /// Transform a word size into a RegType. + [] let toRegType = function | WordSize.Bit8 -> 8 | WordSize.Bit16 -> 16 @@ -60,19 +63,24 @@ module WordSize = | WordSize.Bit64 -> 64 | WordSize.Bit128 -> 128 | WordSize.Bit256 -> 256 - | _ -> failwith "Unknown WordSize." + | _ -> raise InvalidWordSizeException /// Transform a word size into a string. + [] let toString wordSz = (toRegType wordSz).ToString () /// Is the given word size 32 bit? + [] let is32 wordSz = wordSz = WordSize.Bit32 /// Is the given word size 64 bit? + [] let is64 wordSz = wordSz = WordSize.Bit64 /// Is the given word size 128 bit? + [] let is128 wordSz = wordSz = WordSize.Bit128 /// Is the given word size 256 bit? + [] let is256 wordSz = wordSz = WordSize.Bit256 \ No newline at end of file diff --git a/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj b/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj index 1e64cb13..506a7eaa 100644 --- a/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj +++ b/src/FrontEnd/BinFile.Tests/B2R2.FrontEnd.BinFile.Tests.fsproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/FrontEnd/BinFile.Tests/BinFile.Tests.fs b/src/FrontEnd/BinFile.Tests/BinFile.Tests.fs index 8e8074d5..e6997587 100644 --- a/src/FrontEnd/BinFile.Tests/BinFile.Tests.fs +++ b/src/FrontEnd/BinFile.Tests/BinFile.Tests.fs @@ -29,13 +29,16 @@ open B2R2.FrontEnd.BinFile open Microsoft.VisualStudio.TestTools.UnitTesting open System.IO open System.IO.Compression +open type FileFormat exception TestFileNotFoundException +[] module ZIPReader = - let baseDir = System.AppDomain.CurrentDomain.BaseDirectory + let zipFileSrcDir = baseDir + "../../../" + let getFileDir = function | FileFormat.PEBinary -> "PE/" | FileFormat.ELFBinary -> "ELF/" @@ -43,141 +46,435 @@ module ZIPReader = | FileFormat.WasmBinary -> "Wasm/" | _ -> failwith "Invalid file format" - let readFileFromZipFile fmt zName fName = - let zDir = zipFileSrcDir + getFileDir fmt - let archive = ZipFile.Open(zDir + zName, ZipArchiveMode.Read) - let entry = archive.GetEntry(fName) + let readBytesFromZipFile fileFormat zipFileName inZipFileName = + let zipDirectory = zipFileSrcDir + getFileDir fileFormat + let archive = ZipFile.Open (zipDirectory + zipFileName, ZipArchiveMode.Read) + let entry = archive.GetEntry (inZipFileName) let stream = entry.Open () - use ms = new MemoryStream() - stream.CopyTo(ms) - ms.ToArray() + use ms = new MemoryStream () + stream.CopyTo (ms) + ms.ToArray () + +[] +module TestHelper = + let assertFuncSymbolExistence (file: IBinFile) address symbolName = + match file.TryFindFunctionName address with + | Ok n -> Assert.AreEqual (n, symbolName) + | Error _ -> Assert.Fail () + + let getTextSectionAddr (file: IBinFile) = + let sec = file.GetTextSection () + sec.Address + + let assertExistenceOfPair pair pairSequence = + pairSequence + |> Seq.tryFind ((=) pair) + |> Option.isSome + |> Assert.IsTrue module PE = let x64FileName = "pe_x64" let x86FileName = "pe_x86" let x64PDBFileName = "pe_x64.pdb" let x86PDBFileName = "pe_x86.pdb" - let x64StrippedFileName = "pe_x64_without_pdb" - let x86StrippedFileName = "pe_x86_without_pdb" let parseFile fileName (pdbFileName: string) = - let zip = fileName + ".zip" - let file = fileName + ".exe" - let bytes = ZIPReader.readFileFromZipFile FileFormat.PEBinary zip file + let zipFile = fileName + ".zip" + let fileNameInZip = fileName + ".exe" + let bytes = readBytesFromZipFile PEBinary zipFile fileNameInZip let pdbBytes = if pdbFileName.Length = 0 then [||] - else ZIPReader.readFileFromZipFile FileFormat.PEBinary zip pdbFileName - new PEFileInfo (bytes, file, pdbBytes) + else readBytesFromZipFile PEBinary zipFile pdbFileName + PEBinFile (fileNameInZip, bytes, None, pdbBytes) :> IBinFile - let checkSymbol (fileInfo : PEFileInfo) addr symName = - match fileInfo.TryFindFunctionSymbolName addr with - | Ok n -> Assert.AreEqual (n, symName) - | Error _ -> Assert.Fail () + let assertExistenceOfRelocBlock (file: IBinFile) pageRVA blockSize = + (file :?> PEBinFile).PE.RelocBlocks + |> List.map (fun pair -> pair.PageRVA, pair.BlockSize) + |> Seq.ofList + |> assertExistenceOfPair (pageRVA, blockSize) + + let assertExistenceOfSectionHeader (file: IBinFile) address headerName = + (file :?> PEBinFile).PE.SectionHeaders + |> Array.map (fun record -> record.VirtualAddress, record.Name) + |> assertExistenceOfPair (address, headerName) [] - type TestClass () = + type X86TestClass () = + static let file = parseFile x86FileName x86PDBFileName + + [] + member __.``[PE] X86 EntryPoint test`` () = + Assert.AreEqual (Some 0x0040140cUL, file.EntryPoint) + + [] + member __.``[PE] X86 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[PE] X86 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[PE] X86 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[PE] X86 sections length test`` () = + Assert.AreEqual (5, file.GetSections () |> Seq.length) + + [] + member __.``[PE] X86 static symbols length test`` () = + Assert.AreEqual (239, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[PE] X86 dynamic symbols length test`` () = + Assert.AreEqual (41, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[PE] X86 text section address test`` () = + Assert.AreEqual (0x00401000UL, getTextSectionAddr file) + + [] + member __.``[PE] X86 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[PE] X86 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x00401090UL "_add" + + [] + member __.``[PE] X86 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x004010d0UL "_mul" + + [] + member __.``[PE] X86 function symbol test (3)`` () = + assertFuncSymbolExistence file 0x004010e0UL "_main" + + [] + member __.``[PE] X86 Reloc section test (1)`` () = + assertExistenceOfRelocBlock file 8192u 36 + + [] + member __.``[PE] X86 Reloc section test (2)`` () = + assertExistenceOfRelocBlock file 4096u 320 + + [] + member __.``[PE] X86 section header test (1)`` () = + assertExistenceOfSectionHeader file 4096 ".text" + + [] + member __.``[PE] X86 section header test (2)`` () = + assertExistenceOfSectionHeader file 8192 ".rdata" + + [] + member __.``[PE] X86 section header test (3)`` () = + assertExistenceOfSectionHeader file 12288 ".data" + + [] + member __.``[PE] X86 section header test (4)`` () = + assertExistenceOfSectionHeader file 16384 ".rsrc" + + [] + member __.``[PE] X86 section header test (5)`` () = + assertExistenceOfSectionHeader file 20480 ".reloc" + + [] + type X64TestClass () = + static let file = parseFile x64FileName x64PDBFileName + + [] + member __.``[PE] X64 EntryPoint test`` () = + Assert.AreEqual (Some 0x1400014b4UL, file.EntryPoint) + + [] + member __.``[PE] X64 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[PE] X64 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[PE] X64 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[PE] X64 sections length test`` () = + Assert.AreEqual (6, file.GetSections () |> Seq.length) + + [] + member __.``[PE] X64 static symbols length test`` () = + Assert.AreEqual (240, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[PE] X64 dynamic symbols length test`` () = + Assert.AreEqual (43, file.GetDynamicSymbols () |> Seq.length) [] - member __.``[BinFile] PE File Parse Test (X86)`` () = - let fi = parseFile x86FileName x86PDBFileName - Assert.AreEqual (Some 0x0040140cUL, fi.EntryPoint) - Assert.AreEqual (FileType.ExecutableFile, fi.FileType) - Assert.AreEqual (false, fi.IsStripped) - Assert.AreEqual (true, fi.IsNXEnabled) - Assert.AreEqual (5, fi.GetSections () |> Seq.length) - Assert.AreEqual (239, fi.GetStaticSymbols () |> Seq.length) - Assert.AreEqual (41, fi.GetDynamicSymbols () |> Seq.length) - Assert.AreEqual (0x00401000UL, fi.TextStartAddr) - Assert.AreEqual (WordSize.Bit32, fi.WordSize) - checkSymbol fi 0x00401090UL "_add" - checkSymbol fi 0x004010d0UL "_mul" - checkSymbol fi 0x004010e0UL "_main" - - [] - member __.``[BinFile] PE File Parse Test (X64)`` () = - let fi = parseFile x64FileName x64PDBFileName - Assert.AreEqual (Some 0x1400014b4UL, fi.EntryPoint) - Assert.AreEqual (FileType.ExecutableFile, fi.FileType) - Assert.AreEqual (false, fi.IsStripped) - Assert.AreEqual (true, fi.IsNXEnabled) - Assert.AreEqual (6, fi.GetSections () |> Seq.length) - Assert.AreEqual (240, fi.GetStaticSymbols () |> Seq.length) - Assert.AreEqual (43, fi.GetDynamicSymbols () |> Seq.length) - Assert.AreEqual (0x140001000UL, fi.TextStartAddr) - Assert.AreEqual (WordSize.Bit64, fi.WordSize) - checkSymbol fi 0x1400010e0UL "add" - checkSymbol fi 0x140001110UL "mul" - checkSymbol fi 0x140001130UL "main" + member __.``[PE] X64 text section address test`` () = + Assert.AreEqual (0x140001000UL, getTextSectionAddr file) + + [] + member __.``[PE] X64 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[PE] X64 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x1400010e0UL "add" + + [] + member __.``[PE] X64 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x140001110UL "mul" + + [] + member __.``[PE] X64 function symbol test (3)`` () = + assertFuncSymbolExistence file 0x140001130UL "main" + + [] + member __.``[PE] X64 Reloc section test`` () = + assertExistenceOfRelocBlock file 8192u 28 + + [] + member __.``[PE] X64 section header test (1)`` () = + assertExistenceOfSectionHeader file 4096 ".text" + + [] + member __.``[PE] X64 section header test (2)`` () = + assertExistenceOfSectionHeader file 8192 ".rdata" + + [] + member __.``[PE] X64 section header test (3)`` () = + assertExistenceOfSectionHeader file 12288 ".data" + + [] + member __.``[PE] X64 section header test (4)`` () = + assertExistenceOfSectionHeader file 16384 ".pdata" + + [] + member __.``[PE] X64 section header test (5)`` () = + assertExistenceOfSectionHeader file 20480 ".rsrc" + + [] + member __.``[PE] X64 section header test (6)`` () = + assertExistenceOfSectionHeader file 24576 ".reloc" module Mach = let parseFile fileName arch = - let zip = fileName + ".zip" - let bytes = ZIPReader.readFileFromZipFile FileFormat.MachBinary zip fileName + let zipFile = fileName + ".zip" + let bytes = readBytesFromZipFile MachBinary zipFile fileName let isa = ISA.Init arch Endian.Little - new MachFileInfo (bytes, fileName, isa) + MachBinFile (fileName, bytes, isa, None) :> IBinFile - let checkSymbol (fileInfo : MachFileInfo) addr symName = - match fileInfo.TryFindFunctionSymbolName addr with - | Ok n -> Assert.AreEqual (n, symName) - | Error _ -> Assert.Fail () + let assertExistenceOfFlag (file: IBinFile) flags = + (file :?> MachBinFile).Header.Flags.ToString () = flags + |> Assert.IsTrue + + let assertExistenceOfSectionHeader (file: IBinFile) address sectionName = + (file :?> MachBinFile).Sections + |> Seq.map (fun record -> record.SecAddr, record.SecName) + |> assertExistenceOfPair (address, sectionName) [] - type TestClass () = + type X86StrippedTestClass () = + static let file = parseFile "mach_x86_rm_stripped" Architecture.IntelX86 + + [] + member __.``[Mach] X86_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x00002050UL, file.EntryPoint) + + [] + member __.``[Mach] X86_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[Mach] X86_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[Mach] X86_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[Mach] X86_Stripped sections length test`` () = + Assert.AreEqual (9, file.GetSections () |> Seq.length) + + [] + member __.``[Mach] X86_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[Mach] X86_Stripped dynamic symbols length test`` () = + Assert.AreEqual (59, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[Mach] X86_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (45, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[Mach] X86_Stripped text section address test`` () = + Assert.AreEqual (0x00002050UL, getTextSectionAddr file) + + [] + member __.``[Mach] X86_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[Mach] X86_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x00003b28UL "___error" + + [] + member __.``[Mach] X86_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00003b70UL "_fflush" + + [] + member __.``[Mach] X86_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 8272UL "__text" + + [] + member __.``[Mach] X86_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 16620UL "__common" + + [] + member __.``[Mach] X86_Stripped flags test`` () = + let flags = + "MH_NOUNDEFS, MH_DYLDLINK, MH_TWOLEVEL, MH_PIE, MH_NO_HEAP_EXECUTION" + assertExistenceOfFlag file flags + + [] + type X64TestClass () = + static let file = parseFile "mach_x64_wc" Architecture.IntelX64 + + [] + member __.``[Mach] X64 EntryPoint test`` () = + Assert.AreEqual (Some 0x100000E90UL, file.EntryPoint) + + [] + member __.``[Mach] X64 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[Mach] X64 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[Mach] X64 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[Mach] X64 sections length test`` () = + Assert.AreEqual (13, file.GetSections () |> Seq.length) + + [] + member __.``[Mach] X64 static symbols length test`` () = + Assert.AreEqual (885, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[Mach] X64 dynamic symbols length test`` () = + Assert.AreEqual (190, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[Mach] X64 linkageTableEntries length test`` () = + Assert.AreEqual (72, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[Mach] X64 text section address test`` () = + Assert.AreEqual (0x100000D30UL, getTextSectionAddr file) + + [] + member __.``[Mach] X64 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[Mach] X64 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x100000D30UL "_usage" + + [] + member __.``[Mach] X64 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x100005F90UL "_error" + + [] + member __.``[Mach] X64 section header test (1)`` () = + assertExistenceOfSectionHeader file 0x100000D30UL "__text" + + [] + member __.``[Mach] X64 section header test (2)`` () = + assertExistenceOfSectionHeader file 0x10000d680UL "__common" + + [] + member __.``[Mach] X64 flags test`` () = + let flags = "MH_NOUNDEFS, MH_DYLDLINK, MH_TWOLEVEL, MH_PIE" + assertExistenceOfFlag file flags + + [] + type X64StrippedTestClass () = + static let file = parseFile "mach_x64_wc_stripped" Architecture.IntelX64 + + [] + member __.``[Mach] X64_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x100000E90UL, file.EntryPoint) + + [] + member __.``[Mach] X64_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[Mach] X64_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[Mach] X64_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[Mach] X64_Stripped sections length test`` () = + Assert.AreEqual (13, file.GetSections () |> Seq.length) + + [] + member __.``[Mach] X64_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[Mach] X64_Stripped dynamic symbols length test`` () = + Assert.AreEqual (190, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[Mach] X64_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (72, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[Mach] X64_Stripped text section address test`` () = + Assert.AreEqual (0x100000D30UL, getTextSectionAddr file) + + [] + member __.``[Mach] X64_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[Mach] X64_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x10000B076UL "___error" + + [] + member __.``[Mach] X64_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x10000B0D0UL "_fflush" + + [] + member __.``[Mach] X64_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0x100000D30UL "__text" + + [] + member __.``[Mach] X64_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 0x10000d680UL "__common" [] - member __.``[BinFile] Mach File Parse Test (X86_Stripped)`` () = - let fi = parseFile "mach_x86_rm_stripped" Architecture.IntelX86 - Assert.AreEqual (Some 0x00002050UL, fi.EntryPoint) - Assert.AreEqual (FileType.ExecutableFile, fi.FileType) - Assert.AreEqual (true, fi.IsStripped) - Assert.AreEqual (true, fi.IsNXEnabled) - Assert.AreEqual (9, fi.GetSections () |> Seq.length) - Assert.AreEqual (0, fi.GetStaticSymbols () |> Seq.length) - Assert.AreEqual (59, fi.GetDynamicSymbols () |> Seq.length) - Assert.AreEqual (45, fi.GetLinkageTableEntries () |> Seq.length) - Assert.AreEqual (0x00002050UL, fi.TextStartAddr) - Assert.AreEqual (WordSize.Bit32, fi.WordSize) - checkSymbol fi 0x00003b28UL "___error" - checkSymbol fi 0x00003b70UL "_fflush" - - [] - member __.``[BinFile] Mach File Parse Test (X64)`` () = - let fi = parseFile "mach_x64_wc" Architecture.IntelX64 - Assert.AreEqual (Some 0x100000E90UL, fi.EntryPoint) - Assert.AreEqual (FileType.ExecutableFile, fi.FileType) - Assert.AreEqual (false, fi.IsStripped) - Assert.AreEqual (true, fi.IsNXEnabled) - Assert.AreEqual (13, fi.GetSections () |> Seq.length) - Assert.AreEqual (885, fi.GetStaticSymbols () |> Seq.length) - Assert.AreEqual (190, fi.GetDynamicSymbols () |> Seq.length) - Assert.AreEqual (72, fi.GetLinkageTableEntries () |> Seq.length) - Assert.AreEqual (0x100000D30UL, fi.TextStartAddr) - Assert.AreEqual (WordSize.Bit64, fi.WordSize) - checkSymbol fi 0x100000D30UL "_usage" - checkSymbol fi 0x100005F90UL "_error" - - [] - member __.``[BinFile] Mach File Parse Test (X64_Stripped)`` () = - let fi = parseFile "mach_x64_wc_stripped" Architecture.IntelX64 - Assert.AreEqual (Some 0x100000E90UL, fi.EntryPoint) - Assert.AreEqual (FileType.ExecutableFile, fi.FileType) - Assert.AreEqual (true, fi.IsStripped) - Assert.AreEqual (true, fi.IsNXEnabled) - Assert.AreEqual (13, fi.GetSections () |> Seq.length) - Assert.AreEqual (0, fi.GetStaticSymbols () |> Seq.length) - Assert.AreEqual (190, fi.GetDynamicSymbols () |> Seq.length) - Assert.AreEqual (72, fi.GetLinkageTableEntries () |> Seq.length) - Assert.AreEqual (0x100000D30UL, fi.TextStartAddr) - Assert.AreEqual (WordSize.Bit64, fi.WordSize) - checkSymbol fi 0x10000B076UL "___error" - checkSymbol fi 0x10000B0D0UL "_fflush" + member __.``[Mach] X64_Stripped flags test`` () = + let flags = "MH_NOUNDEFS, MH_DYLDLINK, MH_TWOLEVEL, MH_PIE" + assertExistenceOfFlag file flags module ELF = let x64FileName = "elf_x64_ls" let x86FileName = "elf_x86_ls" let x64StrippedFileName = "elf_x64_ls_stripped" let x86StrippedFileName = "elf_x86_ls_stripped" - let arm32FileName = "elf_arm32_ls" let thumbFileName = "elf_thumb_ls" let aarch64FileName = "elf_aarch64_ls" @@ -189,245 +486,1029 @@ module ELF = let mips64StrippedFileName = "elf_mips64_ls_stripped" let parseFile fileName = - let zip = fileName + ".zip" - let bytes = ZIPReader.readFileFromZipFile FileFormat.ELFBinary zip fileName - new ELFFileInfo (bytes, fileName) + let zipFile = fileName + ".zip" + let bytes = readBytesFromZipFile ELFBinary zipFile fileName + ELFBinFile (fileName, bytes, None, None) :> IBinFile - let checkSymbol (fileInfo : ELFFileInfo) addr symName = - match fileInfo.TryFindFunctionSymbolName addr with - | Ok n -> Assert.AreEqual (n, symName) - | Error _ -> Assert.Fail () + let assertExistenceOfRelocation (file: IBinFile) offset symbolName = + (file :?> ELFBinFile).RelocationInfo.RelocByAddr + |> Seq.map (fun pair -> pair.Key, pair.Value.RelSymbol.Value.SymName) + |> assertExistenceOfPair (offset, symbolName) + + let assertExistenceOfSectionHeader (file: IBinFile) sectionNum sectionName = + (file :?> ELFBinFile).SectionHeaders + |> Seq.map (fun record -> record.SecNum, record.SecName) + |> assertExistenceOfPair (sectionNum, sectionName) [] - type TestClass () = + type X86TestClass () = + static let file = parseFile x86FileName [] - member __.``[BinFile] ELF File Parse Test (X86)`` () = - let fi = parseFile x86FileName - Assert.AreEqual (Some 0x8049CD0UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, false) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 31) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 793) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 131) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 114) - Assert.AreEqual (fi.TextStartAddr, 0x8049CD0UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x080495b0UL "unsetenv" - checkSymbol fi 0x08049cb0UL "putchar_unlocked" - - [] - member __.``[BinFile] ELF File Parse Test (X86_Stripped)`` () = - let fi = parseFile x86StrippedFileName - Assert.AreEqual (Some 0x8049CD0UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 29) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 131) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 114) - Assert.AreEqual (fi.TextStartAddr, 0x8049CD0UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x080495b0UL "unsetenv" - checkSymbol fi 0x08049cb0UL "putchar_unlocked" - - [] - member __.``[BinFile] ELF File Parse Test (X64)`` () = - let fi = parseFile x64FileName - Assert.AreEqual (Some 0x404050UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, false) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 38) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 635) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 126) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 110) - Assert.AreEqual (fi.TextStartAddr, 0x4027C0UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit64) - checkSymbol fi 0x004020e0UL "__ctype_toupper_loc" - checkSymbol fi 0x004027a0UL "__sprintf_chk" - - [] - member __.``[BinFile] ELF File Parse Test (X64_Stripped)`` () = - let fi = parseFile x64StrippedFileName - Assert.AreEqual (Some 0x404050UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 29) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 126) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 110) - Assert.AreEqual (fi.TextStartAddr, 0x4027C0UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit64) - checkSymbol fi 0x004020e0UL "__ctype_toupper_loc" - checkSymbol fi 0x004027a0UL "__sprintf_chk" - - [] - member __.``[BinFile] ELF File Parse Test (arm32)`` () = - let fi = parseFile arm32FileName - Assert.AreEqual (Some 0x00013d0cUL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, false) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 38) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 1299) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 136) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 121) - Assert.AreEqual (fi.TextStartAddr, 0x00011f98UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x000119ecUL "fdopen" - checkSymbol fi 0x00011f8cUL "__assert_fail" - - [] - member __.``[BinFile] ELF File Parse Test (arm32_Stripped)`` () = - let fi = parseFile arm32StrippedFileName - Assert.AreEqual (Some 0x00013d0cUL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 28) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 136) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 121) - Assert.AreEqual (fi.TextStartAddr, 0x00011f98UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x000119ecUL "fdopen" - checkSymbol fi 0x00011f8cUL "__assert_fail" - - [] - member __.``[BinFile] ELF File Parse Test (thumb)`` () = - let fi = parseFile thumbFileName - Assert.AreEqual (Some 0x00013605UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, false) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 38) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 1088) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 136) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 121) - Assert.AreEqual (fi.TextStartAddr, 0x00011fe0UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x000119fcUL "fdopen" - checkSymbol fi 0x00011fd0UL "__assert_fail" - - [] - member __.``[BinFile] ELF File Parse Test (thumb_Stripped)`` () = - let fi = parseFile thumbStrippedFileName - Assert.AreEqual (Some 0x00013605UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 28) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 136) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 121) - Assert.AreEqual (fi.TextStartAddr, 0x00011fe0UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x000119fcUL "fdopen" - checkSymbol fi 0x00011fd0UL "__assert_fail" - - [] - member __.``[BinFile] ELF File Parse Test (aarch64)`` () = - let fi = parseFile aarch64FileName - Assert.AreEqual (Some 0x00404788UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, false) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 37) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 935) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 136) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 121) - Assert.AreEqual (fi.TextStartAddr, 0x00402e60UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit64) - checkSymbol fi 0x004026d0UL "mbrtowc" - checkSymbol fi 0x00402e50UL "__fxstatat" - - [] - member __.``[BinFile] ELF File Parse Test (aarch64_Stripped)`` () = - let fi = parseFile aarch64StrippedFileName - Assert.AreEqual (Some 0x00404788UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.ExecutableFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, true) - Assert.AreEqual (fi.GetSections () |> Seq.length, 27) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 136) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 121) - Assert.AreEqual (fi.TextStartAddr, 0x00402e60UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit64) - checkSymbol fi 0x004026d0UL "mbrtowc" - checkSymbol fi 0x00402e50UL "__fxstatat" - - [] - member __.``[BinFile] ELF File Parse Test (mips32_Stripped)`` () = - let fi = parseFile mips32StrippedFileName - Assert.AreEqual (Some 0x00004c80UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.LibFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, false) - Assert.AreEqual (fi.GetSections () |> Seq.length, 34) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 232) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 0) - Assert.AreEqual (fi.TextStartAddr, 0x00002c50UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x0001c280UL "strcmp" - checkSymbol fi 0x0001c240UL "getpwnam" - - [] - member __.``[BinFile] ELF File Parse Test (mips32_Stripped_le)`` () = - let fi = parseFile mips32LEStrippedFileName - Assert.AreEqual (Some 0x00004c80UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.LibFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, false) - Assert.AreEqual (fi.GetSections () |> Seq.length, 34) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 232) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 0) - Assert.AreEqual (fi.TextStartAddr, 0x00002c50UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit32) - checkSymbol fi 0x0001c280UL "__snprintf_chk" - checkSymbol fi 0x0001c240UL "unsetenv" - - [] - member __.``[BinFile] ELF File Parse Test (mips64_Stripped)`` () = - let fi = parseFile mips64StrippedFileName - Assert.AreEqual (Some 0x0000ade0UL, fi.EntryPoint) - Assert.AreEqual (fi.FileType, FileType.LibFile) - Assert.AreEqual (fi.IsStripped, true) - Assert.AreEqual (fi.IsNXEnabled, false) - Assert.AreEqual (fi.GetSections () |> Seq.length, 32) - Assert.AreEqual (fi.GetStaticSymbols () |> Seq.length, 0) - Assert.AreEqual (fi.GetDynamicSymbols () |> Seq.length, 232) - Assert.AreEqual (fi.GetLinkageTableEntries () |> Seq.length, 0) - Assert.AreEqual (fi.TextStartAddr, 0x00008f90UL) - Assert.AreEqual (fi.WordSize, WordSize.Bit64) - checkSymbol fi 0x00022380UL "strcmp" - checkSymbol fi 0x00022320UL "unsetenv" + member __.``[ELF] X86 EntryPoint test`` () = + Assert.AreEqual (Some 0x8049CD0UL, file.EntryPoint) -module Wasm = - let wasmBasicFileName = "wasm_basic" + [] + member __.``[ELF] X86 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) - let parseFile fileName = - let zip = fileName + ".zip" - let file = fileName + ".wasm" - let bytes = - ZIPReader.readFileFromZipFile FileFormat.WasmBinary zip file - new WasmFileInfo (bytes, "") + [] + member __.``[ELF] X86 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[ELF] X86 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] X86 sections length test`` () = + Assert.AreEqual (31, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] X86 static symbols length test`` () = + Assert.AreEqual (793, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] X86 dynamic symbols length test`` () = + Assert.AreEqual (131, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] X86 linkageTableEntries length test`` () = + Assert.AreEqual (114, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] X86 text section address test`` () = + Assert.AreEqual (0x8049CD0UL, getTextSectionAddr file) + + [] + member __.``[ELF] X86 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] X86 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x080495B0UL "unsetenv" + + [] + member __.``[ELF] X86 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x080495B0UL "unsetenv" + + [] + member __.``[ELF] X86 Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x08069FFCUL "__gmon_start__" + + [] + member __.``[ELF] X86 Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0806A3C0UL "optarg" + + [] + member __.``[ELF] X86 Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0806A00CUL "unsetenv" + + [] + member __.``[ELF] X86 Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x0806A1CCUL "putchar_unlocked" + + [] + member __.``[ELF] X86 section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] X86 section header test (2)`` () = + assertExistenceOfSectionHeader file 30 ".strtab" [] - type TestClass () = + type X86StrippedTestClass () = + static let file = parseFile x86StrippedFileName + + [] + member __.``[ELF] X86_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x8049CD0UL, file.EntryPoint) + + [] + member __.``[ELF] X86_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] X86_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] X86_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] X86_Stripped sections length test`` () = + Assert.AreEqual (29, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] X86_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] X86_Stripped dynamic symbols length test`` () = + Assert.AreEqual (131, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] X86_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (114, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] X86_Stripped text section address test`` () = + Assert.AreEqual (0x8049CD0UL, getTextSectionAddr file) + + [] + member __.``[ELF] X86_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] X86_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x080495B0UL "unsetenv" + + [] + member __.``[ELF] X86_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x08049CB0UL "putchar_unlocked" + + [] + member __.``[ELF] X86_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x08069FFCUL "__gmon_start__" + + [] + member __.``[ELF] X86_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0806A3C0UL "optarg" + + [] + member __.``[ELF] X86_Stripped Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0806A00CUL "unsetenv" + + [] + member __.``[ELF] X86_Stripped Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x0806A1CCUL "putchar_unlocked" + + [] + member __.``[ELF] X86_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] X86_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 28 ".shstrtab" + + [] + type X64TestClass () = + static let file = parseFile x64FileName + + [] + member __.``[ELF] X64 EntryPoint test`` () = + Assert.AreEqual (Some 0x404050UL, file.EntryPoint) + + [] + member __.``[ELF] X64 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] X64 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[ELF] X64 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] X64 sections length test`` () = + Assert.AreEqual (38, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] X64 static symbols length test`` () = + Assert.AreEqual (635, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] X64 dynamic symbols length test`` () = + Assert.AreEqual (126, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] X64 linkageTableEntries length test`` () = + Assert.AreEqual (110, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] X64 text section address test`` () = + Assert.AreEqual (0x4027C0UL, getTextSectionAddr file) + + [] + member __.``[ELF] X64 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[ELF] X64 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x004020E0UL "__ctype_toupper_loc" + + [] + member __.``[ELF] X64 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x004027A0UL "__sprintf_chk" + + [] + member __.``[ELF] X64 Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x0061Eff8UL "__gmon_start__" + + [] + member __.``[ELF] X64 Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0061F620UL "stderr" + + [] + member __.``[ELF] X64 Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0061F018UL "__ctype_toupper_loc" + + [] + member __.``[ELF] X64 Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x0061F378UL "__sprintf_chk" + + [] + member __.``[ELF] X64 section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] X64 section header test (2)`` () = + assertExistenceOfSectionHeader file 37 ".strtab" + + [] + type X64StrippedTestClass () = + static let file = parseFile x64StrippedFileName + + [] + member __.``[ELF] X64_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x404050UL, file.EntryPoint) + + [] + member __.``[ELF] X64_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] X64_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] X64_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] X64_Stripped sections length test`` () = + Assert.AreEqual (29, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] X64_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] X64_Stripped dynamic symbols length test`` () = + Assert.AreEqual (126, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] X64_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (110, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] X64_Stripped text section address test`` () = + Assert.AreEqual (0x4027C0UL, getTextSectionAddr file) + + [] + member __.``[ELF] X64_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[ELF] X64_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x004020E0UL "__ctype_toupper_loc" + + [] + member __.``[ELF] X64_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x004027A0UL "__sprintf_chk" + + [] + member __.``[ELF] X64_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x0061EFF8UL "__gmon_start__" + + [] + member __.``[ELF] X64_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0061F620UL "stderr" + + [] + member __.``[ELF] X64_Stripped Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0061F018UL "__ctype_toupper_loc" + + [] + member __.``[ELF] X64_Stripped Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x0061F378UL "__sprintf_chk" + + [] + member __.``[ELF] X64_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] X64_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 28 ".shstrtab" + + [] + type ARM32TestClass () = + static let file = parseFile arm32FileName + + [] + member __.``[ELF] arm32 EntryPoint test`` () = + Assert.AreEqual (Some 0x00013D0CUL, file.EntryPoint) + + [] + member __.``[ELF] arm32 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] arm32 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[ELF] arm32 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] arm32 sections length test`` () = + Assert.AreEqual (38, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] arm32 static symbols length test`` () = + Assert.AreEqual (1299, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] arm32 dynamic symbols length test`` () = + Assert.AreEqual (136, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] arm32 linkageTableEntries length test`` () = + Assert.AreEqual (121, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] arm32 text section address test`` () = + Assert.AreEqual (0x00011F98UL, getTextSectionAddr file) + + [] + member __.``[ELF] arm32 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] arm32 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x000119ECUL "fdopen" + + [] + member __.``[ELF] arm32 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00011F8CUL "__assert_fail" + + [] + member __.``[ELF] arm32 Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x0003F1F0UL "__gmon_start__" + + [] + member __.``[ELF] arm32 Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0003F35CUL "stdout" + + [] + member __.``[ELF] arm32 Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0003F00CUL "fdopen" + + [] + member __.``[ELF] arm32 Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x0003F1eCUL "__assert_fail" + + [] + member __.``[ELF] arm32 section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] arm32 section header test (2)`` () = + assertExistenceOfSectionHeader file 37 ".strtab" + + [] + type ARM32StrippedTestClass () = + static let file = parseFile arm32StrippedFileName + + [] + member __.``[ELF] arm32_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x00013D0CUL, file.EntryPoint) + + [] + member __.``[ELF] arm32_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] arm32_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] arm32_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] arm32_Stripped sections length test`` () = + Assert.AreEqual (28, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] arm32_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] arm32_Stripped dynamic symbols length test`` () = + Assert.AreEqual (136, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] arm32_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (121, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] arm32_Stripped text section address test`` () = + Assert.AreEqual (0x00011F98UL, getTextSectionAddr file) + + [] + member __.``[ELF] arm32_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] arm32_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x000119ECUL "fdopen" + + [] + member __.``[ELF] arm32_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00011F8CUL "__assert_fail" + + [] + member __.``[ELF] arm32_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x0003F1F0UL "__gmon_start__" + + [] + member __.``[ELF] arm32_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0003F35CUL "stdout" + + [] + member __.``[ELF] arm32_Stripped Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0003F00CUL "fdopen" + + [] + member __.``[ELF] arm32_Stripped Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x0003F1ECUL "__assert_fail" + + [] + member __.``[ELF] arm32_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] arm32_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 27 ".shstrtab" + + [] + type ThumbTestClass () = + static let file = parseFile thumbFileName + + [] + member __.``[ELF] thumb EntryPoint test`` () = + Assert.AreEqual (Some 0x00013605UL, file.EntryPoint) + + [] + member __.``[ELF] thumb file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] thumb IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[ELF] thumb IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] thumb sections length test`` () = + Assert.AreEqual (38, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] thumb static symbols length test`` () = + Assert.AreEqual (1088, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] thumb dynamic symbols length test`` () = + Assert.AreEqual (136, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] thumb linkageTableEntries length test`` () = + Assert.AreEqual (121, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] thumb text section address test`` () = + Assert.AreEqual (0x00011FE0UL, getTextSectionAddr file) + + [] + member __.``[ELF] thumb isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] thumb function symbol test (1)`` () = + assertFuncSymbolExistence file 0x000119FCUL "fdopen" + + [] + member __.``[ELF] thumb function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00011FD0UL "__assert_fail" + + [] + member __.``[ELF] thumb Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x000371F0UL "__gmon_start__" + + [] + member __.``[ELF] thumb Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0003735CUL "stdout" + + [] + member __.``[ELF] thumb Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0003700CUL "fdopen" + + [] + member __.``[ELF] thumb Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x000371ECUL "__assert_fail" + + [] + member __.``[ELF] thumb section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] thumb section header test (2)`` () = + assertExistenceOfSectionHeader file 37 ".strtab" + + [] + type ThumbStrippedTestClass () = + static let file = parseFile thumbStrippedFileName + + [] + member __.``[ELF] thumb_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x00013605UL, file.EntryPoint) + + [] + member __.``[ELF] thumb_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] thumb_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] thumb_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] thumb_Stripped sections length test`` () = + Assert.AreEqual (28, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] thumb_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] thumb_Stripped dynamic symbols length test`` () = + Assert.AreEqual (136, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] thumb_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (121, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] thumb_Stripped text section address test`` () = + Assert.AreEqual (0x00011FE0UL, getTextSectionAddr file) + + [] + member __.``[ELF] thumb_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] thumb_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x000119FCUL "fdopen" + + [] + member __.``[ELF] thumb_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00011FD0UL "__assert_fail" + + [] + member __.``[ELF] thumb_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x000371F0UL "__gmon_start__" + + [] + member __.``[ELF] thumb_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0003735CUL "stdout" + + [] + member __.``[ELF] thumb_Stripped Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x0003700CUL "fdopen" + + [] + member __.``[ELF] thumb_Stripped Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x000371ECUL "__assert_fail" + + [] + member __.``[ELF] thumb_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] thumb_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 27 ".shstrtab" + + [] + type AArch64TestClass () = + static let file = parseFile aarch64FileName + + [] + member __.``[ELF] aarch64 EntryPoint test`` () = + Assert.AreEqual (Some 0x00404788UL, file.EntryPoint) + + [] + member __.``[ELF] aarch64 file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] aarch64 IsStripped test`` () = + Assert.AreEqual (false, file.IsStripped) + + [] + member __.``[ELF] aarch64 IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] aarch64 sections length test`` () = + Assert.AreEqual (37, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] aarch64 static symbols length test`` () = + Assert.AreEqual (935, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] aarch64 dynamic symbols length test`` () = + Assert.AreEqual (136, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] aarch64 linkageTableEntries length test`` () = + Assert.AreEqual (121, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] aarch64 text section address test`` () = + Assert.AreEqual (0x00402E60UL, getTextSectionAddr file) + + [] + member __.``[ELF] aarch64 isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[ELF] aarch64 function symbol test (1)`` () = + assertFuncSymbolExistence file 0x004026D0UL "mbrtowc" + + [] + member __.``[ELF] aarch64 function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00402E50UL "__fxstatat" + + [] + member __.``[ELF] aarch64 Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x0042FFD8UL "__gmon_start__" + + [] + member __.``[ELF] aarch64 Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x00430630UL "__progname" + + [] + member __.``[ELF] aarch64 Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x00430000UL "mbrtowc" + + [] + member __.``[ELF] aarch64 Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x004303C0UL "__fxstatat" + + [] + member __.``[ELF] aarch64 section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] aarch64 section header test (2)`` () = + assertExistenceOfSectionHeader file 36 ".strtab" + + [] + type AArch64StrippedTestClass () = + static let file = parseFile aarch64StrippedFileName + + [] + member __.``[ELF] aarch64_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x00404788UL, file.EntryPoint) + + [] + member __.``[ELF] aarch64_Stripped file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[ELF] aarch64_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] aarch64_Stripped IsNXEnabled test`` () = + Assert.AreEqual (true, file.IsNXEnabled) + + [] + member __.``[ELF] aarch64_Stripped sections length test`` () = + Assert.AreEqual (27, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] aarch64_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] aarch64_Stripped dynamic symbols length test`` () = + Assert.AreEqual (136, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] aarch64_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (121, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] aarch64_Stripped text section address test`` () = + Assert.AreEqual (0x00402E60UL, getTextSectionAddr file) + + [] + member __.``[ELF] aarch64_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[ELF] aarch64_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x004026D0UL "mbrtowc" + + [] + member __.``[ELF] aarch64_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00402E50UL "__fxstatat" + + [] + member __.``[ELF] aarch64_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x0042FFD8UL "__gmon_start__" + + [] + member __.``[ELF] aarch64_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x00430630UL "__progname" + + [] + member __.``[ELF] aarch64_Stripped Reloc section PLT test (1)`` () = + assertExistenceOfRelocation file 0x00430000UL "mbrtowc" + + [] + member __.``[ELF] aarch64_Stripped Reloc section PLT test (2)`` () = + assertExistenceOfRelocation file 0x004303C0UL "__fxstatat" + + [] + member __.``[ELF] aarch64_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] aarch64_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 26 ".shstrtab" + + [] + type MIPS32StrippedTestClass () = + static let file = parseFile mips32StrippedFileName + + [] + member __.``[ELF] mips32_Stripped EntryPoint test`` () = + Assert.AreEqual (Some 0x00004C80UL, file.EntryPoint) + + [] + member __.``[ELF] mips32_Stripped file type test`` () = + Assert.AreEqual (FileType.LibFile, file.Type) + + [] + member __.``[ELF] mips32_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] mips32_Stripped IsNXEnabled test`` () = + Assert.AreEqual (false, file.IsNXEnabled) + + [] + member __.``[ELF] mips32_Stripped sections length test`` () = + Assert.AreEqual (34, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped dynamic symbols length test`` () = + Assert.AreEqual (232, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (106, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped text section address test`` () = + Assert.AreEqual (0x00002C50UL, getTextSectionAddr file) + + [] + member __.``[ELF] mips32_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] mips32_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x0001C280UL "strcmp" + + [] + member __.``[ELF] mips32_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x0001C240UL "getpwnam" + + [] + member __.``[ELF] mips32_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x00032B28UL "" + + [] + member __.``[ELF] mips32_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x00033588UL "" + + [] + member __.``[ELF] mips32_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] mips32_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 33 ".shstrtab" + + [] + type MIPS32StrippedLETestClass () = + static let file = parseFile mips32LEStrippedFileName + + [] + member __.``[ELF] mips32_Stripped_le EntryPoint test`` () = + Assert.AreEqual (Some 0x00004C80UL, file.EntryPoint) + + [] + member __.``[ELF] mips32_Stripped_le file type test`` () = + Assert.AreEqual (FileType.LibFile, file.Type) + + [] + member __.``[ELF] mips32_Stripped_le IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] mips32_Stripped_le IsNXEnabled test`` () = + Assert.AreEqual (false, file.IsNXEnabled) + + [] + member __.``[ELF] mips32_Stripped_le sections length test`` () = + Assert.AreEqual (34, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped_le static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped_le dynamic symbols length test`` () = + Assert.AreEqual (232, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped_le linkageTableEntries length test`` () = + Assert.AreEqual (106, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] mips32_Stripped_le text section address test`` () = + Assert.AreEqual (0x00002C50UL, getTextSectionAddr file) + + [] + member __.``[ELF] mips32_Stripped_le isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit32, file.ISA.WordSize) + + [] + member __.``[ELF] mips32_Stripped_le function symbol test (1)`` () = + assertFuncSymbolExistence file 0x0001C280UL "__snprintf_chk" + + [] + member __.``[ELF] mips32_Stripped_le function symbol test (2)`` () = + assertFuncSymbolExistence file 0x0001C240UL "unsetenv" + + [] + member __.``[ELF] mips32_Stripped_le Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x00032B28UL "" + + [] + member __.``[ELF] mips32_Stripped_le Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x00033588UL "" + + [] + member __.``[ELF] mips32_Stripped_le section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] mips32_Stripped_le section header test (2)`` () = + assertExistenceOfSectionHeader file 33 ".shstrtab" + + [] + type MIPS64StrippedTestClass () = + static let file = parseFile mips64StrippedFileName + + [] + member __.``[ELF] mips64_Stripped EntryPoint test`` () = + Assert.AreEqual (file.EntryPoint, Some 0x0000ADE0UL) + + [] + member __.``[ELF] mips64_Stripped file type test`` () = + Assert.AreEqual (FileType.LibFile, file.Type) + + [] + member __.``[ELF] mips64_Stripped IsStripped test`` () = + Assert.AreEqual (true, file.IsStripped) + + [] + member __.``[ELF] mips64_Stripped IsNXEnabled test`` () = + Assert.AreEqual (false, file.IsNXEnabled) + + [] + member __.``[ELF] mips64_Stripped sections length test`` () = + Assert.AreEqual (32, file.GetSections () |> Seq.length) + + [] + member __.``[ELF] mips64_Stripped static symbols length test`` () = + Assert.AreEqual (0, file.GetStaticSymbols () |> Seq.length) + + [] + member __.``[ELF] mips64_Stripped dynamic symbols length test`` () = + Assert.AreEqual (232, file.GetDynamicSymbols () |> Seq.length) + + [] + member __.``[ELF] mips64_Stripped linkageTableEntries length test`` () = + Assert.AreEqual (106, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[ELF] mips64_Stripped text section address test`` () = + Assert.AreEqual (0x00008F90UL, getTextSectionAddr file) + + [] + member __.``[ELF] mips64_Stripped isa wordSize test`` () = + Assert.AreEqual (WordSize.Bit64, file.ISA.WordSize) + + [] + member __.``[ELF] mips64_Stripped function symbol test (1)`` () = + assertFuncSymbolExistence file 0x00022380UL "strcmp" + + [] + member __.``[ELF] mips64_Stripped function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00022320UL "unsetenv" + + [] + member __.``[ELF] mips64_Stripped Reloc section Dyn test (1)`` () = + assertExistenceOfRelocation file 0x00039650UL "" + + [] + member __.``[ELF] mips64_Stripped Reloc section Dyn test (2)`` () = + assertExistenceOfRelocation file 0x0003AA50UL "" + + [] + member __.``[ELF] mips64_Stripped section header test (1)`` () = + assertExistenceOfSectionHeader file 0 "" + + [] + member __.``[ELF] mips64_Stripped section header test (2)`` () = + assertExistenceOfSectionHeader file 31 ".shstrtab" + +module Wasm = + let wasmBasicFileName = "wasm_basic" + + let parseFile fileName = + let zipFile = fileName + ".zip" + let fileNameInZip = fileName + ".wasm" + let bytes = readBytesFromZipFile WasmBinary zipFile fileNameInZip + WasmBinFile ("", bytes) :> IBinFile + + [] + type TestClass () = + static let file = parseFile wasmBasicFileName + + [] + member __.``[Wasm] EntryPoint test`` () = + Assert.AreEqual (Some 0x15AUL, file.EntryPoint) + + [] + member __.``[Wasm] file type test`` () = + Assert.AreEqual (FileType.ExecutableFile, file.Type) + + [] + member __.``[Wasm] IsStripped test`` () = + Assert.IsFalse (file.IsStripped) + + [] + member __.``[Wasm] text section address test`` () = + Assert.AreEqual (0x154UL, getTextSectionAddr file) + + [] + member __.``[Wasm] symbols length test`` () = + Assert.AreEqual (9, file.GetSymbols () |> Seq.length) + + [] + member __.``[Wasm] sections length test`` () = + Assert.AreEqual (12, file.GetSections () |> Seq.length) + + [] + member __.``[Wasm] linkageTableEntries length test`` () = + Assert.AreEqual (4, file.GetLinkageTableEntries () |> Seq.length) + + [] + member __.``[Wasm] function symbol test (1)`` () = + assertFuncSymbolExistence file 0x0000007AUL "putc_js" + [] - member __.``[BinFile] Wasm Module Parse Test`` () = - let fi = parseFile wasmBasicFileName - Assert.AreEqual (FileType.ExecutableFile, fi.FileType) - Assert.IsFalse (fi.IsStripped) - Assert.AreEqual (Some 0x15AUL, fi.EntryPoint) - Assert.AreEqual (0x154UL, fi.TextStartAddr) - Assert.AreEqual (9, fi.GetSymbols () |> Seq.length) - Assert.AreEqual (12, fi.GetSections () |> Seq.length) - Assert.AreEqual (4, fi.GetLinkageTableEntries () |> Seq.length) \ No newline at end of file + member __.``[Wasm] function symbol test (2)`` () = + assertFuncSymbolExistence file 0x00000116UL "writev_c" diff --git a/src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj b/src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj index ac54bc6c..1b6fed52 100644 --- a/src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj +++ b/src/FrontEnd/BinFile/B2R2.FrontEnd.BinFile.fsproj @@ -4,53 +4,65 @@ b2r2-240x240.png README.md B2R2 file parsing engine. + $(OtherFlags)--warnon:3390 - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -63,9 +75,12 @@ + + + - + diff --git a/src/FrontEnd/BinFile/BinFileExceptions.fs b/src/FrontEnd/BinFile/BinFileExceptions.fs new file mode 100644 index 00000000..8df5d2b7 --- /dev/null +++ b/src/FrontEnd/BinFile/BinFileExceptions.fs @@ -0,0 +1,34 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +/// Raised when accessing an invalid address of a binary file. +exception InvalidAddrReadException + +/// Raised when an unexpected file format is detected. +exception InvalidFileFormatException + +/// Raised when a section is not found. +exception SectionNotFoundException diff --git a/src/FrontEnd/BinFile/BinaryPointer.fs b/src/FrontEnd/BinFile/BinFilePointer.fs similarity index 70% rename from src/FrontEnd/BinFile/BinaryPointer.fs rename to src/FrontEnd/BinFile/BinFilePointer.fs index 946687cb..5f7d5b4b 100644 --- a/src/FrontEnd/BinFile/BinaryPointer.fs +++ b/src/FrontEnd/BinFile/BinFilePointer.fs @@ -29,8 +29,8 @@ open System /// A pointer to binary, which is used to exclusively point to a portion of a /// binary, e.g., a section. It holds both the virtual address as well as the -/// file offset. -type BinaryPointer = +/// file offset. Both Offset and MaxOffset are inclusive. +type BinFilePointer = struct /// Virtual address. val Addr: Addr @@ -43,31 +43,29 @@ type BinaryPointer = new (addr, offset, max) = { Addr = addr; Offset = offset; MaxOffset = max } end with - static member Null = BinaryPointer (0UL, 0, 0) + static member Null = BinFilePointer (0UL, 0, 0) - static member inline IsValid (bp: BinaryPointer) = - bp.Offset < bp.MaxOffset + static member inline IsValid (ptr: BinFilePointer) = + ptr.Offset <= ptr.MaxOffset - static member inline IsValidAccess (bp: BinaryPointer) size = - (bp.Offset + size) <= bp.MaxOffset + static member inline IsValidAccess (ptr: BinFilePointer) size = + (ptr.Offset + size - 1) <= ptr.MaxOffset static member OfSection (s: Section) = - BinaryPointer (s.Address, + BinFilePointer (s.Address, Convert.ToInt32 s.FileOffset, - Convert.ToInt32 s.FileOffset + Convert.ToInt32 s.Size) + Convert.ToInt32 s.FileOffset + Convert.ToInt32 s.Size - 1) static member OfSectionOpt section = match section with - | Some s -> BinaryPointer.OfSection s - | None -> BinaryPointer.Null + | Some s -> BinFilePointer.OfSection s + | None -> BinFilePointer.Null - static member IsNull bp = - bp = BinaryPointer.Null + static member IsNull ptr = + ptr = BinFilePointer.Null - static member Advance (bp: BinaryPointer) amount = - BinaryPointer (bp.Addr + uint64 amount, bp.Offset + amount, bp.MaxOffset) + static member Advance (p: BinFilePointer) amount = + BinFilePointer (p.Addr + uint64 amount, p.Offset + amount, p.MaxOffset) override __.ToString () = - String.u64ToHexNoPrefix __.Addr - + " (" + String.i32ToHexNoPrefix __.Offset - + " of " + String.i32ToHexNoPrefix __.MaxOffset + ")" + $"{__.Addr:x} ({__.Offset:x} of {__.MaxOffset:x})" diff --git a/src/FrontEnd/BinFile/ELF.fs b/src/FrontEnd/BinFile/ELF.fs deleted file mode 100644 index b8c4c7a2..00000000 --- a/src/FrontEnd/BinFile/ELF.fs +++ /dev/null @@ -1,125 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.ELF -open B2R2.FrontEnd.BinFile.ELF.Helper - -/// -/// This class represents an ELF binary file. -/// -type ELFFileInfo (bytes, path, baseAddr, regbay) = - inherit FileInfo () - let elf = Parser.parse bytes baseAddr regbay - - new (bytes, path) = ELFFileInfo (bytes, path, None, None) - - override __.Span = ReadOnlySpan bytes - - override __.FileFormat = FileFormat.ELFBinary - - override __.ISA = elf.ISA - - override __.FileType = convFileType elf.ELFHdr.ELFFileType - - override __.FilePath = path - - override __.WordSize = elf.ELFHdr.Class - - override __.IsStripped = not (Map.containsKey ".symtab" elf.SecInfo.SecByName) - - override __.IsNXEnabled = isNXEnabled elf - - override __.IsRelocatable = isRelocatable (ReadOnlySpan bytes) elf - - override __.BaseAddress = elf.BaseAddr - - override __.EntryPoint = Some elf.ELFHdr.EntryPoint - - override __.TextStartAddr = getTextStartAddr elf - - override __.TranslateAddress addr = translateAddr addr elf - - override __.AddSymbol addr symbol = Utils.futureFeature () - - override __.GetSymbols () = getSymbols elf - - override __.GetStaticSymbols () = getStaticSymbols elf - - override __.GetDynamicSymbols (?exc) = getDynamicSymbols exc elf - - override __.GetRelocationSymbols () = getRelocSymbols elf - - override __.GetSections () = getSections elf - - override __.GetSections (addr) = getSectionsByAddr elf addr - - override __.GetSections (name) = getSectionsByName elf name - - override __.GetTextSections () = getTextSections elf - - override __.GetSegments (isLoadable) = getSegments elf isLoadable - - override __.GetLinkageTableEntries () = getPLT elf - - override __.IsLinkageTable addr = isInPLT elf addr - - override __.TryFindFunctionSymbolName (addr) = tryFindFuncSymb elf addr - - override __.ExceptionTable = elf.ExceptionTable - - override __.ToBinaryPointer addr = - BinaryPointer.OfSectionOpt (getSectionsByAddr elf addr |> Seq.tryHead) - - override __.ToBinaryPointer name = - BinaryPointer.OfSectionOpt (getSectionsByName elf name |> Seq.tryHead) - - override __.IsValidAddr addr = isValidAddr elf addr - - override __.IsValidRange range = isValidRange elf range - - override __.IsInFileAddr addr = isInFileAddr elf addr - - override __.IsInFileRange range = isInFileRange elf range - - override __.IsExecutableAddr addr = isExecutableAddr elf addr - - override __.GetNotInFileIntervals range = getNotInFileIntervals elf range - - override __.GetFunctionAddresses () = - base.GetFunctionAddresses () - |> addExtraFunctionAddrs (ReadOnlySpan bytes) elf false - - override __.GetFunctionAddresses (useExcInfo) = - base.GetFunctionAddresses () - |> addExtraFunctionAddrs (ReadOnlySpan bytes) elf useExcInfo - - member __.ELF with get() = elf - - member __.RegisterBay = regbay - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinFile/ELF/ELFARMExceptionHandler.fs b/src/FrontEnd/BinFile/ELF/ELFARMExceptionHandler.fs new file mode 100644 index 00000000..c6d65ea4 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFARMExceptionHandler.fs @@ -0,0 +1,144 @@ +(* +B2R2 - the Next-Generation Reversing Platform + +Copyright (c) SoftSec Lab. @ KAIST, since 2016 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*) + +[] +module internal B2R2.FrontEnd.BinFile.ELF.ELFARMExceptionHandler + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +/// This is a value that the index table can have. +type ExceptionIndexValue = + /// This is the most typical entry value, which stores a pointer to an + /// exception table entry (in `prel31` format). + | PointerToExceptionEntry of Addr + /// This index table entry contains the actual table entry in a compact form. + | CompactEntry + /// This function cannot be unwound. + | CantUnwind + +/// ARM-specific exception handling index table entry. +type IndexTableEntry = { + /// The function who will be in charge of catching an exception. + FuncAddr: Addr + /// Index table entry value. + EntryValue: ExceptionIndexValue +} + +let [] private ARMIndexTable = ".ARM.exidx" +let [] private ARMTable = ".ARM.extab" + +let inline private prel31ToI32 (v: int) = + ((v <<< 1) &&& 0x80000000) ||| v + +let private toExceptionIndexValue myAddr v = + if (v &&& 0xF0000000) = 0x80000000 then CompactEntry + elif v = 1 then CantUnwind + else PointerToExceptionEntry (uint64 (prel31ToI32 v) + myAddr) + +let rec private readIndexTableEntry acc reader (span: ByteSpan) sAddr offset = + if offset >= (span: ByteSpan).Length then List.rev acc + else + let prel31FnAddr = (reader: IBinReader).ReadInt32 (span, offset) + let fnAddr = uint64 (prel31ToI32 prel31FnAddr) + sAddr + let prel31Value = reader.ReadInt32 (span, offset + 4) + let v = toExceptionIndexValue (sAddr + 4UL) prel31Value + let acc = { FuncAddr = fnAddr; EntryValue = v } :: acc + readIndexTableEntry acc reader span (sAddr + 8UL) (offset + 8) + +let private parseIndexTable toolBox indexTableSection = + let offset, size = indexTableSection.SecOffset, indexTableSection.SecSize + let span = ReadOnlySpan (toolBox.Bytes, int offset, int size) + readIndexTableEntry [] toolBox.Reader span indexTableSection.SecAddr 0 + +let private computeLSDAOffset currentOffset (n: int) = + if (n &&& 0xF0000000) = 0x80000000 then (* Compact format *) currentOffset + 4 + else + let msb = (n >>> 24) &&& 0xff (* This means the number of words to parse. *) + currentOffset + 4 + msb * 4 + +/// Read LSDA if the personality routine in a custom model. +let private readLSDAFromCustom reader cls span (sAddr: Addr) addr = + let offset = Convert.ToInt32 (addr - sAddr) + let n = (reader: IBinReader).ReadInt32 (span=span, offset=offset) + if (n &&& 0x80000000) = 0 then (* Custom personality routine with LSDA *) + let _personalityOffset = uint64 (prel31ToI32 n) + addr (* No need for now *) + let offset = offset + 4 + let n = reader.ReadInt32 (span, offset) + let lsdaOffset = computeLSDAOffset offset n + let struct (lsda, _) = + ELFGccExceptTable.parseLSDA cls span reader sAddr lsdaOffset + let lsdaAddr = sAddr + uint64 lsdaOffset + Some (lsda, lsdaAddr) + elif (n &&& 0xF0000000) = 0x80000000 then (* Compact model. *) None + else Utils.impossible () (* Unknown format *) + +let rec private readExnTableEntry (fdes, lsdas) reader cls span sAddr = function + | entry :: tl -> + match entry.EntryValue with + | PointerToExceptionEntry (addr) -> + match readLSDAFromCustom reader cls span sAddr addr with + | Some (lsda, lsdaAddr) -> + let fde = + { PCBegin = entry.FuncAddr + PCEnd = entry.FuncAddr + LSDAPointer = Some lsdaAddr + UnwindingInfo = [] } + let acc = (fde :: fdes, Map.add lsdaAddr lsda lsdas) + readExnTableEntry acc reader cls span sAddr tl + | None -> + readExnTableEntry (fdes, lsdas) reader cls span sAddr tl + | CantUnwind | CompactEntry -> + readExnTableEntry (fdes, lsdas) reader cls span sAddr tl + | [] -> (fdes, lsdas) + +let private parseExnTable toolBox cls exnTblSection entries = + let offset, size = int exnTblSection.SecOffset, int exnTblSection.SecSize + let span = ReadOnlySpan (toolBox.Bytes, offset, size) + let secAddr = exnTblSection.SecAddr + let cie = (* Create a dummy CIE. *) + { Version = 0uy + AugmentationString = "" + CodeAlignmentFactor = 0UL + DataAlignmentFactor = 0L + ReturnAddressRegister = 0uy + InitialRule = Map.empty + InitialCFARegister = 0uy + InitialCFA = UnknownCFA + Augmentations = [] } + let fdes, lsdas = + readExnTableEntry ([], Map.empty) toolBox.Reader cls span secAddr entries + struct ([ { CIERecord = cie; FDERecord = List.toArray fdes } ], lsdas ) + +/// Parse ARM-specific exception handler. The specification is found @ +/// https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst +let parse toolBox cls shdrs = + match Array.tryFind (fun s -> s.SecName = ARMIndexTable) shdrs, + Array.tryFind (fun s -> s.SecName = ARMTable) shdrs with + | Some indexTable, Some exnTable -> + let indexTable = parseIndexTable toolBox indexTable + parseExnTable toolBox cls exnTable indexTable + | _ -> struct ([], Map.empty) \ No newline at end of file diff --git a/src/FrontEnd/BinFile/ELF/ELFBinFile.fs b/src/FrontEnd/BinFile/ELF/ELFBinFile.fs new file mode 100644 index 00000000..8a818eb0 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFBinFile.fs @@ -0,0 +1,244 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.ELF +open B2R2.FrontEnd.BinFile.ELF.Helper + +/// +/// This class represents an ELF binary file. +/// +type ELFBinFile (path, bytes: byte[], baseAddrOpt, rfOpt) = + let toolBox = Header.parse baseAddrOpt bytes + let hdr = toolBox.Header + let phdrs = lazy ProgramHeader.parse toolBox + let shdrs = lazy Section.parse toolBox + let loadables = lazy ProgramHeader.getLoadableProgHeaders phdrs.Value + let symbInfo = lazy Symbol.parse toolBox shdrs.Value + let relocs = lazy RelocationInfo.parse toolBox shdrs.Value symbInfo.Value + let plt = lazy PLT.parse toolBox shdrs.Value symbInfo.Value relocs.Value + let exnInfo = lazy ExceptionInfo.parse toolBox shdrs.Value rfOpt relocs.Value + let notInMemRanges = lazy invalidRangesByVM hdr loadables.Value + let notInFileRanges = lazy invalidRangesByFileBounds hdr loadables.Value + let executableRanges = lazy executableRanges shdrs.Value loadables.Value + + /// ELF Header information. + member __.Header with get() = hdr + + /// List of dynamic section entries. + member __.DynamicSectionEntries with get() = + DynamicSection.readEntries toolBox shdrs.Value + + /// Try to find a section by its name. + member __.TryFindSection (name: string) = + shdrs.Value |> Array.tryFind (fun s -> s.SecName = name) + + /// Find a section by its index. + member __.FindSection (idx: int) = + shdrs.Value[idx] + + /// ELF program headers. + member __.ProgramHeaders with get() = phdrs.Value + + /// ELF section headers. + member __.SectionHeaders with get() = shdrs.Value + + /// PLT. + member __.PLT with get() = plt.Value + + /// Exception information. + member __.ExceptionInfo with get() = exnInfo.Value + + /// ELF symbol information. + member __.SymbolInfo with get() = symbInfo.Value + + /// Relocation information. + member __.RelocationInfo with get() = relocs.Value + + interface IBinFile with + member __.Path with get() = path + + member __.Format with get() = FileFormat.ELFBinary + + member __.ISA with get() = ISA.Init hdr.MachineType hdr.Endian + + member __.Type with get() = toFileType hdr.ELFFileType + + member __.EntryPoint = Some hdr.EntryPoint + + member __.BaseAddress with get() = toolBox.BaseAddress + + member __.IsStripped = + shdrs.Value |> Array.exists (fun s -> s.SecName = ".symtab") |> not + + member __.IsNXEnabled = isNXEnabled phdrs.Value + + member __.IsRelocatable = isRelocatable toolBox shdrs.Value + + member __.GetOffset addr = + translateAddrToOffset loadables.Value shdrs.Value addr |> Convert.ToInt32 + + member __.Slice (addr, size) = + let offset = (__ :> IContentAddressable).GetOffset addr + (__ :> IContentAddressable).Slice (offset=offset, size=size) + + member __.Slice (addr) = + let offset = (__ :> IContentAddressable).GetOffset addr + (__ :> IContentAddressable).Slice (offset=offset) + + member __.Slice (offset: int, size) = + ReadOnlySpan (bytes, offset, size) + + member __.Slice (offset: int) = + ReadOnlySpan(bytes).Slice offset + + member __.Slice (ptr: BinFilePointer, size) = + ReadOnlySpan (bytes, ptr.Offset, size) + + member __.Slice (ptr: BinFilePointer) = + ReadOnlySpan(bytes).Slice ptr.Offset + + member __.ReadByte (addr: Addr) = + let offset = (__ :> IContentAddressable).GetOffset addr + bytes[offset] + + member __.ReadByte (offset: int) = + bytes[offset] + + member __.ReadByte (ptr: BinFilePointer) = + bytes[ptr.Offset] + + member __.IsValidAddr addr = + IntervalSet.containsAddr addr notInMemRanges.Value |> not + + member __.IsValidRange range = + IntervalSet.findAll range notInMemRanges.Value |> List.isEmpty + + member __.IsInFileAddr addr = + IntervalSet.containsAddr addr notInFileRanges.Value |> not + + member __.IsInFileRange range = + IntervalSet.findAll range notInFileRanges.Value |> List.isEmpty + + member __.IsExecutableAddr addr = + IntervalSet.containsAddr addr executableRanges.Value + + member __.GetNotInFileIntervals range = + IntervalSet.findAll range notInFileRanges.Value + |> List.toArray + |> Array.map range.Slice + + member __.ToBinFilePointer addr = + getSectionsByAddr shdrs.Value addr + |> Seq.tryHead + |> BinFilePointer.OfSectionOpt + + member __.ToBinFilePointer name = + getSectionsByName shdrs.Value name + |> Seq.tryHead + |> BinFilePointer.OfSectionOpt + + member __.GetRelocatedAddr relocAddr = + getRelocatedAddr relocs.Value relocAddr + + member __.TryFindFunctionName (addr) = + tryFindFuncSymb symbInfo.Value addr + + member __.GetSymbols () = getSymbols shdrs.Value symbInfo.Value + + member __.GetStaticSymbols () = getStaticSymbols shdrs.Value symbInfo.Value + + member __.GetFunctionSymbols () = + let dict = Collections.Generic.Dictionary () + let self = __ :> IBinFile + self.GetStaticSymbols () + |> Seq.iter (fun s -> + if s.Kind = SymFunctionType then dict[s.Address] <- s + elif s.Kind = SymNoType (* This is to handle ppc's PLT symbols. *) + && s.Address > 0UL && s.Name.Contains "pic32." + then dict[s.Address] <- s + else ()) + self.GetDynamicSymbols (true) |> Seq.iter (fun s -> + if dict.ContainsKey s.Address then () + elif s.Kind = SymFunctionType then dict[s.Address] <- s + else ()) + dict.Values |> Seq.toArray + + member __.GetDynamicSymbols (?exc) = + getDynamicSymbols exc shdrs.Value symbInfo.Value + + member __.GetRelocationSymbols () = getRelocSymbols relocs.Value + + member __.AddSymbol _addr _symbol = Utils.futureFeature () + + member __.GetSections () = getSections shdrs.Value + + member __.GetSections (addr) = getSectionsByAddr shdrs.Value addr + + member __.GetSections (name) = getSectionsByName shdrs.Value name + + member __.GetTextSection () = getTextSection shdrs.Value + + member __.GetSegments (isLoadable) = + if isLoadable then getSegments loadables.Value + else getSegments phdrs.Value + + member __.GetSegments (addr) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (addr >= s.Address) + && (addr < s.Address + uint64 s.Size)) + + member __.GetSegments (perm) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (s.Permission &&& perm = perm) && s.Size > 0u) + + member __.GetLinkageTableEntries () = + plt.Value + |> ARMap.fold (fun acc _ entry -> entry :: acc) [] + |> List.sortBy (fun entry -> entry.TrampolineAddress) + |> List.toArray + + member __.IsLinkageTable addr = ARMap.containsAddr addr plt.Value + + member __.GetFunctionAddresses () = + (__ :> IBinFile).GetFunctionSymbols () + |> Seq.map (fun s -> s.Address) + |> addExtraFunctionAddrs toolBox shdrs.Value loadables.Value + relocs.Value None + + member __.GetFunctionAddresses (useExcInfo) = + let exnInfo = if useExcInfo then Some exnInfo.Value else None + (__ :> IBinFile).GetFunctionSymbols () + |> Seq.map (fun s -> s.Address) + |> addExtraFunctionAddrs toolBox shdrs.Value loadables.Value + relocs.Value exnInfo + + member __.Reader with get() = toolBox.Reader + + member __.RawBytes = bytes + + member __.Length = bytes.Length diff --git a/src/FrontEnd/BinFile/ELFDwarfTypes.fs b/src/FrontEnd/BinFile/ELF/ELFDwarfTypes.fs similarity index 94% rename from src/FrontEnd/BinFile/ELFDwarfTypes.fs rename to src/FrontEnd/BinFile/ELF/ELFDwarfTypes.fs index b21cdd48..867004be 100644 --- a/src/FrontEnd/BinFile/ELFDwarfTypes.fs +++ b/src/FrontEnd/BinFile/ELF/ELFDwarfTypes.fs @@ -25,14 +25,13 @@ namespace B2R2.FrontEnd.BinFile.ELF open LanguagePrimitives -open System open B2R2 open B2R2.BinIR open B2R2.FrontEnd.BinLifter open B2R2.FrontEnd.BinFile /// Raised when an unhandled encoding is encountered. -exception UnhandledEncoding +exception UnhandledEncodingException type ExceptionHeaderValue = /// No value is present. @@ -80,7 +79,8 @@ module ExceptionHeaderEncoding = let computeValue cls span reader venc offset = match venc with | ExceptionHeaderValue.DW_EH_PE_absptr -> - FileHelper.readUIntOfType span reader cls offset + let cv = FileHelper.readUIntOfType span reader cls offset + struct (cv, if cls = WordSize.Bit32 then offset + 4 else offset + 8) | ExceptionHeaderValue.DW_EH_PE_uleb128 -> let cv, offset = parseULEB128 span offset struct (cv, offset) @@ -105,7 +105,7 @@ module ExceptionHeaderEncoding = | ExceptionHeaderValue.DW_EH_PE_sdata8 -> let cv = reader.ReadInt64 (span, offset) struct (uint64 cv, offset + 8) - | _ -> printfn "%A" venc; raise UnhandledEncoding + | _ -> printfn "%A" venc; raise UnhandledEncodingException let parseEncoding b = if b &&& 0xFFuy = 255uy then @@ -434,26 +434,28 @@ module DWRegister = let private toMIPSRegister (n: byte) = MIPS.Register.toRegID (EnumOfValue (int n)) + let private toRISCVRegister (n: byte) = + RISCV.Register.toRegID (EnumOfValue (int n)) + + let private toPPC32Register (n: byte) = + PPC32.Register.toRegID (EnumOfValue (int n)) + + let private toSH4Register (n: byte) = + SH4.Register.toRegID (EnumOfValue (int n)) + let toRegID isa regnum = match isa.Arch with | Architecture.IntelX86 -> toIntelx86Register regnum | Architecture.IntelX64 -> toIntelx64Register regnum | Architecture.AARCH64 -> toAArch64Register regnum - | Architecture.MIPS1 - | Architecture.MIPS2 - | Architecture.MIPS3 - | Architecture.MIPS32 - | Architecture.MIPS32R2 - | Architecture.MIPS32R6 - | Architecture.MIPS4 - | Architecture.MIPS5 - | Architecture.MIPS64 - | Architecture.MIPS64R2 - | Architecture.MIPS64R6 -> toMIPSRegister regnum + | Architecture.MIPS32 | Architecture.MIPS64 -> toMIPSRegister regnum + | Architecture.RISCV64 -> toRISCVRegister regnum + | Architecture.PPC32 -> toPPC32Register regnum + | Architecture.SH4 -> toSH4Register regnum | _ -> Utils.futureFeature () - let toRegisterExpr isa (regbay: RegisterBay) regnum = - toRegID isa regnum |> regbay.RegIDToRegExpr + let toRegisterExpr isa (regFactory: RegisterFactory) regnum = + toRegID isa regnum |> regFactory.RegIDToRegExpr /// The CFA. Machine-independent representation of the current frame address. /// For example, (esp+8) on x86. @@ -463,12 +465,12 @@ type CanonicalFrameAddress = | UnknownCFA module CanonicalFrameAddress = - let regPlusOffset isa regbay regnum offset = + let regPlusOffset isa regFactory regnum offset = RegPlusOffset (DWRegister.toRegID isa regnum, offset) - let toString (regbay: RegisterBay) = function + let toString (regFactory: RegisterFactory) = function | RegPlusOffset (rid, offset) -> - regbay.RegIDToString rid + (offset.ToString ("+0;-#")) + regFactory.RegIDToString rid + (offset.ToString ("+0;-#")) | Expression exp -> LowUIR.Pp.expToString exp | UnknownCFA -> "unknown" @@ -498,7 +500,7 @@ type Action = module Action = let toString = function | Undefined -> "undef" - | SameValue -> "samevalue" + | SameValue -> "sv" | Offset o -> "c" + (o.ToString ("+0;-#")) | ValOffset o -> "v" + (o.ToString ("+0;-#")) | Register rid -> "r(" + rid.ToString () + ")" diff --git a/src/FrontEnd/BinFile/ELF/ELFDynamicSection.fs b/src/FrontEnd/BinFile/ELF/ELFDynamicSection.fs new file mode 100644 index 00000000..d6df5f6f --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFDynamicSection.fs @@ -0,0 +1,185 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.FileHelper + +/// ELF dynamic tags. +type DynamicTag = + | DT_NULL = 0UL + | DT_NEEDED = 1UL + | DT_PLTRELSZ = 2UL + | DT_PLTGOT = 3UL + | DT_HASH = 4UL + | DT_STRTAB = 5UL + | DT_SYMTAB = 6UL + | DT_RELA = 7UL + | DT_RELASZ = 8UL + | DT_RELAENT = 9UL + | DT_STRSZ = 10UL + | DT_SYMENT = 11UL + | DT_INIT = 12UL + | DT_FINI = 13UL + | DT_SONAME = 14UL + | DT_RPATH = 15UL + | DT_SYMBOLIC = 16UL + | DT_REL = 17UL + | DT_RELSZ = 18UL + | DT_RELENT = 19UL + | DT_PLTREL = 20UL + | DT_DEBUG = 21UL + | DT_TEXTREL = 22UL + | DT_JMPREL = 23UL + | DT_BIND_NOW = 24UL + | DT_INIT_ARRAY = 25UL + | DT_FINI_ARRAY = 26UL + | DT_INIT_ARRAYSZ = 27UL + | DT_FINI_ARRAYSZ = 28UL + | DT_RUNPATH = 29UL + | DT_FLAGS = 30UL + | DT_PREINIT_ARRAY = 32UL + | DT_PRE_INIT_ARRAYSZ = 33UL + | DT_MAXPOSTAGS = 34UL + | DT_FLAGS_1 = 0x6ffffffbUL + | DT_RELACOUNT = 0x6ffffff9UL + | DT_LOOS = 0x6000000dUL + | DT_HIOS = 0x6ffff000UL + | DT_VERSYM = 0x6ffffff0UL + | DT_VERNEED = 0x6ffffffeUL + | DT_VERNEEDNUM = 0x6fffffffUL + | DT_VALRNGLO = 0x6ffffd00UL + | DT_GNU_PRELINKED = 0x6ffffdf5UL + | DT_GNU_CONFLICTSZ = 0x6ffffdf6UL + | DT_GNU_LIBLISTSZ = 0x6ffffdf7UL + | DT_CHECKSUM = 0x6ffffdf8UL + | DT_PLTPADSZ = 0x6ffffdf9UL + | DT_MOVEENT = 0x6ffffdfaUL + | DT_MOVESZ = 0x6ffffdfbUL + | DT_FEATURE = 0x6ffffdfcUL + | DT_POSFLAG_1 = 0x6ffffdfdUL + | DT_SYMINSZ = 0x6ffffdfeUL + | DT_SYMINENT = 0x6ffffdffUL + | DT_VALRNGHI = 0x6ffffdffUL + | DT_ADDRRNGLO = 0x6ffffe00UL + | DT_GNU_HASH = 0x6ffffef5UL + | DT_TLSDESC_PLT = 0x6ffffef6UL + | DT_TLSDESC_GOT = 0x6ffffef7UL + | DT_GNU_CONFLICT = 0x6ffffef8UL + | DT_GNU_LIBLIST = 0x6ffffef9UL + | DT_CONFIG = 0x6ffffefaUL + | DT_DEPAUDIT = 0x6ffffefbUL + | DT_AUDIT = 0x6ffffefcUL + | DT_PLTPAD = 0x6ffffefdUL + | DT_MOVETAB = 0x6ffffefeUL + | DT_SYMINFO = 0x6ffffeffUL + | DT_ADDRRNGHI = 0x6ffffeffUL + | DT_PPC_GOT = 0x70000000UL + | DT_PPC_OPT = 0x70000001UL + | DT_PPC64_GLINK = 0x70000000UL + | DT_PPC64_OPD = 0x70000001UL + | DT_PPC64_OPDSZ = 0x70000002UL + | DT_SPARC_REGISTER = 0x70000001UL + | DT_MIPS_RLD_VERSION = 0x70000001UL + | DT_MIPS_TIME_STAMP = 0x70000002UL + | DT_MIPS_ICHECKSUM = 0x70000003UL + | DT_MIPS_IVERSION = 0x70000004UL + | DT_MIPS_FLAGS = 0x70000005UL + | DT_MIPS_BASE_ADDRESS = 0x70000006UL + | DT_MIPS_MSYM = 0x70000007UL + | DT_MIPS_CONFLICT = 0x70000008UL + | DT_MIPS_LIBLIST = 0x70000009UL + | DT_MIPS_LOCAL_GOTNO = 0x7000000aUL + | DT_MIPS_CONFLICTNO = 0x7000000bUL + | DT_MIPS_LIBLISTNO = 0x70000010UL + | DT_MIPS_SYMTABNO = 0x70000011UL + | DT_MIPS_UNREFEXTNO = 0x70000012UL + | DT_MIPS_GOTSYM = 0x70000013UL + | DT_MIPS_HIPAGENO = 0x70000014UL + | DT_MIPS_RLD_MAP = 0x70000016UL + | DT_MIPS_DELTA_CLASS = 0x70000017UL + | DT_MIPS_DELTA_CLASS_NO = 0x70000018UL + | DT_MIPS_DELTA_INSTANCE = 0x70000019UL + | DT_MIPS_DELTA_INSTANCE_NO = 0x7000001aUL + | DT_MIPS_DELTA_RELOC = 0x7000001bUL + | DT_MIPS_DELTA_RELOC_NO = 0x7000001cUL + | DT_MIPS_DELTA_SYM = 0x7000001dUL + | DT_MIPS_DELTA_SYM_NO = 0x7000001eUL + | DT_MIPS_DELTA_CLASSSYM = 0x70000020UL + | DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021UL + | DT_MIPS_CXX_FLAGS = 0x70000022UL + | DT_MIPS_PIXIE_INIT = 0x70000023UL + | DT_MIPS_SYMBOL_LIB = 0x70000024UL + | DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025UL + | DT_MIPS_LOCAL_GOTIDX = 0x70000026UL + | DT_MIPS_HIDDEN_GOTIDX = 0x70000027UL + | DT_MIPS_PROTECTED_GOTIDX = 0x70000028UL + | DT_MIPS_OPTIONS = 0x70000029UL + | DT_MIPS_INTERFACE = 0x7000002aUL + | DT_MIPS_DYNSTR_ALIGN = 0x7000002bUL + | DT_MIPS_INTERFACE_SIZE = 0x7000002cUL + | DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002dUL + | DT_MIPS_PERF_SUFFIX = 0x7000002eUL + | DT_MIPS_COMPACT_SIZE = 0x7000002fUL + | DT_MIPS_GP_VALUE = 0x70000030UL + | DT_MIPS_AUX_DYNAMIC = 0x70000031UL + | DT_MIPS_PLTGOT = 0x70000032UL + | DT_MIPS_RWPLT = 0x70000034UL + | DT_MIPS_RLD_MAP_REL = 0x70000035UL + +/// Dynamic section entry. +type DynamicSectionEntry = { + DTag: DynamicTag + DVal: uint64 +} + +module internal DynamicSection = + let private readDynamicEntry reader cls span = + let dtag = readUIntOfType span reader cls 0 + let dval = readUIntOfType span reader cls (pickNum cls 4 8) + { DTag = LanguagePrimitives.EnumOfValue dtag; DVal = dval } + + let private parseDynamicSection ({ Bytes = bytes } as toolBox) sec = + let reader = toolBox.Reader + let cls = toolBox.Header.Class + let numEntries = int sec.SecSize / int sec.SecEntrySize + let entries = Array.zeroCreate numEntries + let rec parseLoop n offset = + if n = numEntries then entries + else + let span = ReadOnlySpan (bytes, offset, int sec.SecEntrySize) + let ent = readDynamicEntry reader cls span + entries[n] <- ent + if ent.DTag = DynamicTag.DT_NULL && ent.DVal = 0UL then entries[0..n] + else parseLoop (n + 1) (offset + int sec.SecEntrySize) + parseLoop 0 (int sec.SecOffset) + + let readEntries toolBox secHeaders = + let dynamicSection = + secHeaders |> Array.tryFind (fun s -> s.SecType = SectionType.SHT_DYNAMIC) + match dynamicSection with + | Some sec -> parseDynamicSection toolBox sec + | None -> [||] diff --git a/src/FrontEnd/BinFile/ELF/ELFExceptionFrames.fs b/src/FrontEnd/BinFile/ELF/ELFExceptionFrames.fs new file mode 100644 index 00000000..afd9257e --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFExceptionFrames.fs @@ -0,0 +1,799 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open System.Runtime.InteropServices +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinFile.FileHelper +open B2R2.FrontEnd.BinFile.ELF.ExceptionHeaderEncoding + +/// Raised when an unhandled eh_frame version is encountered. +exception UnhandledEHFrameVersionException + +/// Raised when an unhandled augment string is encountered. +exception UnhandledAugStringException + +/// Raised when CIE is not found by FDE +exception CIENotFoundByFDEException + +/// Raised when invalid sequence of dwarf instructions encountered. +exception InvalidDWInstructionExpException + +/// This tells how augmetation data is handled. +type Augmentation = { + Format: char + ValueEncoding: ExceptionHeaderValue + ApplicationEncoding: ExceptionHeaderApplication + PersonalityRoutionPointer: byte [] +} + +/// CIE. Common Information Entry. +type CommonInformationEntry = { + Version: uint8 + AugmentationString: string + CodeAlignmentFactor: uint64 + DataAlignmentFactor: int64 + ReturnAddressRegister: byte + InitialRule: Rule + InitialCFARegister: byte + InitialCFA: CanonicalFrameAddress + Augmentations: Augmentation list +} + +/// FDE. Frame Description Entry. +type FrameDescriptionEntry = { + PCBegin: Addr + PCEnd: Addr + LSDAPointer: Addr option + UnwindingInfo: UnwindingEntry list +} + +/// The main information block of .eh_frame. This exists roughly for every +/// object file, although one object file may have multiple CFIs. +type CallFrameInformation = { + CIERecord: CommonInformationEntry + FDERecord: FrameDescriptionEntry[] +} + +[] +module internal ExceptionFrames = + let [] Ehframe = ".eh_frame" + + let computeNextOffset (span: ByteSpan) (reader: IBinReader) offset len = + if len = -1 then + let len = reader.ReadUInt64 (span, offset) + let offset = offset + 8 + int len + offset, offset + else len + offset, offset + + let parseReturnRegister toolBox (span: ByteSpan) version offset = + if version = 1uy then span[offset], offset + 1 + else + let r, cnt = toolBox.Reader.ReadUInt64LEB128 (span, offset) + byte r, offset + cnt + + let personalityRoutinePointerSize addrSize = function + | 2uy -> 2 + | 3uy -> 4 + | 4uy -> 8 + | _ -> addrSize + + let obtainAugData addrSize (arr: byte []) data offset = function + | 'L' -> + let struct (v, app) = parseEncoding arr[offset] + { Format = 'L' + ValueEncoding = v + ApplicationEncoding = app + PersonalityRoutionPointer = [||] } :: data, offset + 1 + | 'P' -> + let struct (v, app) = parseEncoding arr[offset] + let psz = arr[offset] &&& 7uy |> personalityRoutinePointerSize addrSize + let prp = arr[ offset + 1 .. offset + psz ] + { Format = 'P' + ValueEncoding = v + ApplicationEncoding = app + PersonalityRoutionPointer = prp } :: data, offset + psz + 1 + | 'R' -> + let struct (v, app) = parseEncoding arr[offset] + { Format = 'R' + ValueEncoding = v + ApplicationEncoding = app + PersonalityRoutionPointer = [||] } :: data, offset + 1 + | 'S' -> data, offset (* This is a signal frame. *) + | _ -> raise UnhandledAugStringException + + let parseAugmentationData toolBox (span: ByteSpan) offset addrSize augstr = + if (augstr: string).StartsWith ('z') then + let len, cnt = toolBox.Reader.ReadUInt64LEB128 (span, offset) + let offset = offset + cnt + let span = span.Slice (offset, int len) + let arr = span.ToArray () + augstr[ 1.. ] + |> Seq.fold (fun (data, idx) ch -> + obtainAugData addrSize arr data idx ch) ([], 0) + |> fst + |> List.rev, offset + int len + else [], offset + + let num isa n = + let rt = isa.WordSize |> WordSize.toRegType + AST.num (BitVector.OfUInt64 n rt) + + let regPlusNum isa regFactory reg n = + let regexp = DWRegister.toRegisterExpr isa regFactory reg + AST.binop BinOpType.ADD regexp (num isa n) + + let parseOpBReg isa regFactory exprs (span: ByteSpan) idx reg = + let offset, cnt = LEB128.DecodeUInt64 (span.Slice (idx)) + let exprs = regPlusNum isa regFactory reg offset :: exprs + struct (exprs, idx + cnt) + + let pop exprs = + match exprs with + | fst :: rest -> struct (fst, rest) + | _ -> Utils.impossible () + + let pop2 exprs = + match exprs with + | fst :: snd :: rest -> struct (fst, snd, rest) + | _ -> Utils.impossible () + + let inline hasLessThanTwoOperands exprs = + match exprs with + | [ _ ] | [] -> true + | _ -> false + + let parseBinop op exprs = + let struct (fst, snd, exprs) = pop2 exprs + AST.binop op snd fst :: exprs + + let parsePlusUconst isa exprs (span: ByteSpan) idx = + let n, cnt = LEB128.DecodeUInt64 (span.Slice (idx)) + let n = num isa n + let struct (fst, exprs) = pop exprs + let exprs = AST.binop BinOpType.ADD fst n :: exprs + struct (exprs, idx + cnt) + + let parseRel isa op exprs = + let struct (fst, snd, exprs) = pop2 exprs + let rt = isa.WordSize |> WordSize.toRegType + AST.cast CastKind.ZeroExt rt (AST.relop op snd fst) :: exprs + + let parseLoad isa exprs = + let struct (addr, exprs) = pop exprs + let rt = isa.WordSize |> WordSize.toRegType + AST.loadLE rt addr :: exprs + + let rec parseExprs isa regFct exprs (span: ByteSpan) i maxIdx = + if i >= maxIdx then + match exprs with + | [ exp ] -> exp + | _ -> raise InvalidDWInstructionExpException + else + match span[i] |> DWOperation.parse with + | DWOperation.DW_OP_breg0 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 0uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg1 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 1uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg2 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 2uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg3 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 3uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg4 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 4uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg5 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 5uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg6 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 6uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg7 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 7uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg8 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 8uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg9 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 9uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg10 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 10uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg11 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 11uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg12 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 12uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg13 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 13uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg14 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 14uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg15 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 15uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg16 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 16uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg17 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 17uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg18 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 18uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg19 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 19uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg20 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 20uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg21 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 21uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg22 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 22uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg23 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 23uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg24 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 24uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg25 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 25uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg26 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 26uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg27 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 27uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg28 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 28uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg29 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 29uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg30 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 30uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_breg31 -> + let struct (exprs, i') = parseOpBReg isa regFct exprs span (i + 1) 31uy + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_const1u -> + let exprs = num isa (uint64 span[i + 1]) :: exprs + parseExprs isa regFct exprs span (i + 2) maxIdx + | DWOperation.DW_OP_const1s -> + let exprs = num isa (int64 span[i + 1] |> uint64) :: exprs + parseExprs isa regFct exprs span (i + 2) maxIdx + | DWOperation.DW_OP_const2u -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (uint64 c) :: exprs + parseExprs isa regFct exprs span (i + 3) maxIdx + | DWOperation.DW_OP_const2s -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (int64 c |> uint64) :: exprs + parseExprs isa regFct exprs span (i + 3) maxIdx + | DWOperation.DW_OP_const4u -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (uint64 c) :: exprs + parseExprs isa regFct exprs span (i + 5) maxIdx + | DWOperation.DW_OP_const4s -> + let c = MemoryMarshal.Read (span.Slice (i + 1)) + let exprs = num isa (int64 c |> uint64) :: exprs + parseExprs isa regFct exprs span (i + 5) maxIdx + | DWOperation.DW_OP_lit0 -> + let exprs = num isa 0UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit1 -> + let exprs = num isa 1UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit2 -> + let exprs = num isa 2UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit3 -> + let exprs = num isa 3UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit4 -> + let exprs = num isa 4UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit5 -> + let exprs = num isa 5UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit6 -> + let exprs = num isa 6UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit7 -> + let exprs = num isa 7UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit8 -> + let exprs = num isa 8UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit9 -> + let exprs = num isa 9UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit10 -> + let exprs = num isa 10UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit11 -> + let exprs = num isa 11UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit12 -> + let exprs = num isa 12UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit13 -> + let exprs = num isa 13UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit14 -> + let exprs = num isa 14UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit15 -> + let exprs = num isa 15UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit16 -> + let exprs = num isa 16UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit17 -> + let exprs = num isa 17UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit18 -> + let exprs = num isa 18UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit19 -> + let exprs = num isa 19UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit20 -> + let exprs = num isa 20UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit21 -> + let exprs = num isa 21UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit22 -> + let exprs = num isa 22UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit23 -> + let exprs = num isa 23UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit24 -> + let exprs = num isa 24UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit25 -> + let exprs = num isa 25UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit26 -> + let exprs = num isa 26UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit27 -> + let exprs = num isa 27UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit28 -> + let exprs = num isa 28UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit29 -> + let exprs = num isa 29UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit30 -> + let exprs = num isa 30UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lit31 -> + let exprs = num isa 31UL :: exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_and -> + let exprs = parseBinop BinOpType.AND exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_or -> + let exprs = parseBinop BinOpType.OR exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_xor -> + let exprs = parseBinop BinOpType.XOR exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_div -> + let exprs = parseBinop BinOpType.DIV exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_minus -> + (* There is an exceptional case where ICC compbiler uses DW_OP_minus + with a single opearnd. This is not the standard way. *) + let exprs = + if hasLessThanTwoOperands exprs then [ num isa 0UL ] + else parseBinop BinOpType.SUB exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_plus -> + let exprs = parseBinop BinOpType.ADD exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_plus_uconst -> + let struct (exprs, i') = parsePlusUconst isa exprs span (i + 1) + parseExprs isa regFct exprs span i' maxIdx + | DWOperation.DW_OP_mul -> + let exprs = parseBinop BinOpType.MUL exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_shl -> + let exprs = parseBinop BinOpType.SHL exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_shr -> + let exprs = parseBinop BinOpType.SHR exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_shra -> + let exprs = parseBinop BinOpType.SAR exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_le -> + let exprs = parseRel isa RelOpType.LE exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_ge -> + let exprs = parseRel isa RelOpType.GE exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_eq -> + let exprs = parseRel isa RelOpType.EQ exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_lt -> + let exprs = parseRel isa RelOpType.LT exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_gt -> + let exprs = parseRel isa RelOpType.GT exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_ne -> + let exprs = parseRel isa RelOpType.NEQ exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | DWOperation.DW_OP_deref -> + let exprs = parseLoad isa exprs + parseExprs isa regFct exprs span (i + 1) maxIdx + | op -> printfn "TODO: %A" op; Utils.futureFeature () + + let extractOldOffset = function + | RegPlusOffset (_, o) -> o + | UnknownCFA -> 0 + | e -> Utils.impossible () + + let restoreOne initialRule currentRule target = + match Map.tryFind target initialRule with + | Some oldVal -> Map.add target oldVal currentRule + | None -> Map.remove target currentRule + + let rec getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i loc = + if i >= (span: ByteSpan).Length then + { Location = loc + CanonicalFrameAddress = cfa + Rule = rule } :: acc |> List.rev, cfa, lr + else + let op = span[i] + let oparg = span[i] &&& 0x3fuy + let i = i + 1 + let op = if op &&& 0xc0uy > 0uy then op &&& 0xc0uy else op + match DWCFAInstruction.parse op with + | DWCFAInstruction.DW_CFA_def_cfa -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) + let cfa = CanonicalFrameAddress.regPlusOffset isa rFct reg (int offset) + getUnwind + acc cfa irule rst rule isa rFct reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_sf -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let v, cnt = LEB128.DecodeSInt64 (span.Slice i) + let offset = int (v * df) + let cfa = CanonicalFrameAddress.regPlusOffset isa rFct reg offset + getUnwind + acc cfa irule rst rule isa rFct reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_offset -> + let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) + let cfa = CanonicalFrameAddress.regPlusOffset isa rFct lr (int offset) + getUnwind + acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_offset_sf -> + let offset, cnt = LEB128.DecodeSInt64 (span.Slice i) + let offset = int (offset * df) + let cfa = CanonicalFrameAddress.regPlusOffset isa rFct lr offset + getUnwind + acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_def_cfa_expression -> + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let i = i + cnt + let nextIdx = int v + i + let cfa = parseExprs isa rFct [] span i nextIdx |> Expression + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span nextIdx loc + | DWCFAInstruction.DW_CFA_def_cfa_register -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let rid = DWRegister.toRegID isa reg + let oldOffset = extractOldOffset cfa + let cfa = RegPlusOffset (rid, oldOffset) + getUnwind + acc cfa irule rst rule isa rFct reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_offset -> + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let offset = int64 v * df + let target, action = Rule.offset isa rr oparg offset + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_offset_extended -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) + let target, action = Rule.offset isa rr reg (int64 offset) + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_offset_extended_sf -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let v, cnt = LEB128.DecodeSInt64 (span.Slice i) + let offset = v * df + let target, action = Rule.offset isa rr reg offset + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_undefined -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let target = Rule.getTarget isa rr reg + let rule = Map.remove target rule + getUnwind + acc cfa irule rst rule isa rFct reg cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_register -> + let reg1, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg1 = byte reg1 + let i = i + cnt + let reg2, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg2 = byte reg2 + let target = Rule.getTarget isa rr reg1 + let action = Register (DWRegister.toRegID isa reg2) + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_same_value -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let target = Rule.getTarget isa rr reg + let action = SameValue + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_expression -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let i = i + cnt + let nextIdx = int v + i + let target = Rule.getTarget isa rr reg + let action = parseExprs isa rFct [] span i nextIdx |> ActionExpr + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct reg cf df rr span nextIdx loc + | DWCFAInstruction.DW_CFA_val_expression -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let reg = byte reg + let i = i + cnt + let v, cnt = LEB128.DecodeUInt64 (span.Slice i) + let i = i + cnt + let nextIdx = int v + i + let target = Rule.getTarget isa rr reg + let action = parseExprs isa rFct [] span i nextIdx |> ActionValExpr + let rule = Map.add target action rule + getUnwind acc cfa irule rst rule isa rFct reg cf df rr span nextIdx loc + | DWCFAInstruction.DW_CFA_advance_loc -> + let loc' = loc + uint64 oparg * cf + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i loc' + | DWCFAInstruction.DW_CFA_advance_loc1 -> + let loc' = loc + uint64 span[i] + let i' = i + 1 + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i' loc' + | DWCFAInstruction.DW_CFA_advance_loc2 -> + let loc' = loc + uint64 (MemoryMarshal.Read (span.Slice (i))) + let i' = i + 2 + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i' loc' + | DWCFAInstruction.DW_CFA_advance_loc4 -> + let loc' = loc + uint64 (MemoryMarshal.Read (span.Slice (i))) + let i' = i + 4 + let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } + let acc = ent :: acc + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i' loc' + | DWCFAInstruction.DW_CFA_remember_state -> + let rst = (cfa, rule, lr) :: rst + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i loc + | DWCFAInstruction.DW_CFA_restore -> + let target = Rule.getTarget isa rr oparg + let rule = restoreOne irule rule target + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i loc + | DWCFAInstruction.DW_CFA_restore_extended -> + let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) + let target = Rule.getTarget isa rr (byte reg) + let rule = restoreOne irule rule target + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_restore_state -> + let cfa, rule, lr = List.head rst + let rst = List.tail rst + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i loc + | DWCFAInstruction.DW_CFA_GNU_args_size -> + let _, cnt = LEB128.DecodeUInt64 (span.Slice i) + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span (i + cnt) loc + | DWCFAInstruction.DW_CFA_nop -> + getUnwind acc cfa irule rst rule isa rFct lr cf df rr span i loc + | op -> printfn "%A" op; Utils.futureFeature () + + let extractRule unwindingInfo = + match unwindingInfo with + | [ row ] -> row.Rule + | _ -> Map.empty + + let parseCIE toolBox (secChunk: ByteSpan) cls isa rFct offset nextOffset = + let version = secChunk[offset] + let offset = offset + 1 + if version = 1uy || version = 3uy then + let augstr = ByteArray.extractCStringFromSpan secChunk offset + let addrSize = WordSize.toByteWidth cls + let offset = offset + augstr.Length + 1 + let offset = if augstr.Contains "eh" then offset + addrSize else offset + let cf, cnt = toolBox.Reader.ReadUInt64LEB128 (secChunk, offset) + let offset = offset + cnt + let df, cnt = toolBox.Reader.ReadInt64LEB128 (secChunk, offset) + let offset = offset + cnt + let rr, offset = parseReturnRegister toolBox secChunk version offset + let augs, offset = + parseAugmentationData toolBox secChunk offset addrSize augstr + let instrLen = nextOffset - offset + if instrLen > 0 then + let span = secChunk.Slice (offset, instrLen) + let rule = Map.empty + getUnwind [] UnknownCFA rule [] rule isa rFct rr cf df rr span 0 0UL + else [], UnknownCFA, rr + |> fun (info, cfa, reg) -> + { Version = version + AugmentationString = augstr + CodeAlignmentFactor = cf + DataAlignmentFactor = df + ReturnAddressRegister = byte rr + InitialRule = extractRule info + InitialCFARegister = reg + InitialCFA = cfa + Augmentations = augs } + else + raise UnhandledEHFrameVersionException + + let tryFindAugmentation cie format = + cie.Augmentations |> List.tryFind (fun aug -> aug.Format = format) + + let adjustAddr app myAddr addr = + match app with + | ExceptionHeaderApplication.DW_EH_PE_pcrel -> addr + myAddr + | _ -> addr + + let parsePCInfo cls span reader sAddr relOpt venc aenc offset = + let myAddr = sAddr + uint64 offset + let struct (addr, offset) = computeValue cls span reader venc offset + let struct (range, offset) = computeValue cls span reader venc offset + let beginAddr = adjustAddr aenc myAddr addr + let endAddr = beginAddr + range + match (relOpt: RelocationInfo option) with + | Some relInfo -> + let found, rentry = relInfo.RelocByAddr.TryGetValue beginAddr + if found then + let beginAddr = addr + rentry.RelAddend + struct (beginAddr, beginAddr + range, offset) + else struct (beginAddr, endAddr, offset) + | None -> struct (beginAddr, endAddr, offset) + + let parseLSDA cls span reader sAddr aug offset = + let _, offset = parseULEB128 span offset + let myAddr = sAddr + uint64 offset + let struct (addr, offset) = + computeValue cls span reader aug.ValueEncoding offset + Some (adjustAddr aug.ApplicationEncoding myAddr addr), offset + + let parseCallFrameInstrs cie isa regFactory span offset nextOffset loc = + let span = (span: ByteSpan).Slice (offset, nextOffset - offset) + let insarr = span.ToArray () + if Array.forall (fun b -> b = 0uy) insarr then [] + else + let cf = cie.CodeAlignmentFactor + let df = cie.DataAlignmentFactor + let rr = cie.ReturnAddressRegister + let ir = cie.InitialCFARegister + let r = cie.InitialRule + let cfa = cie.InitialCFA + let info, _, _ = + getUnwind [] cfa r [] r isa regFactory ir cf df rr span 0 loc + info + + let parseFDE cls isa regFct span reader sAddr offset nextOffset reloc cie = + match cie with + | Some cie -> + let venc, aenc = + match tryFindAugmentation cie 'R' with + | Some aug -> aug.ValueEncoding, aug.ApplicationEncoding + | None -> ExceptionHeaderValue.DW_EH_PE_absptr, + ExceptionHeaderApplication.DW_EH_PE_absptr + let struct (b, e, offset) = + parsePCInfo cls span reader sAddr reloc venc aenc offset + let lsdaPointer, offset = + match tryFindAugmentation cie 'L' with + | Some aug -> parseLSDA cls span reader sAddr aug offset + | None -> None, offset + let info = parseCallFrameInstrs cie isa regFct span offset nextOffset b + { PCBegin = b + PCEnd = e + LSDAPointer = lsdaPointer + UnwindingInfo = info } + | None -> raise CIENotFoundByFDEException + + let accumulateCFIs cfis cie fdes = + match cie with + | Some cie -> + { CIERecord = cie + FDERecord = List.rev fdes |> List.toArray } :: cfis + | None -> cfis + + let private parseCFI toolBox cls isa reloc regFct sec = + let secAddr, secOffset, secSize = sec.SecAddr, sec.SecOffset, sec.SecSize + let reader = toolBox.Reader + let rec parseLoop cie cies fdes offset cfis = + let secChunk = ReadOnlySpan (toolBox.Bytes, int secOffset, int secSize) + if offset >= secChunk.Length then + accumulateCFIs cfis cie fdes + else + let originalOffset = offset + let len, offset = reader.ReadInt32 (secChunk, offset), offset + 4 + if len = 0 then accumulateCFIs cfis cie fdes + else + let nextOfs, offset = computeNextOffset secChunk reader offset len + let mybase = offset + let id, offset = reader.ReadInt32 (secChunk, offset), offset + 4 + if id = 0 then + let cfis = accumulateCFIs cfis cie fdes + let cie = parseCIE toolBox secChunk cls isa regFct offset nextOfs + let cies = Map.add originalOffset cie cies + let cie = Some cie + parseLoop cie cies [] nextOfs cfis + else + let cieOffset = mybase - id (* id = a CIE pointer, when id <> 0 *) + let fde = + parseFDE + cls isa regFct secChunk reader secAddr offset nextOfs reloc + (Map.tryFind cieOffset cies) + let fdes = fde :: fdes + parseLoop cie cies fdes nextOfs cfis + parseLoop None Map.empty [] 0 [] + + let parse toolBox cls shdrs isa regFactoryOpt reloc = + match Array.tryFind (fun s -> s.SecName = Ehframe) shdrs, regFactoryOpt with + | Some sec, Some regFactory -> + parseCFI toolBox cls isa reloc regFactory sec + |> List.rev + | _ -> [] diff --git a/src/FrontEnd/BinFile/ELF/ELFExceptionInfo.fs b/src/FrontEnd/BinFile/ELF/ELFExceptionInfo.fs new file mode 100644 index 00000000..1dfde164 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFExceptionInfo.fs @@ -0,0 +1,63 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open B2R2 + +/// Exception information. +type ExceptionInfo = { + /// Exception frames. + ExceptionFrames: CallFrameInformation list + /// LSDAs (Language Specific Data Areas). + LSDAs: Map + /// Unwinding info table. + UnwindingTbl: Map +} + +module internal ExceptionInfo = + let private computeUnwindingTable exns = + exns + |> List.fold (fun tbl (f: CallFrameInformation) -> + f.FDERecord |> Array.fold (fun tbl fde -> + fde.UnwindingInfo |> List.fold (fun tbl i -> + Map.add i.Location i tbl) tbl + ) tbl) Map.empty + + let parse toolBox shdrs regFctOpt reloc = + let hdr = toolBox.Header + let cls = hdr.Class + let isa = ISA.Init hdr.MachineType hdr.Endian + let relocInfo = + if hdr.ELFFileType = ELFFileType.ET_REL then Some reloc else None + let exns = ExceptionFrames.parse toolBox cls shdrs isa regFctOpt relocInfo + let lsdas = ELFGccExceptTable.parse toolBox cls shdrs + match exns with + | [] when isa.Arch = Architecture.ARMv7 -> + let struct (exns, lsdas) = ELFARMExceptionHandler.parse toolBox cls shdrs + { ExceptionFrames = exns; LSDAs = lsdas; UnwindingTbl = Map.empty } + | _ -> + let unwinds = computeUnwindingTable exns + { ExceptionFrames = exns; LSDAs = lsdas; UnwindingTbl = unwinds } + diff --git a/src/FrontEnd/BinFile/ELF/ELFGccExceptTable.fs b/src/FrontEnd/BinFile/ELF/ELFGccExceptTable.fs new file mode 100644 index 00000000..26ab291c --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFGccExceptTable.fs @@ -0,0 +1,216 @@ +(* +B2R2 - the Next-Generation Reversing Platform + +Copyright (c) SoftSec Lab. @ KAIST, since 2016 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.ELF.ExceptionHeaderEncoding +open B2R2.FrontEnd.BinFile + +/// Language Specific Data Area header. +type LSDAHeader = { + /// This is the value encoding of the landing pad pointer. + LPValueEncoding: ExceptionHeaderValue + /// This is the application encoding of the landing pad pointer. + LPAppEncoding: ExceptionHeaderApplication + /// The base of the landing pad pointers. + LPStart: Addr option + /// This is the value encoding of type table (TT). + TTValueEncoding: ExceptionHeaderValue + /// This is the application encoding of type table (TT). + TTAppEncoding: ExceptionHeaderApplication + /// The base of types table. + TTBase: Addr option + // This is the value encoding of the call site table. + CallSiteValueEncoding: ExceptionHeaderValue + // This is the application encoding of the call site table. + CallSiteAppEncoding: ExceptionHeaderApplication + // The size of call site table. + CallSiteTableSize: uint64 +} + +/// An entry in the callsite table of LSDA. +type CallSiteRecord = { + /// Offset of the callsite relative to the previous call site. + Position: uint64 + /// Size of the callsite instruction(s). + Length: uint64 + /// Offset of the landing pad. + LandingPad: uint64 + /// Offset to the action table. Zero means no action entry. + ActionOffset: int + /// Parsed list of type filters from the action table. + ActionTypeFilters: int64 list +} + +/// LSDA. Language Specific Data Area. +type LanguageSpecificDataArea = { + LSDAHeader: LSDAHeader + CallSiteTable: CallSiteRecord list +} + +[] +module ELFGccExceptTable = + let [] GccExceptTable = ".gcc_except_table" + + let parseLSDAHeader cls (span: ByteSpan) reader sAddr offset = + let b = span[offset] + let offset = offset + 1 + let struct (lpv, lpapp) = parseEncoding b + let struct (lpstart, offset) = + if lpv = ExceptionHeaderValue.DW_EH_PE_omit then struct (None, offset) + else + let struct (cv, offset) = computeValue cls span reader lpv offset + struct (Some (sAddr + uint64 offset + cv), offset) + let b = span[offset] + let offset = offset + 1 + let struct (ttv, ttapp) = parseEncoding b + let struct (ttbase, offset) = + if ttv = ExceptionHeaderValue.DW_EH_PE_omit then struct (None, offset) + else + let cv, offset = parseULEB128 span offset + struct (Some (sAddr + uint64 offset + cv), offset) + let b = span[offset] + let offset = offset + 1 + let struct (csv, csapp) = parseEncoding b + let cstsz, offset = parseULEB128 span offset + { LPValueEncoding = lpv + LPAppEncoding = lpapp + LPStart = lpstart + TTValueEncoding = ttv + TTAppEncoding = ttapp + TTBase = ttbase + CallSiteValueEncoding = csv + CallSiteAppEncoding = csapp + CallSiteTableSize = cstsz }, offset + + let rec parseCallSiteTable acc cls span reader offset csv hasAction = + (* We found that GCC sometimes produces a wrong callsite table length, and + the length can be off by one. So we minus one here. This is conservative + anyways, because callsite entry can only be larger than three bytes. *) + if offset >= (span: ByteSpan).Length - 3 then + List.rev acc, hasAction + else + let struct (start, offset) = computeValue cls span reader csv offset + let struct (length, offset) = computeValue cls span reader csv offset + let struct (landingPad, offset) = computeValue cls span reader csv offset + let actionOffset, offset = parseULEB128 span offset + let acc = + if start = 0UL && length = 0UL && landingPad = 0UL && actionOffset = 0UL + then acc (* This can appear due to the miscalculation issue above. *) + else { Position = start + Length = length + LandingPad = landingPad + ActionOffset = int actionOffset + ActionTypeFilters = [] } :: acc + let hasAction = if actionOffset > 0UL then true else hasAction + parseCallSiteTable acc cls span reader offset csv hasAction + + let rec parseActionEntries acc span offset actOffset = + if actOffset > 0 then + let tfilter, offset = parseSLEB128 span (actOffset - 1 + offset) + let next, offset = parseSLEB128 span offset + let acc = tfilter :: acc + parseActionEntries acc span offset (int next) + else List.rev acc + + let rec parseActionTable acc span offset callsites = + match callsites with + | csEntry :: tl -> + let filters = parseActionEntries [] span offset csEntry.ActionOffset + let acc = { csEntry with ActionTypeFilters = filters } :: acc + parseActionTable acc span offset tl + | [] -> List.rev acc + + /// Parse one LSDA entry. + let parseLSDA cls (span: ByteSpan) reader sAddr offset = + let header, offset = parseLSDAHeader cls span reader sAddr offset + let subspn = span.Slice (offset, int header.CallSiteTableSize) + let encoding = header.CallSiteValueEncoding + let callsites, hasAction = + parseCallSiteTable [] cls subspn reader 0 encoding false + let offset = offset + int header.CallSiteTableSize + let callsites = + if hasAction then parseActionTable [] span offset callsites + else callsites + struct ({ LSDAHeader = header; CallSiteTable = callsites }, offset) + + let findMinOrZero lst = + match lst with + | [] -> 0L + | _ -> List.min lst + + let findMinFilter callsites = + if List.isEmpty callsites then 0L + else + callsites + |> List.map (fun cs -> cs.ActionTypeFilters |> findMinOrZero) + |> List.min + + let rec readUntilNull (span: ByteSpan) offset = + if span[offset] = 0uy then (offset + 1) + else readUntilNull span (offset + 1) + + /// We currently just skip the type table by picking up the minimum filter + /// value as we don't use the type table. + let skipTypeTable span ttbase callsites = + let minFilter = findMinFilter callsites + if minFilter < 0L then + let offset = ttbase - int minFilter - 1 + readUntilNull span offset (* Consume exception spec table. *) + else ttbase + + /// Sometimes, we observe dummy zero bytes inserted by the compiler (icc); + /// this is nothing to do with the alignment. This is likely to be the + /// compiler error, but we should safely ignore those dummy bytes. + let rec skipDummyAlign (span: ByteSpan) offset = + if offset >= span.Length then offset + else + let b = span[offset] + if b = 0uy then skipDummyAlign span (offset + 1) + else offset + + /// Parse language-specific data area. + let rec parseLSDASection cls (span: ByteSpan) reader sAddr offset lsdas = + if offset >= span.Length then lsdas + else + let lsdaAddr = sAddr + uint64 offset + let struct (lsda, offset) = parseLSDA cls span reader sAddr offset + let offset = + match lsda.LSDAHeader.TTBase with + | Some ttbase -> int (ttbase - sAddr) + | None -> offset + let offset = skipTypeTable span offset lsda.CallSiteTable + let offset = skipDummyAlign span offset + let lsdas = Map.add lsdaAddr lsda lsdas + parseLSDASection cls span reader sAddr offset lsdas + + let parse toolBox cls shdrs = + match Array.tryFind (fun s -> s.SecName = GccExceptTable) shdrs with + | Some sec -> + let offset, size = int sec.SecOffset, int sec.SecSize + let span = ReadOnlySpan (toolBox.Bytes, offset, size) + parseLSDASection cls span toolBox.Reader sec.SecAddr 0 Map.empty + | None -> Map.empty diff --git a/src/FrontEnd/BinFile/ELF/ELFHeader.fs b/src/FrontEnd/BinFile/ELF/ELFHeader.fs new file mode 100644 index 00000000..52df39d7 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFHeader.fs @@ -0,0 +1,259 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open System.IO +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +/// File type. +type ELFFileType = + /// No file type. + | ET_NONE = 0x0us + /// Relocatable file. + | ET_REL = 0x1us + /// Executable file. + | ET_EXEC = 0x2us + /// Shared object file. + | ET_DYN = 0x3us + /// Core file. + | ET_CORE = 0x4us + +module ELFFileType = + let toString = function + | ELFFileType.ET_REL -> "Relocatable" + | ELFFileType.ET_EXEC -> "Executable" + | ELFFileType.ET_DYN -> "Shared Object" + | ELFFileType.ET_CORE -> "Core" + | _ -> "Unknown" + +/// ABI type. +type OSABI = + /// UNIX System V ABI. + | ELFOSABI_SYSV = 0uy + /// HP-UX ABI. + | ELFOSABI_HPUX = 1uy + /// NetBSD ABI. + | ELFOSABI_NETBSD = 2uy + /// Linux ABI. + | ELFOSABI_GNU = 3uy + /// Linux ABI. + | ELFOSABI_LINUX = 3uy + /// Solaris ABI. + | ELFOSABI_SOLARIS = 6uy + /// IBM AIX ABI. + | ELFOSABI_AIX = 7uy + /// SGI Irix ABI. + | ELFOSABI_IRIX = 8uy + /// FreeBSD ABI. + | ELFOSABI_FREEBSD = 9uy + /// Compaq TRU64 UNIX ABI. + | ELFOSABI_TRU64 = 10uy + /// Novell Modesto ABI. + | ELFOSABI_MODESTO = 11uy + /// OpenBSD ABI. + | ELFOSABI_OPENBSD = 12uy + /// ARM EABI. + | ELFOSABI_ARM_AEABI = 64uy + /// ARM. + | ELFOSABI_ARM = 97uy + /// Standalone (embedded) application. + | ELFOSABI_STANDALONE = 255uy + +module OSABI = + let toString = function + | OSABI.ELFOSABI_SYSV -> "UNIX System V" + | OSABI.ELFOSABI_HPUX -> "HP-UX" + | OSABI.ELFOSABI_NETBSD -> "NetBSD" + | OSABI.ELFOSABI_GNU | OSABI.ELFOSABI_LINUX -> "Linux" + | OSABI.ELFOSABI_SOLARIS -> "Solaris" + | OSABI.ELFOSABI_AIX -> "AIX" + | OSABI.ELFOSABI_IRIX -> "IRIX" + | OSABI.ELFOSABI_FREEBSD -> "FreeBSD" + | OSABI.ELFOSABI_TRU64 -> "TRU64" + | OSABI.ELFOSABI_MODESTO -> "Modesto" + | OSABI.ELFOSABI_OPENBSD -> "OpenBSD" + | OSABI.ELFOSABI_ARM_AEABI -> "ARM EABI" + | OSABI.ELFOSABI_ARM -> "ARM" + | OSABI.ELFOSABI_STANDALONE -> "Standalone" + | _ -> "Unknown" + +/// ELF header. +type ELFHeader = { + /// 32-bit or 64-bit. + Class: WordSize + /// Little or big endian. + Endian: Endian + /// ELF version. + Version: uint32 + /// OS ABI. + OSABI: OSABI + /// ABI version. + OSABIVersion: uint32 + /// ELF file type (e_type). + ELFFileType: ELFFileType + /// Target instruction set architecture (e_machine). + MachineType: Architecture + /// Entry point address (e_entry). + EntryPoint: uint64 + /// Program header table offset (e_phoff). + PHdrTblOffset: uint64 + /// Section header table offset (e_shoff). + SHdrTblOffset: uint64 + /// Processor-specific flags (e_flags). + ELFFlags: uint32 + /// ELF header size (e_ehsize). + HeaderSize: uint16 + /// Size of a program header table entry (e_phentsize). + PHdrEntrySize: uint16 + /// Number of entries in the program header table (e_phnum). + PHdrNum: uint16 + /// Size of a section header table entry (e_shentsize). + SHdrEntrySize: uint16 + /// Number of entries in the section header table (e_shnum). + SHdrNum: uint16 + /// Section header string table index (e_shstrndx). + SHdrStrIdx: uint16 +} + +/// This is a basic toolbox for parsing ELF, which is returned from parsing an +/// ELF header. +type ELFToolbox = { + Bytes: byte[] + Reader: IBinReader + BaseAddress: Addr + Header: ELFHeader +} + +module internal Header = + /// Check if the file has a valid ELF header. + let private isELF (span: ByteSpan) = + let elfMagicNumber = [| 0x7fuy; 0x45uy; 0x4cuy; 0x46uy |] + span.Length > 4 + && span.Slice(0, 4).SequenceEqual (ReadOnlySpan elfMagicNumber) + + let private getEndianness (span: ByteSpan) = + match span[5] with + | 0x1uy -> Endian.Little + | 0x2uy -> Endian.Big + | _ -> raise InvalidEndianException + + let private getClass (span: ByteSpan) = + match span[4] with + | 0x1uy -> WordSize.Bit32 + | 0x2uy -> WordSize.Bit64 + | _ -> raise InvalidWordSizeException + + let private getELFFileType (span: ByteSpan) (reader: IBinReader) = + reader.ReadUInt16 (span, 16) + |> LanguagePrimitives.EnumOfValue: ELFFileType + + let private computeNewBaseAddr ftype baseAddr = + match ftype with + | ELFFileType.ET_EXEC -> 0UL (* Non-PIEs must have zero base. *) + | _ -> defaultArg baseAddr 0UL + + let private getELFFlags span (reader: IBinReader) cls = + reader.ReadUInt32 (span=span, offset=pickNum cls 36 48) + + let private getMIPSArch span reader cls = + match getELFFlags span reader cls &&& 0xf0000000u with + | 0x00000000u + | 0x10000000u + | 0x20000000u + | 0x30000000u + | 0x40000000u + | 0x50000000u + | 0x70000000u + | 0x90000000u -> Architecture.MIPS32 + | 0x60000000u + | 0x80000000u + | 0xa0000000u -> Architecture.MIPS64 + | c -> failwithf "invalid MIPS arch (%02x)" c + + let private getArch (span: ByteSpan) (reader: IBinReader) cls = + match reader.ReadInt16 (span, 18) with + | 0x03s -> Architecture.IntelX86 + | 0x3es -> Architecture.IntelX64 + | 0x28s -> Architecture.ARMv7 + | 0xb7s -> Architecture.AARCH64 + | 0x08s | 0x0as -> getMIPSArch span reader cls + | 0x53s -> Architecture.AVR + | 0x2as -> Architecture.SH4 + | 0x14s -> Architecture.PPC32 + | 0x2bs -> Architecture.SPARC + | 0xf3s -> Architecture.RISCV64 (* FIXME: RISCV *) + | _ -> Architecture.UnknownISA + + let parseFromSpan span (reader: IBinReader) endian baseAddrOpt = + let cls = getClass span + let ftype = getELFFileType span reader + let baseAddr = computeNewBaseAddr ftype baseAddrOpt + let hdr = + { Class = cls + Endian = endian + Version = reader.ReadUInt32 (span, 6) + OSABI = span[7] |> LanguagePrimitives.EnumOfValue + OSABIVersion = span[8] |> uint32 + ELFFileType = ftype + MachineType = getArch span reader cls + EntryPoint = readNative span reader cls 24 24 + baseAddr + PHdrTblOffset = readNative span reader cls 28 32 + SHdrTblOffset = readNative span reader cls 32 40 + ELFFlags = reader.ReadUInt32 (span, pickNum cls 36 48) + HeaderSize = reader.ReadUInt16 (span, pickNum cls 40 52) + PHdrEntrySize = reader.ReadUInt16 (span, pickNum cls 42 54) + PHdrNum = reader.ReadUInt16 (span, pickNum cls 44 56) + SHdrEntrySize = reader.ReadUInt16 (span, pickNum cls 46 58) + SHdrNum = reader.ReadUInt16 (span, pickNum cls 48 60) + SHdrStrIdx = reader.ReadUInt16 (span, pickNum cls 50 62) } + struct (hdr, baseAddr) + + /// Parse the ELF header and return a toolbox, which includes ELF header, + /// preferred base address, and IBinReader. + let parse baseAddrOpt (bytes: byte[]) = + let span = ReadOnlySpan bytes + if not <| isELF span then raise InvalidFileFormatException + else + let endian = getEndianness span + let reader = BinReader.Init endian + let struct (hdr, baseAddr) = parseFromSpan span reader endian baseAddrOpt + { Bytes = bytes + Reader = reader + BaseAddress = baseAddr + Header = hdr } + + /// Check if the file has a valid ELF header, and return an ISA. + let getISA (bytes: byte[]) = + let span = ReadOnlySpan bytes + if isELF span then + let endian = getEndianness span + let reader = BinReader.Init endian + let cls = getClass span + let arch = getArch span reader cls + Ok (ISA.Init arch endian) + else Error ErrorCase.InvalidFormat \ No newline at end of file diff --git a/src/FrontEnd/BinFile/ELF/ELFHelper.fs b/src/FrontEnd/BinFile/ELF/ELFHelper.fs new file mode 100644 index 00000000..b2d9a3f3 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFHelper.fs @@ -0,0 +1,325 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinFile.ELF.Helper + +open System +open System.Collections.Generic +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +let toFileType = function + | ELFFileType.ET_EXEC -> FileType.ExecutableFile + | ELFFileType.ET_DYN -> FileType.LibFile + | ELFFileType.ET_CORE -> FileType.CoreFile + | ELFFileType.ET_REL -> FileType.ObjFile + | _ -> FileType.UnknownFile + +let isNXEnabled progHeaders = + let predicate e = e.PHType = ProgramHeaderType.PT_GNU_STACK + match Array.tryFind predicate progHeaders with + | Some s -> s.PHFlags.HasFlag Permission.Executable |> not + | _ -> false + +let isRelocatable toolBox secHeaders = + let pred (e: DynamicSectionEntry) = e.DTag = DynamicTag.DT_DEBUG + toolBox.Header.ELFFileType = ELFFileType.ET_DYN + && DynamicSection.readEntries toolBox secHeaders |> Array.exists pred + +let inline private computeSubstitute offsetToAddr delta (ptr: Addr) = + if offsetToAddr then ptr + delta + else (* Addr to offset *) ptr - delta + +let translateWithSecs offsetToAddr ptr sections = + let txtOffset = + match Array.tryFind (fun s -> s.SecName = Section.SecText) sections with + | Some text -> text.SecOffset + | None -> 0UL + sections + |> Array.tryFind (fun s -> + let secBase = + if offsetToAddr then s.SecOffset + else s.SecOffset - txtOffset + s.SecAddr + s.SecType = SectionType.SHT_PROGBITS + && s.SecFlags.HasFlag SectionFlag.SHF_EXECINSTR + && secBase <= ptr && (secBase + s.SecSize) > ptr) + |> function + | None -> raise InvalidAddrReadException + | Some s -> computeSubstitute offsetToAddr (s.SecAddr - txtOffset) ptr + +let translateWithSegs offsetToAddr ptr segments = + segments + |> Array.tryFind (fun seg -> + let segBase, segSize = + if offsetToAddr then seg.PHOffset, seg.PHFileSize + else seg.PHAddr, seg.PHMemSize + ptr >= segBase && ptr < segBase + segSize) + |> function + | Some seg -> computeSubstitute offsetToAddr (seg.PHAddr - seg.PHOffset) ptr + | None -> raise InvalidAddrReadException + +let translate loadableSegments sections offsetToAddr ptr = + if Array.isEmpty loadableSegments then + translateWithSecs offsetToAddr ptr sections + else translateWithSegs offsetToAddr ptr loadableSegments + +let translateAddrToOffset loadableSegs sections addr = + translate loadableSegs sections false addr + +let translateOffsetToAddr loadableSegs sections offset = + translate loadableSegs sections true offset + +let isFuncSymb s = + s.SymType = SymbolType.STT_FUNC || s.SymType = SymbolType.STT_GNU_IFUNC + +let inline tryFindFuncSymb symbolInfo addr = + match symbolInfo.AddrToSymbTable.TryGetValue addr with + | true, s -> + if isFuncSymb s then Ok s.SymName + else Error ErrorCase.SymbolNotFound + | false, _ -> Error ErrorCase.SymbolNotFound + +let getStaticSymbols shdrs symbols = + Symbol.getStaticSymArray shdrs symbols.SecNumToSymbTbls + |> Array.map (Symbol.toB2R2Symbol SymbolVisibility.StaticSymbol) + +let getDynamicSymbols excludeImported shdrs symbols = + let excludeImported = defaultArg excludeImported false + let alwaysTrue = fun _ -> true + let filter = + if excludeImported then (fun s -> s.SecHeaderIndex <> SHN_UNDEF) + else alwaysTrue + Symbol.getDynamicSymArray shdrs symbols.SecNumToSymbTbls + |> Array.filter filter + |> Array.map (Symbol.toB2R2Symbol SymbolVisibility.DynamicSymbol) + +let getSymbols shdrs symbols = + let s = getStaticSymbols shdrs symbols + let d = getDynamicSymbols None shdrs symbols + Array.append s d + +let getRelocSymbols relocInfo = + let translate reloc = + reloc.RelSymbol + |> Option.bind (fun s -> + { s with Addr = reloc.RelOffset } + |> Symbol.toB2R2Symbol SymbolVisibility.DynamicSymbol + |> Some) + relocInfo.RelocByName.Values + |> Seq.choose translate + |> Seq.toArray + +let secFlagToSectionKind sec = + if sec.SecFlags &&& SectionFlag.SHF_EXECINSTR = SectionFlag.SHF_EXECINSTR then + if PLT.isPLTSectionName sec.SecName then SectionKind.LinkageTableSection + else SectionKind.ExecutableSection + elif sec.SecFlags &&& SectionFlag.SHF_WRITE = SectionFlag.SHF_WRITE then + SectionKind.WritableSection + else + SectionKind.ExtraSection + +let elfSectionToSection sec = + { Address = sec.SecAddr + FileOffset = uint32 sec.SecOffset + Kind = secFlagToSectionKind sec + Size = uint32 sec.SecSize + Name = sec.SecName } + +let getSections shdrs = + shdrs + |> Array.map elfSectionToSection + +let getSectionsByAddr shdrs addr = + shdrs + |> Array.tryFind (fun section -> + section.SecAddr <= addr && addr < section.SecAddr + section.SecSize) + |> function + | Some section -> [| elfSectionToSection section |] + | None -> [||] + +let getSectionsByName shdrs name = + shdrs + |> Array.tryFind (fun section -> section.SecName = name) + |> function + | Some section -> [| elfSectionToSection section |] + | None -> [||] + +let getTextSection shdrs = + shdrs + |> Array.filter (fun sec -> + (SectionFlag.SHF_EXECINSTR &&& sec.SecFlags = SectionFlag.SHF_EXECINSTR) + && sec.SecName.StartsWith Section.SecText) + |> Array.tryExactlyOne + |> function + | Some sec -> elfSectionToSection sec + | None -> raise SectionNotFoundException + +let getSegments segments = + segments + |> Array.map ProgramHeader.toSegment + +let getRelocatedAddr relocInfo relocAddr = + match relocInfo.RelocByAddr.TryGetValue relocAddr with + | true, rel -> + match rel.RelType with + | RelocationX86 RelocationX86.R_386_32 + | RelocationX64 RelocationX64.R_X86_64_64 -> + match rel.RelSymbol with + | Some sym -> sym.Addr + rel.RelAddend |> Ok + | _ -> Error ErrorCase.ItemNotFound + | RelocationX86 RelocationX86.R_386_JUMP_SLOT + | RelocationX64 RelocationX64.R_X86_64_JUMP_SLOT -> + match rel.RelSymbol with + | Some sym -> sym.Addr |> Ok + | _ -> Error ErrorCase.ItemNotFound + | RelocationX86 RelocationX86.R_386_IRELATIVE + | RelocationX64 RelocationX64.R_X86_64_IRELATIVE -> + Ok rel.RelAddend + | _ -> Error ErrorCase.ItemNotFound + | _ -> Error ErrorCase.ItemNotFound + +let getFuncAddrsFromLibcArr span toolBox loadables shdrs relocInfo section = + let readType = toolBox.Header.Class + let entrySize = WordSize.toByteWidth readType + let secSize = int section.SecSize + let lst = List () + let addr = translateOffsetToAddr loadables shdrs section.SecOffset + for ofs in [| 0 .. entrySize .. secSize - entrySize |] do + readUIntOfType span toolBox.Reader readType ofs + |> (fun fnAddr -> + if fnAddr = 0UL then + match getRelocatedAddr relocInfo (addr + uint64 ofs) with + | Ok relocatedAddr -> lst.Add relocatedAddr + | Error _ -> () + else lst.Add fnAddr) + lst |> seq + +let getAddrsFromInitArray toolBox shdrs loadables relocInfo = + match Array.tryFind (fun s -> s.SecName = ".init_array") shdrs with + | Some s -> + let span = ReadOnlySpan (toolBox.Bytes, int s.SecOffset, int s.SecSize) + getFuncAddrsFromLibcArr span toolBox loadables shdrs relocInfo s + | None -> Seq.empty + +let getAddrsFromFiniArray toolBox shdrs loadables relocInfo = + match Array.tryFind (fun s -> s.SecName = ".fini_array") shdrs with + | Some s -> + let span = ReadOnlySpan (toolBox.Bytes, int s.SecOffset, int s.SecSize) + getFuncAddrsFromLibcArr span toolBox loadables shdrs relocInfo s + | None -> Seq.empty + +let getAddrsFromSpecialSections shdrs = + [ ".init"; ".fini" ] + |> Seq.choose (fun secName -> + match Array.tryFind (fun s -> s.SecName = secName) shdrs with + | Some sec -> Some sec.SecAddr + | None -> None) + +let addExtraFunctionAddrs toolBox shdrs loadables relocInfo exnInfoOpt addrs = + let addrSet = + [ addrs + getAddrsFromInitArray toolBox shdrs loadables relocInfo + getAddrsFromFiniArray toolBox shdrs loadables relocInfo + getAddrsFromSpecialSections shdrs ] + |> Seq.concat + |> Set.ofSeq + match exnInfoOpt with + | Some exnInfo -> + exnInfo.ExceptionFrames + |> List.fold (fun set cfi -> + cfi.FDERecord + |> Array.fold (fun set fde -> Set.add fde.PCBegin set) set + ) addrSet + |> Set.toArray + | None -> addrSet |> Set.toArray + +let private computeInvalidRanges wordSize phdrs getNextStartAddr = + phdrs + |> Array.sortBy (fun seg -> seg.PHAddr) + |> Array.fold (fun (set, saddr) seg -> + let n = getNextStartAddr seg + addInvalidRange set saddr seg.PHAddr, n) (IntervalSet.empty, 0UL) + |> addLastInvalidRange wordSize + +let invalidRangesByVM hdr phdrs = + computeInvalidRanges hdr.Class phdrs (fun s -> s.PHAddr + s.PHMemSize) + +let invalidRangesByFileBounds hdr phdrs = + computeInvalidRanges hdr.Class phdrs (fun s -> s.PHAddr + s.PHFileSize) + +let private computeExecutableRangesFromSections shdrs = + let txtOffset = + match Array.tryFind (fun s -> s.SecName = Section.SecText) shdrs with + | Some text -> text.SecOffset + | None -> 0UL + shdrs + |> Array.fold (fun set sec -> + if sec.SecType = SectionType.SHT_PROGBITS + && sec.SecFlags.HasFlag SectionFlag.SHF_EXECINSTR + then + let offset = sec.SecOffset - txtOffset + let addr = sec.SecAddr + offset + let range = AddrRange (addr, addr + sec.SecSize - 1UL) + IntervalSet.add range set + else set + ) IntervalSet.empty + +let private addIntervalWithoutSection secS secE s e set = + let set = + if s < secS && secS < e then IntervalSet.add (AddrRange (s, secS - 1UL)) set + else set + let set = + if secE < e then IntervalSet.add (AddrRange (secE + 1UL, e)) set + else set + set + +let private addIntervalWithoutROSection rodata seg set = + let roS = rodata.SecAddr + let roE = roS + rodata.SecSize - 1UL + let segS = seg.PHAddr + let segE = segS + seg.PHMemSize - 1UL + if roE < segS || segE < roS then + IntervalSet.add (AddrRange (segS, segE)) set + else addIntervalWithoutSection roS roE segS segE set + +let private addExecutableInterval excludingSection s set = + match excludingSection with + | Some sec -> addIntervalWithoutROSection sec s set + | None -> + IntervalSet.add (AddrRange (s.PHAddr, s.PHAddr + s.PHMemSize - 1UL)) set + +let executableRanges shdrs loadables = + (* Exclude .rodata even though it is included within an executable segment. *) + let rodata = + match Array.tryFind (fun s -> s.SecName = Section.SecROData) shdrs with + | Some rodata when rodata.SecAddr <> 0UL -> Some rodata + | _ -> None + if Array.isEmpty loadables then computeExecutableRangesFromSections shdrs + else + loadables + |> Array.filter (fun seg -> + seg.PHFlags &&& Permission.Executable = Permission.Executable) + |> Array.fold (fun set seg -> + addExecutableInterval rodata seg set) IntervalSet.empty diff --git a/src/FrontEnd/BinFile/ELF/ELFPLT.fs b/src/FrontEnd/BinFile/ELF/ELFPLT.fs new file mode 100644 index 00000000..02403b5a --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFPLT.fs @@ -0,0 +1,751 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinFile.ELF.PLT + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +type CodeKind = + | PIC + | NonPIC + | DontCare + +type PLTLinkMethod = + | LazyBinding + | EagerBinding + | AnyBinding + +type PLTEntryInfo = { + /// This is the address where a relocation operation is performed on. + EntryRelocAddr: Addr + /// Next PLT entry address. + NextEntryAddr: Addr +} + +/// General descriptor of a PLT section. +type PLTDescriptor = { + /// PIC or non-PIC. + CodeKind: CodeKind + /// Lazy vs. Non-lazy (eager) binding. + LinkMethod: PLTLinkMethod + /// Has secondary PLT? + HasSecondary: bool + /// Entry size of the PLT. + EntrySize: uint64 + /// Offset from a start of a PLT entry to the relocatable expression. This can + /// be an offset to a GOT entry or a GOT index, depending on whether the + /// binary is PIC or non-PIC. For example, in an x86 PIE, a PLT entry may + /// include `jmp [ebx+0xc]`. In such a case, we get the GOT index by getting + /// the displacement `0xc`. + RelocOffset: Addr + /// Extra offset field. This is used for different purposes for different + /// architectures. + ExtraOffset: Addr +} + +type PLTSectionType = + /// The regular PLT. + | PLT of desc: PLTDescriptor + /// The PLT pattern is unknown. + | UnknownPLT + +[] +type PLTParser () = + /// Parse PLT entries. This function returns a mapping from a PLT entry + /// address range to LinkageTableEntry. + abstract member Parse: ELFToolbox -> ARMap + + /// Parse the given PLT section. + abstract member ParseSection: + ELFToolbox * ELFSection * ARMap + -> ARMap + + /// Parse the given PLT section. + abstract member ParseEntry: + addr: Addr * idx: int * ELFSection * PLTDescriptor * IBinReader * ByteSpan + -> PLTEntryInfo + +let [] private SecRelPLT = ".rel.plt" +let [] private SecRelaPLT = ".rela.plt" +let [] private SecPLT = ".plt" +let [] private SecPLTSnd = ".plt.sec" +let [] private SecPLTGOT = ".plt.got" +let [] private SecPLTBnd = ".plt.bnd" +let [] private SecGOT = ".got" +let [] private SecGOTPLT = ".got.plt" +let [] private SecMIPSStubs = ".MIPS.stubs" + +let inline private newDesc kind lm hasSecondary entSize relocOff extra = + { CodeKind = kind + LinkMethod = lm + HasSecondary = hasSecondary + EntrySize = entSize + RelocOffset = relocOff + ExtraOffset = extra } + +let private newPLT kind lm hasSecondary entSize relocOff extra = + newDesc kind lm hasSecondary entSize relocOff extra |> PLT + +let private tryFindGOTAddr shdrs = + match Array.tryFind (fun s -> s.SecName = SecGOTPLT) shdrs with + | Some s -> Some s.SecAddr + | None -> + match Array.tryFind (fun s -> s.SecName = SecGOT) shdrs with + | Some s -> Some s.SecAddr + | None -> None + +let private tryFindFirstEntryAddrWithRelPLT reloc shdrs = + match Array.tryFind (fun s -> s.SecName = SecRelPLT) shdrs with + | Some s -> + reloc.RelocByAddr.Values + |> Seq.fold (fun minval r -> + if r.RelSecNumber = s.SecNum then + if r.RelOffset < minval then r.RelOffset else minval + else minval) UInt64.MaxValue + |> Some + | None -> None + +let private tryFindFirstEntryAddrWithRelocation reloc = + reloc.RelocByAddr.Values + |> Seq.fold (fun minval r -> + match r.RelType with + | RelocationARMv8 RelocationARMv8.R_AARCH64_JUMP_SLOT -> + if r.RelOffset < minval then r.RelOffset else minval + | _ -> minval) UInt64.MaxValue + |> fun addr -> if addr = UInt64.MaxValue then None else Some addr + +let isPLTSectionName name = + name = SecPLT || name = SecPLTSnd || name = SecPLTGOT || name = SecPLTBnd + +let private findPLTSections shdrs = + shdrs + |> Array.fold (fun acc s -> + if isPLTSectionName s.SecName then s :: acc else acc) [] + |> List.rev (* .plt, .plt.got, .plt.sec *) + +let private makePLTEntry symbs addr relocAddr (r: RelocationEntry) = + match r.RelSymbol with + | Some symb -> + symbs.AddrToSymbTable[addr] <- symb (* Update the symbol table. *) + { FuncName = symb.SymName + LibraryName = Symbol.versionToLibName symb.VerInfo + TrampolineAddress = addr + TableAddress = r.RelOffset } + | None -> + { FuncName = "" + LibraryName = "" + TrampolineAddress = addr + TableAddress = relocAddr } + +let rec parseEntryLoop p sec rdr span desc symbs rel map idx eAddr addr = + if addr >= eAddr then map + else + let entry = + (p: PLTParser).ParseEntry (addr, idx, sec, desc, rdr, span) + let nextAddr = entry.NextEntryAddr + match rel.RelocByAddr.TryGetValue entry.EntryRelocAddr with + | true, r -> + let entry = makePLTEntry symbs addr entry.EntryRelocAddr r + let ar = AddrRange (addr, nextAddr - 1UL) + let map = ARMap.add ar entry map + parseEntryLoop p sec rdr span desc symbs rel map (idx + 1) eAddr nextAddr + | _ -> + parseEntryLoop p sec rdr span desc symbs rel map (idx + 1) eAddr nextAddr + +let private parseEntries p sec span reader desc symbs rel map eAddr addr = + parseEntryLoop p sec reader span desc symbs rel map 0 eAddr addr + +let rec private parseSections p toolBox map = function + | sec :: rest -> + let map = (p: PLTParser).ParseSection (toolBox, sec, map) + parseSections p toolBox map rest + | [] -> map + +/// This uses relocation information to parse PLT entries. This can be a general +/// parser, but it is rather slow compared to platform-specific parsers. RISCV64 +/// relies on this. +type GeneralPLTParser (shdrs, relocInfo, symbInfo, pltHdrSize, relType) = + inherit PLTParser () + + let relocs = + relocInfo.RelocByAddr.Values + |> Seq.filter (fun r -> r.RelType = relType) + |> Seq.toArray + + member internal __.Relocs with get() = relocs + + member private __.CreateGeneralPLTDescriptor rsec sec = + let count = rsec.SecSize / rsec.SecEntrySize (* number of PLT entries *) + let pltEntrySize = (sec.SecSize - pltHdrSize) / count + let addr = sec.SecAddr + pltHdrSize + assert (__.Relocs.Length = int count) + newPLT DontCare AnyBinding false pltEntrySize 0UL addr + + member private __.FindGeneralPLTType sec = + match Array.tryFind (fun s -> s.SecName = SecRelPLT) shdrs with + | Some rsec -> __.CreateGeneralPLTDescriptor rsec sec + | None -> + match Array.tryFind (fun s -> s.SecName = SecRelaPLT) shdrs with + | Some rsec -> __.CreateGeneralPLTDescriptor rsec sec + | None -> UnknownPLT + + override __.ParseEntry (addr, idx, _sec, desc, _rdr, _span) = + { EntryRelocAddr = __.Relocs[idx].RelOffset + NextEntryAddr = addr + desc.EntrySize } + + override __.ParseSection (toolBox, sec, map) = + match __.FindGeneralPLTType sec with + | PLT desc -> + let sAddr, eAddr = desc.ExtraOffset, sec.SecAddr + sec.SecSize + let bytes = toolBox.Bytes + let reader = toolBox.Reader + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + parseEntries __ sec span reader desc symbInfo relocInfo map eAddr sAddr + | UnknownPLT -> map + + override __.Parse toolBox = + let pltSections = findPLTSections shdrs + parseSections __ toolBox ARMap.empty pltSections + +/// Intel x86 PLT parser. +type X86PLTParser (shdrs, relocInfo, symbInfo) = + inherit PLTParser () + + let gotAddrOpt = tryFindGOTAddr shdrs + + let picLazyZeroEntry = (* push indirect addr; jmp; *) + [| OneByte 0xffuy; OneByte 0xb3uy; OneByte 0x04uy; AnyByte; AnyByte; AnyByte + OneByte 0xffuy; OneByte 0xa3uy; OneByte 0x08uy; AnyByte; AnyByte; AnyByte + |] + + let picLazyIbtEntry = (* (Ind-Branch-Tracking) endbr32; push; jmp rel; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy; + OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + + let nonPicZeroEntry = (* push absolute addr; jmp; *) + [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte |] + + let nonPicIbtEntry = (* (Ind-Branch-Tracking) endbr32; jmp got; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy; + OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + + let picNonLazyEntry = (* jmp indirect addr; nop *) + [| OneByte 0xffuy; OneByte 0xa3uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + + let picNonLazyIbtEntry = (* endbr32; jmp got; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy + OneByte 0xffuy; OneByte 0xa3uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] + + let nonPicNonLazyEntry = (* jmp indirect addr; nop *) + [| OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + + let nonPicNonLazyIbtEntry = (* endbr32; jmp got; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy + OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] + + let findX86PLTType (plt: ByteSpan) = + if BytePattern.matchSpan picLazyZeroEntry plt then + let isIBT = BytePattern.matchSpan picLazyIbtEntry (plt.Slice 16) + let gotoff = if isIBT then 6UL else 2UL + newPLT PIC LazyBinding isIBT 16UL gotoff 0UL + elif BytePattern.matchSpan nonPicZeroEntry plt then + let isIBT = BytePattern.matchSpan nonPicIbtEntry (plt.Slice 16) + let gotoff = if isIBT then 6UL else 2UL + newPLT NonPIC LazyBinding isIBT 16UL gotoff 0UL + elif BytePattern.matchSpan picNonLazyEntry plt then + newPLT PIC EagerBinding false 8UL 2UL 0UL + elif BytePattern.matchSpan picNonLazyIbtEntry plt then + newPLT PIC EagerBinding true 16UL 6UL 0UL + elif BytePattern.matchSpan nonPicNonLazyEntry plt then + newPLT NonPIC EagerBinding false 8UL 2UL 0UL + elif BytePattern.matchSpan nonPicNonLazyIbtEntry plt then + newPLT NonPIC EagerBinding true 16UL 6UL 0UL + else UnknownPLT + + member private __.ComputeRelocAddr (codeKind, baseAddr, relocV) = + match codeKind with + | PIC -> baseAddr + relocV + | NonPIC -> relocV + | DontCare -> Utils.impossible () + + override __.ParseEntry (addr, _, sec, desc, reader, span) = + let baseAddr = Option.get gotAddrOpt + let addrDiff = int (addr - sec.SecAddr) + let o = addrDiff + int desc.RelocOffset + let relocV = reader.ReadInt32 (span, o) |> uint64 + let relocAddr = __.ComputeRelocAddr (desc.CodeKind, baseAddr, relocV) + { EntryRelocAddr = relocAddr; NextEntryAddr = addr + desc.EntrySize } + + override __.ParseSection (toolBox, sec, map) = + let bytes = toolBox.Bytes + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + match findX86PLTType span with + | PLT desc -> + (* This section is an IBT PLT section and it uses lazy binding. This + means we can safely ignore this section because the secondary PLT is + the actual jump table. *) + if desc.LinkMethod = LazyBinding && desc.HasSecondary then map + else + let sAddr, eAddr = sec.SecAddr, sec.SecAddr + sec.SecSize + let reader = toolBox.Reader + parseEntries __ sec span reader desc symbInfo relocInfo map eAddr sAddr + | UnknownPLT -> map + + override __.Parse toolBox = + let pltSections = findPLTSections shdrs + if Option.isSome gotAddrOpt then + parseSections __ toolBox ARMap.empty pltSections + else ARMap.empty + +/// Intel x86-64 PLT parser. +type X64PLTParser (shdrs, relocInfo, symbInfo) = + inherit PLTParser () + + let gotAddrOpt = tryFindGOTAddr shdrs + + let lazyZeroEntry = (* push [got+8]; jmp [got+16]; *) + [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte |] + + let lazyIbtZeroEntry = (* (Ind-Br-Tracking) push [got+8]; bnd jmp [got+16]; *) + [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte + AnyByte; AnyByte |] + + let lazyIbtEntry = (* endbr64; push imm; bnd jmp rel; *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfauy + OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte + OneByte 0xf2uy; OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte |] + + let nonLazyEntry = (* jmp [got+16]; *) + [| OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + + let eagerBndEntry = (* bnd jmp [got+n]] *) + [| OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte |] + + let eagerIbtEntry = (* endbr64; bnd jmp [got+n]] *) + [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfauy + OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; + AnyByte; AnyByte; AnyByte; AnyByte + AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] + + let findX64PLTType (plt: ByteSpan) = + if BytePattern.matchSpan lazyZeroEntry plt then + newPLT DontCare LazyBinding false 16UL 2UL 6UL + elif BytePattern.matchSpan lazyIbtZeroEntry plt then + let off, inssz = + if BytePattern.matchSpan lazyIbtEntry (plt.Slice 16) then 7UL, 11UL + else 3UL, 7UL (* bnd *) + newPLT DontCare LazyBinding true 16UL off inssz + elif BytePattern.matchSpan nonLazyEntry plt then + newPLT DontCare EagerBinding false 8UL 2UL 6UL + elif BytePattern.matchSpan eagerBndEntry plt then + newPLT DontCare EagerBinding true 16UL 3UL 7UL + elif BytePattern.matchSpan eagerIbtEntry plt then + newPLT DontCare EagerBinding true 16UL 7UL 11UL + else UnknownPLT + + override __.ParseEntry (addr, _, sec, desc, reader, span) = + let addrDiff = int (addr - sec.SecAddr) + let o = addrDiff + int desc.RelocOffset + let displ = reader.ReadInt32 (span, o) |> uint64 + { EntryRelocAddr = addr + desc.ExtraOffset + displ + NextEntryAddr = addr + desc.EntrySize } + + override __.ParseSection (toolBox, sec, map) = + let bytes = toolBox.Bytes + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + match findX64PLTType span with + | PLT desc -> + (* This section is an IBT PLT section and it uses lazy binding. This + means we can safely ignore this section because the secondary PLT is + the actual jump table. *) + if desc.LinkMethod = LazyBinding && desc.HasSecondary then map + else + let sAddr, eAddr = sec.SecAddr, sec.SecAddr + sec.SecSize + let reader = toolBox.Reader + parseEntries __ sec span reader desc symbInfo relocInfo map eAddr sAddr + | UnknownPLT -> map + + override __.Parse toolBox = + let pltSections = findPLTSections shdrs + if Option.isSome gotAddrOpt then + parseSections __ toolBox ARMap.empty pltSections + else ARMap.empty + +/// Get the size of the header of PLT (PLT Zero) +let private computeARMPLTHeaderSize reader (span: ByteSpan) = + let v = (reader: IBinReader).ReadInt32 (span, 0) + if v = 0xe52de004 then (* str lr, [sp, #-4] *) + let v = reader.ReadInt32 (span, 16) + if v = 0xe28fc600 then (* add ip, pc, #0, 12 *) Some 16UL + else Some 20UL + elif v = 0xf8dfb500 then (* push {lr} *) Some 16UL + else None + +let private computeARMPLTEntrySize reader (span: ByteSpan) hdrSize delta = + if (reader: IBinReader).ReadInt32 (span, 0) = 0xf8dfb500 then + Ok 16UL (* THUMB-only *) + else + let offset = int hdrSize + delta + let size = if reader.ReadInt16 (span, offset) = 0x4778s then 4 else 0 + let offset = offset + size + let ins = reader.ReadInt32 (span, offset) &&& 0xffffff00 (* strip imm *) + if (hdrSize = 16UL && ins = 0xe28fc600) || ins = 0xe28fc200 then + Ok (uint64 (size + 16)) + elif ins = 0xe28fc600 then Ok (uint64 (size + 12)) + else Error ErrorCase.InvalidFormat + +/// ARMv7 PLT parser. +type ARMv7PLTParser (shdrs, relocInfo, symbInfo) = + inherit PLTParser () + + let baseAddrOpt = tryFindFirstEntryAddrWithRelPLT relocInfo shdrs + + let findARMv7PLTType (span: ByteSpan) reader sec = + match computeARMPLTHeaderSize reader span with + | Some headerSize -> + let startAddr = sec.SecAddr + headerSize + if reader.ReadInt32 (span, 0) = 0xf8dfb500 then + (* push {lr} *) + newPLT DontCare AnyBinding false 16UL 0UL startAddr + else + match computeARMPLTEntrySize reader span headerSize 0 with + | Ok sz -> newPLT DontCare AnyBinding false sz 0UL startAddr + | Error _ -> UnknownPLT + | None -> UnknownPLT + + override __.ParseEntry (addr, idx, _sec, desc, reader, span) = + let addrDiff = int (addr - desc.ExtraOffset) + let hdrSize = computeARMPLTHeaderSize reader span |> Option.get + let baseAddr = Option.get baseAddrOpt + match computeARMPLTEntrySize reader span hdrSize addrDiff with + | Ok entSize -> + { EntryRelocAddr = baseAddr + uint64 (idx * 4) + NextEntryAddr = addr + uint64 entSize } + | Error _ -> (* Just ignore this entry using the default entry size 16. *) + { EntryRelocAddr = 0UL; NextEntryAddr = addr + 16UL } + + override __.ParseSection (toolBox, sec, map) = + let bytes = toolBox.Bytes + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + match findARMv7PLTType span toolBox.Reader sec with + | PLT desc -> + let sAddr, eAddr = desc.ExtraOffset, sec.SecAddr + sec.SecSize + let reader = toolBox.Reader + parseEntries __ sec span reader desc symbInfo relocInfo map eAddr sAddr + | UnknownPLT -> map + + override __.Parse toolBox = + let pltSections = findPLTSections shdrs + if Option.isSome baseAddrOpt then + parseSections __ toolBox ARMap.empty pltSections + else ARMap.empty + +/// AARCH64 PLT parser. +type AARCH64PLTParser (shdrs, relocInfo, symbInfo) = + inherit PLTParser () + + let baseAddrOpt = tryFindFirstEntryAddrWithRelocation relocInfo + + override __.ParseEntry (addr, idx, _sec, _desc, _rdr, _span) = + let baseAddr = Option.get baseAddrOpt + { EntryRelocAddr = baseAddr + uint64 (idx * 8) + NextEntryAddr = addr + 16UL } + + override __.ParseSection (toolBox, sec, map) = + let startAddr = sec.SecAddr + 32UL + let desc = newDesc DontCare AnyBinding false 16UL 0UL startAddr + let sAddr, eAddr = desc.ExtraOffset, sec.SecAddr + sec.SecSize + let bytes, reader = toolBox.Bytes, toolBox.Reader + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + parseEntries __ sec span reader desc symbInfo relocInfo map eAddr sAddr + + override __.Parse toolBox = + let pltSections = findPLTSections shdrs + if Option.isSome baseAddrOpt then + parseSections __ toolBox ARMap.empty pltSections + else ARMap.empty + +let private readMicroMIPSOpcode (span: ByteSpan) (reader: IBinReader) offset = + let v1 = reader.ReadUInt16 (span, offset) |> uint32 + let v2 = reader.ReadUInt16 (span, offset + 2) |> uint32 + int (v1 <<< 16 ||| v2) + +let private computeMIPSPLTHeaderSize span reader = + let opcode = readMicroMIPSOpcode span reader 12 + if opcode = 0x3302fffe then 24UL + else 32UL + +let rec private parseMIPSStubEntries armap offset maxOffset tbl reader span = + if offset >= maxOffset then armap + else + let fst = (reader: IBinReader).ReadInt32 (span = span, offset=offset) + let snd = reader.ReadInt32 (span, offset=offset + 4) + let thr = reader.ReadInt32 (span, offset=offset + 8) + if (fst = 0x8f998010 (* lw t9, -32752(gp) *) + || fst = 0xdf998010 (* ld t9, -32752(gp) *)) + && snd = 0x03e07825 (* move t7, ra *) + && thr = 0x0320f809 (* jalr t9 *) + then + let insBytes = reader.ReadUInt32 (span, offset + 12) + (* FIXME: we could just get the index from .dynamic DT_MIPS_GOTSYM *) + let index = int (insBytes &&& 0xffffu) + let symbol = (tbl: ELFSymbol[])[index] + let entry = + { FuncName = symbol.SymName + LibraryName = Symbol.versionToLibName symbol.VerInfo + TrampolineAddress = symbol.Addr + TableAddress = 0UL } + let ar = AddrRange (symbol.Addr, symbol.Addr + 15UL) + let armap = ARMap.add ar entry armap + parseMIPSStubEntries armap (offset + 16) maxOffset tbl reader span + else armap + +/// MIPS PLT parser. +type MIPSPLTParser (hdr, shdrs, relocInfo, symbInfo) = + inherit PLTParser () + + let isMIPSGOTSym t = t.DTag = DynamicTag.DT_MIPS_GOTSYM + + member __.ParseMIPSStubs toolBox = + match Array.tryFind (fun s -> s.SecName = SecMIPSStubs) shdrs with + | Some sec -> + let bytes, reader = toolBox.Bytes, toolBox.Reader + let entries = DynamicSection.readEntries toolBox shdrs + let offset = 0 + let maxOffset = int sec.SecSize + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + match Array.tryFind isMIPSGOTSym entries with + | Some tag -> + let n = Symbol.getDynamicSymbolSectionNumbers shdrs|> Array.head + let tbl = symbInfo.SecNumToSymbTbls[n] + assert (tbl.Length > int tag.DVal) + parseMIPSStubEntries ARMap.empty offset maxOffset tbl reader span + | None -> ARMap.empty + | None -> ARMap.empty + + override __.ParseEntry (addr, _idx, sec, _desc, reader, span) = + let offset = int (addr - sec.SecAddr) + let opcode = readMicroMIPSOpcode span reader (offset + 4) + match opcode with + | 0x651aeb00 -> (* MIPS16 *) + let entryAddr = reader.ReadUInt32 (span, offset + 12) |> uint64 + { EntryRelocAddr = entryAddr; NextEntryAddr = addr + 16UL } + | 0xff220000 -> (* microMIPS no 32 *) + let hi = uint32 (reader.ReadUInt16 (span, offset)) &&& 0x7fu + let lo = reader.ReadUInt16 (span, offset + 2) |> uint32 + let entryAddr = ((hi ^^^ 0x40u - 0x40u) <<< 18) + (lo <<< 2) + { EntryRelocAddr = uint64 entryAddr; NextEntryAddr = addr + 12UL } + | opcode when opcode &&& 0xffff0000 = 0xff2f0000 -> (* microMIPS 32 *) + let hi = reader.ReadUInt16 (span, offset + 2) |> uint32 + let lo = reader.ReadUInt16 (span, offset + 6) |> uint32 + let entryAddr = + (((hi ^^^ 0x8000u) - 0x8000u) <<< 16) + ((lo ^^^ 0x8000u) - 0x8000u) + { EntryRelocAddr = uint64 entryAddr; NextEntryAddr = addr + 16UL } + | _ -> (* Regular cases. *) + let hi = reader.ReadUInt16 (span, offset) |> uint64 + let lo = reader.ReadInt16 (span, offset + 4) |> uint64 + let entryAddr = (hi <<< 16) + lo + { EntryRelocAddr = uint64 entryAddr; NextEntryAddr = addr + 16UL } + + override __.ParseSection (toolBox, sec, map) = + let bytes, reader = toolBox.Bytes, toolBox.Reader + let span = ReadOnlySpan (bytes, int sec.SecOffset, int sec.SecSize) + let headerSize = computeMIPSPLTHeaderSize span reader + let startAddr = sec.SecAddr + headerSize + let desc = newDesc DontCare AnyBinding false 16UL 0UL startAddr + let sAddr, eAddr = desc.ExtraOffset, sec.SecAddr + sec.SecSize + parseEntries __ sec span reader desc symbInfo relocInfo map eAddr sAddr + + override __.Parse toolBox = + let pltSections = findPLTSections shdrs + if List.isEmpty pltSections then __.ParseMIPSStubs toolBox + else parseSections __ toolBox ARMap.empty pltSections + +/// Classic PPC that uses the .plt section. Modern PPC binaries use the "glink". +type PPCClassicPLTParser (shdrs, relocInfo, symbInfo, pltHdrSize, relType) = + inherit GeneralPLTParser (shdrs, relocInfo, symbInfo, pltHdrSize, relType) + + override __.ParseEntry (_addr, idx, _sec, _desc, _rdr, _span) = + let nextIdx = idx + 1 + let nextEntryAddr = + if __.Relocs.Length > nextIdx then __.Relocs[nextIdx].RelOffset + else UInt64.MaxValue (* No more entries to parse. *) + { EntryRelocAddr = __.Relocs[idx].RelOffset + NextEntryAddr = nextEntryAddr } + +/// PPC PLT parser. +type PPCPLTParser (hdr, shdrs, relocInfo, symbInfo) = + inherit PLTParser () + + override __.ParseEntry (_, _, _, _, _, _) = Utils.impossible () + + override __.ParseSection (toolBox, sec, map) = + let rtyp = RelocationPPC32 RelocationPPC32.R_PPC_JMP_SLOT + let p = PPCClassicPLTParser (shdrs, relocInfo, symbInfo, 0x48UL, rtyp) + p.ParseSection (toolBox, sec, map) + + member private __.ComputeGLinkAddrWithGOT toolBox = + let tags = DynamicSection.readEntries toolBox shdrs + match Array.tryFind (fun t -> t.DTag = DynamicTag.DT_PPC_GOT) tags with + | Some tag -> + let gotAddr = tag.DVal + match Array.tryFind (fun s -> s.SecName = SecGOT) shdrs with + | Some gotSection -> + let bytes, reader = toolBox.Bytes, toolBox.Reader + let gotElemOneOffset = (* The second elem of GOT, i.e., GOT[1] *) + gotAddr - gotSection.SecAddr + 4UL + gotSection.SecOffset + let gotElemOne = reader.ReadUInt32 (bytes, int gotElemOneOffset) + if gotElemOne = 0u then None else Some (uint64 gotElemOne) + | None -> None + | None -> None + + member private __.ComputeGLinkAddrWithPLT toolBox = + match Array.tryFind (fun s -> s.SecName = SecPLT) shdrs with + | Some sec -> (* Get the glink address from the first entry of PLT *) + let bytes, reader = toolBox.Bytes, toolBox.Reader + let glinkVMA = reader.ReadUInt32 (bytes, int sec.SecOffset) + if glinkVMA = 0u then None else Some (uint64 glinkVMA) + | None -> None + + member private __.ComputePLTEntryDelta (span, reader, stubOff, delta) = + let lastPLTEntryOffset = stubOff - delta + let ins1 = (reader: IBinReader).ReadUInt32 (span=span, + offset=lastPLTEntryOffset) + let ins2 = reader.ReadUInt32 (span, lastPLTEntryOffset + 4) + let ins3 = reader.ReadUInt32 (span, lastPLTEntryOffset + 8) + let ins4 = reader.ReadUInt32 (span, lastPLTEntryOffset + 12) + let isNonPICGlinkStub = + ((ins1 &&& 0xffff0000u) = 0x3d600000u) (* lis r11, ... *) + && ((ins2 &&& 0xffff0000u) = 0x816b0000u) (* lwz r11, ... *) + && (ins3 = 0x7d6903a6u) (* mtctr r11 *) + && (ins4 = 0x4e800420u) (* bctr *) + if isNonPICGlinkStub then Some delta + elif delta < 32 then + __.ComputePLTEntryDelta (span, reader, stubOff, delta + 8) + else None + + member private __.ReadEntryLoop relocs delta idx map addr = + if idx >= 0 then + let reloc = (relocs: RelocationEntry[])[idx] + let ar = AddrRange (addr, addr + delta - 1UL) + let entry = makePLTEntry symbInfo addr addr reloc + let map = ARMap.add ar entry map + __.ReadEntryLoop relocs delta (idx - 1) map (addr - delta) + else map + + /// Read from the last PLT entry to the first. This is possible because we + /// have computed the delta between the last entry to the glink stub. + member private __.ReadPLTEntriesBackwards (glinkAddr, delta, count) = + let rtype = RelocationPPC32 RelocationPPC32.R_PPC_JMP_SLOT + let relocs = + relocInfo.RelocByAddr.Values + |> Seq.filter (fun r -> r.RelType = rtype) + |> Seq.toArray + assert (relocs.Length = count) + let addr = glinkAddr - delta + __.ReadEntryLoop relocs (uint64 delta) (count - 1) ARMap.empty addr + + member private __.ReadPLTWithGLink (toolBox, glinkAddr) = + let relaPltSecOpt = Array.tryFind (fun s -> s.SecName = SecRelaPLT) shdrs + let glinkSecOpt = + Array.tryFind (fun s -> s.SecAddr <= glinkAddr + && glinkAddr < s.SecAddr + s.SecSize) shdrs + match glinkSecOpt, relaPltSecOpt with + | Some glinkSec, Some relaSec -> + let bytes, reader = toolBox.Bytes, toolBox.Reader + let glinkSecAddr = glinkSec.SecAddr + let glinkOffset, glinkSize = int glinkSec.SecOffset, int glinkSec.SecSize + let glinkSec = ReadOnlySpan (bytes, glinkOffset, glinkSize) + let stubOff = glinkAddr - glinkSecAddr |> int + let count = relaSec.SecSize / 12UL |> int (* Each entry has 12 bytes. *) + match __.ComputePLTEntryDelta (glinkSec, reader, stubOff, 16) with + | Some delta -> + __.ReadPLTEntriesBackwards (glinkAddr, uint64 delta, count) + | None -> ARMap.empty + | _ -> ARMap.empty + + member private __.ParseWithGLink toolBox = + match __.ComputeGLinkAddrWithGOT toolBox with + | Some glinkAddr -> __.ReadPLTWithGLink (toolBox, glinkAddr) + | None -> + match __.ComputeGLinkAddrWithPLT toolBox with + | Some glinkAddr -> __.ReadPLTWithGLink (toolBox, glinkAddr) + | None -> ARMap.empty + + override __.Parse toolBox = + match Array.tryFind (fun s -> s.SecName = SecPLT) shdrs with + | Some sec when sec.SecFlags.HasFlag SectionFlag.SHF_EXECINSTR -> + (* The given binary uses the classic format. *) + parseSections __ toolBox ARMap.empty [ sec ] + | _ -> __.ParseWithGLink toolBox + +/// This will simply return an empty map. +type NullPLTParser () = + inherit PLTParser () + override __.ParseEntry (_, _, _, _, _, _) = Utils.impossible () + override __.ParseSection (_, _, _) = Utils.impossible () + override __.Parse _ = ARMap.empty + +let initPLTParser hdr shdrs relocInfo symbInfo = + match hdr.MachineType with + | Architecture.IntelX86 -> + X86PLTParser (shdrs, relocInfo, symbInfo) :> PLTParser + | Architecture.IntelX64 -> + X64PLTParser (shdrs, relocInfo, symbInfo) :> PLTParser + | Architecture.ARMv7 | Architecture.AARCH32 -> + ARMv7PLTParser (shdrs, relocInfo, symbInfo) :> PLTParser + | Architecture.AARCH64 -> + AARCH64PLTParser (shdrs, relocInfo, symbInfo) :> PLTParser + | Architecture.MIPS32 | Architecture.MIPS64 -> + MIPSPLTParser (hdr, shdrs, relocInfo, symbInfo) :> PLTParser + | Architecture.PPC32 -> + PPCPLTParser (hdr, shdrs, relocInfo, symbInfo) :> PLTParser + | Architecture.RISCV64 -> + let rtype = RelocationRISCV RelocationRISCV.R_RISCV_JUMP_SLOT + GeneralPLTParser (shdrs, relocInfo, symbInfo, 32UL, rtype) :> PLTParser + | Architecture.SH4 -> + let rtype = RelocationSH4 RelocationSH4.R_SH_JMP_SLOT + GeneralPLTParser (shdrs, relocInfo, symbInfo, 28UL, rtype) :> PLTParser + | _ -> NullPLTParser () :> PLTParser + +let parse toolBox shdrs symbInfo relocInfo = + let parser = initPLTParser toolBox.Header shdrs relocInfo symbInfo + parser.Parse toolBox diff --git a/src/FrontEnd/BinFile/ELF/ELFProgramHeader.fs b/src/FrontEnd/BinFile/ELF/ELFProgramHeader.fs new file mode 100644 index 00000000..4c3aff14 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFProgramHeader.fs @@ -0,0 +1,151 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +/// This member tells what kind of segment this array element describes or +/// how to interpret the array element's information. A segment is also known as +/// a 'program header'. +type ProgramHeaderType = + /// This program header is not used. + | PT_NULL = 0x00u + /// This is a loadable segment. + | PT_LOAD = 0x01u + /// This segment contains dynamic linking information. + | PT_DYNAMIC = 0x02u + /// This segment contains the location and size of a null-terminated path name + /// to invoke an interpreter. This segment type is meaningful only for + /// executable files, but not for shared objects. This segment may not occur + /// more than once in a file. If it is present, it must precede any loadable + /// segment entry. + | PT_INTERP = 0x03u + /// This segment contains the location and size of auxiliary information. + | PT_NOTE = 0x04u + /// This segment type is reserved but has unspecified semantics. + | PT_SHLIB = 0x05u + /// This segment specifies the location and size of the program header table + /// itself, It may occur only if the program header table is part of the + /// memory image of the program. If it is present, it must precede any + /// loadable segment entry. + | PT_PHDR = 0x06u + /// This segment contains the Thread-Local Storage template. + | PT_TLS = 0x07u + /// The lower bound of OS-specific program header type. + | PT_LOOS = 0x60000000u + /// The upper bound of OS-specific program header type. + | PT_HIOS = 0x6fffffffu + /// This segment specifies the location and size of the exception handling + /// information as defined by the .eh_frame_hdr section. + | PT_GNU_EH_FRAME = 0x6474e550u + /// This segment specifies the permissions on the segment containing the stack + /// and is used to indicate weather the stack should be executable. The + /// absence of this header indicates that the stack will be executable. + | PT_GNU_STACK = 0x6474e551u + /// This segment specifies the location and size of a segment which may be + /// made read-only after relocations have been processed. + | PT_GNU_RELRO = 0x6474e552u + /// This segment contains PAX flags. + | PT_PAX_FLAGS = 0x65041580u + /// The lower bound of processor-specific program header type. + | PT_LOPROC = 0x70000000u + /// The exception unwind table. + | PT_ARM_EXIDX = 0x70000001u + /// MIPS ABI flags. + | PT_MIPS_ABIFLAGS = 0x70000003u + /// The upper bound of processor-specific program header type. + | PT_HIPROC = 0x7fffffffu + +/// An executable or shared object file's program header table is an array of +/// structures, each of which describes a segment or the other information a +/// system needs to prepare for execution. An object file segment contains one +/// or more sections. Program headers are meaningful only for executable and +/// shared object files. A file specifies its own program header size with +/// the ELF header's members. +type ProgramHeader = { + /// Program header type. + PHType: ProgramHeaderType + /// Flags relevant to the segment. + PHFlags: Permission + /// An offset from the beginning of the file at which the first byte of the + /// segment resides in memory. + PHOffset: uint64 + /// The virtual address at which the first byte of the segment resides in + /// memory. + PHAddr: Addr + /// The physical address of the segment. This is reserved for systems using + /// physical addresses. + PHPhyAddr: Addr + /// The number of bytes in the file image of the segment. + PHFileSize: uint64 + /// The number of bytes in the memory image of the segment. This can be + /// greater than PHFileSize as some sections (w/ SHTNoBits type) occupy + /// nothing in the binary file, but can be mapped in the segment at runtime. + PHMemSize: uint64 + /// The value to which the segments are aligned in memory and in the file. + PHAlignment: uint64 +} + +module ProgramHeader = + let peekPHdrFlags (span: ByteSpan) (reader: IBinReader) cls = + reader.ReadInt32 (span, pickNum cls 24 4) + |> LanguagePrimitives.EnumOfValue + + let parseProgHeader toolBox (span: ByteSpan) = + let reader, cls = toolBox.Reader, toolBox.Header.Class + let phType = reader.ReadUInt32 (span, 0) + { PHType = LanguagePrimitives.EnumOfValue phType + PHFlags = peekPHdrFlags span reader cls + PHOffset = readNative span reader cls 4 8 + PHAddr = readNative span reader cls 8 16 + toolBox.BaseAddress + PHPhyAddr = readNative span reader cls 12 24 + PHFileSize = readNative span reader cls 16 32 + PHMemSize = readNative span reader cls 20 40 + PHAlignment = readNative span reader cls 28 48 } + + /// Parse program headers and returns them as an array. + let parse ({ Bytes = bytes; Header = hdr } as toolBox) = + let entrySize = pickNum hdr.Class 32 56 + let numEntries = int hdr.PHdrNum + let progHeaders = Array.zeroCreate numEntries + for i = 0 to numEntries - 1 do + let offset = int hdr.PHdrTblOffset + i * entrySize + let span = ReadOnlySpan (bytes, offset, entrySize) + progHeaders[i] <- parseProgHeader toolBox span + progHeaders + + let getLoadableProgHeaders (progHeaders: ProgramHeader[]) = + progHeaders + |> Array.filter (fun ph -> ph.PHType = ProgramHeaderType.PT_LOAD) + + let toSegment phdr = + { Address = phdr.PHAddr + Offset = uint32 phdr.PHOffset + Size = uint32 phdr.PHMemSize + SizeInFile = uint32 phdr.PHFileSize + Permission = phdr.PHFlags } diff --git a/src/FrontEnd/BinFile/ELF/ELFRelocationInfo.fs b/src/FrontEnd/BinFile/ELF/ELFRelocationInfo.fs new file mode 100644 index 00000000..31e89fe1 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFRelocationInfo.fs @@ -0,0 +1,729 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open System.Collections.Generic +open B2R2 +open B2R2.FrontEnd.BinFile.FileHelper + +/// Relocation type for x86. +type RelocationX86 = + /// No relocation. + | R_386_NONE = 0UL + /// Direct 32-bit (S + A). + | R_386_32 = 1UL + /// PC-relative 32-bit (S + A - P). + | R_386_PC32 = 2UL + /// 32-bit GOT entry (G + A). + | R_386_GOT32 = 3UL + /// 32-bit PLT entry (L + A - P). + | R_386_PLT32 = 4UL + /// Copy symbol at runtime. + | R_386_COPY = 5UL + /// Create GOT entry (S). + | R_386_GLOB_DATA = 6UL + /// Create PLT entry (S). + | R_386_JUMP_SLOT = 7UL + /// Adjust by program base (S + A). + | R_386_RELATIVE = 8UL + /// 32-bit offset to GOT (S + A - GOT). + | R_386_GOTOFF = 9UL + /// PC-relative offset to GOT (GOT + A - P). + | R_386_GOTPC = 10UL + /// (L + A). + | R_386_32PLT = 11UL + | R_386_TLS_TPOFF = 14UL + | R_386_TLS_IE = 15UL + | R_386_TLS_GOTIE = 16UL + | R_386_TLS_LE = 17UL + | R_386_TLS_GD = 18UL + | R_386_TLS_LDM = 19UL + /// (S + A). + | R_386_16 = 20UL + /// (S + A - P). + | R_386_PC16 = 21UL + /// (S + A). + | R_386_8 = 22UL + /// (S + A - P). + | R_386_PC8 = 23UL + | R_386_TLS_GD_32 = 24UL + | R_386_TLS_GD_PUSH = 25UL + | R_386_TLS_GD_CALL = 26UL + | R_386_TLS_GD_POP = 27UL + | R_386_TLS_LDM_32 = 28UL + | R_386_TLS_LDM_PUSH = 29UL + | R_386_TLS_LDM_CALL = 30UL + | R_386_TLS_LDM_POP = 31UL + | R_386_TLS_LDO_32 = 32UL + | R_386_TLS_IE_32 = 33UL + | R_386_TLS_LE_32 = 34UL + | R_386_TLS_DTPMOD32 = 35UL + | R_386_TLS_DTPOFF32 = 36UL + | R_386_TLS_TPOFF32 = 37UL + /// (Z + A). + | R_386_SIZE32 = 38UL + /// x86 more TLS relocations + | R_386_TLS_GOTDESC = 39UL + | R_386_TLS_DESC_CALL = 40UL + | R_386_TLS_DESC = 41UL + /// Indirect (B + A). + | R_386_IRELATIVE = 42UL + /// (G + A - GOT/G + A) + | R_386_GOT32X = 43UL + /// (A + (S >> 4)). + | R_386_SEG16 = 44UL + /// (A - S). + | R_386_SUB16 = 45UL + /// (A - S). + | R_386_SUB32 = 46UL + +/// Relocation type for x86-64. +type RelocationX64 = + /// No relocation. + | R_X86_64_None = 0UL + /// Direct 64-bit. + | R_X86_64_64 = 1UL + /// PC-relative 32-bit. + | R_X86_64_PC32 = 2UL + /// 32-bit GOT entry. + | R_X86_64_GOT32 = 3UL + /// 32-bit PLT entry. + | R_X86_64_PLT32 = 4UL + /// Copy symbol at runtime. + | R_X86_64_COPY = 5UL + /// Create GOT entry. + | R_X86_64_GLOB_DATA = 6UL + /// Create PLT entry. + | R_X86_64_JUMP_SLOT = 7UL + /// Adjust by program base. + | R_X86_64_RELATIVE = 8UL + /// 32-bit signed PC-relative offset to GOT. + | R_X86_64_GOTPCREL = 9UL + /// Direct 32-bit zero extended. + | R_X86_64_32 = 10UL + /// Direct 32-bit sign extended. + | R_X86_64_32S = 11UL + /// Direct 16-bit zero extended. + | R_X86_64_16 = 12UL + /// 16-bit sign extended PC relative. + | R_X86_64_PC16 = 13UL + /// Direct 8-bit sign extended. + | R_X86_64_8 = 14UL + /// 8-bit sign extended PC relative. + | R_X86_64_PC8 = 15UL + /// PC-relative 64 bit. + | R_X86_64_PC64 = 24UL + /// 64-bit offset to GOT. + | R_X86_64_GOTOFF64 = 25UL + /// 32-bit signed PC-relative offset to GOT. + | R_X86_64_GOTPC32 = 26UL + /// 64-bit GOT entry offset. + | R_X86_64_GOT64 = 27UL + /// 64-bit PC-relative offset to GOT entry. + | R_X86_64_GOTPCREL64 = 28UL + /// 64-bit PC relative offset to GOT. + | R_X86_64_GOTPC64 = 29UL + /// 64-bit GOT entry offset requiring PLT. + | R_X86_64_GOTPLT64 = 30UL + /// 64-bit GOT relative offset to PLT entry. + | R_X86_64_PLTOFF64 = 31UL + /// Size of symbol plus 32-bit addend. + | R_X86_64_SIZE32 = 32UL + /// Size of symbol plus 64-bit addend. + | R_X86_64_SIZE64 = 33UL + /// Adjust indirectly by program base. + | R_X86_64_IRELATIVE = 37UL + +/// Relocation type for ARMv7. +type RelocationARMv7 = + /// No reloc. + | R_ARM_None = 0UL + /// PC-relative 26-bit branch. + | R_ARM_PC24 = 1UL + /// Direct 32 bit. + | R_ARM_ABS32 = 2UL + /// PC-relative 32 bit. + | R_ARM_REL32 = 3UL + /// PC-relative LDR. + | R_ARM_LDR_PC_G0 = 4UL + /// Direct 16 bit. + | R_ARM_ABS16 = 5UL + /// Direct 12 bit. + | R_ARM_ABS12 = 6UL + /// Direct 8 bit. + | R_ARM_ABS8 = 8UL + /// Copy symbol at runtime. + | R_ARM_COPY = 20UL + /// Create GOT entry. + | R_ARM_GLOB_DATA = 21UL + /// Create PLT entry. + | R_ARM_JUMP_SLOT = 22UL + /// Adjust by program base. + | R_ARM_RELATIVE = 23UL + /// 32-bit offset to GOT. + | R_ARM_GOTOFF32 = 24UL + /// 32-bit PC-relative offset to GOT. + | R_ARM_BASE_PREL = 25UL + /// 32-bit GOT entry. + | R_ARM_GOT_BREL = 26UL + /// 32-bit PLT address. + | R_ARM_PLT32 = 27UL + +/// Relocation type for ARMv8. +type RelocationARMv8 = + /// No reloc. + | R_AARCH64_NONE = 0UL + /// Direct 64 bit. + | R_AARCH64_ABS64 = 257UL + /// Direct 32 bit. + | R_AARCH64_ABS32 = 258UL + /// Direct 16 bit. + | R_AARCH64_ABS16 = 259UL + /// PC-relative 64 bit. + | R_AARCH64_PREL64 = 260UL + /// PC-relative 32 bit. + | R_AARCH64_PREL32 = 261UL + /// PC-relative 16 bit. + | R_AARCH64_PREL16 = 262UL + /// GOT-relative 64 bit. + | R_AARCH64_GOTREL64 = 307UL + /// GOT-relative 32 bit. + | R_AARCH64_GOTREL32 = 308UL + /// Copy symbol at runtime. + | R_AARCH64_COPY = 1024UL + /// Create GOT entry. + | R_AARCH64_GLOB_DATA = 1025UL + /// Create PLT entry. + | R_AARCH64_JUMP_SLOT = 1026UL + /// Delta(S) + A. + | R_AARCH64_RELATIVE = 1027UL + +/// Relocation type for MIPS. +type RelocationMIPS = + /// No reloc. + | R_MIPS_NONE = 0UL + /// Direct 16 bit. + | R_MIPS_16 = 1UL + /// Direct 32 bit. + | R_MIPS_32 = 2UL + /// PC-relative 32 bit. + | R_MIPS_REL32 = 3UL + /// Direct 26 bit shifted. + | R_MIPS_26 = 4UL + /// High 16 bit. + | R_MIPS_HI16 = 5UL + /// Low 16 bit. + | R_MIPS_LO16 = 6UL + /// GP-relative 16 bit. + | R_MIPS_GPREL16 = 7UL + /// 16-bit literal entry. + | R_MIPS_LITERAL = 8UL + /// 16-bit GOT entry. + | R_MIPS_GOT16 = 9UL + /// PC-relative 16 bit. + | R_MIPS_PC16 = 10UL + /// 16-bit GOT entry for function. + | R_MIPS_CALL16 = 11UL + /// GP-relative 32 bit. + | R_MIPS_GPREL32 = 12UL + /// 5-bit shift field. + | R_MIPS_SHIFT5 = 16UL + /// 6-bit shift field. + | R_MIPS_SHIFT6 = 17UL + /// direct 64 bit. + | R_MIPS_64 = 18UL + /// displacement in the GOT. + | R_MIPS_GOT_DISP = 19UL + /// displacement to page pointer in the GOT. + | R_MIPS_GOT_PAGE = 20UL + /// Offset from page pointer in the GOT. + | R_MIPS_GOT_OFST = 21UL + /// HIgh 16 bits of displacement in the GOT. + | R_MIPS_GOT_HI16 = 22UL + /// Low 16 bits of displacement in the GOT. + | R_MIPS_GOT_LO16 = 23UL + /// 64-bit subtraction. + | R_MIPS_SUB = 24UL + /// Insert the addend as an instruction. + | R_MIPS_INSERT_A = 25UL + /// Insert the addend as an instruction, and change all relocations to + /// refer to the old instruction at the address. + | R_MIPS_INSERT_B = 26UL + /// Delete a 32 bit instruction. + | R_MIPS_DELETE = 27UL + /// Get the higher value of a 64 bit addend. + | R_MIPS_HIGHER = 28UL + /// Get the highest value of a 64 bit addend. + | R_MIPS_HIGHEST = 29UL + /// High 16 bits of displacement in GOT. + | R_MIPS_CALL_HI16 = 30UL + /// Low 16 bits of displacement in GOT. + | R_MIPS_CALL_LO16 = 31UL + /// Section displacement, used by an associated event location section. + | R_MIPS_SCN_DISP = 32UL + /// PC-relative 16 bit. + | R_MIPS_REL16 = 33UL + /// Similiar to R_MIPS__REL32, but used for relocations in a GOT section. + | R_MIPS_RELGOT = 36UL + /// Protected jump conversion. + | R_MIPS_JALR = 37UL + /// Module number 32 bit. + | R_MIPS_TLS_DTPMOD32 = 38UL + /// Module-relative offset 32 bit. + | R_MIPS_TLS_DTPREL32 = 39UL + /// Module number 64 bit. + | R_MIPS_TLS_DTPMOD64 = 40UL + /// Module-relative offset 64 bit. + | R_MIPS_TLS_DTPREL64 = 41UL + /// 16 bit GOT offset for GD. + | R_MIPS_TLS_GD = 42UL + /// 16 bit GOT offset for LDM. + | R_MIPS_TLS_LDM = 43UL + /// Module-relative offset, high 16 bits. + | R_MIPS_TLS_DTPREL_HI16 = 44UL + /// Module-relative offset, low 16 bits. + | R_MIPS_TLS_DTPREL_LO16 = 45UL + /// 16 bit GOT offset for IE. + | R_MIPS_TLS_GOTPREL = 46UL + /// TP-relative offset, 32 bit. + | R_MIPS_TLS_TPREL32 = 47UL + /// TP-relative offset, 64 bit. + | R_MIPS_TLS_TPREL64 = 48UL + /// TP-relative offset, high 16 bits. + | R_MIPS_TLS_TPREL_HI16 = 49UL + /// TP-relative offset, low 16 bits. + | R_MIPS_TLS_TPREL_LO16 = 50UL + /// 32 bit relocation with no addend. + | R_MIPS_GLOB_DAT = 51UL + /// Copy symbol at runtime. + | R_MIPS_COPY = 126UL + /// Jump slot. + | R_MIPS_JUMP_SLOT = 127UL + /// 32-bit PC-relative. + | R_MIPS_PC32 = 248UL + +/// Relocation type for SH4. +type RelocationSH4 = + | R_SH_NONE = 0UL + | R_SH_DIR32 = 1UL + | R_SH_REL32 = 2UL + | R_SH_DIR8WPN = 3UL + | R_SH_IND12W = 4UL + | R_SH_DIR8WPL = 5UL + | R_SH_DIR8WPZ = 6UL + | R_SH_DIR8BP = 7UL + | R_SH_DIR8W = 8UL + | R_SH_DIR8L = 9UL + | R_SH_LOOP_START = 10UL + | R_SH_LOOP_END = 11UL + | R_SH_GNU_VTINHERIT = 22UL + | R_SH_GNU_VTENTRY = 23UL + | R_SH_SWITCH8 = 24UL + | R_SH_SWITCH16 = 25UL + | R_SH_SWITCH32 = 26UL + | R_SH_USES = 27UL + | R_SH_COUNT = 28UL + | R_SH_ALIGN = 29UL + | R_SH_CODE = 30UL + | R_SH_DATA = 31UL + | R_SH_LABEL = 32UL + | R_SH_DIR16 = 33UL + | R_SH_DIR8 = 34UL + | R_SH_DIR8UL = 35UL + | R_SH_DIR8UW = 36UL + | R_SH_DIR8U = 37UL + | R_SH_DIR8SW = 38UL + | R_SH_DIR8S = 39UL + | R_SH_DIR4UL = 40UL + | R_SH_DIR4UW = 41UL + | R_SH_DIR4U = 42UL + | R_SH_PSHA = 43UL + | R_SH_PSHL = 44UL + | R_SH_DIR5U = 45UL + | R_SH_DIR6U = 46UL + | R_SH_DIR6S = 47UL + | R_SH_DIR10S = 48UL + | R_SH_DIR10SW = 49UL + | R_SH_DIR10SL = 50UL + | R_SH_DIR10SQ = 51UL + | R_SH_DIR16S = 53UL + | R_SH_TLS_GD_32 = 144UL + | R_SH_TLS_LD_32 = 145UL + | R_SH_TLS_LDO_32 = 146UL + | R_SH_TLS_IE_32 = 147UL + | R_SH_TLS_LE_32 = 148UL + | R_SH_TLS_DTPMOD32 = 149UL + | R_SH_TLS_DTPOFF32 = 150UL + | R_SH_TLS_TPOFF32 = 151UL + | R_SH_GOT32 = 160UL + | R_SH_PLT32 = 161UL + | R_SH_COPY = 162UL + | R_SH_GLOB_DAT = 163UL + | R_SH_JMP_SLOT = 164UL + | R_SH_RELATIVE = 165UL + | R_SH_GOTOFF = 166UL + | R_SH_GOTPC = 167UL + | R_SH_GOTPLT32 = 168UL + | R_SH_GOT_LOW16 = 169UL + | R_SH_GOT_MEDLOW16 = 170UL + | R_SH_GOT_MEDHI16 = 171UL + | R_SH_GOT_HI16 = 172UL + | R_SH_GOTPLT_LOW16 = 173UL + | R_SH_GOTPLT_MEDLOW16 = 174UL + | R_SH_GOTPLT_MEDHI16 = 175UL + | R_SH_GOTPLT_HI16 = 176UL + | R_SH_PLT_LOW16 = 177UL + | R_SH_PLT_MEDLOW16 = 178UL + | R_SH_PLT_MEDHI16 = 179UL + | R_SH_PLT_HI16 = 180UL + | R_SH_GOTOFF_LOW16 = 181UL + | R_SH_GOTOFF_MEDLOW16 = 182UL + | R_SH_GOTOFF_MEDHI16 = 183UL + | R_SH_GOTOFF_HI16 = 184UL + | R_SH_GOTPC_LOW16 = 185UL + | R_SH_GOTPC_MEDLOW16 = 186UL + | R_SH_GOTPC_MEDHI16 = 187UL + | R_SH_GOTPC_HI16 = 188UL + | R_SH_GOT10BY4 = 189UL + | R_SH_GOTPLT10BY4 = 190UL + | R_SH_GOT10BY8 = 191UL + | R_SH_GOTPLT10BY8 = 192UL + | R_SH_COPY64 = 193UL + | R_SH_GLOB_DAT64 = 194UL + | R_SH_JMP_SLOT64 = 195UL + | R_SH_RELATIVE64 = 196UL + | R_SH_GOT20 = 201UL + | R_SH_GOTOFF20 = 202UL + | R_SH_GOTFUNCDESC = 203UL + | R_SH_GOTFUNCDESC20 = 204UL + | R_SH_GOTOFFFUNCDESC = 205UL + | R_SH_GOTOFFFUNCDESC20 = 206UL + | R_SH_FUNCDESC = 207UL + | R_SH_FUNCDESC_VALUE = 208UL + | R_SH_SHMEDIA_CODE = 242UL + | R_SH_PT_16 = 243UL + | R_SH_IMMS16 = 244UL + | R_SH_IMMU16 = 245UL + | R_SH_IMM_LOW16 = 246UL + | R_SH_IMM_LOW16_PCREL = 247UL + | R_SH_IMM_MEDLOW16 = 248UL + | R_SH_IMM_MEDLOW16_PCREL = 249UL + | R_SH_IMM_MEDHI16 = 250UL + | R_SH_IMM_MEDHI16_PCREL = 251UL + | R_SH_IMM_HI16 = 252UL + | R_SH_IMM_HI16_PCREL = 253UL + | R_SH_64 = 254UL + | R_SH_64_PCREL = 255UL + +/// Relocation type for RISCV. +type RelocationRISCV = + | R_RISCV_NONE = 0UL + | R_RISCV_32 = 1UL + | R_RISCV_64 = 2UL + | R_RISCV_RELATIVE = 3UL + | R_RISCV_COPY = 4UL + | R_RISCV_JUMP_SLOT = 5UL + | R_RISCV_TLS_DTPMOD32 = 6UL + | R_RISCV_TLS_DTPMOD64 = 7UL + | R_RISCV_TLS_DTPREL32 = 8UL + | R_RISCV_TLS_DTPREL64 = 9UL + | R_RISCV_TLS_TPREL32 = 10UL + | R_RISCV_TLS_TPREL64 = 11UL + | R_RISCV_BRANCH = 16UL + | R_RISCV_JAL = 17UL + | R_RISCV_CALL = 18UL + | R_RISCV_CALL_PLT = 19UL + | R_RISCV_GOT_HI20 = 20UL + | R_RISCV_TLS_GOT_HI20 = 21UL + | R_RISCV_TLS_GD_HI20 = 22UL + | R_RISCV_PCREL_HI20 = 23UL + | R_RISCV_PCREL_LO12_I = 24UL + | R_RISCV_PCREL_LO12_S = 25UL + | R_RISCV_HI20 = 26UL + | R_RISCV_LO12_I = 27UL + | R_RISCV_LO12_S = 28UL + | R_RISCV_TPREL_HI20 = 29UL + | R_RISCV_TPREL_LO12_I = 30UL + | R_RISCV_TPREL_LO12_S = 31UL + | R_RISCV_TPREL_ADD = 32UL + | R_RISCV_ADD8 = 33UL + | R_RISCV_ADD16 = 34UL + | R_RISCV_ADD32 = 35UL + | R_RISCV_ADD64 = 36UL + | R_RISCV_SUB8 = 37UL + | R_RISCV_SUB16 = 38UL + | R_RISCV_SUB32 = 39UL + | R_RISCV_SUB64 = 40UL + | R_RISCV_GNU_VTINHERIT = 41UL + | R_RISCV_GNU_VTENTRY = 42UL + | R_RISCV_ALIGN = 43UL + | R_RISCV_RVC_BRANCH = 44UL + | R_RISCV_RVC_JUMP = 45UL + | R_RISCV_RVC_LUI = 46UL + | R_RISCV_GPREL_I = 47UL + | R_RISCV_GPREL_S = 48UL + | R_RISCV_TPREL_I = 49UL + | R_RISCV_TPREL_S = 50UL + | R_RISCV_RELAX = 51UL + | R_RISCV_SUB6 = 52UL + | R_RISCV_SET6 = 53UL + | R_RISCV_SET8 = 54UL + | R_RISCV_SET16 = 55UL + | R_RISCV_SET32 = 56UL + | R_RISCV_32_PCREL = 57UL + +/// Relocation type for PPC32. +type RelocationPPC32 = + | R_PPC_NONE = 0UL + | R_PPC_ADDR32 = 1UL + | R_PPC_ADDR24 = 2UL + | R_PPC_ADDR16 = 3UL + | R_PPC_ADDR16_LO = 4UL + | R_PPC_ADDR16_HI = 5UL + | R_PPC_ADDR16_HA = 6UL + | R_PPC_ADDR14 = 7UL + | R_PPC_ADDR14_BRTAKEN = 8UL + | R_PPC_ADDR14_BRNTAKEN = 9UL + | R_PPC_REL24 = 10UL + | R_PPC_REL14 = 11UL + | R_PPC_REL14_BRTAKEN = 12UL + | R_PPC_REL14_BRNTAKEN = 13UL + | R_PPC_GOT16 = 14UL + | R_PPC_GOT16_LO = 15UL + | R_PPC_GOT16_HI = 16UL + | R_PPC_GOT16_HA = 17UL + | R_PPC_PLTREL24 = 18UL + | R_PPC_COPY = 19UL + | R_PPC_GLOB_DAT = 20UL + | R_PPC_JMP_SLOT = 21UL + | R_PPC_RELATIVE = 22UL + | R_PPC_LOCAL24PC = 23UL + | R_PPC_UADDR32 = 24UL + | R_PPC_UADDR16 = 25UL + | R_PPC_REL32 = 26UL + | R_PPC_PLT32 = 27UL + | R_PPC_PLTREL32 = 28UL + | R_PPC_PLT16_LO = 29UL + | R_PPC_PLT16_HI = 30UL + | R_PPC_PLT16_HA = 31UL + | R_PPC_SDAREL16 = 32UL + | R_PPC_SECTOFF = 33UL + | R_PPC_SECTOFF_LO = 34UL + | R_PPC_SECTOFF_HI = 35UL + | R_PPC_SECTOFF_HA = 36UL + | R_PPC_TLS = 67UL + | R_PPC_DTPMOD32 = 68UL + | R_PPC_TPREL16 = 69UL + | R_PPC_TPREL16_LO = 70UL + | R_PPC_TPREL16_HI = 71UL + | R_PPC_TPREL16_HA = 72UL + | R_PPC_TPREL32 = 73UL + | R_PPC_DTPREL16 = 74UL + | R_PPC_DTPREL16_LO = 75UL + | R_PPC_DTPREL16_HI = 76UL + | R_PPC_DTPREL16_HA = 77UL + | R_PPC_DTPREL32 = 78UL + | R_PPC_GOT_TLSGD16 = 79UL + | R_PPC_GOT_TLSGD16_LO = 80UL + | R_PPC_GOT_TLSGD16_HI = 81UL + | R_PPC_GOT_TLSGD16_HA = 82UL + | R_PPC_GOT_TLSLD16 = 83UL + | R_PPC_GOT_TLSLD16_LO = 84UL + | R_PPC_GOT_TLSLD16_HI = 85UL + | R_PPC_GOT_TLSLD16_HA = 86UL + | R_PPC_GOT_TPREL16 = 87UL + | R_PPC_GOT_TPREL16_LO = 88UL + | R_PPC_GOT_TPREL16_HI = 89UL + | R_PPC_GOT_TPREL16_HA = 90UL + | R_PPC_GOT_DTPREL16 = 91UL + | R_PPC_GOT_DTPREL16_LO = 92UL + | R_PPC_GOT_DTPREL16_HI = 93UL + | R_PPC_GOT_DTPREL16_HA = 94UL + | R_PPC_TLSGD = 95UL + | R_PPC_TLSLD = 96UL + | R_PPC_EMB_NADDR32 = 101UL + | R_PPC_EMB_NADDR16 = 102UL + | R_PPC_EMB_NADDR16_LO = 103UL + | R_PPC_EMB_NADDR16_HI = 104UL + | R_PPC_EMB_NADDR16_HA = 105UL + | R_PPC_EMB_SDAI16 = 106UL + | R_PPC_EMB_SDA2I16 = 107UL + | R_PPC_EMB_SDA2REL = 108UL + | R_PPC_EMB_SDA21 = 109UL + | R_PPC_EMB_MRKREF = 110UL + | R_PPC_EMB_RELSEC16 = 111UL + | R_PPC_EMB_RELST_LO = 112UL + | R_PPC_EMB_RELST_HI = 113UL + | R_PPC_EMB_RELST_HA = 114UL + | R_PPC_EMB_BIT_FLD = 115UL + | R_PPC_EMB_RELSDA = 116UL + | R_PPC_DIAB_SDA21_LO = 180UL + | R_PPC_DIAB_SDA21_HI = 181UL + | R_PPC_DIAB_SDA21_HA = 182UL + | R_PPC_DIAB_RELSDA_LO = 183UL + | R_PPC_DIAB_RELSDA_HI = 184UL + | R_PPC_DIAB_RELSDA_HA = 185UL + | R_PPC_IRELATIVE = 248UL + | R_PPC_REL16 = 249UL + | R_PPC_REL16_LO = 250UL + | R_PPC_REL16_HI = 251UL + | R_PPC_REL16_HA = 252UL + | R_PPC_TOC16 = 255UL + +/// Relocation type. +type RelocationType = + | RelocationX86 of RelocationX86 + | RelocationX64 of RelocationX64 + | RelocationARMv7 of RelocationARMv7 + | RelocationARMv8 of RelocationARMv8 + | RelocationMIPS of RelocationMIPS + | RelocationSH4 of RelocationSH4 + | RelocationRISCV of RelocationRISCV + | RelocationPPC32 of RelocationPPC32 +with + static member FromNum arch n = + match arch with + | Architecture.IntelX86 -> + RelocationX86 <| LanguagePrimitives.EnumOfValue n + | Architecture.IntelX64 -> + RelocationX64 <| LanguagePrimitives.EnumOfValue n + | Architecture.ARMv7 -> + RelocationARMv7 <| LanguagePrimitives.EnumOfValue n + | Architecture.AARCH32 + | Architecture.AARCH64 -> + RelocationARMv8 <| LanguagePrimitives.EnumOfValue n + | Architecture.MIPS32 + | Architecture.MIPS64 -> + RelocationMIPS <| LanguagePrimitives.EnumOfValue n + | Architecture.SH4 -> + RelocationSH4 <| LanguagePrimitives.EnumOfValue n + | Architecture.RISCV64 -> + RelocationRISCV <| LanguagePrimitives.EnumOfValue n + | Architecture.PPC32 -> + RelocationPPC32 <| LanguagePrimitives.EnumOfValue n + | _ -> invalidArg (nameof arch) "Unsupported architecture for relocation." + + static member ToString rt = + match rt with + | RelocationX86 t -> t.ToString () + | RelocationX64 t -> t.ToString () + | RelocationARMv7 t -> t.ToString () + | RelocationARMv8 t -> t.ToString () + | RelocationMIPS t -> t.ToString () + | RelocationSH4 t -> t.ToString () + | RelocationRISCV t -> t.ToString () + | RelocationPPC32 t -> t.ToString () + +/// Relocation entry. +type RelocationEntry = { + /// The location at which to apply the relocation action. + RelOffset: uint64 + /// Relocation symbol. Symbol can be None when only the addend is used. + RelSymbol: ELFSymbol option + /// Relocation type. + RelType: RelocationType + /// A constant addend used to compute the value to be stored into the + /// relocatable field. + RelAddend: uint64 + /// The number of the section that defines this relocation. + RelSecNumber: int +} + +/// Relocation information +type RelocationInfo = { + RelocByAddr: Dictionary + RelocByName: Dictionary +} + +module internal RelocationInfo = + let private readInfoWithArch { Reader = reader; Header = hdr } span = + let info = readNative span reader hdr.Class 4 8 + match hdr.MachineType with + | Architecture.MIPS64 -> + (* MIPS64el has a a 32-bit LE symbol index followed by four individual + byte fields. *) + if hdr.Endian = Endian.Little then + (info &&& 0xffffffffUL) <<< 32 + ||| ((info >>> 56) &&& 0xffUL) + ||| ((info >>> 40) &&& 0xff00UL) + ||| ((info >>> 24) &&& 0xff0000UL) + ||| ((info >>> 8) &&& 0xff000000UL) + else info + | _ -> info + + let inline private getRelocSIdx hdr (i: uint64) = + if hdr.Class = WordSize.Bit32 then i >>> 8 else i >>> 32 + + let private getRelocEntry toolBox hasAddend typMask symTbl span sec = + let hdr = toolBox.Header + let reader = toolBox.Reader + let info = readInfoWithArch toolBox span + let cls = hdr.Class + { RelOffset = readUIntOfType span reader cls 0 + toolBox.BaseAddress + RelType = typMask &&& info |> RelocationType.FromNum hdr.MachineType + RelSymbol = Array.tryItem (getRelocSIdx hdr info |> int) symTbl + RelAddend = if hasAddend then readNative span reader cls 8 16 else 0UL + RelSecNumber = sec.SecNum } + + let private tryFindSymbTable idx symbInfo = + match symbInfo.SecNumToSymbTbls.TryGetValue idx with + | true, tbl -> tbl + | false, _ -> [||] + + let private accumulateRelocInfo relInfo rel = + match rel.RelSymbol with + | None -> relInfo.RelocByAddr[rel.RelOffset] <- rel + | Some name -> + relInfo.RelocByAddr[rel.RelOffset] <- rel + relInfo.RelocByName[name.SymName] <- rel + + let private parseRelocSection toolBox symbInfo relInfo sec (span: ByteSpan) = + let hdr = toolBox.Header + let hasAddend = sec.SecType = SectionType.SHT_RELA + let typMask = pickNum hdr.Class 0xFFUL 0xFFFFFFFFUL + let entrySize = + if hasAddend then (uint64 <| WordSize.toByteWidth hdr.Class * 3) + else (uint64 <| WordSize.toByteWidth hdr.Class * 2) + let numEntries = int (sec.SecSize / entrySize) + for i = 0 to (numEntries - 1) do + let symTbl = tryFindSymbTable (int sec.SecLink) symbInfo + let offset = i * int entrySize + getRelocEntry toolBox hasAddend typMask symTbl (span.Slice offset) sec + |> accumulateRelocInfo relInfo + + let parse toolBox shdrs symbInfo = + let relInfo = { RelocByAddr = Dictionary (); RelocByName = Dictionary () } + for sec in shdrs do + match sec.SecType with + | SectionType.SHT_REL + | SectionType.SHT_RELA -> + if sec.SecSize = 0UL then () + else + let offset, size = int sec.SecOffset, int sec.SecSize + let span = ReadOnlySpan (toolBox.Bytes, offset, size) + parseRelocSection toolBox symbInfo relInfo sec span + | _ -> () + relInfo diff --git a/src/FrontEnd/BinFile/ELF/ELFSection.fs b/src/FrontEnd/BinFile/ELF/ELFSection.fs new file mode 100644 index 00000000..f9a73ee7 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFSection.fs @@ -0,0 +1,278 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open System.IO +open B2R2 +open B2R2.FrontEnd.BinFile.FileHelper + +/// This member categorizes the section's contents and semantics. +type SectionType = + /// This section is inactive. + | SHT_NULL = 0x00u + /// This section holds information defined by the program, whose format and + /// meaning are determined solely by the program. + | SHT_PROGBITS = 0x01u + /// This section holds a symbol table. + | SHT_SYMTAB = 0x02u + /// This section holds a string table. + | SHT_STRTAB = 0x03u + /// This section holds relocation entries with explicit addends. + | SHT_RELA = 0x04u + /// This section holds a symbol hash table. All ELF files participating in + /// dynamic linking must contain a symbol hash table. + | SHT_HASH = 0x05u + /// This section holds information for dynamic linking. + | SHT_DYNAMIC = 0x06u + /// This section holds a note. + | SHT_NOTE = 0x07u + /// This section occupies no space, although SecOffset contains a conceptual + /// offset to it. + | SHT_NOBITS = 0x08u + /// This section holds relocation entries without explicit addends. + | SHT_REL = 0x09u + /// This section is reserved (unknown purpose). + | SHT_SHLIB = 0x0au + /// This section contains a minimal set of dynamic linking symbols. + | SHT_DYNSYM = 0x0bu + /// This section contains initialization function pointers. + | SHT_INIT_ARRAY = 0x0eu + /// This section contains termination function pointers. + | SHT_FINI_ARRAY = 0x0fu + /// This section contains pre-initialization function pointers. + | SHT_PREINIT_ARRAY = 0x10u + /// This section holds section group information. + | SHT_GROUP = 0x11u + /// This section holds section indexes. + | SHT_SYMTAB_SHNDX = 0x12u + /// This section marks the start of processor-specific section type. + | SHT_LOPROC = 0x70000000u + /// ARM unwind section. + | SHT_ARM_EXIDX = 0x70000001u + /// Preemption details. + | SHT_ARM_PREEMPTMAP = 0x70000002u + /// ARM attributes section. + | SHT_ARM_ATTRIBUTES = 0x70000003u + /// Section holds overlay debug info. + | SHT_ARM_DEBUGOVERLAY = 0x70000004u + /// Section holds GDB and overlay integration info. + | SHT_ARM_OVERLAYSECTION = 0x70000005u + /// Register usage information. + | SHT_MIPS_REGINFO = 0x70000006u + /// Miscellaneous options. + | SHT_MIPS_OPTIONS = 0x7000000du + /// ABI related flags section. + | SHT_MIPS_ABIFLAGS = 0x7000002au + /// This section marks the end of processor-specific section type. + | SHT_HIPROC = 0x7fffffffu + /// This section specifies the lower bound of program-specific section type. + | SHT_LOUSER = 0x80000000u + /// This section specifies the upper bound of program-specific section type. + | SHT_HIUSER = 0xffffffffu + /// Object attributes. + | SHT_GNU_ATTRIBUTES = 0x6ffffff5u + /// GNU-style hash table. + | SHT_GNU_HASH = 0x6ffffff6u + /// Prelink library list. + | SHT_GNU_LIBLIST = 0x6ffffff7u + /// This section holds Linux-specific version information (Elfxx_VerDef). This + /// stores version information of functions defined in the binary. + | SHT_GNU_verdef = 0x6ffffffdu + /// This section holds Linux-specific version information (Elfxx_VerNeed). + /// This stores version information of external functions, which is needed by + /// the caller binary. + | SHT_GNU_verneed = 0x6ffffffeu + /// This section holds Linux-specific version information. It specifically + /// contains an array of elements of type Elfxx_Half. It has as many entries + /// as the dynamic symbol table. + | SHT_GNU_versym = 0x6fffffffu + +/// Every symbol table entry is defined in relation to some section. +/// This member holds the relevant section header table index. +type SectionHeaderIdx = + /// This is the start of the reserved range. + | SHN_LORESERVE + /// The symbol is undefined. Linker should update references to this symbol + /// with the actual definition from another file. + | SHN_UNDEF + /// The lower bound of processor-specific section index value. + | SHN_LOPROC + /// The upper bound of processor-specific section index value. + | SHN_HIPROC + /// The lower bound of OS-specific section index value. + | SHN_LOOS + /// The upper bound of OS-specific section index value. + | SHN_HIOS + /// The symbol has an absolute value that will not change because of + /// relocation. + | SHN_ABS + /// The symbol labels a common block that has not yet been allocated. + | SHN_COMMON + /// An escape value indicating that the actual section header index is too + /// large to fit in the containing field. The header section index is found in + /// another location specific to the structure where it appears. + | SHN_XINDEX + /// The upper boundary of the range of the reserved range. + | SHN_HIRESERVE + /// This symbol index holds an index into the section header table. + | SectionIndex of int +with + static member IndexFromInt n = + match n with + | 0x00 -> SHN_UNDEF + | 0xff00 -> SHN_LORESERVE + | 0xfff1 -> SHN_ABS + | 0xfff2 -> SHN_COMMON + | n -> SectionIndex n + +/// Sections support 1-bit flags that describe miscellaneous attributes. +[] +type SectionFlag = + /// This section contains data that should be writable during process + /// execution. + | SHF_WRITE = 0x1UL + /// This section occupies memory during process execution. + | SHF_ALLOC = 0x2UL + /// This section contains executable machine code. + | SHF_EXECINSTR = 0x4UL + /// This section may be merged. + | SHF_MERGE = 0x10UL + /// This section contains null-terminated strings. + | SHF_STRINGS = 0x20UL + /// This section holds section indexes. + | SHF_INFO_LINK = 0x40UL + /// This section adds special ordering requirements to the link editor. + | SHF_LINK_ORDER = 0x80UL + /// This section requires special OS-specific processing beyond the standard + /// linking rules to avoid incorrect behavior + | SHF_OS_NONCONFORMING = 0x100UL + /// This section is a member, perhaps the only one, of a section group. + | SHF_GROUP = 0x200UL + /// This section contains TLS data. + | SHF_TLS = 0x400UL + /// This section contains compressed data. + | SHF_COMPRESSED = 0x800UL + /// All bits included in this mask are reserved for operating system-specific + /// semantics. + | SHF_MASKOS = 0x0ff00000UL + /// All bits included in this mask are reserved for processor-specific + /// semantics. + | SHF_MASKPROC = 0xf0000000UL + /// This section requires ordering in relation to other sections of the same + /// type. + | SHF_ORDERED = 0x40000000UL + /// This section is excluded from input to the link-edit of an executable or + /// shared object + | SHF_EXCLUDE = 0x80000000UL + /// This section can hold more than 2GB. + | SHF_X86_64_LARGE = 0x10000000UL + +/// ELF Section +type ELFSection = { + /// Unique section number. + SecNum: int + /// The name of the section. + SecName: string + /// Categorizes the section's contents and semantics. + SecType: SectionType + /// Misc. attributes about the section. + SecFlags: SectionFlag + /// The address at which the section's first byte should reside. If this + /// section will not appear in the process memory, this value is 0. + SecAddr: Addr + /// Byte offset from the beginning of the file to the first byte in the + /// section. + SecOffset: uint64 + /// The section's size in bytes. + SecSize: uint64 + /// A section header table index link. The interpretation of this field + /// depends on the section type. + SecLink: uint32 + /// Extra information. The interpretation of this info depends on the section + /// type. + SecInfo: uint32 + /// Some sections have address alignment constraints. + SecAlignment: uint64 + /// Some sections hold a table of fixed-size entries, such as a symbol + /// table. For such a section, this member gives the size in bytes of each + /// entry. + SecEntrySize: uint64 +} + +module internal Section = + let [] SecText = ".text" + let [] SecROData = ".rodata" + + /// Return the section file offset and size, which represents the section + /// names separated by null character. + let parseSectionNameTableInfo hdr ({ Reader = reader } as toolBox) = + let secPtr = hdr.SHdrTblOffset + uint64 (hdr.SHdrStrIdx * hdr.SHdrEntrySize) + let ptrSize = WordSize.toByteWidth hdr.Class + let shAddrOffset = 8UL + uint64 (ptrSize * 2) + let shAddrPtr = secPtr + shAddrOffset (* pointer to sh_offset *) + let shAddrSize = ptrSize * 2 (* sh_offset, sh_size *) + let span = ReadOnlySpan (toolBox.Bytes, int shAddrPtr, shAddrSize) + let offset = readUIntOfType span reader hdr.Class 0 + let size = readUIntOfType span reader hdr.Class (pickNum hdr.Class 4 8) + ReadOnlySpan (toolBox.Bytes, int offset, int size) + + let peekSecType (span: ByteSpan) (reader: IBinReader) = + reader.ReadUInt32 (span, 4) + |> LanguagePrimitives.EnumOfValue: SectionType + + let peekSecFlags span reader cls = + readUIntOfType span reader cls 8 + |> LanguagePrimitives.EnumOfValue: SectionFlag + + let parseSectionHdr toolBox num nameTbl (secHdr: ByteSpan) = + let reader = toolBox.Reader + let nameOffset = reader.ReadInt32 (secHdr, 0) + let cls = toolBox.Header.Class + { SecNum = num + SecName = ByteArray.extractCStringFromSpan nameTbl nameOffset + SecType = peekSecType secHdr reader + SecFlags = peekSecFlags secHdr reader cls + SecAddr = readNative secHdr reader cls 12 16 + toolBox.BaseAddress + SecOffset = readNative secHdr reader cls 16 24 + SecSize = readNative secHdr reader cls 20 32 + SecLink = reader.ReadUInt32 (secHdr, pickNum cls 24 40) + SecInfo = reader.ReadUInt32 (secHdr, pickNum cls 28 44) + SecAlignment = readNative secHdr reader cls 32 48 + SecEntrySize = readNative secHdr reader cls 36 56 } + + let parse ({ Bytes = bytes } as toolBox) = + let hdr = toolBox.Header + let nameTbl = parseSectionNameTableInfo hdr toolBox + let secHdrEntrySize = int hdr.SHdrEntrySize + let secHdrCount = int hdr.SHdrNum + let secHeaders = Array.zeroCreate secHdrCount + let mutable offset = int hdr.SHdrTblOffset + for i = 0 to secHdrCount - 1 do + let span = ReadOnlySpan (bytes, offset, secHdrEntrySize) + let hdr = parseSectionHdr toolBox i nameTbl span + secHeaders[i] <- hdr + offset <- offset + secHdrEntrySize + secHeaders diff --git a/src/FrontEnd/BinFile/ELF/ELFSymbol.fs b/src/FrontEnd/BinFile/ELF/ELFSymbol.fs new file mode 100644 index 00000000..531906a8 --- /dev/null +++ b/src/FrontEnd/BinFile/ELF/ELFSymbol.fs @@ -0,0 +1,390 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.ELF + +open System +open System.Collections.Generic +open B2R2 +open B2R2.Monads.Maybe +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +/// A symbol's binding determines the linkage visibility and behavior. +type SymbolBind = + /// Local symbols are not visible outside. Local symbols of the same name may + /// exist in multiple files without interfering with each other. + | STB_LOCAL = 0uy + /// Global symbols are visible to all object files being combined. + | STB_GLOBAL = 1uy + /// Weak symbols resemble global symbols, but their definitions have lower + /// precedence. + | STB_WEAK = 2uy + /// The lower bound of OS-specific binding type. + | STB_LOOS = 10uy + /// The upper bound of OS-specific binding type. + | STB_HIOS = 12uy + /// The lower bound of processor-specific binding type. + | STB_LOPROC = 13uy + /// The upper bound of processor-specific binding type. + | STB_HIPROC = 15uy + +/// A symbol's type provides a general classification for the associated entity. +type SymbolType = + /// Symbol's type is not specified. + | STT_NOTYPE = 0uy + /// This symbol is associated with a data object, such as variable and an + /// array. + | STT_OBJECT = 1uy + /// This symbol is associated with a function. + | STT_FUNC = 2uy + /// This symbol is associated with a section. Symbol table entries of this + /// type exist primarily for relocation and normally have STBLocal binding. + | STT_SECTION = 3uy + /// This symbol represents the name of the source file associated with the + /// object file. + | STT_FILE = 4uy + /// This symbol labels an uninitialized common block. + | STT_COMMON = 5uy + /// The symbol specifies a Thread-Local Storage entity. + | STT_TLS = 6uy + /// The lower bound of OS-specific symbol type. + | STT_LOOS = 10uy + /// A symbol with type STT_GNU_IFUNC is a function, but the symbol does not + /// provide the address of the function as usual. Instead, the symbol provides + /// the address of a function which returns a pointer to the actual function. + | STT_GNU_IFUNC = 10uy + /// The upper bound of OS-specific binding type. + | STT_HIOS = 12uy + /// The lower bound of processor-specific symbol type. + | STT_LOPROC = 13uy + /// The upper bound of processor-specific symbol type. + | STT_HIPROC = 15uy + +/// This member currently specifies a symbol's visibility +type SymbolVisibility = + /// Use the visibility specified by the symbol's binding type (SymbolBind). + | STV_DEFAULT = 0x0uy + /// This visibility attribute is currently reserved. + | STV_INTERNAL = 0x01uy + /// A symbol defined in the current component is hidden if its name is not + /// visible to other components. Such a symbol is necessarily protected. This + /// attribute is used to control the external interface of a component. An + /// object named by such a symbol may still be referenced from another + /// component if its address is passed outside. + | STV_HIDDEN = 0x02uy + /// A symbol defined in the current component is protected if it is visible in + /// other components but cannot be preempted. Any reference to such a symbol + /// from within the defining component must be resolved to the definition in + /// that component, even if there is a definition in another component that + /// would interpose by the default rules. + | STV_PROTECTED = 0x03uy + +/// Symbol version information. +type SymVerInfo = { + /// Is this a hidden symbol? This is a GNU-specific extension indicated as + /// VERSYM_HIDDEN. + IsHidden: bool + /// Version string. + VerName: string +} + +type ELFSymbol = { + /// Address of the symbol. + Addr: Addr + /// Symbol's name. + SymName: string + /// Size of the symbol (e.g., size of the data object). + Size: uint64 + /// Symbol binding. + Bind: SymbolBind + /// Symbol type. + SymType: SymbolType + /// Symbol visibility. + Vis: SymbolVisibility + /// The index of the relevant section with regard to this symbol. + SecHeaderIndex: SectionHeaderIdx + /// Parent section of this section. + ParentSection: ELFSection option + /// Version information. + VerInfo: SymVerInfo option + /// ArchOperationMode. + ArchOperationMode: ArchOperationMode +} + +/// Main data structure for storing symbol information. +type ELFSymbolInfo = { + /// Linux-specific symbol version table containing versions required to link. + VersionTable: Dictionary + /// A mapping from a section number to the corresponding symbol table. + SecNumToSymbTbls: Dictionary + /// Address to symbol mapping. + AddrToSymbTable: Dictionary +} + +module internal Symbol = + let getSymbKind ndx = function + | SymbolType.STT_OBJECT -> SymObjectType + | SymbolType.STT_GNU_IFUNC + | SymbolType.STT_FUNC -> + if ndx = SHN_UNDEF then SymNoType + else SymFunctionType + | SymbolType.STT_SECTION -> SymSectionType + | SymbolType.STT_FILE ->SymFileType + | _ -> SymNoType + + let versionToLibName version = + match version with + | Some version -> version.VerName + | None -> "" + + let toB2R2Symbol vis (symb: ELFSymbol) = + { Address = symb.Addr + Name = symb.SymName + Kind = getSymbKind symb.SecHeaderIndex symb.SymType + Visibility = vis + LibraryName = versionToLibName symb.VerInfo + ArchOperationMode = symb.ArchOperationMode } + + let verName (strTab: ByteSpan) vnaNameOffset = + if vnaNameOffset >= strTab.Length then "" + else ByteArray.extractCStringFromSpan strTab vnaNameOffset + + let rec parseNeededVerFromSecAux span (reader: IBinReader) verTbl strTbl pos = + let idx = reader.ReadUInt16 (span=span, offset=pos + 6) (* vna_other *) + let nameOffset = reader.ReadInt32 (span, pos + 8) + (verTbl: Dictionary<_, _>)[idx] <- verName strTbl nameOffset + let next = reader.ReadInt32 (span, pos + 12) + if next = 0 then () + else parseNeededVerFromSecAux span reader verTbl strTbl (pos + next) + + let rec parseNeededVerFromSec span reader verTbl strTbl offset = + let auxOffset = (* vn_aux + current file offset *) + (reader: IBinReader).ReadInt32 (span=span, offset=offset + 8) + offset + parseNeededVerFromSecAux span reader verTbl strTbl auxOffset + let next = reader.ReadInt32 (span, offset + 12) (* vn_next *) + if next = 0 then () + else parseNeededVerFromSec span reader verTbl strTbl (offset + next) + + let parseNeededVersionTable toolBox verTbl strTbl = function + | None -> () + | Some { SecOffset = offset; SecSize = size } -> + let span = ReadOnlySpan (toolBox.Bytes, int offset, int size) + parseNeededVerFromSec span toolBox.Reader verTbl strTbl 0 + + let rec parseDefinedVerFromSec span (reader: IBinReader) verTbl strTbl ofs = + let auxOffset = (* vd_aux + current file offset *) + reader.ReadInt32 (span=span, offset=ofs + 12) + ofs + let idx = reader.ReadUInt16 (span, ofs + 4) (* vd_ndx *) + let nameOffset = reader.ReadInt32 (span, auxOffset) (* vda_name *) + (verTbl: Dictionary<_, _>)[idx] <- verName strTbl nameOffset + let next = reader.ReadInt32 (span, ofs + 16) (* vd_next *) + if next = 0 then () + else parseDefinedVerFromSec span reader verTbl strTbl (ofs + next) + + let parseDefinedVersionTable toolBox verTbl strTbl = function + | None -> () + | Some { SecOffset = offset; SecSize = size } -> + let span = ReadOnlySpan (toolBox.Bytes, int offset, int size) + parseDefinedVerFromSec span toolBox.Reader verTbl strTbl 0 + + let findVerNeedSection shdrs = + shdrs + |> Array.tryFind (fun s -> s.SecType = SectionType.SHT_GNU_verneed) + + let findVerDefSection shdrs = + shdrs + |> Array.tryFind (fun s -> s.SecType = SectionType.SHT_GNU_verdef) + + let getStaticSymbolSectionNumbers shdrs = + shdrs + |> Array.choose (fun s -> + if s.SecType = SectionType.SHT_SYMTAB then Some s.SecNum else None) + + let getDynamicSymbolSectionNumbers shdrs = + shdrs + |> Array.choose (fun s -> + if s.SecType = SectionType.SHT_DYNSYM then Some s.SecNum else None) + + let parseVersionTable ({ Bytes = bytes; Reader = reader } as toolBox) shdrs = + let verTbl = Dictionary () + let verNeedSec = findVerNeedSection shdrs + let verDefSec = findVerDefSection shdrs + for n in getDynamicSymbolSectionNumbers shdrs do + let symSection = shdrs[n] + let strSection = shdrs[Convert.ToInt32 symSection.SecLink] + let size = Convert.ToInt32 strSection.SecSize + let strTbl = ReadOnlySpan (bytes, int strSection.SecOffset, size) + parseNeededVersionTable toolBox verTbl strTbl verNeedSec + parseDefinedVersionTable toolBox verTbl strTbl verDefSec + verTbl + + let retrieveVer (verTbl: Dictionary<_, _>) verData = + let isHidden = verData &&& 0x8000us <> 0us + match verTbl.TryGetValue (verData &&& 0x7fffus) with + | true, verStr -> Some { IsHidden = isHidden; VerName = verStr } + | false, _ -> None + + let adjustSymAddr baseAddr addr = + if addr = 0UL then 0UL + else addr + baseAddr + + let readSymAddr baseAddr span reader cls parent txtOffset = + let symAddr = readUIntOfType span reader cls (pickNum cls 4 8) + match (parent: ELFSection option) with + | None -> symAddr + | Some sec -> + (* This is to give a meaningful address to static symbols in a relocatable + object. We let .text section's address to be zero, and assume that the + .text section always precedes the other sections. See + https://github.com/B2R2-org/B2R2/issues/25 for more details. *) + if sec.SecAddr = baseAddr && sec.SecOffset > txtOffset then + sec.SecOffset - txtOffset + symAddr + else symAddr + |> adjustSymAddr baseAddr + + let computeArchOpMode hdr symbolName = + if hdr.MachineType = Architecture.ARMv7 + || hdr.MachineType = Architecture.AARCH32 + then + if symbolName = "$a" then ArchOperationMode.ARMMode + elif symbolName = "$t" then ArchOperationMode.ThumbMode + else ArchOperationMode.NoMode + else ArchOperationMode.NoMode + + let parseVersData (reader: IBinReader) symIdx verInfoTbl = + let pos = symIdx * 2 + let versData = reader.ReadUInt16 (span=verInfoTbl, offset=pos) + if versData > 1us then Some versData + else None + + let getVerInfo toolBox verTbl verInfoTblOpt symIdx = + match verInfoTblOpt with + | Some verInfoTbl -> + let offset, size = int verInfoTbl.SecOffset, int verInfoTbl.SecSize + let span = ReadOnlySpan (toolBox.Bytes, offset, size) + parseVersData toolBox.Reader symIdx span >>= retrieveVer verTbl + | None -> None + + let getSymbol toolBox shdrs strTbl verTbl symbol verInfoTbl txtOffset symIdx = + let cls = toolBox.Header.Class + let reader = toolBox.Reader + let nameIdx = reader.ReadUInt32 (span=symbol, offset=0) + let sname = ByteArray.extractCStringFromSpan strTbl (int nameIdx) + let info = symbol[pickNum cls 12 4] + let other = symbol[pickNum cls 13 5] + let ndx = reader.ReadUInt16 (symbol, pickNum cls 14 6) |> int + let parent = Array.tryItem ndx shdrs + let secIdx = SectionHeaderIdx.IndexFromInt ndx + let verInfo = getVerInfo toolBox verTbl verInfoTbl symIdx + { Addr = readSymAddr toolBox.BaseAddress symbol reader cls parent txtOffset + SymName = sname + Size = readUIntOfType symbol reader cls (pickNum cls 8 16) + Bind = info >>> 4 |> LanguagePrimitives.EnumOfValue + SymType = info &&& 0xfuy |> LanguagePrimitives.EnumOfValue + Vis = other &&& 0x3uy |> LanguagePrimitives.EnumOfValue + SecHeaderIndex = secIdx + ParentSection = parent + VerInfo = verInfo + ArchOperationMode = computeArchOpMode toolBox.Header sname } + + let nextSymOffset cls offset = + offset + pickNum cls 16 24 + + let getTextSectionOffset shdrs = + match shdrs |> Array.tryFind (fun s -> s.SecName = Section.SecText) with + | None -> 0UL + | Some sec -> sec.SecOffset + + let parseSymbols toolBox shdrs verTbl verInfoTbl symTblSec = + let cls = toolBox.Header.Class + let txt = getTextSectionOffset shdrs + let ssec = shdrs[Convert.ToInt32 symTblSec.SecLink] (* Get string sect. *) + let offset = int ssec.SecOffset + let size = Convert.ToInt32 ssec.SecSize + let strTbl = ReadOnlySpan (toolBox.Bytes, offset, size) + let offset = int symTblSec.SecOffset + let size = Convert.ToInt32 symTblSec.SecSize + let verInfoTbl = (* symbol versioning is only valid for dynamic symbols. *) + if symTblSec.SecType = SectionType.SHT_DYNSYM then verInfoTbl else None + let symTbl = ReadOnlySpan (toolBox.Bytes, offset, size) + let numEntries = int symTblSec.SecSize / (pickNum cls 16 24) + let symbols = Array.zeroCreate numEntries + for i = 0 to numEntries - 1 do + let offset = i * (pickNum cls 16 24) + let entry = symTbl.Slice offset + let sym = getSymbol toolBox shdrs strTbl verTbl entry verInfoTbl txt i + symbols[i] <- sym + symbols + + let getVerInfoTable shdrs = + shdrs + |> Array.tryFind (fun s -> s.SecType = SectionType.SHT_GNU_versym) + + let parseSymTabs toolBox symTbl shdrs verTbl symSecs = + let verInfoTbl = getVerInfoTable shdrs + for (n, symTblSec) in symSecs do + let symbols = parseSymbols toolBox shdrs verTbl verInfoTbl symTblSec + (symTbl: Dictionary)[n] <- symbols + + let getSymbolSections shdrs = + shdrs + |> Array.choose (fun s -> + if s.SecType = SectionType.SHT_SYMTAB + || s.SecType = SectionType.SHT_DYNSYM + then Some s.SecNum + else None) + |> Array.map (fun n -> n, shdrs[n]) + + let getMergedSymbolTbl (symTbls: Dictionary<_, _>) numbers = + numbers + |> Array.fold (fun acc n -> Array.append (symTbls[n]) acc) [||] + + let getStaticSymArray shdrs symTbl = + getStaticSymbolSectionNumbers shdrs + |> getMergedSymbolTbl symTbl + + let getDynamicSymArray shdrs symTbl = + getDynamicSymbolSectionNumbers shdrs + |> getMergedSymbolTbl symTbl + + let buildSymbolMap staticSymArr dynamicSymArr = + let map = Dictionary () + let iterator sym = + if sym.Addr > 0UL then map[sym.Addr] <- sym + else () + staticSymArr |> Array.iter iterator + dynamicSymArr |> Array.iter iterator + map + + let parse toolBox shdrs = + let verTbl = parseVersionTable toolBox shdrs + let symSecs = getSymbolSections shdrs + let symTbl = Dictionary () + parseSymTabs toolBox symTbl shdrs verTbl symSecs + let staticSymArr = getStaticSymArray shdrs symTbl + let dynamicSymArr = getDynamicSymArray shdrs symTbl + { VersionTable = verTbl + SecNumToSymbTbls = symTbl + AddrToSymbTable = buildSymbolMap staticSymArr dynamicSymArr } diff --git a/src/FrontEnd/BinFile/ELFExceptionFrames.fs b/src/FrontEnd/BinFile/ELFExceptionFrames.fs deleted file mode 100644 index 197f5cf9..00000000 --- a/src/FrontEnd/BinFile/ELFExceptionFrames.fs +++ /dev/null @@ -1,746 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -[] -module internal B2R2.FrontEnd.BinFile.ELF.ExceptionFrames - -open System -open System.Runtime.InteropServices -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.FrontEnd.BinFile.ELF.ExceptionHeaderEncoding - -/// Raised when an unhandled eh_frame version is encountered. -exception UnhandledExceptionHandlingFrameVersion - -/// Raised when an unhandled augment string is encountered. -exception UnhandledAugString - -/// Raised when CIE is not found by FDE -exception CIENotFoundByFDE - -/// Raised when invalid sequence of dwarf instructions encountered. -exception InvalidDWInstructionExpression - -let [] Ehframe = ".eh_frame" - -let inline readInt (span: ByteSpan) (reader: IBinReader) offset = - struct (reader.ReadInt32 (span, offset), offset + 4) - -let inline readUInt64 (span: ByteSpan) (reader: IBinReader) offset = - struct (reader.ReadUInt64 (span, offset), offset + 8) - -let computeNextOffset len span (reader: IBinReader) offset = - if len = -1 then - let struct (len, offset) = readUInt64 span reader offset - int len + offset, offset - else len + offset, offset - -let parseReturnRegister (span: ByteSpan) version offset = - if version = 1uy then span[offset], offset + 1 - else - let r, offset = parseULEB128 span offset - byte r, offset - -let personalityRoutinePointerSize addrSize = function - | 2uy -> 2 - | 3uy -> 4 - | 4uy -> 8 - | _ -> addrSize - -let obtainAugData addrSize (arr: byte []) data offset = function - | 'L' -> - let struct (v, app) = parseEncoding arr[offset] - { Format = 'L' - ValueEncoding = v - ApplicationEncoding = app - PersonalityRoutionPointer = [||] } :: data, offset + 1 - | 'P' -> - let struct (v, app) = parseEncoding arr[offset] - let psz = arr[offset] &&& 7uy |> personalityRoutinePointerSize addrSize - let prp = arr[ offset + 1 .. offset + psz ] - { Format = 'P' - ValueEncoding = v - ApplicationEncoding = app - PersonalityRoutionPointer = prp } :: data, offset + psz + 1 - | 'R' -> - let struct (v, app) = parseEncoding arr[offset] - { Format = 'R' - ValueEncoding = v - ApplicationEncoding = app - PersonalityRoutionPointer = [||] } :: data, offset + 1 - | 'S' -> data, offset (* This is a signal frame. *) - | _ -> raise UnhandledAugString - -let parseAugmentationData span offset addrSize augstr = - if (augstr: string).StartsWith ('z') then - let len, offset = parseULEB128 span offset - let span = span.Slice (offset, int len) - let arr = span.ToArray () - augstr[ 1.. ] - |> Seq.fold (fun (data, idx) ch -> - obtainAugData addrSize arr data idx ch) ([], 0) - |> fst - |> List.rev, offset + int len - else [], offset - -let num isa n = - let rt = isa.WordSize |> WordSize.toRegType - AST.num (BitVector.ofUInt64 n rt) - -let regPlusNum isa regbay reg n = - let regexp = DWRegister.toRegisterExpr isa regbay reg - AST.binop BinOpType.ADD regexp (num isa n) - -let parseOpBReg isa regbay exprs (span: ByteSpan) idx reg = - let offset, cnt = LEB128.DecodeUInt64 (span.Slice (idx)) - let exprs = regPlusNum isa regbay reg offset :: exprs - struct (exprs, idx + cnt) - -let pop exprs = - match exprs with - | fst :: rest -> struct (fst, rest) - | _ -> Utils.impossible () - -let pop2 exprs = - match exprs with - | fst :: snd :: rest -> struct (fst, snd, rest) - | _ -> Utils.impossible () - -let inline hasLessThanTwoOperands exprs = - match exprs with - | [ _ ] | [] -> true - | _ -> false - -let parseBinop op exprs = - let struct (fst, snd, exprs) = pop2 exprs - AST.binop op snd fst :: exprs - -let parsePlusUconst isa exprs (span: ByteSpan) idx = - let n, cnt = LEB128.DecodeUInt64 (span.Slice (idx)) - let n = num isa n - let struct (fst, exprs) = pop exprs - let exprs = AST.binop BinOpType.ADD fst n :: exprs - struct (exprs, idx + cnt) - -let parseRel isa op exprs = - let struct (fst, snd, exprs) = pop2 exprs - let rt = isa.WordSize |> WordSize.toRegType - AST.cast CastKind.ZeroExt rt (AST.relop op snd fst) :: exprs - -let parseLoad isa exprs = - let struct (addr, exprs) = pop exprs - let rt = isa.WordSize |> WordSize.toRegType - AST.loadLE rt addr :: exprs - -let rec parseExprs isa regbay exprs (span: ByteSpan) i maxIdx = - if i >= maxIdx then - match exprs with - | [ exp ] -> exp - | _ -> raise InvalidDWInstructionExpression - else - match span[i] |> DWOperation.parse with - | DWOperation.DW_OP_breg0 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 0uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg1 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 1uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg2 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 2uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg3 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 3uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg4 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 4uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg5 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 5uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg6 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 6uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg7 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 7uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg8 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 8uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg9 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 9uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg10 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 10uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg11 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 11uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg12 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 12uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg13 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 13uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg14 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 14uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg15 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 15uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg16 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 16uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg17 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 17uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg18 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 18uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg19 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 19uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg20 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 20uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg21 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 21uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg22 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 22uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg23 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 23uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg24 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 24uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg25 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 25uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg26 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 26uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg27 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 27uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg28 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 28uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg29 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 29uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg30 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 30uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_breg31 -> - let struct (exprs, i') = parseOpBReg isa regbay exprs span (i + 1) 31uy - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_const1u -> - let exprs = num isa (uint64 span[i + 1]) :: exprs - parseExprs isa regbay exprs span (i + 2) maxIdx - | DWOperation.DW_OP_const1s -> - let exprs = num isa (int64 span[i + 1] |> uint64) :: exprs - parseExprs isa regbay exprs span (i + 2) maxIdx - | DWOperation.DW_OP_const2u -> - let c = MemoryMarshal.Read (span.Slice (i + 1)) - let exprs = num isa (uint64 c) :: exprs - parseExprs isa regbay exprs span (i + 3) maxIdx - | DWOperation.DW_OP_const2s -> - let c = MemoryMarshal.Read (span.Slice (i + 1)) - let exprs = num isa (int64 c |> uint64) :: exprs - parseExprs isa regbay exprs span (i + 3) maxIdx - | DWOperation.DW_OP_const4u -> - let c = MemoryMarshal.Read (span.Slice (i + 1)) - let exprs = num isa (uint64 c) :: exprs - parseExprs isa regbay exprs span (i + 5) maxIdx - | DWOperation.DW_OP_const4s -> - let c = MemoryMarshal.Read (span.Slice (i + 1)) - let exprs = num isa (int64 c |> uint64) :: exprs - parseExprs isa regbay exprs span (i + 5) maxIdx - | DWOperation.DW_OP_lit0 -> - let exprs = num isa 0UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit1 -> - let exprs = num isa 1UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit2 -> - let exprs = num isa 2UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit3 -> - let exprs = num isa 3UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit4 -> - let exprs = num isa 4UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit5 -> - let exprs = num isa 5UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit6 -> - let exprs = num isa 6UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit7 -> - let exprs = num isa 7UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit8 -> - let exprs = num isa 8UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit9 -> - let exprs = num isa 9UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit10 -> - let exprs = num isa 10UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit11 -> - let exprs = num isa 11UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit12 -> - let exprs = num isa 12UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit13 -> - let exprs = num isa 13UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit14 -> - let exprs = num isa 14UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit15 -> - let exprs = num isa 15UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit16 -> - let exprs = num isa 16UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit17 -> - let exprs = num isa 17UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit18 -> - let exprs = num isa 18UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit19 -> - let exprs = num isa 19UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit20 -> - let exprs = num isa 20UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit21 -> - let exprs = num isa 21UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit22 -> - let exprs = num isa 22UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit23 -> - let exprs = num isa 23UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit24 -> - let exprs = num isa 24UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit25 -> - let exprs = num isa 25UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit26 -> - let exprs = num isa 26UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit27 -> - let exprs = num isa 27UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit28 -> - let exprs = num isa 28UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit29 -> - let exprs = num isa 29UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit30 -> - let exprs = num isa 30UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lit31 -> - let exprs = num isa 31UL :: exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_and -> - let exprs = parseBinop BinOpType.AND exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_or -> - let exprs = parseBinop BinOpType.OR exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_xor -> - let exprs = parseBinop BinOpType.XOR exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_div -> - let exprs = parseBinop BinOpType.DIV exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_minus -> - (* There is an exceptional case where ICC compbiler uses DW_OP_minus with - a single opearnd. This is not the standard way. *) - let exprs = - if hasLessThanTwoOperands exprs then [ num isa 0UL ] - else parseBinop BinOpType.SUB exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_plus -> - let exprs = parseBinop BinOpType.ADD exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_plus_uconst -> - let struct (exprs, i') = parsePlusUconst isa exprs span (i + 1) - parseExprs isa regbay exprs span i' maxIdx - | DWOperation.DW_OP_mul -> - let exprs = parseBinop BinOpType.MUL exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_shl -> - let exprs = parseBinop BinOpType.SHL exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_shr -> - let exprs = parseBinop BinOpType.SHR exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_shra -> - let exprs = parseBinop BinOpType.SAR exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_le -> - let exprs = parseRel isa RelOpType.LE exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_ge -> - let exprs = parseRel isa RelOpType.GE exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_eq -> - let exprs = parseRel isa RelOpType.EQ exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_lt -> - let exprs = parseRel isa RelOpType.LT exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_gt -> - let exprs = parseRel isa RelOpType.GT exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_ne -> - let exprs = parseRel isa RelOpType.NEQ exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | DWOperation.DW_OP_deref -> - let exprs = parseLoad isa exprs - parseExprs isa regbay exprs span (i + 1) maxIdx - | op -> printfn "TODO: %A" op; Utils.futureFeature () - -let extractOldOffset = function - | RegPlusOffset (_, o) -> o - | UnknownCFA -> 0 - | e -> Utils.impossible () - -let restoreOne initialRule currentRule target = - match Map.tryFind target initialRule with - | Some oldVal -> Map.add target oldVal currentRule - | None -> Map.remove target currentRule - -let rec getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc = - if i >= (span: ByteSpan).Length then - { Location = loc - CanonicalFrameAddress = cfa - Rule = rule } :: acc |> List.rev, cfa, lr - else - let op = span[i] - let oparg = span[i] &&& 0x3fuy - let i = i + 1 - let op = if op &&& 0xc0uy > 0uy then op &&& 0xc0uy else op - match DWCFAInstruction.parse op with - | DWCFAInstruction.DW_CFA_def_cfa -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let i = i + cnt - let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) - let cfa = CanonicalFrameAddress.regPlusOffset isa rbay reg (int offset) - getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_def_cfa_sf -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let i = i + cnt - let v, cnt = LEB128.DecodeSInt64 (span.Slice i) - let offset = int (v * df) - let cfa = CanonicalFrameAddress.regPlusOffset isa rbay reg offset - getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_def_cfa_offset -> - let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) - let cfa = CanonicalFrameAddress.regPlusOffset isa rbay lr (int offset) - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_def_cfa_offset_sf -> - let offset, cnt = LEB128.DecodeSInt64 (span.Slice i) - let offset = int (offset * df) - let cfa = CanonicalFrameAddress.regPlusOffset isa rbay lr offset - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_def_cfa_expression -> - let v, cnt = LEB128.DecodeUInt64 (span.Slice i) - let i = i + cnt - let nextIdx = int v + i - let cfa = parseExprs isa rbay [] span i nextIdx |> Expression - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span nextIdx loc - | DWCFAInstruction.DW_CFA_def_cfa_register -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let rid = DWRegister.toRegID isa reg - let oldOffset = extractOldOffset cfa - let cfa = RegPlusOffset (rid, oldOffset) - getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_offset -> - let v, cnt = LEB128.DecodeUInt64 (span.Slice i) - let offset = int64 v * df - let target, action = Rule.offset isa rr oparg offset - let rule = Map.add target action rule - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_offset_extended -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let i = i + cnt - let offset, cnt = LEB128.DecodeUInt64 (span.Slice i) - let target, action = Rule.offset isa rr reg (int64 offset) - let rule = Map.add target action rule - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_offset_extended_sf -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let i = i + cnt - let v, cnt = LEB128.DecodeSInt64 (span.Slice i) - let offset = v * df - let target, action = Rule.offset isa rr reg offset - let rule = Map.add target action rule - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_undefined -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let target = Rule.getTarget isa rr reg - let rule = Map.remove target rule - getUnwind acc cfa irule rst rule isa rbay reg cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_register -> - let reg1, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg1 = byte reg1 - let i = i + cnt - let reg2, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg2 = byte reg2 - let target = Rule.getTarget isa rr reg1 - let action = Register (DWRegister.toRegID isa reg2) - let rule = Map.add target action rule - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_expression -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let i = i + cnt - let v, cnt = LEB128.DecodeUInt64 (span.Slice i) - let i = i + cnt - let nextIdx = int v + i - let target = Rule.getTarget isa rr reg - let action = parseExprs isa rbay [] span i nextIdx |> ActionExpr - let rule = Map.add target action rule - getUnwind acc cfa irule rst rule isa rbay reg cf df rr span nextIdx loc - | DWCFAInstruction.DW_CFA_val_expression -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let reg = byte reg - let i = i + cnt - let v, cnt = LEB128.DecodeUInt64 (span.Slice i) - let i = i + cnt - let nextIdx = int v + i - let target = Rule.getTarget isa rr reg - let action = parseExprs isa rbay [] span i nextIdx |> ActionValExpr - let rule = Map.add target action rule - getUnwind acc cfa irule rst rule isa rbay reg cf df rr span nextIdx loc - | DWCFAInstruction.DW_CFA_advance_loc -> - let loc' = loc + uint64 oparg * cf - let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } - let acc = ent :: acc - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc' - | DWCFAInstruction.DW_CFA_advance_loc1 -> - let loc' = loc + uint64 span[i] - let i' = i + 1 - let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } - let acc = ent :: acc - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i' loc' - | DWCFAInstruction.DW_CFA_advance_loc2 -> - let loc' = loc + uint64 (MemoryMarshal.Read (span.Slice (i))) - let i' = i + 2 - let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } - let acc = ent :: acc - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i' loc' - | DWCFAInstruction.DW_CFA_advance_loc4 -> - let loc' = loc + uint64 (MemoryMarshal.Read (span.Slice (i))) - let i' = i + 4 - let ent = { Location = loc; CanonicalFrameAddress = cfa; Rule = rule } - let acc = ent :: acc - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i' loc' - | DWCFAInstruction.DW_CFA_remember_state -> - let rst = (cfa, rule, lr) :: rst - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc - | DWCFAInstruction.DW_CFA_restore -> - let target = Rule.getTarget isa rr oparg - let rule = restoreOne irule rule target - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc - | DWCFAInstruction.DW_CFA_restore_extended -> - let reg, cnt = LEB128.DecodeUInt64 (span.Slice i) - let target = Rule.getTarget isa rr (byte reg) - let rule = restoreOne irule rule target - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_restore_state -> - let cfa, rule, lr = List.head rst - let rst = List.tail rst - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc - | DWCFAInstruction.DW_CFA_GNU_args_size -> - let _, cnt = LEB128.DecodeUInt64 (span.Slice i) - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span (i + cnt) loc - | DWCFAInstruction.DW_CFA_nop -> - getUnwind acc cfa irule rst rule isa rbay lr cf df rr span i loc - | op -> printfn "%A" op; Utils.futureFeature () - -let extractRule unwindingInfo = - match unwindingInfo with - | [ row ] -> row.Rule - | _ -> Map.empty - -let parseCIE cls isa rbay span offset nextOffset = - let version = (span: ByteSpan)[offset] - let offset = offset + 1 - if version = 1uy || version = 3uy then - let augstr = ByteArray.extractCStringFromSpan span offset - let addrSize = WordSize.toByteWidth cls - let offset = offset + augstr.Length + 1 - let offset = if augstr.Contains "eh" then offset + addrSize else offset - let cf, offset = parseULEB128 span offset - let df, offset = parseSLEB128 span offset - let rr, offset = parseReturnRegister span version offset - let augs, offset = parseAugmentationData span offset addrSize augstr - let instrLen = nextOffset - offset - if instrLen > 0 then - let span = span.Slice (offset, instrLen) - let rule = Map.empty - getUnwind [] UnknownCFA rule [] rule isa rbay rr cf df rr span 0 0UL - else [], UnknownCFA, rr - |> fun (info, cfa, reg) -> - { Version = version - AugmentationString = augstr - CodeAlignmentFactor = cf - DataAlignmentFactor = df - ReturnAddressRegister = byte rr - InitialRule = extractRule info - InitialCFARegister = reg - InitialCFA = cfa - Augmentations = augs } - else - raise UnhandledExceptionHandlingFrameVersion - -let tryFindAugmentation cie format = - cie.Augmentations |> List.tryFind (fun aug -> aug.Format = format) - -let adjustAddr app myAddr addr = - match app with - | ExceptionHeaderApplication.DW_EH_PE_pcrel -> addr + myAddr - | _ -> addr - -let parsePCInfo cls span reader sAddr (rel: RelocInfo option) venc aenc offset = - let myAddr = sAddr + uint64 offset - let struct (addr, offset) = computeValue cls span reader venc offset - let struct (range, offset) = computeValue cls span reader venc offset - let beginAddr = adjustAddr aenc myAddr addr - let endAddr = beginAddr + range - match rel with - | Some relInfo -> - let found, rentry = relInfo.RelocByAddr.TryGetValue beginAddr - if found then - let beginAddr = addr + rentry.RelAddend - struct (beginAddr, beginAddr + range, offset) - else struct (beginAddr, endAddr, offset) - | None -> struct (beginAddr, endAddr, offset) - -let parseLSDA cls span reader sAddr aug offset = - let _, offset = parseULEB128 span offset - let myAddr = sAddr + uint64 offset - let struct (addr, offset) = - computeValue cls span reader aug.ValueEncoding offset - Some (adjustAddr aug.ApplicationEncoding myAddr addr), offset - -let parseCallFrameInstrs cie isa regbay (span: ByteSpan) offset nextOffset loc = - let span = span.Slice (offset, nextOffset - offset) - let insarr = span.ToArray () - if Array.forall (fun b -> b = 0uy) insarr then [] - else - let cf = cie.CodeAlignmentFactor - let df = cie.DataAlignmentFactor - let rr = cie.ReturnAddressRegister - let ir = cie.InitialCFARegister - let r = cie.InitialRule - let cfa = cie.InitialCFA - let info, _, _ = getUnwind [] cfa r [] r isa regbay ir cf df rr span 0 loc - info - -let parseFDE cls isa regbay span reader sAddr offset nextOffset reloc cie = - match cie with - | Some cie -> - let venc, aenc = - match tryFindAugmentation cie 'R' with - | Some aug -> aug.ValueEncoding, aug.ApplicationEncoding - | None -> ExceptionHeaderValue.DW_EH_PE_absptr, - ExceptionHeaderApplication.DW_EH_PE_absptr - let struct (b, e, offset) = - parsePCInfo cls span reader sAddr reloc venc aenc offset - let lsdaPointer, offset = - match tryFindAugmentation cie 'L' with - | Some aug -> parseLSDA cls span reader sAddr aug offset - | None -> None, offset - let info = parseCallFrameInstrs cie isa regbay span offset nextOffset b - { PCBegin = b - PCEnd = e - LSDAPointer = lsdaPointer - UnwindingInfo = info } - | None -> raise CIENotFoundByFDE - -let accumulateCFIs cfis cie fdes = - match cie with - | Some cie -> - { CIERecord = cie - FDERecord = List.rev fdes |> List.toArray } :: cfis - | None -> cfis - -let rec parseCFI cls isa rb span reader sAddr cie cies fdes offset cfis reloc = - if offset >= (span: ByteSpan).Length then - accumulateCFIs cfis cie fdes - else - let originalOffset = offset - let struct (len, offset) = readInt span reader offset - if len = 0 then accumulateCFIs cfis cie fdes - else - let nextOfs, offset = computeNextOffset len span reader offset - let mybase = offset - let struct (id, offset) = readInt span reader offset - if id = 0 then - let cfis = accumulateCFIs cfis cie fdes - let cie = parseCIE cls isa rb span offset nextOfs - let cies = Map.add originalOffset cie cies - let cie = Some cie - parseCFI cls isa rb span reader sAddr cie cies [] nextOfs cfis reloc - else - let cieOffset = mybase - id (* id = a CIE pointer, when id <> 0 *) - let fde = - parseFDE cls isa rb span reader sAddr offset nextOfs reloc - (Map.tryFind cieOffset cies) - let fdes = fde :: fdes - parseCFI cls isa rb span reader sAddr cie cies fdes nextOfs cfis reloc - -let parse span (reader: IBinReader) cls (secs: SectionInfo) isa regbay reloc = - match Map.tryFind Ehframe secs.SecByName with - | Some sec when Option.isSome regbay -> - let size = Convert.ToInt32 sec.SecSize - let offset = Convert.ToInt32 sec.SecOffset - let span = (span: ByteSpan).Slice (offset, size) - let regbay = Option.get regbay - parseCFI cls isa regbay span reader sec.SecAddr None Map.empty [] 0 [] reloc - |> List.rev - | _ -> [] diff --git a/src/FrontEnd/BinFile/ELFGccExceptTable.fs b/src/FrontEnd/BinFile/ELFGccExceptTable.fs deleted file mode 100644 index 42fca814..00000000 --- a/src/FrontEnd/BinFile/ELFGccExceptTable.fs +++ /dev/null @@ -1,169 +0,0 @@ -(* -B2R2 - the Next-Generation Reversing Platform - -Copyright (c) SoftSec Lab. @ KAIST, since 2016 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*) - -[] -module internal B2R2.FrontEnd.BinFile.ELF.ELFGccExceptTable - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.ELF.ExceptionHeaderEncoding - -let [] GccExceptTable = ".gcc_except_table" - -let parseLSDAHeader cls (span: ByteSpan) reader sAddr offset = - let b = span[offset] - let offset = offset + 1 - let struct (lpv, lpapp) = parseEncoding b - let struct (lpstart, offset) = - if lpv = ExceptionHeaderValue.DW_EH_PE_omit then struct (None, offset) - else - let struct (cv, offset) = computeValue cls span reader lpv offset - struct (Some (sAddr + uint64 offset + cv), offset) - let b = span[offset] - let offset = offset + 1 - let struct (ttv, ttapp) = parseEncoding b - let struct (ttbase, offset) = - if ttv = ExceptionHeaderValue.DW_EH_PE_omit then struct (None, offset) - else - let cv, offset = parseULEB128 span offset - struct (Some (sAddr + uint64 offset + cv), offset) - let b = span[offset] - let offset = offset + 1 - let struct (csv, csapp) = parseEncoding b - let cstsz, offset = parseULEB128 span offset - { LPValueEncoding = lpv - LPAppEncoding = lpapp - LPStart = lpstart - TTValueEncoding = ttv - TTAppEncoding = ttapp - TTBase = ttbase - CallSiteValueEncoding = csv - CallSiteAppEncoding = csapp - CallSiteTableSize = cstsz }, offset - -let rec parseCallSiteTable acc cls span reader offset csv hasAction = - (* We found that GCC sometimes produces a wrong callsite table length, and the - length can be off by one. So we minus one here. This is conservative - anyways, because callsite entry can only be larger than three bytes. *) - if offset >= (span: ByteSpan).Length - 3 then - List.rev acc, hasAction - else - let struct (start, offset) = computeValue cls span reader csv offset - let struct (length, offset) = computeValue cls span reader csv offset - let struct (landingPad, offset) = computeValue cls span reader csv offset - let actionOffset, offset = parseULEB128 span offset - let acc = - if start = 0UL && length = 0UL && landingPad = 0UL && actionOffset = 0UL - then acc (* This can appear due to the miscalculation issue above. *) - else { Position = start - Length = length - LandingPad = landingPad - ActionOffset = int actionOffset - ActionTypeFilters = [] } :: acc - let hasAction = if actionOffset > 0UL then true else hasAction - parseCallSiteTable acc cls span reader offset csv hasAction - -let rec parseActionEntries acc span offset actOffset = - if actOffset > 0 then - let tfilter, offset = parseSLEB128 span (actOffset - 1 + offset) - let next, offset = parseSLEB128 span offset - let acc = tfilter :: acc - parseActionEntries acc span offset (int next) - else List.rev acc - -let rec parseActionTable acc span offset callsites = - match callsites with - | csEntry :: tl -> - let filters = parseActionEntries [] span offset csEntry.ActionOffset - let acc = { csEntry with ActionTypeFilters = filters } :: acc - parseActionTable acc span offset tl - | [] -> List.rev acc - -let findMinOrZero lst = - match lst with - | [] -> 0L - | _ -> List.min lst - -let findMinFilter callsites = - if List.isEmpty callsites then 0L - else - callsites - |> List.map (fun cs -> cs.ActionTypeFilters |> findMinOrZero) - |> List.min - -let rec readUntilNull (span: ByteSpan) offset = - if span[offset] = 0uy then (offset + 1) - else readUntilNull span (offset + 1) - -/// We currently just skip the type table by picking up the minimum filter value -/// as we don't use the type table. -let skipTypeTable span ttbase callsites = - let minFilter = findMinFilter callsites - if minFilter < 0L then - let offset = ttbase - int minFilter - 1 - readUntilNull span offset (* Consume exception spec table. *) - else ttbase - -/// Sometimes, we observe dummy zero bytes inserted by the compiler (icc); this -/// is nothing to do with the alignment. This is likely to be the compiler -/// error, but we should safely ignore those dummy bytes. -let rec skipDummyAlign (span: ByteSpan) offset = - if offset >= span.Length then offset - else - let b = span[offset] - if b = 0uy then skipDummyAlign span (offset + 1) - else offset - -/// Parse language-specific data area. -let rec parseLSDA cls (span: ByteSpan) reader sAddr offset lsdas = - if offset >= span.Length then lsdas - else - let lsdaAddr = sAddr + uint64 offset - let header, offset = parseLSDAHeader cls span reader sAddr offset - let subspn = span.Slice (offset, int header.CallSiteTableSize) - let encoding = header.CallSiteValueEncoding - let callsites, hasAction = - parseCallSiteTable [] cls subspn reader 0 encoding false - let offset = offset + int header.CallSiteTableSize - let callsites = - if hasAction then parseActionTable [] span offset callsites - else callsites - let offset = - match header.TTBase with - | Some ttbase -> int (ttbase - sAddr) - | None -> offset - let offset = skipTypeTable span offset callsites - let offset = skipDummyAlign span offset - let lsda = { Header = header; CallSiteTable = callsites } - let lsdas = Map.add lsdaAddr lsda lsdas - parseLSDA cls span reader sAddr offset lsdas - -let parse (span: ByteSpan) reader cls (secs: SectionInfo) = - match Map.tryFind GccExceptTable secs.SecByName with - | Some sec -> - let size = Convert.ToInt32 sec.SecSize - let offset = Convert.ToInt32 sec.SecOffset - let span = span.Slice (offset, size) - parseLSDA cls span reader sec.SecAddr 0 Map.empty - | None -> Map.empty diff --git a/src/FrontEnd/BinFile/ELFHeader.fs b/src/FrontEnd/BinFile/ELFHeader.fs deleted file mode 100644 index a6e60705..00000000 --- a/src/FrontEnd/BinFile/ELFHeader.fs +++ /dev/null @@ -1,111 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.Header - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.FileHelper - -let private elfMagicNumber = [| 0x7fuy; 0x45uy; 0x4cuy; 0x46uy |] - -/// Check if the file has a valid ELF header. -let isELF (span: ByteSpan) = - span.Length > 4 - && span.Slice(0, 4).SequenceEqual (ReadOnlySpan elfMagicNumber) - -let peekClass (span: ByteSpan) = - match span[4] with - | 0x1uy -> WordSize.Bit32 - | 0x2uy -> WordSize.Bit64 - | _ -> raise InvalidWordSizeException - -let peekEndianness (span: ByteSpan) = - match span[5] with - | 0x1uy -> Endian.Little - | 0x2uy -> Endian.Big - | _ -> raise InvalidEndianException - -let peekELFFileType (span: ByteSpan) (reader: IBinReader) = - reader.ReadUInt16 (span, 16) - |> LanguagePrimitives.EnumOfValue: ELFFileType - -let peekELFFlags span reader cls = - peekHeaderU32 span reader cls 0 36 48 - -let getMIPSISA span reader cls = - match peekELFFlags span reader cls &&& 0xf0000000u with - | 0x00000000u -> Arch.MIPS1 - | 0x10000000u -> Arch.MIPS2 - | 0x20000000u -> Arch.MIPS3 - | 0x30000000u -> Arch.MIPS4 - | 0x40000000u -> Arch.MIPS5 - | 0x50000000u -> Arch.MIPS32 - | 0x60000000u -> Arch.MIPS64 - | 0x70000000u -> Arch.MIPS32R2 - | 0x80000000u -> Arch.MIPS64R2 - | 0x90000000u -> Arch.MIPS32R6 - | 0xa0000000u -> Arch.MIPS64R6 - | c -> failwithf "invalid MIPS arch (%02x)" c - -let peekArch (span: ByteSpan) (reader: IBinReader) cls = - match reader.ReadInt16 (span, 18) with - | 0x03s -> Arch.IntelX86 - | 0x3es -> Arch.IntelX64 - | 0x28s -> Arch.ARMv7 - | 0xb7s -> Arch.AARCH64 - | 0x08s | 0x0as -> getMIPSISA span reader cls - | 0x53s -> Arch.AVR - | 0x2as -> Arch.SH4 - | 0x14s -> Arch.PPC32 - | 0x2bs -> Arch.Sparc64 - | 0xf3s -> Arch.RISCV64 (* FIXME: RISCV *) - | _ -> Arch.UnknownISA - -let computeNewBaseAddr ftype baseAddr = - match ftype with - | ELFFileType.Executable -> 0UL (* Non-pie executable must have zero base. *) - | _ -> defaultArg baseAddr 0UL - -let parse span (reader: IBinReader) baseAddr = - let cls = peekClass span - let ftype = peekELFFileType span reader - let baseAddr = computeNewBaseAddr ftype baseAddr - { Class = cls - Endian = peekEndianness span - Version = peekHeaderU32 span reader cls 0 6 6 - OSABI = span[7] |> LanguagePrimitives.EnumOfValue - OSABIVersion = span[8] |> uint32 - ELFFileType = ftype - MachineType = peekArch span reader cls - EntryPoint = peekHeaderNative span reader cls 0 24 24 + baseAddr - PHdrTblOffset = peekHeaderNative span reader cls 0 28 32 - SHdrTblOffset = peekHeaderNative span reader cls 0 32 40 - ELFFlags = peekELFFlags span reader cls - HeaderSize = peekHeaderU16 span reader cls 0 40 52 - PHdrEntrySize = peekHeaderU16 span reader cls 0 42 54 - PHdrNum = peekHeaderU16 span reader cls 0 44 56 - SHdrEntrySize = peekHeaderU16 span reader cls 0 46 58 - SHdrNum = peekHeaderU16 span reader cls 0 48 60 - SHdrStrIdx = peekHeaderU16 span reader cls 0 50 62 }, baseAddr diff --git a/src/FrontEnd/BinFile/ELFHelper.fs b/src/FrontEnd/BinFile/ELFHelper.fs deleted file mode 100644 index 21f4113e..00000000 --- a/src/FrontEnd/BinFile/ELFHelper.fs +++ /dev/null @@ -1,231 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.Helper - -open System -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile - -let convFileType = function - | ELFFileType.Executable -> FileType.ExecutableFile - | ELFFileType.SharedObject -> FileType.LibFile - | ELFFileType.Core -> FileType.CoreFile - | ELFFileType.Relocatable -> FileType.ObjFile - | _ -> FileType.UnknownFile - -let isNXEnabled elf = - let predicate e = e.PHType = ProgramHeaderType.PTGNUStack - match List.tryFind predicate elf.ProgHeaders with - | Some s -> s.PHFlags.HasFlag Permission.Executable |> not - | _ -> false - -let isRelocatable span elf = - let pred (e: DynamicSectionEntry) = e.DTag = DynamicSectionTag.DTDebug - elf.ELFHdr.ELFFileType = ELFFileType.SharedObject - && Section.getDynamicSectionEntries span elf.BinReader elf.SecInfo - |> List.exists pred - -let inline getTextStartAddr elf = - (Map.find Section.SecText elf.SecInfo.SecByName).SecAddr - -let inline private inMem seg addr = - let vAddr = seg.PHAddr - addr >= vAddr && addr < vAddr + seg.PHMemSize - -let translateWithSecs addr (secs: ELFSection []) = - secs - |> Array.tryFindIndex (fun s -> - s.SecType = SectionType.SHTProgBits - && s.SecAddr <= addr && (s.SecAddr + s.SecSize) > addr) - |> function - | None -> raise InvalidAddrReadException - | Some idx -> secs[idx].SecOffset + addr |> Convert.ToInt32 - -let rec translateWithSegs addr = function - | seg :: tl -> - if inMem seg addr then Convert.ToInt32 (addr - seg.PHAddr + seg.PHOffset) - else translateWithSegs addr tl - | [] -> raise InvalidAddrReadException - -let translateAddr addr elf = - match elf.LoadableSegments with - | [] -> translateWithSecs addr elf.SecInfo.SecByNum - | segs -> translateWithSegs addr segs - -let isFuncSymb s = - s.SymType = SymbolType.STTFunc || s.SymType = SymbolType.STTGNUIFunc - -let inline tryFindFuncSymb elf addr = - match Map.tryFind addr elf.SymInfo.AddrToSymbTable with - | None -> Error ErrorCase.SymbolNotFound - | Some s -> - if isFuncSymb s then Ok s.SymName - else Error ErrorCase.SymbolNotFound - -let getStaticSymbols elf = - Symbol.getStaticSymArray elf - |> Array.map (Symbol.toB2R2Symbol TargetKind.StaticSymbol) - |> Array.toSeq - -let getDynamicSymbols excludeImported elf = - let excludeImported = defaultArg excludeImported false - let alwaysTrue = fun _ -> true - let filter = - if excludeImported then (fun s -> s.SecHeaderIndex <> SHNUndef) - else alwaysTrue - Symbol.getDynamicSymArray elf - |> Array.filter filter - |> Array.map (Symbol.toB2R2Symbol TargetKind.DynamicSymbol) - |> Array.toSeq - -let getSymbols elf = - let s = getStaticSymbols elf - let d = getDynamicSymbols None elf - Seq.append s d - -let getRelocSymbols elf = - let translate reloc = - reloc.RelSymbol - |> Option.bind (fun s -> - { s with Addr = reloc.RelOffset } - |> Symbol.toB2R2Symbol TargetKind.DynamicSymbol - |> Some) - elf.RelocInfo.RelocByName.Values - |> Seq.choose translate - -let secFlagToSectionKind sec = - if sec.SecFlags &&& SectionFlag.SHFExecInstr = SectionFlag.SHFExecInstr then - if PLT.isPLTSectionName sec.SecName then SectionKind.LinkageTableSection - else SectionKind.ExecutableSection - elif sec.SecFlags &&& SectionFlag.SHFWrite = SectionFlag.SHFWrite then - SectionKind.WritableSection - else - SectionKind.ExtraSection - -let elfSectionToSection sec = - { Address = sec.SecAddr - FileOffset = sec.SecOffset - Kind = secFlagToSectionKind sec - Size = sec.SecSize - Name = sec.SecName } - -let getSections elf = - elf.SecInfo.SecByNum - |> Array.map elfSectionToSection - |> Array.toSeq - -let getSectionsByAddr elf addr = - match ARMap.tryFindByAddr addr elf.SecInfo.SecByAddr with - | Some s -> elfSectionToSection s |> Seq.singleton - | None -> Seq.empty - -let getSectionsByName elf name = - match Map.tryFind name elf.SecInfo.SecByName with - | Some s -> elfSectionToSection s |> Seq.singleton - | None -> Seq.empty - -let getTextSections elf = - elf.SecInfo.SecByNum - |> Array.filter (fun sec -> - (SectionFlag.SHFExecInstr &&& sec.SecFlags = SectionFlag.SHFExecInstr) - && sec.SecName.StartsWith Section.SecText) - |> Array.map elfSectionToSection - |> Array.toSeq - -let getSegments elf isLoadable = - if isLoadable then elf.LoadableSegments else elf.ProgHeaders - |> List.map ProgHeader.toSegment - |> List.toSeq - -let getPLT elf = - let create pltAddr (symb: ELFSymbol) = - { FuncName = symb.SymName - LibraryName = Symbol.versionToLibName symb.VerInfo - TrampolineAddress = pltAddr - TableAddress = symb.Addr } - elf.PLT - |> ARMap.fold (fun acc addrRange s -> create addrRange.Min s :: acc) [] - |> List.sortBy (fun entry -> entry.TrampolineAddress) - |> List.toSeq - -let isInPLT elf addr = - ARMap.containsAddr addr elf.PLT - -let inline isValidAddr elf addr = - IntervalSet.containsAddr addr elf.InvalidAddrRanges |> not - -let inline isValidRange elf range = - IntervalSet.findAll range elf.InvalidAddrRanges |> List.isEmpty - -let inline isInFileAddr elf addr = - IntervalSet.containsAddr addr elf.NotInFileRanges |> not - -let inline isInFileRange elf range = - IntervalSet.findAll range elf.NotInFileRanges |> List.isEmpty - -let inline isExecutableAddr elf addr = - IntervalSet.containsAddr addr elf.ExecutableRanges - -let getNotInFileIntervals elf range = - IntervalSet.findAll range elf.NotInFileRanges - |> List.map (FileHelper.trimByRange range) - |> List.toSeq - -let getFunctionAddrsFromLibcArray span elf s = - let offset = int s.SecOffset - let entrySize = int s.SecEntrySize - let readType: WordSize = LanguagePrimitives.EnumOfValue (entrySize * 8) - let size = int s.SecSize - if entrySize = 0 then Seq.empty - else - let lst = List () - for o in [| offset .. entrySize .. offset + size - entrySize |] do - lst.Add (FileHelper.peekUIntOfType span elf.BinReader readType o) - lst - -let getAddrsFromInitArray span elf = - match Map.tryFind ".init_array" elf.SecInfo.SecByName with - | Some s -> getFunctionAddrsFromLibcArray span elf s - | None -> Seq.empty - -let getAddrsFromFiniArray span elf = - match Map.tryFind ".fini_array" elf.SecInfo.SecByName with - | Some s -> getFunctionAddrsFromLibcArray span elf s - | None -> Seq.empty - -let addExtraFunctionAddrs span elf useExceptionInfo addrs = - let addrSet = - [ addrs; getAddrsFromInitArray span elf; getAddrsFromFiniArray span elf ] - |> Seq.concat - |> Set.ofSeq - if useExceptionInfo then (* XXX *) - elf.ExceptionFrame - |> List.fold (fun set cfi -> - cfi.FDERecord - |> Array.fold (fun set fde -> Set.add fde.PCBegin set) set - ) addrSet - |> Set.toSeq - else addrSet |> Set.toSeq diff --git a/src/FrontEnd/BinFile/ELFPLT.fs b/src/FrontEnd/BinFile/ELFPLT.fs deleted file mode 100644 index ae9f4952..00000000 --- a/src/FrontEnd/BinFile/ELFPLT.fs +++ /dev/null @@ -1,492 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.PLT - -open System -open B2R2 - -type CodeKind = - | PIC - | NonPIC - | DontCare - -type PLTLinkMethod = - | LazyBinding - | EagerBinding - -type PLTEntryInfo = { - EntryRelocAddr: Addr - NextEntryAddr: Addr -} - -type PLTDescriptor = { - /// PLT start address. - StartAddr: Addr - /// PIC or non-PIC. - CodeKind: CodeKind - /// Lazy vs. Non-lazy (eager) binding. - LinkMethod: PLTLinkMethod - /// Is secondary PLT? - IsSecondary: bool - /// Entry size of the PLT. - EntrySize: int - /// Offset from a start of a PLT entry to the index to the GOT. - GOTOffset: Addr - /// Size of the instruction that refers to the GOT. - InstrSize: Addr - /// Compute a EntryInfo from (Entry index, current entry address, - /// PLTDescriptor, BinReader, gotBaseAddr). Each PLT has its own retriever. - InfoRetriever: IPLTInfoRetriever -} - -and IPLTInfoRetriever = - abstract Get: - Addr - * int - * PLTDescriptor - * ByteSpan - * IBinReader - * ELFSection - * Addr - -> Result - -type PLTType = - /// The regular PLT. - | PLT of desc: PLTDescriptor - /// The PLT pattern is unknown. - | UnknownPLT - -let newPLT start kind lm isSecondary size gotoff inslen retriever = - PLT { StartAddr = start - CodeKind = kind - LinkMethod = lm - IsSecondary = isSecondary - EntrySize = size - GOTOffset = gotoff - InstrSize = inslen - InfoRetriever = retriever } - -let isPLTSectionName name = - name = ".plt" || name = ".plt.sec" || name = ".plt.got" || name = ".plt.bnd" - -let isSecondaryLazy desc = - desc.IsSecondary && desc.LinkMethod = LazyBinding - -let gotAddr sections = - match Map.tryFind ".got.plt" sections.SecByName with - | Some s -> Some s.SecAddr - | None -> - match Map.tryFind ".got" sections.SecByName with - | Some s -> Some s.SecAddr - | None -> None - -let findFirstPLTGOTAddr reloc sections = - match Map.tryFind ".rel.plt" sections.SecByName with - | Some s -> - reloc.RelocByAddr.Values - |> Seq.fold (fun minval r -> - if r.RelSecNumber = s.SecNum then - if r.RelOffset < minval then r.RelOffset else minval - else minval) UInt64.MaxValue - | None -> 0UL - -let findFirstJumpSlot reloc = - reloc.RelocByAddr.Values - |> Seq.fold (fun minval r -> - match r.RelType with - | RelocationARMv8 RelocationARMv8.RelocAARCH64JmpSlot -> - if r.RelOffset < minval then r.RelOffset else minval - | _ -> minval) UInt64.MaxValue - -let findGOTBase arch reloc sections = - let got = gotAddr sections - match arch with - | Arch.IntelX86 - | Arch.IntelX64 -> got - | Arch.ARMv7 - | Arch.AARCH32 -> - got |> Option.map (fun _ -> findFirstPLTGOTAddr reloc sections) - | Arch.AARCH64 -> - got |> Option.map (fun _ -> findFirstJumpSlot reloc) - | _ -> got - -let filterPLTSections sections = - sections.SecByName |> Map.fold (fun acc _ s -> - if isPLTSectionName s.SecName then s :: acc else acc) [] - |> List.rev (* .plt, .plt.got, .plt.sec *) - -type X86NonPICRetriever () = - interface IPLTInfoRetriever with - member __.Get (addr, _, typ, span: ByteSpan, r: IBinReader, sec, _) = - let addrDiff = int (addr - typ.StartAddr) - let offset = addrDiff + int typ.GOTOffset + int sec.SecOffset - { EntryRelocAddr = r.ReadInt32 (span, offset) |> uint64 - NextEntryAddr = addr + uint64 typ.EntrySize } |> Ok - -type X86PICRetriever () = - interface IPLTInfoRetriever with - member __.Get (addr, _, typ, span: ByteSpan, r: IBinReader, sec, gotBase) = - let addrDiff = int (addr - typ.StartAddr) - let offset = addrDiff + int typ.GOTOffset + int sec.SecOffset - { EntryRelocAddr = (r.ReadInt32 (span, offset) |> uint64) + gotBase - NextEntryAddr = addr + uint64 typ.EntrySize } |> Ok - -let x86PICLazy (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let zeroEntry = (* push indirect addr; jmp; *) - [| OneByte 0xffuy; OneByte 0xb3uy; OneByte 0x04uy; AnyByte; AnyByte; AnyByte - OneByte 0xffuy; OneByte 0xa3uy; OneByte 0x08uy; AnyByte; AnyByte; AnyByte - |] - let ibtEntry = (* (Ind-Branch-Tracking) endbr32; push; jmp rel; *) - [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy; - OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte - OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte |] - if BytePattern.matchSpan zeroEntry plt then - let isIBT = BytePattern.matchSpan ibtEntry (plt.Slice 16) - let gotoff = if isIBT then 6UL else 2UL - let retriever = X86PICRetriever () :> IPLTInfoRetriever - newPLT sec.SecAddr PIC LazyBinding isIBT 16 gotoff 0UL retriever |> Some - else None - -let x86NonPICLazy (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let zeroEntry = (* push absolute addr; jmp; *) - [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte - OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte |] - let ibtEntry = (* (Ind-Branch-Tracking) endbr32; jmp got; *) - [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy; - OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte - OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte |] - if BytePattern.matchSpan zeroEntry plt then - let isIBT = BytePattern.matchSpan ibtEntry (plt.Slice 16) - let gotoff = if isIBT then 6UL else 2UL - let retriever = X86NonPICRetriever () :> IPLTInfoRetriever - newPLT sec.SecAddr NonPIC LazyBinding isIBT 16 gotoff 0UL retriever |> Some - else None - -let x86PICNonLazy (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let entry = (* jmp indirect addr; nop *) - [| OneByte 0xffuy; OneByte 0xa3uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte |] - let ibtEntry = (* endbr32; jmp got; *) - [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy - OneByte 0xffuy; OneByte 0xa3uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] - if BytePattern.matchSpan entry plt then - let retriever = X86PICRetriever () :> IPLTInfoRetriever - newPLT sec.SecAddr PIC EagerBinding false 8 2UL 0UL retriever |> Some - elif BytePattern.matchSpan ibtEntry plt then - let retriever = X86PICRetriever () :> IPLTInfoRetriever - newPLT sec.SecAddr PIC EagerBinding true 8 6UL 0UL retriever |> Some - else None - -let x86NonPICNonLazy (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let entry = (* jmp indirect addr; nop *) - [| OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte |] - let ibtEntry = (* endbr32; jmp got; *) - [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfbuy - OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] - if BytePattern.matchSpan entry plt then - let retriever = X86NonPICRetriever () :> IPLTInfoRetriever - newPLT sec.SecAddr NonPIC EagerBinding false 8 2UL 0UL retriever |> Some - elif BytePattern.matchSpan ibtEntry plt then - let retriever = X86NonPICRetriever () :> IPLTInfoRetriever - newPLT sec.SecAddr NonPIC EagerBinding true 8 6UL 0UL retriever |> Some - else None - -type X64Retriever () = - interface IPLTInfoRetriever with - member __.Get (addr, _, typ, span: ByteSpan, r: IBinReader, sec, _) = - let addrDiff = int (addr - typ.StartAddr) - let offset = addrDiff + int typ.GOTOffset + int sec.SecOffset - let v = r.ReadInt32 (span, offset) - { EntryRelocAddr = addr + typ.InstrSize + uint64 v - NextEntryAddr = addr + uint64 typ.EntrySize } |> Ok - -let x64Lazy (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let zeroEntry = (* push [got+8]; jmp [got+16]; *) - [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte - OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte |] - let ibtZeroEntry = (* (Ind-Branch-Tracking) push [got+8]; bnd jmp [got+16]; *) - [| OneByte 0xffuy; OneByte 0x35uy; AnyByte; AnyByte; AnyByte; AnyByte - OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte - AnyByte; AnyByte |] - let ibtEntry = (* endbr64; push imm; bnd jmp rel; *) - [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfauy - OneByte 0x68uy; AnyByte; AnyByte; AnyByte; AnyByte - OneByte 0xf2uy; OneByte 0xe9uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte |] - if BytePattern.matchSpan zeroEntry plt then - let retriever = X64Retriever () :> IPLTInfoRetriever - newPLT sec.SecAddr DontCare LazyBinding false 16 2UL 6UL retriever |> Some - elif BytePattern.matchSpan ibtZeroEntry plt then - let off, inssz = - if BytePattern.matchSpan ibtEntry (plt.Slice 16) then 7UL, 11UL - else 3UL, 7UL (* bnd *) - let retriever = X64Retriever () :> IPLTInfoRetriever - newPLT sec.SecAddr DontCare LazyBinding true 16 off inssz retriever |> Some - else None - -let x64NonLazy (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let entry = (* jmp [got+16]; *) - [| OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte |] - if BytePattern.matchSpan entry plt then - let retriever = X64Retriever () :> IPLTInfoRetriever - newPLT sec.SecAddr DontCare EagerBinding false 8 2UL 6UL retriever |> Some - else None - -let x64IBT (span: ByteSpan) sec = - let plt = span.Slice (int sec.SecOffset, int sec.SecSize) - let bndEntry = (* bnd jmp [got+n]] *) - [| OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte |] - let ibtEntry = (* endbr64; bnd jmp [got+n]] *) - [| OneByte 0xf3uy; OneByte 0x0fuy; OneByte 0x1euy; OneByte 0xfauy - OneByte 0xf2uy; OneByte 0xffuy; OneByte 0x25uy; - AnyByte; AnyByte; AnyByte; AnyByte - AnyByte; AnyByte; AnyByte; AnyByte; AnyByte |] - if BytePattern.matchSpan bndEntry plt then - let retriever = X64Retriever () :> IPLTInfoRetriever - newPLT sec.SecAddr DontCare EagerBinding true 16 3UL 7UL retriever |> Some - elif BytePattern.matchSpan ibtEntry plt then - let retriever = X64Retriever () :> IPLTInfoRetriever - newPLT sec.SecAddr DontCare EagerBinding true 16 7UL 11UL retriever |> Some - else None - -let computeARMPLTEntrySize (span: ByteSpan) reader sec headerSize delta = - if (reader: IBinReader).ReadInt32 (span, int sec.SecOffset) = 0xf8dfb500 then - Ok 16 (* THUMB-only *) - else - let offset = int sec.SecOffset + int headerSize + delta - let size = if reader.ReadInt16 (span, offset) = 0x4778s then 4 else 0 - let offset = offset + size - let ins = reader.ReadInt32 (span, offset) &&& 0xffffff00 (* strip imm *) - if (headerSize = 16UL && ins = 0xe28fc600) || ins = 0xe28fc200 then - Ok (size + 16) - elif ins = 0xe28fc600 then Ok (size + 12) - else Error ErrorCase.InvalidFileFormat - -/// Get the size of the header of PLT (PLT Zero) -let computeARMPLTHeaderSize (span: ByteSpan) reader sec = - let v = (reader: IBinReader).ReadInt32 (span, int sec.SecOffset) - if v = 0xe52de004 then (* str lr, [sp, #-4] *) - let v = reader.ReadInt32 (span, int sec.SecOffset + 16) - if v = 0xe28fc600 then (* add ip, pc, #0, 12 *) Some 16UL - else Some 20UL - elif v = 0xf8dfb500 then (* push {lr} *) Some 16UL - else None - -type ARMv7Retriever () = - interface IPLTInfoRetriever with - member __.Get (addr, idx, typ, span: ByteSpan, r, sec, gotBase) = - let addrDiff = int (addr - typ.StartAddr) - let hdrSize = computeARMPLTHeaderSize span r sec |> Option.get - match computeARMPLTEntrySize span r sec hdrSize addrDiff with - | Ok entSize -> - { EntryRelocAddr = gotBase + uint64 (idx * 4) - NextEntryAddr = addr + uint64 entSize } |> Ok - | Error _ -> (* Just ignore this entry using the default entry size 16. *) - { EntryRelocAddr = 0UL; NextEntryAddr = addr + 16UL } |> Ok - -let armv7PLT span reader sec = - match computeARMPLTHeaderSize span reader sec with - | Some headerSize -> - let startAddr = sec.SecAddr + headerSize - if reader.ReadInt32 (span, int sec.SecOffset) = 0xf8dfb500 then - (* push {lr} *) - let retriever = ARMv7Retriever () :> IPLTInfoRetriever - newPLT startAddr DontCare LazyBinding false 16 4UL 4UL retriever - else - match computeARMPLTEntrySize span reader sec headerSize 0 with - | Ok sz -> - let retriever = ARMv7Retriever () :> IPLTInfoRetriever - newPLT startAddr DontCare LazyBinding false sz 4UL 4UL retriever - | Error _ -> UnknownPLT - | None -> UnknownPLT - -type AArch64Retriever () = - interface IPLTInfoRetriever with - member __.Get (addr, idx, _, _, _reader, _sec, gotBase) = - { EntryRelocAddr = gotBase + uint64 (idx * 8) - NextEntryAddr = addr + 16UL } |> Ok - -let aarchPLT _reader sec = - let startAddr = sec.SecAddr + 32UL - let retriever = AArch64Retriever () :> IPLTInfoRetriever - newPLT startAddr DontCare LazyBinding false 16 0UL 4UL retriever - -let readMicroMIPSOpcode (span: ByteSpan) (reader: IBinReader) offset = - let v1 = reader.ReadUInt16 (span, offset) |> uint32 - let v2 = reader.ReadUInt16 (span, offset + 2) |> uint32 - int (v1 <<< 16 ||| v2) - -let computeMIPSPLTHeaderSize span reader sec = - let offset = int sec.SecOffset + 12 - let opcode = readMicroMIPSOpcode span reader offset - if opcode = 0x3302fffe then Some 24UL - else Some 32UL - -type MIPSRetriever () = - interface IPLTInfoRetriever with - member __.Get (addr, _, _, span: ByteSpan, r: IBinReader, sec, _) = - let offset = int (addr - sec.SecAddr + sec.SecOffset) - let opcode = readMicroMIPSOpcode span r (offset + 4) - match opcode with - | 0x651aeb00 -> (* MIPS16 *) - let entryAddr = r.ReadUInt32 (span, offset + 12) |> uint64 - Ok { EntryRelocAddr = entryAddr; NextEntryAddr = addr + 16UL } - | 0xff220000 -> (* microMIPS no 32 *) - let hi = uint32 (r.ReadUInt16 (span, offset)) &&& 0x7fu - let lo = r.ReadUInt16 (span, offset + 2) |> uint32 - let entryAddr = ((hi ^^^ 0x40u - 0x40u) <<< 18) + (lo <<< 2) - Ok { EntryRelocAddr = uint64 entryAddr; NextEntryAddr = addr + 12UL } - | opcode when opcode &&& 0xffff0000 = 0xff2f0000 -> (* microMIPS 32 *) - let hi = r.ReadUInt16 (span, offset + 2) |> uint32 - let lo = r.ReadUInt16 (span, offset + 6) |> uint32 - let entryAddr = - (((hi ^^^ 0x8000u) - 0x8000u) <<< 16) + ((lo ^^^ 0x8000u) - 0x8000u) - Ok { EntryRelocAddr = uint64 entryAddr; NextEntryAddr = addr + 16UL } - | _ -> (* Regular cases. *) - let hi = r.ReadUInt16 (span, offset) |> uint64 - let lo = r.ReadInt16 (span, offset + 4) |> uint64 - let entryAddr = (hi <<< 16) + lo - Ok { EntryRelocAddr = uint64 entryAddr; NextEntryAddr = addr + 16UL } - -let mipsPLT span reader sec = - match computeMIPSPLTHeaderSize span reader sec with - | Some headerSize -> - let startAddr = sec.SecAddr + headerSize - let retriever = MIPSRetriever () :> IPLTInfoRetriever - newPLT startAddr DontCare LazyBinding false 16 0UL 4UL retriever - | None -> UnknownPLT - -type SH4Retriever () = - interface IPLTInfoRetriever with - member __.Get (addr, _, typ, span: ByteSpan, r: IBinReader, sec, _) = - let offset = int (addr - sec.SecAddr + sec.SecOffset) + 24 - Ok { EntryRelocAddr = r.ReadInt32 (span, offset) |> uint64 - NextEntryAddr = addr + uint64 typ.EntrySize } - -let sh4PLT sec = - let retriever = SH4Retriever () :> IPLTInfoRetriever - newPLT (sec.SecAddr + 28UL) DontCare LazyBinding false 28 0UL 2UL retriever - -let findX86PLTType span sec = - (* This is dirty, but we cannot use a monad due to Span. *) - match x86PICLazy span sec with - | Some t -> t - | None -> - match x86NonPICLazy span sec with - | Some t -> t - | None -> - match x86PICNonLazy span sec with - | Some t -> t - | None -> - match x86NonPICNonLazy span sec with - | Some t -> t - | None -> UnknownPLT - -let findX64PLTType span sec = - (* This is dirty, but we cannot use a monad due to Span. *) - match x64Lazy span sec with - | Some t -> t - | None -> - match x64NonLazy span sec with - | Some t -> t - | None -> - match x64IBT span sec with - | Some t -> t - | None -> UnknownPLT - -let findPLTType arch span reader sec = - match arch with - | Arch.IntelX86 -> findX86PLTType span sec - | Arch.IntelX64 -> findX64PLTType span sec - | Arch.ARMv7 - | Arch.AARCH32 -> armv7PLT span reader sec - | Arch.AARCH64 -> aarchPLT reader sec - | Arch.MIPS1 - | Arch.MIPS2 - | Arch.MIPS3 - | Arch.MIPS32 - | Arch.MIPS32R2 - | Arch.MIPS32R6 - | Arch.MIPS4 - | Arch.MIPS5 - | Arch.MIPS64 - | Arch.MIPS64R2 - | Arch.MIPS64R6 -> mipsPLT span reader sec - | Arch.SH4 -> sh4PLT sec - | _ -> Utils.futureFeature () - -let rec private parsePLTLoop gotBase typ rel span reader s eAddr idx map addr = - if addr >= eAddr then map - else - let info = - typ.InfoRetriever.Get (addr, idx, typ, span, reader, s, gotBase) - |> Result.get - // printfn "%x -> %x" addr info.EntryRelocAddr - let nextAddr = info.NextEntryAddr - let ar = AddrRange (addr, nextAddr - 1UL) - match rel.RelocByAddr.TryGetValue info.EntryRelocAddr with - | true, r when r.RelSymbol.IsSome -> - let symb = Option.get r.RelSymbol - let symb = { symb with Addr = r.RelOffset } - let map = ARMap.add ar symb map - parsePLTLoop gotBase typ rel span reader s eAddr (idx + 1) map nextAddr - | _ -> - parsePLTLoop gotBase typ rel span reader s eAddr (idx + 1) map nextAddr - -let private parsePLT gotBase typ reloc span reader (s: ELFSection) map = - let startAddr, endAddr = typ.StartAddr, s.SecAddr + s.SecSize - parsePLTLoop gotBase typ reloc span reader s endAddr 0 map startAddr - -let rec loopSections map gotBase arch reloc span reader = function - | sec :: rest -> - match findPLTType arch span reader sec with - | PLT desc -> - let map = - if isSecondaryLazy desc then map (* Ignore secondary lazy plt. *) - else parsePLT gotBase desc reloc span reader sec map - loopSections map gotBase arch reloc span reader rest - | _ -> map - | [] -> map - -let parse arch sections reloc span reader = - let gotBase = findGOTBase arch reloc sections - let sections = filterPLTSections sections - match gotBase with - | Some gotBase -> - loopSections ARMap.empty gotBase arch reloc span reader sections - | _ -> ARMap.empty diff --git a/src/FrontEnd/BinFile/ELFParser.fs b/src/FrontEnd/BinFile/ELFParser.fs deleted file mode 100644 index bea187c1..00000000 --- a/src/FrontEnd/BinFile/ELFParser.fs +++ /dev/null @@ -1,175 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.Parser - -open System -open B2R2 -open B2R2.FrontEnd.BinFile - -let private parseGlobalSymbols reloc = - let folder map (KeyValue (addr, rel: RelocationEntry)) = - match rel.RelType with - | RelocationX86 RelocationX86.Reloc386GlobData - | RelocationX64 RelocationX64.RelocX64GlobData -> - Map.add addr (Option.get rel.RelSymbol) map - | _ -> map - reloc.RelocByAddr |> Seq.fold folder Map.empty - -let inline private loadCallSiteTable lsdaPointer gccexctbl = - let lsda = Map.find lsdaPointer gccexctbl - lsda.CallSiteTable - -let rec private loopCallSiteTable fde acc = function - | [] -> acc - | csrec :: rest -> - let acc = - let landingPad = - if csrec.LandingPad = 0UL then 0UL - else fde.PCBegin + csrec.LandingPad - let blockStart = fde.PCBegin + csrec.Position - let blockEnd = fde.PCBegin + csrec.Position + csrec.Length - 1UL - ARMap.add (AddrRange (blockStart, blockEnd)) landingPad acc - loopCallSiteTable fde acc rest - -let private buildExceptionTable fde gccexctbl tbl = - match fde.LSDAPointer with - | None -> tbl - | Some lsdaPointer -> - loopCallSiteTable fde tbl (loadCallSiteTable lsdaPointer gccexctbl) - -let private accumulateExceptionTableInfo fde gccexctbl map = - fde - |> Array.fold (fun map fde -> - let functionRange = AddrRange (fde.PCBegin, fde.PCEnd - 1UL) - let exceptTable = buildExceptionTable fde gccexctbl ARMap.empty - if ARMap.isEmpty exceptTable then map - else ARMap.add functionRange exceptTable map) map - -let private isRelocatable (eHdr: ELFHeader) = - eHdr.ELFFileType = ELFFileType.Relocatable - -let private computeExceptionTable excframes gccexctbl = - excframes - |> List.fold (fun map frame -> - accumulateExceptionTableInfo frame.FDERecord gccexctbl map) ARMap.empty - -let private computeUnwindingTable excframes = - excframes - |> List.fold (fun tbl (f: CallFrameInformation) -> - f.FDERecord |> Array.fold (fun tbl fde -> - fde.UnwindingInfo |> List.fold (fun tbl i -> - Map.add i.Location i tbl) tbl - ) tbl) Map.empty - -let private invRanges wordSize segs getNextStartAddr = - segs - |> List.sortBy (fun seg -> seg.PHAddr) - |> List.fold (fun (set, saddr) seg -> - let n = getNextStartAddr seg - FileHelper.addInvRange set saddr seg.PHAddr, n) (IntervalSet.empty, 0UL) - |> FileHelper.addLastInvRange wordSize - -let private addIntervalWithoutSection secS secE s e set = - let set = - if s < secS && secS < e then IntervalSet.add (AddrRange (s, secS - 1UL)) set - else set - let set = - if secE < e then IntervalSet.add (AddrRange (secE + 1UL, e)) set - else set - set - -let private addIntervalWithoutROSection rodata seg set = - let roS = rodata.SecAddr - let roE = roS + rodata.SecSize - 1UL - let segS = seg.PHAddr - let segE = segS + seg.PHMemSize - 1UL - if roE < segS || segE < roS then - IntervalSet.add (AddrRange (segS, segE)) set - else addIntervalWithoutSection roS roE segS segE set - -let private addExecutableInterval excludingSection s set = - match excludingSection with - | Some sec -> addIntervalWithoutROSection sec s set - | None -> - IntervalSet.add (AddrRange (s.PHAddr, s.PHAddr + s.PHMemSize - 1UL)) set - -let private execRanges secs segs = - (* Exclude .rodata even though it is included within an executable segment. *) - let rodata = - match Map.tryFind Section.SecROData secs.SecByName with - | Some rodata when rodata.SecAddr <> 0UL -> Some rodata - | _ -> None - segs - |> List.filter (fun seg -> - seg.PHFlags &&& Permission.Executable = Permission.Executable) - |> List.fold (fun set seg -> - addExecutableInterval rodata seg set) IntervalSet.empty - -let private parseELF baseAddr regbay span (reader: IBinReader) = - let eHdr, baseAddr = Header.parse span reader baseAddr - let isa = ISA.Init eHdr.MachineType eHdr.Endian - let cls = eHdr.Class - let secs = Section.parse baseAddr eHdr span reader - let proghdrs = ProgHeader.parse baseAddr eHdr span reader - let segs = ProgHeader.getLoadableProgHeaders proghdrs - let loadableSecNums = ProgHeader.getLoadableSecNums secs segs - let symbs = Symbol.parse baseAddr eHdr secs span reader - let reloc = Relocs.parse baseAddr eHdr secs symbs span reader - let plt = PLT.parse eHdr.MachineType secs reloc span reader - let globals = parseGlobalSymbols reloc - let symbs = Symbol.updatePLTSymbols plt symbs |> Symbol.updateGlobals globals - let excrel = if isRelocatable eHdr then Some reloc else None - let excframes = ExceptionFrames.parse span reader cls secs isa regbay excrel - let lsdas = ELFGccExceptTable.parse span reader cls secs - let exctbls = computeExceptionTable excframes lsdas - let unwindings = computeUnwindingTable excframes - { ELFHdr = eHdr - BaseAddr = baseAddr - ProgHeaders = proghdrs - LoadableSegments = segs - LoadableSecNums = loadableSecNums - SecInfo = secs - SymInfo = symbs - RelocInfo = reloc - PLT = plt - Globals = globals - ExceptionFrame = excframes - ExceptionTable = exctbls - LSDAs = lsdas - InvalidAddrRanges = invRanges cls segs (fun s -> s.PHAddr + s.PHMemSize) - NotInFileRanges = invRanges cls segs (fun s -> s.PHAddr + s.PHFileSize) - ExecutableRanges = execRanges secs segs - ISA = isa - UnwindingTbl = unwindings - BinReader = reader } - -let parse (bytes: byte[]) baseAddr regbay = - let span = ReadOnlySpan bytes - if Header.isELF span then () - else raise FileFormatMismatchException - match Header.peekEndianness span with - | Endian.Little -> parseELF baseAddr regbay span BinReader.binReaderLE - | Endian.Big -> parseELF baseAddr regbay span BinReader.binReaderBE - | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinFile/ELFProgHeader.fs b/src/FrontEnd/BinFile/ELFProgHeader.fs deleted file mode 100644 index 78caa9e0..00000000 --- a/src/FrontEnd/BinFile/ELFProgHeader.fs +++ /dev/null @@ -1,83 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.ProgHeader - -open System -open B2R2 -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinFile.FileHelper - -let peekPHdrFlags (span: ByteSpan) (reader: IBinReader) cls offset = - let pHdrPHdrFlagsOffset = if cls = WordSize.Bit32 then 24 else 4 - reader.ReadInt32 (span, offset + pHdrPHdrFlagsOffset) - |> LanguagePrimitives.EnumOfValue - -let parseProgHeader baseAddr cls (span: ByteSpan) reader offset = - let phType = (reader: IBinReader).ReadUInt32 (span, offset) - { PHType = LanguagePrimitives.EnumOfValue phType - PHFlags = peekPHdrFlags span reader cls offset - PHOffset = peekHeaderNative span reader cls offset 4 8 - PHAddr = peekHeaderNative span reader cls offset 8 16 + baseAddr - PHPhyAddr = peekHeaderNative span reader cls offset 12 24 - PHFileSize = peekHeaderNative span reader cls offset 16 32 - PHMemSize = peekHeaderNative span reader cls offset 20 40 - PHAlignment = peekHeaderNative span reader cls offset 28 48 } - -let rec private parseLoop span reader pNum baseAddr eHdr acc delta offset = - if pNum = 0us then List.rev acc - else - let phdr = parseProgHeader baseAddr eHdr.Class span reader offset - parseLoop span reader (pNum - 1us) baseAddr eHdr (phdr :: acc) - delta (offset + delta) - -/// Parse and associate program headers with section headers to return the list -/// of segments. -let parse baseAddr eHdr span reader = - let nextPHdrOffset = if eHdr.Class = WordSize.Bit32 then 32 else 56 - parseLoop span reader eHdr.PHdrNum baseAddr eHdr [] - nextPHdrOffset (Convert.ToInt32 eHdr.PHdrTblOffset) - -let getLoadableProgHeaders pHdrs = - pHdrs |> List.filter (fun ph -> ph.PHType = ProgramHeaderType.PTLoad) - -let gatherLoadlabeSecNums pHdr secs = - let foldSHdr acc sec = - let lb = pHdr.PHOffset - let ub = lb + pHdr.PHFileSize - if sec.SecOffset >= lb && sec.SecOffset < ub then sec.SecNum :: acc else acc - ARMap.fold (fun acc _ s -> foldSHdr acc s) [] secs.SecByAddr - -let getLoadableSecNums secs segs = - let loop set seg = - gatherLoadlabeSecNums seg secs - |> List.fold (fun set n -> Set.add n set) set - segs |> List.fold loop Set.empty - -let toSegment phdr = - { Address = phdr.PHAddr - Offset = phdr.PHOffset - Size = phdr.PHMemSize - SizeInFile = phdr.PHFileSize - Permission = phdr.PHFlags } diff --git a/src/FrontEnd/BinFile/ELFRelocs.fs b/src/FrontEnd/BinFile/ELFRelocs.fs deleted file mode 100644 index f6516418..00000000 --- a/src/FrontEnd/BinFile/ELFRelocs.fs +++ /dev/null @@ -1,99 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.Relocs - -open System -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile.FileHelper - -let peekInfoWithArch span reader eHdr offset = - let info = peekHeaderNative span reader eHdr.Class offset 4 8 - match eHdr.MachineType with - | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> - (* MIPS64el has a a 32-bit LE symbol index followed by four individual byte - fields. *) - if eHdr.Endian = Endian.Little then - (info &&& 0xffffffffUL) <<< 32 - ||| ((info >>> 56) &&& 0xffUL) - ||| ((info >>> 40) &&& 0xff00UL) - ||| ((info >>> 24) &&& 0xff0000UL) - ||| ((info >>> 8) &&& 0xff000000UL) - else info - | _ -> info - -let inline getRelocSIdx eHdr (i: uint64) = - if eHdr.Class = WordSize.Bit32 then i >>> 8 else i >>> 32 - -let inline relocEntry baseAddr hasAdd eHdr typMask symTbl span reader pos sec = - let info = peekInfoWithArch span reader eHdr pos - let cls = eHdr.Class - { RelOffset = peekUIntOfType span reader cls pos + baseAddr - RelType = typMask &&& info |> RelocationType.FromNum eHdr.MachineType - RelSymbol = Array.tryItem (getRelocSIdx eHdr info |> Convert.ToInt32) symTbl - RelAddend = - if hasAdd then peekHeaderNative span reader cls pos 8 16 else 0UL - RelSecNumber = sec.SecNum } - -let nextRelOffset hasAdd cls offset = - if cls = WordSize.Bit32 then offset + (if hasAdd then 12 else 8) - else offset + (if hasAdd then 24 else 16) - -let tryFindSymbTable idx symbInfo = - match Map.tryFind idx symbInfo.SecNumToSymbTbls with - | None -> [||] - | Some tbl -> tbl - -let accumulateRelocInfo relInfo rel = - match rel.RelSymbol with - | None -> relInfo.RelocByAddr[rel.RelOffset] <- rel - | Some name -> - relInfo.RelocByAddr[rel.RelOffset] <- rel - relInfo.RelocByName[name.SymName] <- rel - -let parseRelocSection baseAddr eHdr span reader sec symbInfo relInfo = - let hasAdd = sec.SecType = SectionType.SHTRela (* Has addend? *) - let typMask = if eHdr.Class = WordSize.Bit32 then 0xFFUL else 0xFFFFFFFFUL - let entrySize = - if hasAdd then (uint64 <| WordSize.toByteWidth eHdr.Class * 3) - else (uint64 <| WordSize.toByteWidth eHdr.Class * 2) - let numEntries = int (sec.SecSize / entrySize) - let mutable ofs = Convert.ToInt32 sec.SecOffset - for _ = numEntries downto 1 do - let symTbl = tryFindSymbTable (int sec.SecLink) symbInfo - relocEntry baseAddr hasAdd eHdr typMask symTbl span reader ofs sec - |> accumulateRelocInfo relInfo - ofs <- nextRelOffset hasAdd eHdr.Class ofs - -let parse baseAddr eHdr secInfo symbInfo span reader = - let relInfo = { RelocByAddr = Dictionary (); RelocByName = Dictionary () } - for sec in secInfo.SecByNum do - match sec.SecType with - | SectionType.SHTRel - | SectionType.SHTRela -> - if sec.SecSize = 0UL then () - else parseRelocSection baseAddr eHdr span reader sec symbInfo relInfo - | _ -> () - relInfo diff --git a/src/FrontEnd/BinFile/ELFSection.fs b/src/FrontEnd/BinFile/ELFSection.fs deleted file mode 100644 index 8a34d768..00000000 --- a/src/FrontEnd/BinFile/ELFSection.fs +++ /dev/null @@ -1,162 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.Section - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.FileHelper - -let [] SecText = ".text" -let [] SecROData = ".rodata" - -/// Return the raw memory contents that represent the section names separated by -/// null character. -let parseSectionNameContents eHdr span reader = - let off = eHdr.SHdrTblOffset + uint64 (eHdr.SHdrStrIdx * eHdr.SHdrEntrySize) - let padding = (8 + (WordSize.toByteWidth eHdr.Class * 2)) - let pos = Convert.ToInt32 off + padding - let struct (strOffset, nextOffset) = readUIntOfType span reader eHdr.Class pos - let size = peekUIntOfType span reader eHdr.Class nextOffset - span.Slice (Convert.ToInt32 strOffset, Convert.ToInt32 size) - -let peekSecType (span: ByteSpan) (reader: IBinReader) offset = - reader.ReadUInt32 (span, offset + 4) - |> LanguagePrimitives.EnumOfValue: SectionType - -let peekSecFlags span reader cls offset = - peekUIntOfType span reader cls (offset + 8) - |> LanguagePrimitives.EnumOfValue: SectionFlag - -let parseSection baseAddr num names cls (span: ByteSpan) reader ofs = - let nameOffset = (reader: IBinReader).ReadInt32 (span, ofs) - { SecNum = num - SecName = ByteArray.extractCStringFromSpan names nameOffset - SecType = peekSecType span reader ofs - SecFlags = peekSecFlags span reader cls ofs - SecAddr = peekHeaderNative span reader cls ofs 12 16 + baseAddr - SecOffset = peekHeaderNative span reader cls ofs 16 24 - SecSize = peekHeaderNative span reader cls ofs 20 32 - SecLink = peekHeaderU32 span reader cls ofs 24 40 - SecInfo = peekHeaderU32 span reader cls ofs 28 44 - SecAlignment = peekHeaderNative span reader cls ofs 32 48 - SecEntrySize = peekHeaderNative span reader cls ofs 36 56 } - -let inline hasSHFTLS flags = - flags &&& SectionFlag.SHFTLS = SectionFlag.SHFTLS - -let inline hasSHFAlloc flags = - flags &&& SectionFlag.SHFAlloc = SectionFlag.SHFAlloc - -let nextSecOffset cls offset = - offset + (if cls = WordSize.Bit32 then 40 else 64) - -let secHasValidAddr baseAddr sec = - (* .tbss has a meaningless virtual address as per - https://stackoverflow.com/questions/25501044/. *) - let secEndAddr = sec.SecAddr + sec.SecSize - sec.SecAddr <> baseAddr - && not <| hasSHFTLS sec.SecFlags - && secEndAddr > sec.SecAddr - -let addSecToAddrMap baseAddr sec map = - if secHasValidAddr baseAddr sec then - let endAddr = sec.SecAddr + sec.SecSize - 1UL - ARMap.addRange sec.SecAddr endAddr sec map - else map - -let accSymbTabNum lst predicate sec = - if predicate sec.SecType then sec.SecNum :: lst else lst - -let isStatic t = t = SectionType.SHTSymTab - -let isDynamic t = t = SectionType.SHTDynSym - -let updateVerSec predicate sec = function - | None -> if predicate sec.SecType then Some sec else None - | s -> s - -let isVerSym t = t = SectionType.SHTGNUVerSym - -let isVerNeed t = t = SectionType.SHTGNUVerNeed - -let isVerDef t = t = SectionType.SHTGNUVerDef - -let rec parseLoop baseAddr eHdr span reader names secByNum info sIdx offset = - if int eHdr.SHdrNum = sIdx then - { info with SecByNum = List.rev secByNum |> Array.ofList } - else - let sec = parseSection baseAddr sIdx names eHdr.Class span reader offset - let secByNum = sec :: secByNum - let offset' = nextSecOffset eHdr.Class offset - let info' = - { info with - SecByAddr = addSecToAddrMap baseAddr sec info.SecByAddr - SecByName = Map.add sec.SecName sec info.SecByName - StaticSymSecNums = accSymbTabNum info.StaticSymSecNums isStatic sec - DynSymSecNums = accSymbTabNum info.DynSymSecNums isDynamic sec - VerSymSec = updateVerSec isVerSym sec info.VerSymSec - VerNeedSec = updateVerSec isVerNeed sec info.VerNeedSec - VerDefSec = updateVerSec isVerDef sec info.VerDefSec } - parseLoop baseAddr eHdr span reader names secByNum info' (sIdx + 1) offset' - -let parse baseAddr eHdr span reader = - let nameContents = parseSectionNameContents eHdr span reader - let emptyInfo = - { SecByAddr = ARMap.empty - SecByName = Map.empty - SecByNum = [||] - StaticSymSecNums = [] - DynSymSecNums = [] - VerSymSec = None - VerNeedSec = None - VerDefSec = None } - let offset = Convert.ToInt32 eHdr.SHdrTblOffset - parseLoop baseAddr eHdr span reader nameContents [] emptyInfo 0 offset - -let rec private readDynSecLoop acc span reader secEnd readType readSize offset = - if offset >= secEnd then List.rev acc - else - let tag = peekUIntOfType span reader readType offset - let value = peekUIntOfType span reader readType (offset + readSize) - let entry = { DTag = LanguagePrimitives.EnumOfValue tag; DVal = value } - let nextOffset = offset + readSize + readSize - (* Ignore after null entry *) - let nextOffset = if value = 0UL && tag = 0UL then secEnd else nextOffset - readDynSecLoop (entry :: acc) span reader secEnd readType readSize nextOffset - -let parseDynamicSection span reader (sec: ELFSection) = - let secStart = int sec.SecOffset - let secEnd = secStart + int sec.SecSize - let readSize = int (sec.SecEntrySize / 2UL) - let readType: WordSize = LanguagePrimitives.EnumOfValue (readSize * 8) - readDynSecLoop [] span reader secEnd readType readSize secStart - -let getDynamicSectionEntries span reader secInfo = - let sec = - secInfo.SecByNum - |> Array.tryFind (fun s -> s.SecType = SectionType.SHTDynamic) - match sec with - | Some sec -> parseDynamicSection span reader sec - | None -> [] diff --git a/src/FrontEnd/BinFile/ELFSymbol.fs b/src/FrontEnd/BinFile/ELFSymbol.fs deleted file mode 100644 index 424868b2..00000000 --- a/src/FrontEnd/BinFile/ELFSymbol.fs +++ /dev/null @@ -1,265 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.ELF.Symbol - -open System -open B2R2 -open B2R2.Monads.Maybe -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinFile.FileHelper - -let getSymbKind ndx = function - | SymbolType.STTObject -> SymObjectType - | SymbolType.STTGNUIFunc - | SymbolType.STTFunc -> - if ndx = SHNUndef then NoType - else SymFunctionType - | SymbolType.STTSection -> SymSectionType - | SymbolType.STTFile ->SymFileType - | _ -> NoType - -let versionToLibName version = - match version with - | Some version -> version.VerName - | None -> "" - -let toB2R2Symbol target (symb: ELFSymbol) = - { Address = symb.Addr - Name = symb.SymName - Kind = getSymbKind symb.SecHeaderIndex symb.SymType - Target = target - LibraryName = versionToLibName symb.VerInfo - ArchOperationMode = symb.ArchOperationMode } - -let verName (strTab: ByteSpan) vnaNameOffset = - if vnaNameOffset >= strTab.Length then "" - else ByteArray.extractCStringFromSpan strTab vnaNameOffset - -let rec parseNeededVerFromSecAux span (reader: IBinReader) strTab map pos = - let idx = reader.ReadUInt16 (span=span, offset=pos + 6) (* vna_other *) - let nameOffset = reader.ReadInt32 (span, pos + 8) - let map = Map.add idx (verName strTab nameOffset) map - let next = reader.ReadInt32 (span, pos + 12) - if next = 0 then map - else parseNeededVerFromSecAux span reader strTab map (pos + next) - -let rec parseNeededVerFromSec span (reader: IBinReader) strTab map pos = - let auxOffset = - reader.ReadInt32 (span=span, offset=pos + 8) + pos (* vn_aux + pos *) - let map = parseNeededVerFromSecAux span reader strTab map auxOffset - let next = reader.ReadInt32 (span, pos + 12) (* vn_next *) - if next = 0 then map - else parseNeededVerFromSec span reader strTab map (pos + next) - -let parseNeededVersionTable tbl span reader strTab = function - | None -> tbl - | Some sec -> - parseNeededVerFromSec span reader strTab tbl (Convert.ToInt32 sec.SecOffset) - -let rec parseDefinedVerFromSec span (reader: IBinReader) strTab map pos = - let auxOffset = - reader.ReadInt32 (span=span, offset=pos + 12) + pos (* vd_aux + pos *) - let idx = reader.ReadUInt16 (span, pos + 4) (* vd_ndx *) - let nameOffset = reader.ReadInt32 (span, auxOffset) (* vda_name *) - let map = Map.add idx (verName strTab nameOffset) map - let next = reader.ReadInt32 (span, pos + 16) (* vd_next *) - if next = 0 then map - else parseDefinedVerFromSec span reader strTab map (pos + next) - -let parseDefinedVersionTable tbl span reader strTab = function - | None -> tbl - | Some sec -> - parseDefinedVerFromSec span reader strTab tbl - (Convert.ToInt32 sec.SecOffset) - -let rec accumulateVerTbl (span: ByteSpan) reader secs tbl nlst = - match nlst with - | n :: rest -> - let symTblSec = secs.SecByNum[n] - let ss = secs.SecByNum[Convert.ToInt32 symTblSec.SecLink] - let size = Convert.ToInt32 ss.SecSize - let offset = Convert.ToInt32 ss.SecOffset - let strTab = span.Slice (offset, size) - let tbl = parseNeededVersionTable tbl span reader strTab secs.VerNeedSec - let tbl = parseDefinedVersionTable tbl span reader strTab secs.VerDefSec - accumulateVerTbl span reader secs tbl rest - | [] -> tbl - -let parseVersionTable secs (span: ByteSpan) reader = - accumulateVerTbl span reader secs Map.empty secs.DynSymSecNums - -let parseVersData span (reader: IBinReader) symIdx verSymSec = - let pos = verSymSec.SecOffset + (symIdx * 2UL) |> Convert.ToInt32 - let versData = reader.ReadUInt16 (span=span, offset=pos) - if versData > 1us then Some versData - else None - -let retrieveVer vtbl verData = - let t = if verData &&& 0x8000us = 0us then VerRegular else VerHidden - match Map.tryFind (verData &&& 0x7fffus) vtbl with - | None -> None - | Some verStr -> Some { VerType = t; VerName = verStr } - -let adjustSymAddr baseAddr addr = - if addr = 0UL then 0UL - else addr + baseAddr - -let readSymAddr baseAddr span reader cls parent txtOffset offset = - let symAddrOffset = if cls = WordSize.Bit32 then 4 else 8 - let symAddr = peekUIntOfType span reader cls (offset + symAddrOffset) - match (parent: ELFSection option) with - | None -> symAddr - | Some sec -> - (* This is to give a meaningful address to static symbols in a relocatable - object. We let .text section's address to be zero, and assume that the - .text section always precedes the other sections. See - https://github.com/B2R2-org/B2R2/issues/25 for more details. *) - if sec.SecAddr = baseAddr && sec.SecOffset > txtOffset then - sec.SecOffset - txtOffset + symAddr - else symAddr - |> adjustSymAddr baseAddr - -let readSymSize span reader cls offset = - let symSizeOffset = if cls = WordSize.Bit32 then 8 else 16 - peekUIntOfType span reader cls (offset + symSizeOffset) - -let computeArchOpMode eHdr symbolName = - if eHdr.MachineType = Architecture.ARMv7 - || eHdr.MachineType = Architecture.AARCH32 - then - if symbolName = "$a" then ArchOperationMode.ARMMode - elif symbolName = "$t" then ArchOperationMode.ThumbMode - else ArchOperationMode.NoMode - else ArchOperationMode.NoMode - -let getVerInfo span reader vtbl symIdx secs = - match secs.VerSymSec with - | Some ssec -> - parseVersData span reader symIdx ssec >>= retrieveVer vtbl - | None -> None - -let getSymbol baseAddr secs strTab vtbl eHdr span reader txt symIdx pos = - let cls = eHdr.Class - let nameIdx = (reader: IBinReader).ReadUInt32 (span=span, offset=pos) - let sname = ByteArray.extractCStringFromSpan strTab (Convert.ToInt32 nameIdx) - let info = peekHeaderB span reader cls pos 12 4 - let other = peekHeaderB span reader cls pos 13 5 - let ndx = peekHeaderU16 span reader cls pos 14 6 |> int - let parent = Array.tryItem ndx secs.SecByNum - let secIdx = SectionHeaderIdx.IndexFromInt ndx - let verInfo = getVerInfo span reader vtbl symIdx secs - { Addr = readSymAddr baseAddr span reader cls parent txt pos - SymName = sname - Size = readSymSize span reader cls pos - Bind = info >>> 4 |> LanguagePrimitives.EnumOfValue - SymType = info &&& 0xfuy |> LanguagePrimitives.EnumOfValue - Vis = other &&& 0x3uy |> LanguagePrimitives.EnumOfValue - SecHeaderIndex = secIdx - ParentSection = parent - VerInfo = verInfo - ArchOperationMode = computeArchOpMode eHdr sname } - -let getVerSymSection symTblSec secByType = - if symTblSec.SecType = SectionType.SHTDynSym then - Map.tryFind SectionType.SHTGNUVerSym secByType - else None - -let nextSymOffset eHdr offset = - offset + if eHdr.Class = WordSize.Bit32 then 16 else 24 - -let getTextSectionOffset secs = - match Map.tryFind Section.SecText secs.SecByName with - | None -> 0UL - | Some sec -> sec.SecOffset - -let rec parseSymAux - baseAddr eHdr secs span reader txt vtbl stbl cnt max offset acc = - if cnt = max then List.rev acc - else - let sym = getSymbol baseAddr secs stbl vtbl eHdr span reader txt cnt offset - let cnt = cnt + 1UL - let offset = nextSymOffset eHdr offset - let acc = sym :: acc - parseSymAux baseAddr eHdr secs span reader txt vtbl stbl cnt max offset acc - -let parseSymbols baseAddr eHdr secs (span: ByteSpan) reader vtbl acc symTblSec = - let cls = eHdr.Class - let ss = secs.SecByNum[Convert.ToInt32 symTblSec.SecLink] (* Get the sec. *) - let size = Convert.ToInt32 ss.SecSize - let offset = Convert.ToInt32 ss.SecOffset - let max = symTblSec.SecSize / (if cls = WordSize.Bit32 then 16UL else 24UL) - let txt = getTextSectionOffset secs - let stbl = span.Slice (offset, size) - let offset = Convert.ToInt32 symTblSec.SecOffset - parseSymAux baseAddr eHdr secs span reader txt vtbl stbl 0UL max offset acc - -let getMergedSymbolTbl numbers symTbls = - numbers - |> List.fold (fun acc n -> Array.append (Map.find n symTbls) acc) [||] - -let private getStaticSymArrayInternal secInfo symTbl = - getMergedSymbolTbl secInfo.StaticSymSecNums symTbl - -let getStaticSymArray elf = - getStaticSymArrayInternal elf.SecInfo elf.SymInfo.SecNumToSymbTbls - -let private getDynamicSymArrayInternal secInfo symTbl = - getMergedSymbolTbl secInfo.DynSymSecNums symTbl - -let getDynamicSymArray elf = - getDynamicSymArrayInternal elf.SecInfo elf.SymInfo.SecNumToSymbTbls - -let buildSymbolMap staticSymArr dynamicSymArr = - let folder map sym = - if sym.Addr > 0UL then Map.add sym.Addr sym map - else map - let map = staticSymArr |> Array.fold folder Map.empty - dynamicSymArr |> Array.fold folder map - -let rec getSymTabs map baseAddr eHdr secs span reader vtbl = function - | (n, symTblSec) :: rest -> - let symbols = parseSymbols baseAddr eHdr secs span reader vtbl [] symTblSec - let map = Map.add n (Array.ofList symbols) map - getSymTabs map baseAddr eHdr secs span reader vtbl rest - | [] -> map - -let parse baseAddr eHdr secs span reader = - let vtbl = parseVersionTable secs span reader - let symTabNumbers = List.append secs.StaticSymSecNums secs.DynSymSecNums - let symSecs = List.map (fun n -> n, secs.SecByNum[n]) symTabNumbers - let symTbls = getSymTabs Map.empty baseAddr eHdr secs span reader vtbl symSecs - let staticSymArr = getStaticSymArrayInternal secs symTbls - let dynamicSymArr = getDynamicSymArrayInternal secs symTbls - { VersionTable = vtbl - SecNumToSymbTbls = symTbls - AddrToSymbTable = buildSymbolMap staticSymArr dynamicSymArr } - -let updatePLTSymbols (plt: ARMap) symInfo = - let update map = plt |> ARMap.fold (fun map r s -> Map.add r.Min s map) map - { symInfo with AddrToSymbTable = update symInfo.AddrToSymbTable } - -let updateGlobals (globals: Map) symInfo = - let update map = globals |> Map.fold (fun map a s -> Map.add a s map) map - { symInfo with AddrToSymbTable = update symInfo.AddrToSymbTable } diff --git a/src/FrontEnd/BinFile/ELFTypes.fs b/src/FrontEnd/BinFile/ELFTypes.fs deleted file mode 100644 index bf54c625..00000000 --- a/src/FrontEnd/BinFile/ELFTypes.fs +++ /dev/null @@ -1,1063 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile.ELF - -open System -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile - -/// File type. -type ELFFileType = - | ETNone = 0x0us - | Relocatable = 0x1us - | Executable = 0x2us - | SharedObject = 0x3us - | Core = 0x4us - -/// ABI type. -type OSABI = - | ABISystemV = 0x0uy - | ABIHPUX = 0x1uy - | ABINetBSD = 0x2uy - | ABILinux = 0x3uy - | ABISolaris = 0x6uy - | ABIAIX = 0x7uy - | ABIIRIX = 0x8uy - | ABIFreeBSD = 0x9uy - -/// ELF header. -type ELFHeader = { - Class: WordSize - Endian: Endian - Version: uint32 - OSABI: OSABI - OSABIVersion: uint32 - ELFFileType: ELFFileType - MachineType: Architecture - EntryPoint: uint64 - PHdrTblOffset: uint64 - SHdrTblOffset: uint64 - ELFFlags: uint32 - HeaderSize: uint16 - PHdrEntrySize: uint16 - PHdrNum: uint16 - SHdrEntrySize: uint16 - SHdrNum: uint16 - SHdrStrIdx: uint16 -} - -/// This member categorizes the section's contents and semantics. -type SectionType = - /// This section is inactive. - | SHTNull = 0x00u - /// This section holds information defined by the program, whose format and - /// meaning are determined solely by the program. - | SHTProgBits = 0x01u - /// This section holds a symbol table. - | SHTSymTab = 0x02u - /// This section holds a string table. - | SHTStrTab = 0x03u - /// This section holds relocation entries with explicit addends. - | SHTRela = 0x04u - /// This section holds a symbol hash table. All ELF files participating in - /// dynamic linking must contain a symbol hash table. - | SHTHash = 0x05u - /// This section holds information for dynamic linking. - | SHTDynamic = 0x06u - /// This section holds a note. - | SHTNote = 0x07u - /// This section occupies no space, although SecOffset contains a conceptual - /// offset to it. - | SHTNoBits = 0x08u - /// This section holds relocation entries without explicit addends. - | SHTRel = 0x09u - /// This section is reserved (unknown purpose). - | SHTShLib = 0x0au - /// This section contains a minimal set of dynamic linking symbols. - | SHTDynSym = 0x0bu - /// This section contains initialization function pointers. - | SHTInitArray = 0x0eu - /// This section contains termination function pointers. - | SHTFiniArray = 0x0fu - /// This section contains pre-initialization function pointers. - | SHTPreInitArray = 0x10u - /// This section holds section group information. - | SHTGroup = 0x11u - /// This section holds section indexes. - | SHTSymTabShIdx = 0x12u - /// This section marks the start of processor-specific section type. - | SHTLoProc = 0x70000000u - | SHTARMExIdx = 0x70000001u - | SHTARMPreMap = 0x70000002u - | SHTARMAttr = 0x70000003u - | SHTARMDebug = 0x70000004u - | SHTARMOverlay = 0x70000005u - | SHTMIPSRegInfo = 0x70000006u - | SHTMIPSOptions = 0x7000000du - | SHTMIPSABIFlags = 0x7000002au - /// This section marks the end of processor-specific section type. - | SHTHiProc = 0x7fffffffu - /// This section specifies the lower bound of program-specific section type. - | SHTLoUser = 0x80000000u - /// This section specifies the upper bound of program-specific section type. - | SHTHiUser = 0xffffffffu - | SHTGNUAttributes = 0x6ffffff5u - | SHTGNUHash = 0x6ffffff6u - | SHTGNULibList = 0x6ffffff7u - /// This section holds Linux-specific version information (Elfxx_VerDef). This - /// stores version information of functions defined in the binary. - | SHTGNUVerDef = 0x6ffffffdu - /// This section holds Linux-specific version information (Elfxx_VerNeed). - /// This stores version information of external functions, which is needed by - /// the caller binary. - | SHTGNUVerNeed = 0x6ffffffeu - /// This section holds Linux-specific version information. It specifically - /// contains an array of elements of type Elfxx_Half. It has as many entries - /// as the dynamic symbol table. - | SHTGNUVerSym = 0x6fffffffu - -/// Sections support 1-bit flags that describe miscellaneous attributes. -[] -type SectionFlag = - /// This section contains data that should be writable during process - /// execution. - | SHFWrite = 0x1UL - /// This section occupies memory during process execution. - | SHFAlloc = 0x2UL - /// This section contains executable machine code. - | SHFExecInstr = 0x4UL - /// This section may be merged. - | SHFMerge = 0x10UL - /// This section contains string. - | SHFString = 0x20UL - /// This section holds section indexes. - | SHFInfoLink = 0x40UL - /// This section adds special ordering requirements to the link editor. - | SHFLinkOrder = 0x80UL - /// This section requires special OS-specific processing beyond the standard - /// linking rules to avoid incorrect behavior - | SHFOSNonConforming = 0x100UL - /// This section is a member, perhaps the only one, of a section group. - | SHFGroup = 0x200UL - /// This section contains TLS data. - | SHFTLS = 0x400UL - /// This section contains compressed data. - | SHFCompressed = 0x800UL - /// All bits included in this mask are reserved for operating system-specific - /// semantics. - | SHFMaskOS = 0x0ff00000UL - /// All bits included in this mask are reserved for processor-specific - /// semantics. - | SHFMaskProc = 0xf0000000UL - /// This section requires ordering in relation to other sections of the same - /// type. - | SHFOrdered = 0x40000000UL - /// This section is excluded from input to the link-edit of an executable or - /// shared object - | SHFExclude = 0x80000000UL - /// This section can hold more than 2GB. - | SHFX8664Large = 0x10000000UL - -/// ELF Section -type ELFSection = { - /// Unique section number. - SecNum: int - /// The name of the section. - SecName: string - /// Categorizes the section's contents and semantics. - SecType: SectionType - /// Misc. attributes about the section. - SecFlags: SectionFlag - /// The address at which the section's first byte should reside. If this - /// section will not appear in the process memory, this value is 0. - SecAddr: Addr - /// Byte offset from the beginning of the file to the first byte in the - /// section. - SecOffset: uint64 - /// The section's size in bytes. - SecSize: uint64 - /// A section header table index link. The interpretation of this field - /// depends on the section type. - SecLink: uint32 - /// Extra information. The interpretation of this info depends on the section - /// type. - SecInfo: uint32 - /// Some sections have address alignment constraints. - SecAlignment: uint64 - /// Some sections hold a table of fixed-size entries, such as a symbol - /// table. For such a section, this member gives the size in bytes of each - /// entry. - SecEntrySize: uint64 -} - -/// Section information. -type SectionInfo = { - /// Section by address. - SecByAddr: ARMap - /// Section by name. - SecByName: Map - /// Section by its number. - SecByNum: ELFSection [] - /// Static symbol section numbers. - StaticSymSecNums: int list - /// Dynamic symbol section numbers. - DynSymSecNums: int list - /// GNU version symbol section. - VerSymSec: ELFSection option - /// GNU version need section. - VerNeedSec: ELFSection option - /// GNU version definition section. - VerDefSec: ELFSection option -} - -/// ELF dynamic section tags. -type DynamicSectionTag = - | DTNull = 0UL - | DTNeeded = 1UL - | DTPLTRelSz = 2UL - | DTPLTRelGot = 3UL - | DTHash = 4UL - | DTStrTab = 5UL - | DTSymTab = 6UL - | DTRELA = 7UL - | DTRELASz = 8UL - | DTRELAEnt = 9UL - | DTStrSz = 10UL - | DTSymEnt = 11UL - | DTInit = 12UL - | DTFini = 13UL - | DTSOName = 14UL - | DTRPath = 15UL - | DTSymbolic = 16UL - | DTREL = 17UL - | DTRELSz = 18UL - | DTRELEnt = 19UL - | DTPLTRel = 20UL - | DTDebug = 21UL - | DTTextRel = 22UL - | DTJmpRel = 23UL - | DTBindNow = 24UL - | DTInitArray = 25UL - | DTFiniArray = 26UL - | DTInitArraySz = 27UL - | DTFiniArraySz = 28UL - | DTRunPath = 29UL - | DTFlags = 30UL - | DTEncoding = 31UL - | DTPreInitArray = 32UL - | DTPreInitArraySz = 33UL - | DTMaxPosTags = 34UL - | DTFlags1 = 0x6ffffffbUL - | DTRELACount = 0x6ffffff9UL - | DTVerSym = 0x6ffffff0UL - | DTVerNeed = 0x6ffffffeUL - | DTVerNeedNum = 0x6fffffffUL - -/// Dynamic section entry. -type DynamicSectionEntry = { - DTag: DynamicSectionTag - DVal: uint64 -} - -/// A symbol's binding determines the linkage visibility and behavior. -type SymbolBind = - /// Local symbols are not visible outside. Local symbols of the same name may - /// exist in multiple files without interfering with each other. - | STBLocal = 0x0uy - /// Global symbols are visible to all object files being combined. - | STBGlobal = 0x1uy - /// Weak symbols resemble global symbols, but their definitions have lower - /// precedence. - | STBWeak = 0x2uy - /// The lower bound of OS-specific binding type. - | STBLoOS = 0xauy - /// The upper bound of OS-specific binding type. - | STBHiOS = 0xcuy - /// The lower bound of processor-specific binding type. - | STBLoProc = 0xduy - /// The upper bound of processor-specific binding type. - | STBHiProc = 0xfuy - -/// A symbol's type provides a general classification for the associated entity. -type SymbolType = - /// Symbol's type is not specified. - | STTNoType = 0x00uy - /// This symbol is associated with a data object, such as variable and an - /// array. - | STTObject = 0x01uy - /// This symbol is associated with a function. - | STTFunc = 0x02uy - /// This symbol is associated with a section. Symbol table entries of this - /// type exist primarily for relocation and normally have STBLocal binding. - | STTSection = 0x03uy - /// This symbol represents the name of the source file associated with the - /// object file. - | STTFile = 0x04uy - /// This symbol labels an uninitialized common block. - | STTCommon = 0x05uy - /// The symbol specifies a Thread-Local Storage entity. - | STTTLS = 0x06uy - /// A symbol with type STT_GNU_IFUNC is a function, but the symbol does not - /// provide the address of the function as usual. Instead, the symbol provides - /// the address of a function which returns a pointer to the actual function. - | STTGNUIFunc = 0x0auy - /// The lower bound of OS-specific symbol type. - | STTLoOS = 0x0auy - /// The upper bound of OS-specific binding type. - | STTHiOS = 0x0cuy - /// The lower bound of processor-specific symbol type. - | STTLoProc = 0x0duy - /// The upper bound of processor-specific symbol type. - | STTHiProc = 0x0fuy - -/// This member currently specifies a symbol's visibility -type SymbolVisibility = - /// Use the visibility specified by the symbol's binding type (SymbolBind). - | STVDefault = 0x0uy - /// This visibility attribute is currently reserved. - | STVInternal = 0x01uy - /// A symbol defined in the current component is hidden if its name is not - /// visible to other components. Such a symbol is necessarily protected. This - /// attribute is used to control the external interface of a component. An - /// object named by such a symbol may still be referenced from another - /// component if its address is passed outside. - | STVHidden = 0x02uy - /// A symbol defined in the current component is protected if it is visible in - /// other components but cannot be preempted. Any reference to such a symbol - /// from within the defining component must be resolved to the definition in - /// that component, even if there is a definition in another component that - /// would interpose by the default rules. - | STVProtected = 0x03uy - -/// Every symbol table entry is defined in relation to some section. -/// This member holds the relevant section header table index. -type SectionHeaderIdx = - /// This is the start of the reserved range. - | SHNLoReserve - /// The symbol is undefined. Linker should update references to this symbol - /// with the actual definition from another file. - | SHNUndef - /// The lower bound of processor-specific section index value. - | SHNLoProc - /// The upper bound of processor-specific section index value. - | SHNHiProc - /// The lower bound of OS-specific section index value. - | SHNLoOS - /// The upper bound of OS-specific section index value. - | SHNHiOS - /// The symbol has an absolute value that will not change because of - /// relocation. - | SHNABS - /// The symbol labels a common block that has not yet been allocated. - | SHNCommon - /// An escape value indicating that the actual section header index is too - /// large to fit in the containing field. The header section index is found in - /// another location specific to the structure where it appears. - | SHNXIndex - /// The upper boundary of the range of the reserved range. - | SHNHiReserve - /// This symbol index holds an index into the section header table. - | SecIdx of int -with - static member IndexFromInt n = - match n with - | 0x00 -> SHNUndef - | 0xff00 -> SHNLoReserve - | 0xfff1 -> SHNABS - | 0xfff2 -> SHNCommon - | n -> SecIdx n - -type VersionType = - /// Regular version number. - | VerRegular - /// Unversioned local symbol. - | VerLocal - /// Unversioned global symbol. - | VerGlobal - /// Hidden symbol. - | VerHidden - -/// Symbol version information. -type SymVerInfo = { - /// Version type. - VerType: VersionType - /// Version string. - VerName: string -} - -type ELFSymbol = { - /// Address of the symbol. - Addr: Addr - /// Symbol's name. - SymName: string - /// Size of the symbol (e.g., size of the data object). - Size: uint64 - /// Symbol binding. - Bind: SymbolBind - /// Symbol type. - SymType: SymbolType - /// Symbol visibility. - Vis: SymbolVisibility - /// The index of the relevant section with regard to this symbol. - SecHeaderIndex: SectionHeaderIdx - /// Parent section of this section. - ParentSection: ELFSection option - /// Version information. - VerInfo: SymVerInfo option - /// ArchOperationMode. - ArchOperationMode: ArchOperationMode -} - -/// Relocation type for x86. -type RelocationX86 = - /// x86: no relocation. - | Reloc386None = 0UL - /// x86: direct 32-bit (S + A). - | Reloc38632 = 1UL - /// x86: PC-relative 32-bit (S + A - P). - | Reloc386PC32 = 2UL - /// x86: 32-bit GOT entry (G + A). - | Reloc386GOT32 = 3UL - /// x86: 32-bit PLT entry (L + A - P). - | Reloc386PLT32 = 4UL - /// x86: copy symbol at runtime. - | Reloc386Copy = 5UL - /// x86: create GOT entry (S). - | Reloc386GlobData = 6UL - /// x86: create PLT entry (S). - | Reloc386JmpSlot = 7UL - /// x86: adjust by program base (S + A). - | Reloc386Relative = 8UL - /// x86: 32-bit offset to GOT (S + A - GOT). - | Reloc386GOTOffset = 9UL - /// x86: pc-relative offset to GOT (GOT + A - P). - | Reloc386GOTPC = 10UL - /// x86: (L + A). - | Reloc38632PLT = 11UL - /// x86 TLS relocations - | Reloc386TLSTPOFF = 14UL - | Reloc386TLSIE = 15UL - | Reloc386TLSGOTIE = 16UL - | Reloc386TLSLE = 17UL - | Reloc386TLSGD = 18UL - | Reloc386TLSLDM = 19UL - /// x86: (S + A). - | Reloc38616 = 20UL - /// x86: (S + A - P). - | Reloc386PC16 = 21UL - /// x86: (S + A). - | Reloc3868 = 22UL - /// x86: (S + A - P). - | Reloc386PC8 = 23UL - /// x86 more TLS relocations - | Reloc386TLSGD32 = 24UL - | Reloc386TLSGDPUSH = 25UL - | Reloc386TLSGDCALL = 26UL - | Reloc386TLSGDPOP = 27UL - | Reloc386TLSLDM32 = 28UL - | Reloc386TLSLDMPUSH = 29UL - | Reloc386TLSLDMCALL = 30UL - | Reloc386TLSLDMPOP = 31UL - | Reloc386TLSLDO32 = 32UL - | Reloc386TLSIE32 = 33UL - | Reloc386TLSLE32 = 34UL - | Reloc386TLSDTPMOD32 = 35UL - | Reloc386TLSDTPOFF32 = 36UL - | Reloc386TLSTPOFF32 = 37UL - /// x86: (Z + A). - | Reloc386SIZE32 = 38UL - /// x86 more TLS relocations - | Reloc386TLSGOTDESC = 39UL - | Reloc386TLSDESCCALL = 40UL - | Reloc386TLSDESC = 41UL - /// x86: indirect (B + A). - | Reloc386IRELATIVE = 42UL - /// x86: (G + A - GOT/G + A) - | Reloc386GOT32X = 43UL - /// x86: (A + (S >> 4)). - | Reloc386SEG16 = 44UL - /// x86: (A - S). - | Reloc386SUB16 = 45UL - /// x86: (A - S). - | Reloc386SUB32 = 46UL - -/// Relocation type for x86-64. -type RelocationX64 = - /// x86-64: no relocation. - | RelocX64None = 0UL - /// x86-64: direct 64-bit. - | RelocX6464 = 1UL - /// x86-64: PC-relative 32-bit. - | RelocX64PC32 = 2UL - /// x86-64: 32-bit GOT entry. - | RelocX64GOT32 = 3UL - /// x86-64: 32-bit PLT entry. - | RelocX64PLT32 = 4UL - /// x86-64: copy symbol at runtime. - | RelocX64Copy = 5UL - /// x86-64: create GOT entry. - | RelocX64GlobData = 6UL - /// x86-64: create PLT entry. - | RelocX64JmpSlot = 7UL - /// x86-64: adjust by program base. - | RelocX64Relative = 8UL - /// x86-64: 32-bit signed PC-relative offset to GOT. - | RelocX64GOTPCREL = 9UL - /// x86-64: direct 32-bit zero extended. - | RelocX6432 = 10UL - /// x86-64: direct 32-bit sign extended. - | RelocX6432S = 11UL - /// x86-64: direct 16-bit zero extended. - | RelocX6416 = 12UL - /// x86-64: 16-bit sign extended PC relative. - | RelocX64PC16 = 13UL - /// x86-64: direct 8-bit sign extended. - | RelocX648 = 14UL - /// x86-64: 8-bit sign extended PC relative. - | RelocX64PC8 = 15UL - /// x86-64: PC-relative 64 bit. - | RelocX64PC64 = 24UL - /// x86-64: 64-bit offset to GOT. - | RelocX64GOTOFF64 = 25UL - /// x86-64: 32-bit signed PC-relative offset to GOT. - | RelocX64GOTPC32 = 26UL - /// x86-64: 64-bit GOT entry offset. - | RelocX64GOT64 = 27UL - /// x86-64: 64-bit PC-relative offset to GOT entry. - | RelocX64GOTPCREL64 = 28UL - /// x86-64: 64-bit PC relative offset to GOT. - | RelocX64GOTPC64 = 29UL - /// x86-64: 64-bit GOT entry offset requiring PLT. - | RelocX64GOTPLT64 = 30UL - /// x86-64: 64-bit GOT relative offset to PLT entry. - | RelocX64PLTOFF64 = 31UL - /// x86-64: size of symbol plus 32-bit addend. - | RelocX64Size32 = 32UL - /// x86-64: size of symbol plus 64-bit addend. - | RelocX64Size64 = 33UL - /// x86-64: adjust indirectly by program base. - | RelocX64IRelative = 37UL - -/// Relocation type for ARMv7. -type RelocationARMv7 = - /// ARM: no reloc. - | RelocARMNone = 0UL - /// ARM: PC-relative 26-bit branch. - | RelocARMPC24 = 1UL - /// ARM: direct 32 bit. - | RelocARMABS32 = 2UL - /// ARM: PC-relative 32 bit. - | RelocARMREL32 = 3UL - /// ARM: PC-relative LDR. - | RelocARMPC13 = 4UL - /// ARM: direct 16 bit. - | RelocARMABS16 = 5UL - /// ARM: direct 12 bit. - | RelocARMABS12 = 6UL - /// ARM: direct 8 bit. - | RelocARMABS8 = 8UL - /// ARM: copy symbol at runtime. - | RelocARMCopy = 20UL - /// ARM: create GOT entry. - | RelocARMGlobData = 21UL - /// ARM: create PLT entry. - | RelocARMJmpSlot = 22UL - /// ARM: adjust by program base. - | RelocARMRelative = 23UL - /// ARM: 32-bit offset to GOT. - | RelocARMGOTOffset = 24UL - /// ARM: 32-bit PC-relative offset to GOT. - | RelocARMGOTPC = 25UL - /// ARM: 32-bit GOT entry. - | RelocARMGOT32 = 26UL - /// ARM: 32-bit PLT address. - | RelocARMPLT32 = 27UL - -/// Relocation type for ARMv8. -type RelocationARMv8 = - /// AARCH64: no reloc. - | RelocAARCH64None = 0UL - /// AARCH64: direct 64 bit. - | RelocAARCH64ABS64 = 257UL - /// AARCH64: direct 32 bit. - | RelocAARCH64ABS32 = 258UL - /// AARCH64: direct 16 bit. - | RelocAARCH64ABS16 = 259UL - /// AARCH64: PC-relative 64 bit. - | RelocAARCH64PREL64 = 260UL - /// AARCH64: PC-relative 32 bit. - | RelocAARCH64PREL32 = 261UL - /// AARCH64: PC-relative 16 bit. - | RelocAARCH64PREL16 = 262UL - /// AARCH64: GOT-relative 64 bit. - | RelocAARCH64GOTREL64 = 307UL - /// AARCH64: GOT-relative 32 bit. - | RelocAARCH64GOTREL32 = 308UL - /// AARCH64: copy symbol at runtime. - | RelocAARCH64Copy = 1024UL - /// AARCH64: create GOT entry. - | RelocAARCH64GlobData = 1025UL - /// AARCH64: create PLT entry. - | RelocAARCH64JmpSlot = 1026UL - -/// Relocation type for MIPS. -type RelocationMIPS = - /// MIPS: no reloc. - | RelocMIPSNone = 0UL - /// MIPS: direct 16 bit. - | RelocMIPS16 = 1UL - /// MIPS: direct 32 bit. - | RelocMIPS32 = 2UL - /// MIPS: PC-relative 32 bit. - | RelocMIPSREL32 = 3UL - /// MIPS: direct 26 bit shifted. - | RelocMIPS26 = 4UL - /// MIPS: high 16 bit. - | RelocMIPSHigh16 = 5UL - /// MIPS: low 16 bit. - | RelocMIPSLow16 = 6UL - /// MIPS: GP-relative 16 bit. - | RelocMIPSGPREL16 = 7UL - /// MIPS: 16-bit literal entry. - | RelocMIPSLiteral = 8UL - /// MIPS: 16-bit GOT entry. - | RelocMIPSGOT16 = 9UL - /// MIPS: PC-relative 16 bit. - | RelocMIPSPC16 = 10UL - /// MIPS: 16-bit GOT entry for function. - | RelocMIPSCall16 = 11UL - /// MIPS: GP-relative 32 bit. - | RelocMIPSGPREL32 = 12UL - /// MIPS: 5-bit shift field. - | RelocMIPSShift5 = 16UL - /// MIPS: 6-bit shift field. - | RelocMIPSShift6 = 17UL - /// MIPS: direct 64 bit. - | RelocMIPS64 = 18UL - /// MIPS: displacement in the GOT. - | RelocMIPSGOTDisp = 19UL - /// MIPS: displacement to page pointer in the GOT. - | RelocMIPSGOTPage = 20UL - /// MIPS: Offset from page pointer in the GOT. - | RelocMIPSGOTOfst = 21UL - /// MIPS: HIgh 16 bits of displacement in the GOT. - | RelocMIPSHI16 = 22UL - /// MIPS: Low 16 bits of displacement in the GOT. - | RelocMIPSLO16 = 23UL - /// MIPS: 64-bit subtraction. - | RelocMIPSSub = 24UL - /// MIPS: Insert the addend as an instruction. - | RelocMIPSInsertA = 25UL - /// MIPS: Insert the addend as an instruction, and change all relocations to - /// refer to the old instruction at the address. - | RelocMIPSInsertB = 26UL - /// MIPS: Delete a 32 bit instruction. - | RelocMIPSDelete = 27UL - /// MIPS: Get the higher value of a 64 bit addend. - | RelocMIPSHigher = 28UL - /// MIPS: Get the highest value of a 64 bit addend. - | RelocMIPSHighest = 29UL - /// MIPS: High 16 bits of displacement in GOT. - | RelocMIPSCallHI16 = 30UL - /// MIPS: Low 16 bits of displacement in GOT. - | RelocMIPSCallLO16 = 31UL - /// MIPS: Section displacement, used by an associated event location section. - | RelocMIPSScnDisp = 32UL - /// MIPS: PC-relative 16 bit. - | RelocMIPSREL16 = 33UL - /// MIPS: Similiar to R_MIPS_REL32, but used for relocations in a GOT section. - | RelocMIPSRelGOT = 36UL - /// MIPS: Protected jump conversion. - | RelocMIPSJALR = 37UL - /// MIPS: Module number 32 bit. - | RelocMIPSTLSDTPMOD32 = 38UL - /// MIPS: Module-relative offset 32 bit. - | RelocMIPSTLSDTPREL32 = 39UL - /// MIPS: Module number 64 bit. - | RelocMIPSTLSDTPMOD64 = 40UL - /// MIPS: Module-relative offset 64 bit. - | RelocMIPSTLSDTPREL64 = 41UL - /// MIPS: 16 bit GOT offset for GD. - | RelocMIPSTLSGD = 42UL - /// MIPS: 16 bit GOT offset for LDM. - | RelocMIPSTLSLDM = 43UL - /// MIPS: Module-relative offset, high 16 bits. - | RelocMIPSTLSDTPRELHI16 = 44UL - /// MIPS: Module-relative offset, low 16 bits. - | RelocMIPSTLSDTPRELLO16 = 45UL - /// MIPS: 16 bit GOT offset for IE. - | RelocMIPSTLSGOTPRel = 46UL - /// MIPS: TP-relative offset, 32 bit. - | RelocMIPSTLSTPRel32 = 47UL - /// MIPS: TP-relative offset, 64 bit. - | RelocMIPSTLSTPRel64 = 48UL - /// MIPS: TP-relative offset, high 16 bits. - | RelocMIPSTLSTPRelHI16 = 49UL - /// MIPS: TP-relative offset, low 16 bits. - | RelocMIPSTLSTPRelLO16 = 50UL - /// MIPS: 32 bit relocation with no addend. - | RelocMIPSGlobDat = 51UL - /// MIPS: Copy symbol at runtime. - | RelocMIPSCopy = 126UL - /// MIPS: Jump slot. - | RelocMIPSJumpSlot = 127UL - /// MIPS: 32-bit PC-relative. - | RelocMIPSPC32 = 248UL - -/// Relocation type for SH4. -type RelocationSH4 = - /// SH4: no reloc. - | RelocSHUnused = 0UL - /// SH4: 32 bit immediate for WinCE. - | RelocSHIMM32CE = 2UL - /// SH4: 8-bit PC rel. - | RelocSHPCREL8 = 3UL - /// SH4: 16-bit PC rel. - | RelocSHPCREL16 = 4UL - /// SH4: high 8 bits of 24 bit address. - | RelocSHHigh8 = 5UL - /// SH4: low 16 bits of 24 bit immediate. - | RelocSHLow16 = 7UL - /// SH4: 24 bit immediate. - | RelocSH_IMM24 = 6UL - /// SH4: PC rel 8 bits *4 +ve. - | RelocSHPCDISP8BY4 = 9UL - /// SH4: PC rel 8 bits *2 +ve. - | RelocSHPCDISP8BY2 = 10UL - /// SH4: 8 bit branch. - | RelocSHPCDISP8 = 11UL - /// SH4: 12 bit branch. - | RelocSHPCDISP = 12UL - /// SH4: 32 bit immediate. - | RelocSHIMM32 = 14UL - /// SH4: 8 bit immediate. - | RelocSHIMM8 = 16UL - /// SH4: 8 bit immediate *2. - | RelocSHIMM8BY2 = 17UL - /// SH4: 8 bit immediate *4. - | RelocSHIMM8BY4 = 18UL - /// SH4: 4 bit immediate. - | RelocSHIMM4 = 19UL - /// SH4: 4 bit immediate *2. - | RelocSHIMM4BY2 = 20UL - /// SH4: 4 bit immediate *4. - | RelocSHIMM4BY4 = 21UL - /// SH4: PC rel 8 bits *2 unsigned. - | RelocSHPCRELIMM8BY2 = 22UL - /// SH4: PC rel 8 bits *4 unsigned. - | RelocSHPCRELIMM8BY4 = 23UL - /// SH4: 16 bit immediate. - | RelocSHIMM16 = 24UL - /// SH4: 8 bit switch table entry. - | RelocSHSWITCH8 = 33UL - /// SH4: 16 bit switch table entry. - | RelocSHSWITCH16 = 25UL - /// SH4: 32 bit switch table entry. - | RelocSHSWITCH32 = 26UL - /// SH4: .uses pseudo-op. - | RelocSHUses = 27UL - /// SH4: Count of constant pool uses. - | RelocSHCount = 28UL - /// SH4: .align pseudo-op - | RelocSHAlign = 29UL - /// SH4: start of code. - | RelocSHCode = 30UL - /// SH4: start of data. - | RelocSHData = 31UL - /// SH4: label. - | RelocSHLabel = 32UL - /// SH4: loop start. - | RelocSHLoopStart = 34UL - /// SH4: loop end. - | RelocSHLoopEnd = 35UL - -/// Relocation type. -type RelocationType = - | RelocationX86 of RelocationX86 - | RelocationX64 of RelocationX64 - | RelocationARMv7 of RelocationARMv7 - | RelocationARMv8 of RelocationARMv8 - | RelocationMIPS of RelocationMIPS - | RelocationSH4 of RelocationSH4 -with - static member FromNum arch n = - match arch with - | Architecture.IntelX86 -> - RelocationX86 <| LanguagePrimitives.EnumOfValue n - | Architecture.IntelX64 -> - RelocationX64 <| LanguagePrimitives.EnumOfValue n - | Architecture.ARMv7 -> - RelocationARMv7 <| LanguagePrimitives.EnumOfValue n - | Architecture.AARCH32 - | Architecture.AARCH64 -> - RelocationARMv8 <| LanguagePrimitives.EnumOfValue n - | Architecture.MIPS1 - | Architecture.MIPS2 - | Architecture.MIPS3 - | Architecture.MIPS4 - | Architecture.MIPS5 - | Architecture.MIPS32 - | Architecture.MIPS32R2 - | Architecture.MIPS32R6 - | Architecture.MIPS64 - | Architecture.MIPS64R2 - | Architecture.MIPS64R6 -> - RelocationMIPS <| LanguagePrimitives.EnumOfValue n - | Architecture.SH4 -> - RelocationSH4 <| LanguagePrimitives.EnumOfValue n - | _ -> invalidArg (nameof arch) "Unsupported architecture for relocation." - -/// Relocation entry. -type RelocationEntry = { - /// The location at which to apply the relocation action. - RelOffset: uint64 - /// Relocation symbol. Symbol can be None when only the addend is used. - RelSymbol: ELFSymbol option - /// Relocation type. - RelType: RelocationType - /// A constant addend used to compute the value to be stored into the - /// relocatable field. - RelAddend: uint64 - /// The number of the section that defines this relocation. - RelSecNumber: int -} - -/// Relocation information -type RelocInfo = { - RelocByAddr: Dictionary - RelocByName: Dictionary -} - -/// Main data structure for storing symbol information. -type ELFSymbolInfo = { - /// Linux-specific symbol version table containing versions required to link. - VersionTable: Map - /// A mapping from a section number to the corresponding symbol table. - SecNumToSymbTbls: Map - /// Address to symbol mapping. - AddrToSymbTable: Map -} - -/// This member tells what kind of segment this array element describes or -/// how to interpret the array element's information. A segment is also known as -/// a 'program header'. -type ProgramHeaderType = - /// This program header is not used. - | PTNull = 0x00u - /// This is a loadable segment. - | PTLoad = 0x01u - /// This segment contains dynamic linking information. - | PTDynamic = 0x02u - /// This segment contains the location and size of a null-terminated path name - /// to invoke an interpreter. This segment type is meaningful only for - /// executable files, but not for shared objects. This segment may not occur - /// more than once in a file. If it is present, it must precede any loadable - /// segment entry. - | PTInterp = 0x03u - /// This segment contains the location and size of auxiliary information. - | PTNote = 0x04u - /// This segment type is reserved but has unspecified semantics. - | PTShLib = 0x05u - /// This segment specifies the location and size of the program header table - /// itself, It may occur only if the program header table is part of the - /// memory image of the program. If it is present, it must precede any - /// loadable segment entry. - | PTPhdr = 0x06u - /// This segment contains the Thread-Local Storage template. - | PTTLS = 0x07u - /// The lower bound of OS-specific program header type. - | PTLoOS = 0x60000000u - /// The upper bound of OS-specific program header type. - | PTHiOS = 0x6fffffffu - /// The lower bound of processor-specific program header type. - | PTLoProc = 0x70000000u - /// The exception unwind table (PT_ARM_EXIDX). - | PTARMExIdx = 0x70000001u - /// MIPS ABI flags (PT_MIPS_ABIFLAGS). - | PTMIPSABIFlags = 0x70000003u - /// The upper bound of processor-specific program header type. - | PTHiProc = 0x7fffffffu - /// This segment specifies the location and size of the exception handling - /// information as defined by the .eh_frame_hdr section. - | PTGNUEHFrame = 0x6474e550u - /// This segment specifies the permissions on the segment containing the stack - /// and is used to indicate weather the stack should be executable. The - /// absence of this header indicates that the stack will be executable. - | PTGNUStack = 0x6474e551u - /// This segment specifies the location and size of a segment which may be - /// made read-only after relocations have been processed. - | PTGNURelro = 0x6474e552u - /// This segment contains PAX flags. - | PTPAXFlags = 0x65041580u - -/// An executable or shared object file's program header table is an array of -/// structures, each of which describes a segment or the other information a -/// system needs to prepare for execution. An object file segment contains one -/// or more sections. Program headers are meaningful only for executable and -/// shared object files. A file specifies its own program header size with -/// the ELF header's members. -type ProgramHeader = { - /// Program header type. - PHType: ProgramHeaderType - /// Flags relevant to the segment. - PHFlags: Permission - /// An offset from the beginning of the file at which the first byte of the - /// segment resides in memory. - PHOffset: uint64 - /// The virtual address at which the first byte of the segment resides in - /// memory. - PHAddr: Addr - /// The physical address of the segment. This is reserved for systems using - /// physical addresses. - PHPhyAddr: Addr - /// The number of bytes in the file image of the segment. - PHFileSize: uint64 - /// The number of bytes in the memory image of the segment. This can be - /// greater than PHFileSize as some sections (w/ SHTNoBits type) occupy - /// nothing in the binary file, but can be mapped in the segment at runtime. - PHMemSize: uint64 - /// The value to which the segments are aligned in memory and in the file. - PHAlignment: uint64 -} - -/// Language Specific Data Area header. -type LSDAHeader = { - /// This is the value encoding of the landing pad pointer. - LPValueEncoding: ExceptionHeaderValue - /// This is the application encoding of the landing pad pointer. - LPAppEncoding: ExceptionHeaderApplication - /// The base of the landing pad pointers. - LPStart: Addr option - /// This is the value encoding of type table (TT). - TTValueEncoding: ExceptionHeaderValue - /// This is the application encoding of type table (TT). - TTAppEncoding: ExceptionHeaderApplication - /// The base of types table. - TTBase: Addr option - // This is the value encoding of the call site table. - CallSiteValueEncoding: ExceptionHeaderValue - // This is the application encoding of the call site table. - CallSiteAppEncoding: ExceptionHeaderApplication - // The size of call site table. - CallSiteTableSize: uint64 -} - -/// An entry in the callsite table of LSDA. -type CallSiteRecord = { - /// Offset of the callsite relative to the previous call site. - Position: uint64 - /// Size of the callsite instruction(s). - Length: uint64 - /// Offset of the landing pad. - LandingPad: uint64 - /// Offset to the action table. Zero means no action entry. - ActionOffset: int - /// Parsed list of type filters from the action table. - ActionTypeFilters: int64 list -} - -/// LSDA. Language Specific Data Area. -type LanguageSpecificDataArea = { - Header: LSDAHeader - CallSiteTable: CallSiteRecord list -} - -/// This tells how augmetation data is handled. -type Augmentation = { - Format: char - ValueEncoding: ExceptionHeaderValue - ApplicationEncoding: ExceptionHeaderApplication - PersonalityRoutionPointer: byte [] -} - -/// CIE. Common Information Entry. -type CommonInformationEntry = { - Version: uint8 - AugmentationString: string - CodeAlignmentFactor: uint64 - DataAlignmentFactor: int64 - ReturnAddressRegister: byte - InitialRule: Rule - InitialCFARegister: byte - InitialCFA: CanonicalFrameAddress - Augmentations: Augmentation list -} - -/// FDE. Frame Description Entry. -type FrameDescriptionEntry = { - PCBegin: Addr - PCEnd: Addr - LSDAPointer: Addr option - UnwindingInfo: UnwindingEntry list -} - -/// The main information block of .eh_frame. -type CallFrameInformation = { - CIERecord: CommonInformationEntry - FDERecord: FrameDescriptionEntry [] -} - -/// Main ELF format representation. -type ELF = { - /// ELF header. - ELFHdr: ELFHeader - /// Preferred base address. - BaseAddr: Addr - /// Segment information. - ProgHeaders: ProgramHeader list - /// Loadable segments. - LoadableSegments: ProgramHeader list - /// Loadable section numbers. - LoadableSecNums: Set - /// Section information. - SecInfo: SectionInfo - /// Symbol information. - SymInfo: ELFSymbolInfo - /// Relocation information. - RelocInfo: RelocInfo - /// Procedure Linkage Table. - PLT: ARMap - /// Global symbols (such as R_X86_64_GLOB_DAT). - Globals: Map - /// Exception frame. - ExceptionFrame: CallFrameInformation list - /// Exception table. - ExceptionTable: ARMap> - /// LSDAs (Language Specific Data Areas). - LSDAs: Map - /// Invalid address ranges. - InvalidAddrRanges: IntervalSet - /// Not-in-file address ranges. - NotInFileRanges: IntervalSet - /// Executable address ranges. - ExecutableRanges: IntervalSet - /// ISA. - ISA: ISA - /// Unwinding info table. - UnwindingTbl: Map - /// IBinReader. - BinReader: IBinReader -} diff --git a/src/FrontEnd/BinFile/FileFactory.fs b/src/FrontEnd/BinFile/FileFactory.fs new file mode 100644 index 00000000..2c014ec9 --- /dev/null +++ b/src/FrontEnd/BinFile/FileFactory.fs @@ -0,0 +1,45 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 + +[] +module FileFactory = + let load path bytes fmt isa regFactory baseAddrOpt = + match fmt with + | FileFormat.ELFBinary -> + ELFBinFile (path, bytes, baseAddrOpt, Some regFactory) :> IBinFile + | FileFormat.PEBinary -> + PEBinFile (path, bytes, baseAddrOpt, [||]) :> IBinFile + | FileFormat.MachBinary -> + MachBinFile (path, bytes, isa, baseAddrOpt) :> IBinFile + | FileFormat.WasmBinary -> + WasmBinFile (path, bytes) :> IBinFile + | _ -> + RawBinFile (path, bytes, isa, baseAddrOpt) :> IBinFile + + let loadELF path bytes regFactory baseAddrOpt = + ELFBinFile (path, bytes, baseAddrOpt, Some regFactory) \ No newline at end of file diff --git a/src/FrontEnd/BinFile/FileHelper.fs b/src/FrontEnd/BinFile/FileHelper.fs index 2aa7c2c3..337064f1 100644 --- a/src/FrontEnd/BinFile/FileHelper.fs +++ b/src/FrontEnd/BinFile/FileHelper.fs @@ -24,68 +24,47 @@ module internal B2R2.FrontEnd.BinFile.FileHelper -open System open B2R2 -let peekUIntOfType (span: ByteSpan) (reader: IBinReader) bitType o = - if bitType = WordSize.Bit32 then reader.ReadUInt32 (span, o) |> uint64 - else reader.ReadUInt64 (span, o) - -let readUIntOfType span reader bitType o = - let inline sizeByCls bitType = if bitType = WordSize.Bit32 then 4 else 8 - struct (peekUIntOfType span reader bitType o, o + sizeByCls bitType) - -let peekHeaderB (span: ByteSpan) (reader: IBinReader) cls offset d32 d64 = - reader.ReadByte (span, offset + (if cls = WordSize.Bit32 then d32 else d64)) - -let peekHeaderU16 (span: ByteSpan) (reader: IBinReader) cls offset d32 d64 = - reader.ReadUInt16 (span, offset + (if cls = WordSize.Bit32 then d32 else d64)) +/// Pick a number based on the word size. +let inline pickNum wordSize o32 o64 = + if wordSize = WordSize.Bit32 then o32 else o64 -let peekHeaderI32 (span: ByteSpan) (reader: IBinReader) cls offset d32 d64 = - reader.ReadInt32 (span, offset + (if cls = WordSize.Bit32 then d32 else d64)) - -let peekHeaderU32 (span: ByteSpan) (reader: IBinReader) cls offset d32 d64 = - reader.ReadUInt32 (span, offset + (if cls = WordSize.Bit32 then d32 else d64)) +let readUIntOfType (span: ByteSpan) (reader: IBinReader) cls o = + if cls = WordSize.Bit32 then reader.ReadUInt32 (span, o) |> uint64 + else reader.ReadUInt64 (span, o) -let peekHeaderNative span reader cls offset d32 d64 = - let offset = offset + (if cls = WordSize.Bit32 then d32 else d64) - peekUIntOfType span reader cls offset +let readNative span reader cls d32 d64 = + readUIntOfType span reader cls (pickNum cls d32 d64) let rec private cstrLoop (span: ByteSpan) acc pos = let byte = span[pos] if byte = 0uy then List.rev (0uy :: acc) |> List.toArray else cstrLoop span (byte :: acc) (pos + 1) -let peekCString (span: ByteSpan) offset = +let readCString (span: ByteSpan) offset = let bs = cstrLoop span [] offset ByteArray.extractCString bs 0 -let addInvRange set saddr eaddr = +let addInvalidRange set saddr eaddr = if saddr = eaddr then set else IntervalSet.add (AddrRange (saddr, eaddr - 1UL)) set -let addLastInvRange wordSize (set, saddr) = +let addLastInvalidRange wordSize (set, saddr) = let laddr = if wordSize = WordSize.Bit32 then 0xFFFFFFFFUL else 0xFFFFFFFFFFFFFFFFUL IntervalSet.add (AddrRange (saddr, laddr)) set -/// Trim the target range based on my range (myrange) in such a way that the -/// resulting range is always included in myrange. -let trimByRange myrange target = - let l = max (AddrRange.GetMin myrange) (AddrRange.GetMin target) - let h = min (AddrRange.GetMax myrange) (AddrRange.GetMax target) - AddrRange (l, h) - let getNotInFileIntervals fileBase fileSize (range: AddrRange) = let lastAddr = fileBase + fileSize - 1UL - if range.Max < fileBase then Seq.singleton range + if range.Max < fileBase then [| range |] elif range.Max <= lastAddr && range.Min < fileBase then - Seq.singleton (AddrRange (range.Min, fileBase - 1UL)) + [| AddrRange (range.Min, fileBase - 1UL) |] elif range.Max > lastAddr && range.Min < fileBase then - [ AddrRange (range.Min, fileBase - 1UL) - AddrRange (lastAddr + 1UL, range.Max) ] - |> List.toSeq + [| AddrRange (range.Min, fileBase - 1UL) + AddrRange (lastAddr + 1UL, range.Max) |] elif range.Max > lastAddr && range.Min <= lastAddr then - Seq.singleton (AddrRange (lastAddr + 1UL, range.Max)) - elif range.Max > lastAddr && range.Min > lastAddr then Seq.singleton range - else Seq.empty + [| AddrRange (lastAddr + 1UL, range.Max) |] + elif range.Max > lastAddr && range.Min > lastAddr then [| range |] + else [||] + diff --git a/src/FrontEnd/BinFile/FileInfo.fs b/src/FrontEnd/BinFile/FileInfo.fs deleted file mode 100644 index ea5a0640..00000000 --- a/src/FrontEnd/BinFile/FileInfo.fs +++ /dev/null @@ -1,452 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open System.Runtime.InteropServices -open B2R2 - -/// FileInfo describes a binary file in a format-agnostic way. -[] -type FileInfo () = - /// - /// Raw byte values as a `ByteSpan`. - /// - abstract Span: ByteSpan - - /// - /// The format of this file: ELF, PE, Mach-O, or etc. - /// - abstract FileFormat: FileFormat - - /// - /// The ISA that this file expects to run on. - /// - abstract ISA: ISA - - /// - /// What kind of binary is this? - /// - abstract FileType: FileType - - /// - /// The file path where this file is located. - /// - abstract FilePath: string - - /// - /// Word size of the CPU that this binary can run on. - /// - abstract WordSize: WordSize - - /// - /// Is this binary stripped? - /// - abstract IsStripped: bool - - /// - /// Is NX enabled for this binary? (DEP enabled or not) - /// - abstract IsNXEnabled: bool - - /// - /// Is this binary relocatable (position-independent)? - /// - abstract IsRelocatable: bool - - /// - /// The base address of this binary at which this binary is prefered to be - /// loaded in memory. - /// - abstract BaseAddress: Addr - - /// - /// The entry point of this binary (the start address that this binary runs - /// at). Note that some binaries (e.g., PE DLL files) do not have a specific - /// entry point, and EntryPoint will return None in such a case. - /// - abstract EntryPoint: Addr option - - /// - /// The beginning of the text section of this binary. - /// - abstract TextStartAddr: Addr - - /// - /// Translate a virtual address into a relative offset to this binary. - /// - /// Virtual address. - /// - /// Returns an offset to this binary for a given virtual address. - /// - /// - /// Thrown when the given address is out of a valid address range. - /// - abstract member TranslateAddress: addr: Addr -> int - - /// - /// Add a symbol for the address. This function is useful when we can - /// obtain extra symbol information from outside of B2R2. - /// - /// - /// Does not return a value. - /// - abstract member AddSymbol: Addr -> Symbol -> unit - - /// - /// Return a list of all the symbols from the binary. - /// - /// - /// A sequence of symbols. - /// - abstract member GetSymbols: unit -> seq - - /// - /// Return a list of all the static symbols from the binary. Static symbols - /// can be removed when we strip the binary. Unlike dynamic symbols, static - /// symbols are not required to run the binary, thus they can be safely - /// removed before releasing it. - /// - /// - /// A sequence of static symbols. - /// - abstract member GetStaticSymbols: unit -> seq - - /// - /// Return a list of all the dynamic symbols from the binary. Dynamic - /// symbols are the ones that are required to run the binary. The - /// "excludeImported" argument indicates whether to exclude external symbols - /// that are imported from other files. However, even if "excludeImported" - /// is true, returned symbols may include a forwarding entry that redirects - /// to another function in an external file (cf. SymbolKind.ForwardType). - /// When "excludeImported" argument is not given, this function will simply - /// return all possible dynamic symbols. - /// - /// - /// A sequence of dynamic symbols. - /// - abstract member GetDynamicSymbols: ?excludeImported: bool -> seq - - /// - /// Return a list of all relocation symbols from the binary. - /// - /// - /// A sequence of relocation symbols. - /// - abstract member GetRelocationSymbols: unit -> seq - - /// - /// Return a list of all the sections from the binary. - /// - /// - /// A sequence of sections. - /// - abstract member GetSections: unit -> seq
- - /// - /// Return a section that contains the given address. - /// - /// The address that belongs to a section. - /// - /// A sequence of sections. This function returns a singleton if there - /// exists a corresponding section. Otherwise, it returns an empty sequence. - /// - abstract member GetSections: addr: Addr -> seq
- - /// - /// Return a section that has the specified name. - /// - /// The name of the section. - /// - /// A sequence of sections that have the specified name. This function - /// returns an empty sequence if there is no section of the given name. - /// - abstract member GetSections: name: string -> seq
- - /// - /// Return a sequence text sections. - /// - /// - /// A sequence of text sections. - /// - abstract member GetTextSections: unit -> seq
- - /// - /// Return a list of segments from the binary. If the isLoadable parameter - /// is true, it will only return a list of "loadable" segments. Otherwise, - /// it will return all possible segments. By default, this function returns - /// only loadable segments, e.g., PT_LOAD segment of ELF. - /// - /// - /// A sequence of segments. - /// - abstract member GetSegments: - [] isLoadable:bool - -> seq - - /// - /// Return a list of the segments from the binary, which contain the given - /// address. - /// - /// The address that belongs to segments. - /// - /// A sequence of segments. - /// - member __.GetSegments (addr: Addr) = - __.GetSegments () - |> Seq.filter (fun s -> (addr >= s.Address) && (addr < s.Address + s.Size)) - - /// - /// For a given permission, return a list of segments that satisfy the - /// permission. For a given "READ-only" permission, this function may return - /// a segment whose permission is "READABLE and WRITABLE", as an instance. - /// - /// - /// A sequence of segments. - /// - member __.GetSegments (perm: Permission) = - __.GetSegments () - |> Seq.filter (fun s -> (s.Permission &&& perm = perm) && s.Size > 0UL) - - /// - /// Return a list of all the linkage table entries from the binary. - /// - /// - /// A sequence of linkage table entries, e.g., PLT entries for ELF files. - /// - abstract member GetLinkageTableEntries: unit -> seq - - /// - /// Return if a given address is an address of a linkage table entry. - /// - /// - /// True if the address is a linkage table address, false otherwise. - /// - abstract member IsLinkageTable: Addr -> bool - - /// - /// Find the symbol name for a given address. - /// - /// - /// Returns a symbol as an Ok value if a symbol exists, otherwise returns - /// an Error value. - /// - abstract member TryFindFunctionSymbolName: Addr -> Result - - /// - /// An exception table, which is a mapping from a function address to a set - /// of landing pads. The landing pads are mappings from a range of - /// instruction addresses to a landing pad address. - /// - abstract member ExceptionTable: ARMap> - - /// - /// Convert the section at the address (Addr) into a binary pointer, which - /// can exclusively point to binary contents of the section. - /// - abstract member ToBinaryPointer: Addr -> BinaryPointer - - /// - /// Convert the section of the name (string) into a binary pointer, which - /// can exclusively point to binary contents of the section. - /// - abstract member ToBinaryPointer: string -> BinaryPointer - - /// - /// Check if the given address is valid for this binary. We say a given - /// address is valid for the binary if the address is within the range of - /// statically computable segment ranges. - /// - /// - /// Returns true if the address is within a valid range, false otherwise. - /// - abstract member IsValidAddr: Addr -> bool - - /// - /// Check if the given address range is valid. This function returns true - /// only if the whole range of the addressess are valid (for every address - /// in the range, IsValidAddr should return true). - /// - /// - /// Returns true if the whole range of addresses is within a valid range, - /// false otherwise. - /// - abstract member IsValidRange: AddrRange -> bool - - /// - /// Check if the given address is valid and there is an actual mapping from - /// the binary file to the corresponding memory. Unlike IsValidAddr, this - /// function checks if we can decide the actual value of the given address - /// from the binary. For example, a program header of an ELF file may - /// contain 100 bytes in size, but when it is mapped to a segment in memory, - /// the size of the segment can be larger than the size of the program - /// header. This function checks if the given address is in the range of the - /// segment that has a direct mapping to the file's program header. - /// - /// - /// Returns true if the address is within a mapped address range, false - /// otherwise. - /// - abstract member IsInFileAddr: Addr -> bool - - /// - /// Check if the given address range is valid and there exists a - /// corresponding region in the actual binary file. This function returns - /// true only if the whole range of the addressess are valid (for every - /// address in the range, IsInFileAddr should return true). - /// - /// - /// Returns true if the whole range of addresses is within a valid range, - /// false otherwise. - /// - abstract member IsInFileRange: AddrRange -> bool - - /// - /// Check if the given address is executable address for this binary. We say - /// a given address is executable if the address is within an executable - /// segment. Note we consider the addresses of known read-only sections - /// (such as .rodata) as non-executable, even though those sections are - /// within an executable segment. - /// - /// - /// Returns true if the address is executable, false otherwise. - /// - abstract member IsExecutableAddr: Addr -> bool - - /// - /// Given a range r, return a list of address ranges (intervals) that are - /// within r, and that are not in-file. - /// - /// - /// Returns an empty list when the given range r is valid, i.e., - /// `IsInFileRange r = true`. - /// - abstract member GetNotInFileIntervals: AddrRange -> seq - - /// - /// Returns a sequence of local function symbols (excluding external - /// functions) from a given FileInfo. - /// - /// - /// A sequence of function symbols. - /// - member __.GetFunctionSymbols () = - let dict = Collections.Generic.Dictionary () - __.GetStaticSymbols () |> Seq.iter (fun s -> dict[s.Address] <- s) - __.GetDynamicSymbols (true) |> Seq.iter (fun s -> - if dict.ContainsKey s.Address then () else dict[s.Address] <- s) - dict - |> Seq.map (fun (KeyValue (_, s)) -> s) - |> Seq.filter (fun s -> s.Kind = SymFunctionType) - - /// - /// Returns a sequence of local function addresses (excluding external - /// functions) from a given FileInfo. This function only considers addresses - /// that are certain. - /// - /// - /// A sequence of function addresses. - /// - abstract member GetFunctionAddresses: unit -> seq - - default __.GetFunctionAddresses () = - __.GetFunctionSymbols () - |> Seq.map (fun s -> s.Address) - - /// - /// Returns a sequence of local function addresses (excluding external - /// functions) from a given FileInfo. If the argument is true, then this - /// funciton utilizes exception information of the binary to infer function - /// entries. Note that the inference process is not necessarily precise, so - /// this is really just an experimental feature, and will be removed in the - /// future. - /// - /// - /// A sequence of function addresses. - /// - abstract member GetFunctionAddresses: bool -> seq - - default __.GetFunctionAddresses (_) = - __.GetFunctionSymbols () - |> Seq.map (fun s -> s.Address) - - /// - /// Get a sequence of executable sections including linkage table code - /// sections such as PLT. - /// - /// - /// A sequence of executable sections. - /// - member __.GetExecutableSections () = - __.GetSections () - |> Seq.filter (fun s -> (s.Kind = SectionKind.ExecutableSection) - || (s.Kind = SectionKind.LinkageTableSection)) - - /// - /// Convert FileType to - /// string. - /// - /// A FileType to convert. - /// - /// A converted string. - /// - static member FileTypeToString (ty) = - match ty with - | FileType.ExecutableFile -> "Executable" - | FileType.CoreFile -> "Core dump" - | FileType.LibFile -> "Library" - | FileType.ObjFile -> "Object" - | _ -> "Unknown" - - /// - /// Convert from permission to string. - /// - /// A permission to convert. - /// - /// A converted string. - /// - static member PermissionToString (p: Permission) = - let r = - if p &&& Permission.Readable = LanguagePrimitives.EnumOfValue 0 then "" - else "R" - let w = - if p &&& Permission.Writable = LanguagePrimitives.EnumOfValue 0 then "" - else "W" - let x = - if p &&& Permission.Executable = LanguagePrimitives.EnumOfValue 0 then "" - else "X" - r + w + x - - /// - /// Convert from entrypoint information to string. - /// - /// Entry point of a given binary. - /// - /// A converted string. - /// - static member EntryPointToString (entryPoint: Addr option) = - match entryPoint with - | None -> "none" - | Some entry -> sprintf "0x%x" entry diff --git a/src/FrontEnd/BinFile/FileLoader.fs b/src/FrontEnd/BinFile/FileLoader.fs deleted file mode 100644 index daa5b748..00000000 --- a/src/FrontEnd/BinFile/FileLoader.fs +++ /dev/null @@ -1,80 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// FileLoader provides an interface for loading a binary. -[] -module B2R2.FrontEnd.BinFile.FileLoader - -open B2R2 -open B2R2.FrontEnd.BinLifter - -let private loadRegBay isa = - match isa.Arch with - | Arch.IntelX64 - | Arch.IntelX86 -> Intel.Basis.initRegBay isa.WordSize - | Arch.ARMv7 -> ARM32.Basis.initRegBay () - | Arch.AARCH64 -> ARM64.Basis.initRegBay () - | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 - | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 - | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> MIPS.Basis.initRegBay isa - | _ -> Utils.futureFeature () - -/// Load a given byte array (binary file) and return a `FileInfo`. -[] -let load (binPath: string) (bytes: byte []) isa baseAddr = - let fmt, isa = FormatDetector.identify bytes isa - let regbay = loadRegBay isa - match fmt with - | FileFormat.ELFBinary -> - ELFFileInfo (bytes, binPath, baseAddr, Some regbay) :> FileInfo - | FileFormat.PEBinary -> - PEFileInfo (bytes, binPath, baseAddr) :> FileInfo - | FileFormat.MachBinary -> - MachFileInfo (bytes, binPath, isa, baseAddr) :> FileInfo - | _ -> RawFileInfo (bytes, binPath, isa, baseAddr) :> FileInfo - -/// Load a given byte array (binary file) and return a `ELFFileInfo`. -[] -let loadELF (binPath: string) (bytes: byte []) isa baseAddr = - let fmt, isa = FormatDetector.identify bytes isa - let regbay = loadRegBay isa - match fmt with - | FileFormat.ELFBinary -> ELFFileInfo (bytes, binPath, baseAddr, Some regbay) - | _ -> raise InvalidFileTypeException - -/// Load a given byte array (binary file) and return a `PEFileInfo`. -[] -let loadPE (binPath: string) (bytes: byte []) isa baseAddr = - let fmt, isa = FormatDetector.identify bytes isa - match fmt with - | FileFormat.PEBinary -> PEFileInfo (bytes, binPath, baseAddr=baseAddr) - | _ -> raise InvalidFileTypeException - -/// Load a given byte array (binary file) and return a `MachFileInfo`. -[] -let loadMach (binPath: string) (bytes: byte []) isa baseAddr = - let fmt, isa = FormatDetector.identify bytes isa - match fmt with - | FileFormat.MachBinary -> MachFileInfo (bytes, binPath, isa, baseAddr) - | _ -> raise InvalidFileTypeException diff --git a/src/FrontEnd/BinFile/FileTypes.fs b/src/FrontEnd/BinFile/FileTypes.fs deleted file mode 100644 index 4cd6b2a0..00000000 --- a/src/FrontEnd/BinFile/FileTypes.fs +++ /dev/null @@ -1,173 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open B2R2 - -/// Raised when accessing an invalid address of a binary file. -exception InvalidAddrReadException - -/// Raised when an unexpected file format is detected. -exception FileFormatMismatchException - -/// Raised when an invalid file type is encountered. -exception InvalidFileTypeException - -/// Kinds of a symbol. -type SymbolKind = - /// The symbol type is not specified. - | NoType - /// The symbol is associated with a data object, such as a variable. - | SymObjectType - /// The symbol is associated with a general function. - | SymFunctionType - /// The symbol is associated with an external (imported) function. - | SymExternFunctionType - /// The symbol is associated with a trampoline instruction, such as PLT. - | SymTrampolineType - /// The symbol is associated with a section. - | SymSectionType - /// The symbol gives the name of the source file associated with the obj file. - | SymFileType - /// The symbol is associated with a forwarding entry. - | SymForwardType of bin: string * func: string - -/// Is the symbol used for static target (static link editor) or dynamic target -/// (dynamic linker)? -type TargetKind = - /// Static symbols are used by link editor, and can be stripped off. - | StaticSymbol = 1 - /// Dynamic symbols cannot be stripped off. - | DynamicSymbol = 2 - -/// A symbol object defined in a file-format-agnostic way. -type Symbol = { - /// Address of the symbol. - Address: Addr - /// Symbol name. - Name: string - /// Symbol kind. - Kind: SymbolKind - /// Symbol target. - Target: TargetKind - /// Corresponding library name. - LibraryName: string - /// Corresponding ArchOperationMode for this symbol, which is only meaningful - /// for ARM. - ArchOperationMode: ArchOperationMode -} - -/// Kinds of sections. -type SectionKind = - /// Executable section. - | ExecutableSection = 1 - /// Writable section. - | WritableSection = 2 - /// Linkage table, such as PLT, section. - | LinkageTableSection = 3 - /// Extra section. - | ExtraSection = 4 - -/// A section object defined in a file-format-agnostic way. A Section in B2R2 -/// should be located inside a segment. -type Section = { - /// Address of the section. - Address: Addr - /// File offset of the section. - FileOffset: uint64 - /// Section kind. - Kind: SectionKind - /// Size of the section. - Size: uint64 - /// Name of the section. - Name: string -} -with - /// Convert the section into an AddrRange based on its starting address and - /// the size. - member __.ToAddrRange () = - AddrRange (__.Address, __.Address + __.Size - 1UL) - -/// Linkage table entry object, which basically refers to PLT or IAT. -type LinkageTableEntry = { - /// Target function name for dynamic linking. - FuncName: string - /// Corresponding library name. - LibraryName: string - /// Trampoline code address, e.g., PLT. - TrampolineAddress: Addr - /// The address of the table that stores the actual target address, e.g., GOT. - TableAddress: Addr -} - -/// FileType represents categories for binary files. -type FileType = - /// Executable. - | ExecutableFile = 1 - /// Core (core dump). - | CoreFile = 2 - /// Library. - | LibFile = 3 - /// Object. - | ObjFile = 4 - /// Other types. - | UnknownFile = 5 - -/// File permission. Each permission corresponds to a bit, and thus, multiple -/// permissions can be OR-ed. -[] -type Permission = - /// File is readable. - | Readable = 4 - /// File is writable. - | Writable = 2 - /// File is executable. - | Executable = 1 - -module Permission = - /// Permission to string. - [] - let toString (p: Permission) = - let r = if p.HasFlag Permission.Readable then "r" else "-" - let w = if p.HasFlag Permission.Writable then "w" else "-" - let x = if p.HasFlag Permission.Executable then "x" else "-" - r + w + x - -/// A segment is a block of code/data that is loaded in the real memory at -/// runtime. A segment can contain multiple sections in it. -type Segment = { - /// Address of the segment. - Address: Addr - /// Offset in the file. - Offset: uint64 - /// Size of the segment. - Size: uint64 - /// Size of the corresponding segment in file. This can be smaller than - /// `Size` in which case the missing part is filled with zeros. - SizeInFile: uint64 - /// Permission of the segment. - Permission: Permission -} diff --git a/src/FrontEnd/BinFile/FormatDetector.fs b/src/FrontEnd/BinFile/FormatDetector.fs index cc4b106b..e9eec446 100644 --- a/src/FrontEnd/BinFile/FormatDetector.fs +++ b/src/FrontEnd/BinFile/FormatDetector.fs @@ -26,63 +26,45 @@ [] module B2R2.FrontEnd.BinFile.FormatDetector -open System open B2R2 -let private identifyELF span = - if ELF.Header.isELF span then - let cls = ELF.Header.peekClass span - let endian = ELF.Header.peekEndianness span - let reader = - if endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - let arch = ELF.Header.peekArch span reader cls - let isa = ISA.Init arch endian - Some (FileFormat.ELFBinary, isa) - else None +let private identifyELF bytes = + match ELF.Header.getISA bytes with + | Ok isa -> Some struct (FileFormat.ELFBinary, isa) + | _ -> None let private identifyPE bytes = - match PE.Helper.getPEArch bytes 0 with + match PE.Helper.getPEArch bytes with | Ok arch -> let isa = ISA.Init arch Endian.Little - Some (FileFormat.PEBinary, isa) + Some struct (FileFormat.PEBinary, isa) | Error _ -> None -let private identifyMach span isa = - let reader = BinReader.binReaderLE - if Mach.Header.isMach span reader then - if Mach.Header.isFat span reader then - let fat = - Mach.Fat.loadFats span reader - |> Mach.Fat.findMatchingFatRecord isa - let arch = Mach.Header.cpuTypeToArch fat.CPUType fat.CPUSubType - let endian = Mach.Header.peekEndianness (span.Slice fat.Offset) reader - let isa = ISA.Init arch endian - Some (FileFormat.MachBinary, isa) - else - let arch = Mach.Header.peekArch span reader - let endian = Mach.Header.peekEndianness span reader - let isa = ISA.Init arch endian - Some (FileFormat.MachBinary, isa) +let private identifyMach bytes isa = + if Mach.Header.isMach bytes 0UL then + let toolBox = Mach.Header.parse bytes None isa + let isa = Mach.Helper.getISA toolBox.Header + Some struct (FileFormat.MachBinary, isa) else None -let private identifyWASM span isa = - if Wasm.Header.isWasm span BinReader.binReaderLE then - Some (FileFormat.WasmBinary, isa) +let private identifyWASM bytes isa = + let reader = BinReader.Init Endian.Little + if Wasm.Header.isWasm bytes reader then + Some struct (FileFormat.WasmBinary, isa) else None /// -/// Given a binary (byte array), identify its binary file format -/// (B2R2.FileFormat) and its underlying ISA (B2R2.ISA). For FAT binaries, -/// this function will select an ISA only when there is a match with the given -/// input ISA. Otherwise, this function will raise InvalidISAException. +/// Given a binary bytes, identify its binary file format (B2R2.FileFormat) +/// and its underlying ISA (B2R2.ISA). For FAT binaries, this function will +/// select an ISA only when there is a match with the given input ISA. +/// Otherwise, this function will raise InvalidISAException. /// [] let identify bytes isa = Monads.OrElse.orElse { - yield! identifyELF (ReadOnlySpan bytes) + yield! identifyELF bytes yield! identifyPE bytes - yield! identifyMach (ReadOnlySpan bytes) isa - yield! identifyWASM (ReadOnlySpan bytes) isa + yield! identifyMach bytes isa + yield! identifyWASM bytes isa yield! Some (FileFormat.RawBinary, isa) } |> Option.get diff --git a/src/FrontEnd/BinFile/IBinFile.fs b/src/FrontEnd/BinFile/IBinFile.fs new file mode 100644 index 00000000..40c984ae --- /dev/null +++ b/src/FrontEnd/BinFile/IBinFile.fs @@ -0,0 +1,46 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 + +/// IBinFile describes a binary file in a format-agnostic way. +type IBinFile = + inherit IBinMetadata + inherit IBinProperty + inherit IContentAddressable + inherit IBinSymbolTable + inherit IBinOrganization + + /// + /// Return a reader for this binary file. + /// + abstract Reader: IBinReader + + /// The raw file content as a byte array. + abstract RawBytes: byte[] + + /// The size of the associated binary file. + abstract Length: int \ No newline at end of file diff --git a/src/FrontEnd/BinFile/IBinMetadata.fs b/src/FrontEnd/BinFile/IBinMetadata.fs new file mode 100644 index 00000000..0bbab2b3 --- /dev/null +++ b/src/FrontEnd/BinFile/IBinMetadata.fs @@ -0,0 +1,81 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 + +/// FileType represents categories for binary files. +type FileType = + /// Executable. + | ExecutableFile = 1 + /// Core (core dump). + | CoreFile = 2 + /// Library. + | LibFile = 3 + /// Object. + | ObjFile = 4 + /// Other types. + | UnknownFile = 5 + +module FileType = + /// + /// Convert FileType to + /// string. + /// + /// A FileType to convert. + /// + /// A converted string. + /// + [] + let toString ty = + match ty with + | FileType.ExecutableFile -> "Executable" + | FileType.CoreFile -> "Core dump" + | FileType.LibFile -> "Library" + | FileType.ObjFile -> "Object" + | _ -> "Unknown" + +/// Basic metadata of a binary file. +type IBinMetadata = + /// The file path where this file is located. + abstract Path: string + + /// The format of this file: ELF, PE, Mach-O, or etc. + abstract Format: FileFormat + + /// The ISA that this file expects to run on. + abstract ISA: ISA + + /// What kind of binary is this? + abstract Type: FileType + + /// The entry point of this binary (the start address that this binary runs + /// at). Note that some binaries (e.g., PE DLL files) do not have a specific + /// entry point, and EntryPoint will return None in such a case. + abstract EntryPoint: Addr option + + /// The base address of the associated binary at which it is prefered to be + /// loaded in memory. + abstract BaseAddress: Addr diff --git a/src/FrontEnd/BinFile/IBinOrganization.fs b/src/FrontEnd/BinFile/IBinOrganization.fs new file mode 100644 index 00000000..e5fbd3cd --- /dev/null +++ b/src/FrontEnd/BinFile/IBinOrganization.fs @@ -0,0 +1,141 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open System.Runtime.InteropServices +open B2R2 + +/// Organization of a binary file, such as sections, segments, and linkage +/// table. +type IBinOrganization = + /// + /// Return a list of all the sections from the binary. + /// + /// + /// A sequence of sections. + /// + abstract GetSections: unit -> Section[] + + /// + /// Return a section that contains the given address. + /// + /// The address that belongs to a section. + /// + /// A sequence of sections. This function returns a singleton if there + /// exists a corresponding section. Otherwise, it returns an empty sequence. + /// + abstract GetSections: addr: Addr -> Section[] + + /// + /// Return a section that has the specified name. + /// + /// The name of the section. + /// + /// A sequence of sections that have the specified name. This function + /// returns an empty sequence if there is no section of the given name. + /// + abstract GetSections: name: string -> Section[] + + /// + /// Return a text section from the binary. If there's no text section, this + /// function raises an exception. + /// + /// + /// A sequence of text sections. + /// + abstract GetTextSection: unit -> Section + + /// + /// Return a list of segments from the binary. If the isLoadable parameter + /// is true, it will only return a list of "loadable" segments. Otherwise, + /// it will return all possible segments. By default, this function returns + /// only loadable segments, e.g., PT_LOAD segment of ELF. + /// + /// + /// A sequence of segments. + /// + abstract GetSegments: + [] isLoadable:bool + -> Segment[] + + /// + /// Return a list of the segments from the binary, which contain the given + /// address. + /// + /// The address that belongs to segments. + /// + /// A sequence of segments. + /// + abstract GetSegments: addr: Addr -> Segment[] + + /// + /// For a given permission, return a list of segments that satisfy the + /// permission. For a given "READ-only" permission, this function may return + /// a segment whose permission is "READABLE and WRITABLE", as an instance. + /// + /// + /// A sequence of segments. + /// + abstract GetSegments: Permission -> Segment[] + + /// + /// Return a list of all the linkage table entries from the binary. + /// + /// + /// A sequence of linkage table entries, e.g., PLT entries for ELF files. + /// + abstract GetLinkageTableEntries: unit -> LinkageTableEntry[] + + /// + /// Return if a given address is an address of a linkage table entry. + /// + /// + /// True if the address is a linkage table address, false otherwise. + /// + abstract IsLinkageTable: Addr -> bool + + /// + /// Returns a sequence of local function addresses (excluding external + /// functions) from a given BinFile. This function only considers addresses + /// that are certain. + /// + /// + /// A sequence of function addresses. + /// + abstract GetFunctionAddresses: unit -> Addr[] + + /// + /// Returns a sequence of local function addresses (excluding external + /// functions) from a given BinFile. If the argument is true, then this + /// funciton utilizes exception information of the binary to infer function + /// entries. Note that the inference process is not necessarily precise, so + /// this is really just an experimental feature, and will be removed in the + /// future. + /// + /// + /// A sequence of function addresses. + /// + abstract GetFunctionAddresses: bool -> Addr[] + diff --git a/src/MiddleEnd/ConcEval/ConcEvalTypes.fs b/src/FrontEnd/BinFile/IBinProperty.fs similarity index 77% rename from src/MiddleEnd/ConcEval/ConcEvalTypes.fs rename to src/FrontEnd/BinFile/IBinProperty.fs index a028eee7..f313bb21 100644 --- a/src/MiddleEnd/ConcEval/ConcEvalTypes.fs +++ b/src/FrontEnd/BinFile/IBinProperty.fs @@ -22,18 +22,15 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.ConcEval +namespace B2R2.FrontEnd.BinFile -open B2R2 +/// Basic properties of a binary file. +type IBinProperty = + /// Is this binary stripped? + abstract IsStripped: bool -/// Raised when undefined expression is encountered. -exception UndefExpException + /// Is NX enabled for this binary? (DEP enabled or not) + abstract IsNXEnabled: bool -/// Raised when an invalid memory access. -exception InvalidMemException of Addr - -/// A value is either defined or undefined. -[] -type EvalValue = - | Undef - | Def of BitVector + /// Is this binary relocatable (i.e., position-independent)? + abstract IsRelocatable: bool diff --git a/src/FrontEnd/BinFile/IBinSymbolTable.fs b/src/FrontEnd/BinFile/IBinSymbolTable.fs new file mode 100644 index 00000000..3a8c5080 --- /dev/null +++ b/src/FrontEnd/BinFile/IBinSymbolTable.fs @@ -0,0 +1,62 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Symbol table of a binary file. +type IBinSymbolTable = + inherit INameReadable + + /// Return an array of all the symbols from the binary. + abstract GetSymbols: unit -> Symbol[] + + /// Return a list of all the static symbols from the binary. Static symbols + /// can be removed when we strip the binary. Unlike dynamic symbols, static + /// symbols are not required to run the binary, thus they can be safely + /// removed before releasing it. + abstract GetStaticSymbols: unit -> Symbol[] + + /// Returns a sequence of local function symbols (excluding external + /// functions) from a given binary. + abstract GetFunctionSymbols: unit -> Symbol[] + + /// Return a list of all the dynamic symbols from the binary. Dynamic symbols + /// are the ones that are required to run the binary. The "excludeImported" + /// argument indicates whether to exclude external symbols that are imported + /// from other files. However, even if "excludeImported" is true, returned + /// symbols may include a forwarding entry that redirects to another function + /// in an external file (cf. SymbolKind.ForwardType). When "excludeImported" + /// argument is not given, this function will simply return all possible + /// dynamic symbols. + abstract GetDynamicSymbols: ?excludeImported: bool -> Symbol[] + + /// Return a list of all symbols for relocatable entries in the binary. + abstract GetRelocationSymbols: unit -> Symbol[] + + /// Add a symbol for the address. This function is useful when we can obtain + /// extra symbol information from outside of B2R2. + abstract AddSymbol: Addr -> Symbol -> unit \ No newline at end of file diff --git a/src/FrontEnd/BinFile/IContentAddressable.fs b/src/FrontEnd/BinFile/IContentAddressable.fs new file mode 100644 index 00000000..f582f35e --- /dev/null +++ b/src/FrontEnd/BinFile/IContentAddressable.fs @@ -0,0 +1,171 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 + +/// Can be used to access the binary content of a file via a virtual address or +/// a file offset. +type IContentAddressable = + /// + /// Translate a virtual address into a relative offset to the binary file. + /// + /// Virtual address. + /// + /// Returns an offset to the binary for a given virtual address. + /// + /// + /// Thrown when the given address is out of a valid address range. + /// + abstract GetOffset: addr: Addr -> int + + /// Slice a portion of the associated binary file based on the given virtual + /// `addr` and its `size`. + abstract Slice: addr: Addr * size: int -> ByteSpan + + /// Slice a maximum possible portion of the associated binary file based on + /// the given virtual `addr`. + abstract Slice: addr: Addr -> ByteSpan + + /// Slice a portion of the associated binary file based on the given file + /// `offset` and its `size`. + abstract Slice: offset: int * size: int -> ByteSpan + + /// Slice a maximum possible portion of the associated binary file based on + /// the given file `offset`. + abstract Slice: offset: int -> ByteSpan + + /// Slice a portion of the associated binary file based on the given pointer + /// `ptr` and its `size`. + abstract Slice: ptr: BinFilePointer * size: int -> ByteSpan + + /// Slice a maximum possible portion of the associated binary file based on + /// the given virtual `addr`. + abstract Slice: ptr: BinFilePointer -> ByteSpan + + /// Read a byte at the given virtual address. + abstract ReadByte: addr: Addr -> byte + + /// Read a byte pointed to by the given file `offset`. + abstract ReadByte: offset: int -> byte + + /// Read a byte pointed to by the given binary file pointer. + abstract ReadByte: ptr: BinFilePointer -> byte + + /// + /// Check if the given address is valid for the associated binary. We say a + /// given address is valid for the binary if the address is within the range + /// of statically computable segment ranges. + /// + /// + /// Returns true if the address is within a valid range, false otherwise. + /// + abstract IsValidAddr: Addr -> bool + + /// + /// Check if the given address range is valid. This function returns true + /// only if the whole range of the addressess are valid (for every address + /// in the range, IsValidAddr should return true). + /// + /// + /// Returns true if the whole range of addresses is within a valid range, + /// false otherwise. + /// + abstract IsValidRange: AddrRange -> bool + + /// + /// Check if the given address is valid and there is an actual mapping from + /// the associated binary file to the corresponding memory. Unlike + /// IsValidAddr, this function checks if we can decide the actual value of + /// the given address from the binary. For example, a program header of an + /// ELF file may contain 100 bytes in size, but when it is mapped to a + /// segment in memory, the size of the segment can be larger than the size + /// of the program header. This function checks if the given address is in + /// the range of the segment that has a direct mapping to the file's program + /// header. + /// + /// + /// Returns true if the address is within a mapped address range, false + /// otherwise. + /// + abstract IsInFileAddr: Addr -> bool + + /// + /// Check if the given address range is valid and there exists a + /// corresponding region in the actual binary file. This function returns + /// true only if the whole range of the addressess are valid (for every + /// address in the range, IsInFileAddr should return true). + /// + /// + /// Returns true if the whole range of addresses is within a valid range, + /// false otherwise. + /// + abstract IsInFileRange: AddrRange -> bool + + /// + /// Check if the given address is executable address for this binary. We say + /// a given address is executable if the address is within an executable + /// segment. Note we consider the addresses of known read-only sections + /// (such as .rodata) as non-executable, even though those sections are + /// within an executable segment. For object files, we simply consider a + /// .text section's address range as executable. + /// + /// + /// Returns true if the address is executable, false otherwise. + /// + abstract IsExecutableAddr: Addr -> bool + + /// + /// Given a range r, return a list of address ranges (intervals) that are + /// within r and not in-file. + /// + /// + /// Returns an empty list when the given range r is valid, i.e., + /// `IsInFileRange r = true`. + /// + abstract GetNotInFileIntervals: AddrRange -> AddrRange[] + + /// + /// Convert the section at the address (Addr) into a binary pointer, which + /// can exclusively point to binary contents of the section. + /// + abstract ToBinFilePointer: Addr -> BinFilePointer + + /// + /// Convert the section of the name (string) into a binary pointer, which + /// can exclusively point to binary contents of the section. + /// + abstract ToBinFilePointer: string -> BinFilePointer + + /// + /// Return a relocation target address of the given virtual address if there + /// is a corresponding relocation entry. + /// + /// Virtual address be relocated. + /// + /// Returns a relocated address for a given virtual address. + /// + abstract GetRelocatedAddr: relocAddr: Addr -> Result + diff --git a/src/FrontEnd/BinFile/LinkageTable.fs b/src/FrontEnd/BinFile/LinkageTable.fs new file mode 100644 index 00000000..4ebd89b3 --- /dev/null +++ b/src/FrontEnd/BinFile/LinkageTable.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 + +/// Linkage table entry object. +type LinkageTableEntry = { + /// Target function name for dynamic linking. + FuncName: string + /// Corresponding library name. + LibraryName: string + /// Trampoline code address, e.g., PLT. + TrampolineAddress: Addr + /// The address of the table that stores the actual target address, e.g., GOT. + TableAddress: Addr +} + +/// Linkage table, which basically refers to a PLT or an IAT. +type LinkageTable = LinkageTableEntry[] diff --git a/src/FrontEnd/BinFile/Mach.fs b/src/FrontEnd/BinFile/Mach.fs deleted file mode 100644 index af5989ba..00000000 --- a/src/FrontEnd/BinFile/Mach.fs +++ /dev/null @@ -1,80 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.Mach -open B2R2.FrontEnd.BinFile.Mach.Helper - -/// -/// This class represents a Mach-O binary file. -/// -type MachFileInfo (bytes, path, isa, baseAddr) = - inherit FileInfo () - let mach = Parser.parse baseAddr bytes isa - let isa = getISA mach - - new (bytes, path, isa) = MachFileInfo (bytes, path, isa, None) - override __.Span = ReadOnlySpan bytes - override __.FileFormat = FileFormat.MachBinary - override __.ISA = isa - override __.FileType = convFileType mach.MachHdr.FileType - override __.FilePath = path - override __.WordSize = mach.MachHdr.Class - override __.IsStripped = isStripped mach - override __.IsNXEnabled = isNXEnabled mach - override __.IsRelocatable = mach.MachHdr.Flags.HasFlag MachFlag.MHPIE - override __.BaseAddress = mach.BaseAddr - override __.EntryPoint = mach.EntryPoint - override __.TextStartAddr = getTextStartAddr mach - override __.TranslateAddress addr = translateAddr mach addr - override __.AddSymbol addr symbol = Utils.futureFeature () - override __.GetSymbols () = getSymbols mach - override __.GetStaticSymbols () = getStaticSymbols mach |> Array.toSeq - override __.GetDynamicSymbols (?e) = getDynamicSymbols e mach |> Array.toSeq - override __.GetRelocationSymbols () = mach.Relocations |> Array.toSeq - override __.GetSections () = getSections mach - override __.GetSections (addr) = getSectionsByAddr mach addr - override __.GetSections (name) = getSectionsByName mach name - override __.GetTextSections () = getTextSections mach - override __.GetSegments (isLoadable) = Segment.getSegments mach isLoadable - override __.GetLinkageTableEntries () = getPLT mach - override __.IsLinkageTable addr = isPLT mach addr - override __.TryFindFunctionSymbolName (addr) = tryFindFuncSymb mach addr - override __.ExceptionTable = ARMap.empty - override __.ToBinaryPointer addr = - BinaryPointer.OfSectionOpt (getSectionsByAddr mach addr |> Seq.tryHead) - override __.ToBinaryPointer name = - BinaryPointer.OfSectionOpt (getSectionsByName mach name |> Seq.tryHead) - override __.IsValidAddr addr = isValidAddr mach addr - override __.IsValidRange range = isValidRange mach range - override __.IsInFileAddr addr = isInFileAddr mach addr - override __.IsInFileRange range = isInFileRange mach range - override __.IsExecutableAddr addr = isExecutableAddr mach addr - override __.GetNotInFileIntervals range = getNotInFileIntervals mach range - member __.Mach with get() = mach - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinFile/Mach/MachBinFile.fs b/src/FrontEnd/BinFile/Mach/MachBinFile.fs new file mode 100644 index 00000000..30bc107b --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachBinFile.fs @@ -0,0 +1,200 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.Mach +open B2R2.FrontEnd.BinFile.Mach.Helper + +/// +/// This class represents a Mach-O binary file. +/// +type MachBinFile (path, bytes: byte[], isa, baseAddrOpt) = + let toolBox = Header.parse bytes baseAddrOpt isa + let cmds = lazy LoadCommand.parse toolBox + let segCmds = lazy Segment.extract cmds.Value + let segMap = lazy Segment.buildMap segCmds.Value + let secs = lazy Section.parse toolBox segCmds.Value + let symInfo = lazy Symbol.parse toolBox cmds.Value secs.Value + let relocs = lazy Reloc.parse toolBox symInfo.Value secs.Value + let notInMemRanges = lazy invalidRangesByVM toolBox segCmds.Value + let notInFileRanges = lazy invalidRangesByFileBounds toolBox segCmds.Value + let executableRanges = lazy executableRanges segCmds.Value + + member __.Header with get() = toolBox.Header + + member __.Commands with get() = cmds.Value + + member __.Sections with get() = secs.Value + + member __.SymbolInfo with get() = symInfo.Value + + interface IBinFile with + member __.Path with get() = path + + member __.Format with get() = FileFormat.MachBinary + + member __.ISA with get() = getISA toolBox.Header + + member __.Type with get() = convFileType toolBox.Header.FileType + + member __.EntryPoint = computeEntryPoint segCmds.Value cmds.Value + + member __.BaseAddress with get() = toolBox.BaseAddress + + member __.IsStripped = isStripped secs.Value symInfo.Value + + member __.IsNXEnabled = isNXEnabled toolBox.Header + + member __.IsRelocatable = toolBox.Header.Flags.HasFlag MachFlag.MH_PIE + + member __.GetOffset addr = translateAddr segMap.Value addr + + member __.Slice (addr, size) = + let offset = translateAddr segMap.Value addr |> Convert.ToInt32 + (__ :> IBinFile).Slice (offset=offset, size=size) + + member __.Slice (addr) = + let offset = translateAddr segMap.Value addr |> Convert.ToInt32 + (__ :> IBinFile).Slice (offset=offset) + + member __.Slice (offset: int, size) = + ReadOnlySpan (bytes, offset, size) + + member __.Slice (offset: int) = + ReadOnlySpan(bytes).Slice offset + + member __.Slice (ptr: BinFilePointer, size) = + ReadOnlySpan (bytes, ptr.Offset, size) + + member __.Slice (ptr: BinFilePointer) = + ReadOnlySpan(bytes).Slice ptr.Offset + + member __.ReadByte (addr: Addr) = + let offset = translateAddr segMap.Value addr |> Convert.ToInt32 + bytes[offset] + + member __.ReadByte (offset: int) = + bytes[offset] + + member __.ReadByte (ptr: BinFilePointer) = + bytes[ptr.Offset] + + member __.IsValidAddr addr = + IntervalSet.containsAddr addr notInMemRanges.Value |> not + + member __.IsValidRange range = + IntervalSet.findAll range notInMemRanges.Value |> List.isEmpty + + member __.IsInFileAddr addr = + IntervalSet.containsAddr addr notInFileRanges.Value |> not + + member __.IsInFileRange range = + IntervalSet.findAll range notInFileRanges.Value |> List.isEmpty + + member __.IsExecutableAddr addr = + IntervalSet.containsAddr addr executableRanges.Value + + member __.GetNotInFileIntervals range = + IntervalSet.findAll range notInFileRanges.Value + |> List.toArray + |> Array.map range.Slice + + member __.ToBinFilePointer addr = + getSectionsByAddr secs.Value segMap.Value addr + |> Seq.tryHead + |> BinFilePointer.OfSectionOpt + + member __.ToBinFilePointer name = + getSectionsByName secs.Value segMap.Value name + |> Seq.tryHead + |> BinFilePointer.OfSectionOpt + + member __.GetRelocatedAddr _relocAddr = Utils.futureFeature () + + member __.TryFindFunctionName (addr) = + tryFindFuncSymb symInfo.Value addr + + member __.GetSymbols () = getSymbols secs.Value symInfo.Value + + member __.GetStaticSymbols () = + getStaticSymbols secs.Value symInfo.Value + + member __.GetFunctionSymbols () = + let self = __ :> IBinFile + let staticSymbols = + self.GetStaticSymbols () + |> Array.filter (fun s -> s.Kind = SymFunctionType) + let dynamicSymbols = + self.GetDynamicSymbols (true) + |> Array.filter (fun s -> s.Kind = SymFunctionType) + Array.append staticSymbols dynamicSymbols + + member __.GetDynamicSymbols (?e) = + getDynamicSymbols e secs.Value symInfo.Value + + member __.GetRelocationSymbols () = relocs.Value + + member __.AddSymbol _addr _symbol = Utils.futureFeature () + + member __.GetSections () = getSections secs.Value segMap.Value + + member __.GetSections (addr) = + getSectionsByAddr secs.Value segMap.Value addr + + member __.GetSections (name) = + getSectionsByName secs.Value segMap.Value name + + member __.GetTextSection () = getTextSection secs.Value segMap.Value + + member __.GetSegments (isLoadable) = + Segment.toArray segCmds.Value isLoadable + + member __.GetSegments (addr) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (addr >= s.Address) + && (addr < s.Address + uint64 s.Size)) + + member __.GetSegments (perm) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (s.Permission &&& perm = perm) && s.Size > 0u) + + member __.GetLinkageTableEntries () = getPLT symInfo.Value + + member __.IsLinkageTable addr = isPLT symInfo.Value addr + + member __.GetFunctionAddresses () = + (__ :> IBinFile).GetFunctionSymbols () + |> Array.map (fun s -> s.Address) + + member __.GetFunctionAddresses (_) = + (__ :> IBinFile).GetFunctionAddresses () + + member __.Reader with get() = toolBox.Reader + + member __.RawBytes = bytes + + member __.Length = bytes.Length \ No newline at end of file diff --git a/src/FrontEnd/BinFile/Mach/MachCPUType.fs b/src/FrontEnd/BinFile/Mach/MachCPUType.fs new file mode 100644 index 00000000..5f26de1b --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachCPUType.fs @@ -0,0 +1,78 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open B2R2 + +/// CPUType indicates the architecture. +type CPUType = + | Any = 0xFFFFFFFF + | VAX = 0x00000001 + | ROMP = 0x00000002 + | NS32032 = 0x00000004 + | NS32332 = 0x00000005 + | MC680x0 = 0x00000006 + | I386 = 0x00000007 + | X64 = 0x01000007 + | MIPS = 0x00000008 + | NS32532 = 0x00000009 + | HPPA = 0x0000000B + | ARM = 0x0000000C + | MC88000 = 0x0000000D + | SPARC = 0x0000000E + | I860 = 0x0000000F + | I860LITTLE = 0x00000010 + | RS6000 = 0x00000011 + | POWERPC = 0x00000012 + | ABI64 = 0x01000000 + | POWERPC64 = 0x01000012 + | VEO = 0x000000FF + | ARM64 = 0x0100000C + +/// CPUSubType specifies the exact model of the CPU. +type CPUSubType = + | MIPSAll = 0 + | MIPSR2300 = 1 + | MIPSR2600 = 2 + | MIPSR2800 = 3 + | MIPSR2000A = 4 + +module CPUType = + let private toMIPSArch = function + | CPUSubType.MIPSAll + | CPUSubType.MIPSR2300 + | CPUSubType.MIPSR2600 + | CPUSubType.MIPSR2800 + | CPUSubType.MIPSR2000A -> Architecture.MIPS32 (* MIPS32R2 *) + | _ -> raise InvalidISAException + + let toArch cputype subtype = + match cputype with + | CPUType.I386 -> Architecture.IntelX86 + | CPUType.X64 -> Architecture.IntelX64 + | CPUType.ARM -> Architecture.ARMv7 + | CPUType.ARM64 -> Architecture.AARCH64 + | CPUType.MIPS -> toMIPSArch subtype + | _ -> Architecture.UnknownISA diff --git a/src/FrontEnd/BinFile/Mach/MachFat.fs b/src/FrontEnd/BinFile/Mach/MachFat.fs new file mode 100644 index 00000000..718486f2 --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachFat.fs @@ -0,0 +1,67 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open System +open B2R2 + +/// Describes the location within the binary of an object file targeted at a +/// single architecture (fat_arch). +type FatArch = { + CPUType: CPUType + CPUSubType: CPUSubType + Offset: int + Size: int + Align: int +} + +module Fat = + let private readFatArch (span: ByteSpan) (reader: IBinReader) offset = + let cpuType = reader.ReadInt32 (span, offset) + let cpuSubType = reader.ReadInt32 (span, offset + 4) + { CPUType = cpuType |> LanguagePrimitives.EnumOfValue + CPUSubType = cpuSubType |> LanguagePrimitives.EnumOfValue + Offset = reader.ReadInt32 (span, offset + 8) + Size = reader.ReadInt32 (span, offset + 12) + Align = reader.ReadInt32 (span, offset + 16) } + + let loadFatArchs (bytes: byte[]) = + let reader = BinReader.Init Endian.Big + let magic = reader.ReadUInt32 (bytes, 0) + let nArch = reader.ReadInt32 (bytes, 4) + assert (LanguagePrimitives.EnumOfValue magic = Magic.FAT_MAGIC) + let span = ReadOnlySpan (bytes, 8, 20 * nArch) + let archs = Array.zeroCreate nArch + for i = 0 to nArch - 1 do + archs[i] <- readFatArch span reader (i * 20) + archs + + let private matchingISA isa fatArch = + isa.Arch = CPUType.toArch fatArch.CPUType fatArch.CPUSubType + + let loadArch bytes isa = + loadFatArchs bytes + |> Array.tryFind (matchingISA isa) + |> function Some arch -> arch | None -> raise InvalidISAException \ No newline at end of file diff --git a/src/FrontEnd/BinFile/Mach/MachHeader.fs b/src/FrontEnd/BinFile/Mach/MachHeader.fs new file mode 100644 index 00000000..380ac20a --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachHeader.fs @@ -0,0 +1,246 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open System +open B2R2 +open B2R2.FrontEnd.BinFile + +/// Usage of the file. +type MachFileType = + /// Intermediate object files. + | MH_OBJECT = 0x1 + /// Standard executable programs. + | MH_EXECUTE = 0x2 + /// Fixed VM shared library file. + | MH_FVMLIB = 0x3 + /// Core file. + | MH_CORE = 0x4 + /// Preloaded executable file. + | MH_PRELOAD = 0x5 + /// Dynamically bound shared library file. + | MH_DYLIB = 0x6 + /// Dynamically bound shared library file. + | MH_DYLINKER = 0x7 + /// Dynamically bound bundle file. + | MH_BUNDLE = 0x8 + /// Shared library stub for static linking only, no section contents. + | MH_DYLIB_STUB = 0x9 + /// Companion file with only debug sections. + | MH_DSYM = 0xa + /// x86_64 kexts. + | MH_KEXT_BUNDLE = 0xb + +/// Attribute of the file. +[] +type MachFlag = + /// The object file has no undefined references. + | MH_NOUNDEFS = 0x1 + /// The object file is the output of an incremental link against a base file + /// and can't be linked against a base file and can't be link edited again. + | MH_INCRLINK = 0x2 + /// The object file is input for the dynamic linker and can't be statically + /// link edited again. + | MH_DYLDLINK = 0x4 + /// The object file's undefined references are bound by the dynamic linker + /// when loaded. + | MH_BINDATLOAD = 0x8 + /// The file has its dynamic undefined references prebound. + | MH_PREBOUND = 0x10 + /// The file has its read-only and read-write segments split. + | MH_SPLIT_SEGS = 0x20 + /// the shared library init routine is to be run lazily via catching memory + /// faults to its writeable segments (obsolete). + | MH_LAZY_INIT = 0x40 + /// The image is using two-level name space bindings. + | MH_TWOLEVEL = 0x80 + /// The executable is forcing all images to use flat name space bindings. + | MH_FORCE_FLAT = 0x100 + /// This umbrella guarantees no multiple defintions of symbols in its + /// sub-images so the two-level namespace hints can always be used. + | MH_NOMULTIDEFS = 0x200 + /// Do not have dyld notify the prebinding agent about this executable. + | MH_NOFIXPREBINDING = 0x400 + /// the binary is not prebound but can have its prebinding redone. only used + /// when MH_PREBOUND is not set. + | MH_PREBINDABLE = 0x800 + /// Indicates that this binary binds to all two-level namespace modules of + /// its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL + /// are both set. + | MH_ALLMODSBOUND = 0x1000 + /// Safe to divide up the sections into sub-sections via symbols for dead code + /// stripping. + | MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000 + /// The binary has been canonicalized via the unprebind operation. + | MH_CANONICAL = 0x4000 + /// The final linked image contains external weak symbols. + | MH_WEAK_DEFINES = 0x8000 + /// The final linked image uses weak symbols. + | MH_BINDS_TO_WEAK = 0x10000 + /// When this bit is set, all stacks in the task will be given stack execution + /// privilege. Only used in MH_EXECUTE filetypes. + | MH_ALLOW_STACK_EXECUTION = 0x20000 + /// When this bit is set, the binary declares it is safe for use in processes + /// with uid zero. + | MH_ROOT_SAFE = 0x40000 + /// When this bit is set, the binary declares it is safe for use in processes + /// when issetugid() is true. + | MH_SETUID_SAFE = 0x80000 + /// When this bit is set on a dylib, the static linker does not need to + /// examine dependent dylibs to see if any are re-exported. + | MH_NO_REEXPORTED_DYLIBS = 0x100000 + /// When this bit is set, the OS will load the main executable at a random + /// address. + | MH_PIE = 0x200000 + /// Only for use on dylibs. When linking against a dylib that has this bit + /// set, the static linker will automatically not create a LC_LOAD_DYLIB load + /// command to the dylib if no symbols are being referenced from the dylib. + | MH_DEAD_STRIPPABLE_DYLIB = 0x400000 + /// Contains a section of type ThreadLocalVariables. + | MH_HAS_TLV_DESCRIPTORS = 0x800000 + /// When this bit is set, the OS will run the main executable with a + /// non-executable heap even on platforms (e.g. i386) that don't require it. + /// Only used in MH_EXECUTE filetypes. + | MH_NO_HEAP_EXECUTION = 0x1000000 + /// The code was linked for use in an application extension. + | MH_APP_EXTENSION_SAFE = 0x02000000 + +/// Mach-O file format header. +type MachHeader = { + /// Magic number. + Magic: Magic + /// Word size. + Class: WordSize + /// CPU type. + CPUType: CPUType + /// CPU subtype. + CPUSubType: CPUSubType + /// File type. + FileType: MachFileType + /// The number of load commands. + NumCmds: uint32 + /// The number of bytes occupied by the load commands following the header + /// structure. + SizeOfCmds: uint32 + /// A set of bit flags indicating the state of certain optional features of + /// the Mach-O file format. + Flags: MachFlag +} + +/// This is a basic toolbox for parsing Mach-O binaries, which is returned from +/// parsing a Mach-O header. +type MachToolbox = { + Bytes: byte[] + Reader: IBinReader + BaseAddress: Addr + Header: MachHeader + /// Offset from the start of the file to the Mach-O file format header. This + /// is only meaningful for universal binaries. + MachOffset: uint64 +} + +module Header = + let isMach (bytes: byte[]) offset = + let span = ReadOnlySpan (bytes, int offset, 4) + let reader = BinReader.Init Endian.Little + match Magic.read span reader with + | Magic.MH_CIGAM | Magic.MH_CIGAM_64 + | Magic.MH_MAGIC | Magic.MH_MAGIC_64 + | Magic.FAT_CIGAM | Magic.FAT_MAGIC -> true + | _ -> false + + let isFat (bytes: byte[]) = + let reader = BinReader.Init Endian.Little + match Magic.read (ReadOnlySpan bytes) reader with + | Magic.FAT_CIGAM | Magic.FAT_MAGIC -> true + | _ -> false + + let inline private readCPUType (span: ByteSpan) (reader: IBinReader) = + reader.ReadInt32 (span, 4) |> LanguagePrimitives.EnumOfValue + + let inline private readCPUSubType (span: ByteSpan) (reader: IBinReader) = + reader.ReadInt32 (span, 8) |> LanguagePrimitives.EnumOfValue + + let inline private readFileType (span: ByteSpan) (reader: IBinReader) = + reader.ReadInt32 (span, 12) |> LanguagePrimitives.EnumOfValue + + let inline private readFlags (span: ByteSpan) (reader: IBinReader) = + reader.ReadInt32 (span, 24) |> LanguagePrimitives.EnumOfValue + + let private readClass span reader = + match Magic.read span reader with + | Magic.MH_MAGIC | Magic.MH_CIGAM -> WordSize.Bit32 + | Magic.MH_MAGIC_64 | Magic.MH_CIGAM_64 -> WordSize.Bit64 + | _ -> raise InvalidFileFormatException + + let magicToEndian = function + | Magic.MH_MAGIC | Magic.MH_MAGIC_64 | Magic.FAT_MAGIC -> Endian.Little + | Magic.MH_CIGAM | Magic.MH_CIGAM_64 | Magic.FAT_CIGAM -> Endian.Big + | _ -> raise InvalidFileFormatException + + let readEndianness span reader = + Magic.read span reader + |> magicToEndian + + /// Detect the endianness and return an appropriate IBinReader. + let private getMachBinReader span = + let reader = BinReader.Init Endian.Little + let endian = readEndianness span reader + BinReader.Init endian + + let private parseHeader bytes offset = + let headerSpan = ReadOnlySpan (bytes, int offset, 28) + let reader = getMachBinReader headerSpan + { Magic = Magic.read headerSpan reader + Class = readClass headerSpan reader + CPUType = readCPUType headerSpan reader + CPUSubType = readCPUSubType headerSpan reader + FileType = readFileType headerSpan reader + NumCmds = reader.ReadUInt32 (headerSpan, 16) + SizeOfCmds = reader.ReadUInt32 (headerSpan, 20) + Flags = readFlags headerSpan reader } + + let private computeMachOffset bytes isa = + if isFat bytes then + let fatArch = Fat.loadArch bytes isa + uint64 fatArch.Offset + else 0UL + + let private computeBaseAddr machHdr baseAddr = + if machHdr.Flags.HasFlag MachFlag.MH_PIE then defaultArg baseAddr 0UL + else 0UL + + /// Parse the Mach-O file format header, and return a MachToolbox. + let parse bytes baseAddrOpt isa = + let offset = computeMachOffset bytes isa + if isMach bytes offset then + let hdr = parseHeader bytes offset + let baseAddr = computeBaseAddr hdr baseAddrOpt + { Bytes = bytes + Reader = BinReader.Init (magicToEndian hdr.Magic) + BaseAddress = baseAddr + Header = hdr + MachOffset = offset } + else raise InvalidFileFormatException diff --git a/src/FrontEnd/BinFile/Mach/MachHelper.fs b/src/FrontEnd/BinFile/Mach/MachHelper.fs new file mode 100644 index 00000000..f62102cf --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachHelper.fs @@ -0,0 +1,209 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinFile.Mach.Helper + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +/// Mach-specific virtual memory permission (for maxprot and initprot). Note +/// that these values are different than the B2R2.Permission type. +[] +type MachVMProt = + /// File is readable. + | Readable = 1 + /// File is writable. + | Writable = 2 + /// File is executable. + | Executable = 4 + +let getISA hdr = + let cputype = hdr.CPUType + let cpusubtype = hdr.CPUSubType + let arch = CPUType.toArch cputype cpusubtype + let endian = Header.magicToEndian hdr.Magic + ISA.Init arch endian + +let convFileType = function + | MachFileType.MH_EXECUTE -> FileType.ExecutableFile + | MachFileType.MH_OBJECT -> FileType.ObjFile + | MachFileType.MH_DYLIB + | MachFileType.MH_FVMLIB -> FileType.LibFile + | MachFileType.MH_CORE -> FileType.CoreFile + | _ -> FileType.UnknownFile + +let isMainCmd = function + | Main _ -> true + | _ -> false + +let getMainOffset cmds = + match cmds |> Array.tryFind isMainCmd with + | Some (Main m) -> m.EntryOff + | _ -> 0UL + +let getTextSegOffset segs = + let isTextSegment s = s.SegCmdName = LoadCommand.TextSegName + match segs |> Array.tryFind isTextSegment with + | Some s -> s.VMAddr + | _ -> raise InvalidFileFormatException + +let computeEntryPoint segs cmds = + let mainOffset = getMainOffset cmds + if mainOffset = 0UL then None + else Some (mainOffset + getTextSegOffset segs) + +let machTypeToSymbKind sym secText = + if (sym.SymType = SymbolType.N_FUN && sym.SymName.Length > 0) + || (sym.SymType.HasFlag SymbolType.N_SECT + && sym.SecNum = (secText + 1) + && sym.SymDesc = 0s) then + SymFunctionType + elif sym.SymType = SymbolType.N_SO + || sym.SymType = SymbolType.N_OSO then + SymFileType + else + SymNoType + +let machSymbolToSymbol secText vis sym = + { Address = sym.SymAddr + Name = sym.SymName + Kind = machTypeToSymbKind sym secText + Visibility = vis + LibraryName = Symbol.getSymbolLibName sym + ArchOperationMode = ArchOperationMode.NoMode } + +let getStaticSymbols secs symInfo = + let secText = Section.getTextSectionIndex secs + symInfo.Symbols + |> Array.filter Symbol.isStatic + |> Array.map (machSymbolToSymbol secText SymbolVisibility.StaticSymbol) + +let isStripped secs symInfo = + getStaticSymbols secs symInfo + |> Array.exists (fun s -> s.Kind = SymFunctionType) + |> not + +let isNXEnabled hdr = + not (hdr.Flags.HasFlag MachFlag.MH_ALLOW_STACK_EXECUTION) + || hdr.Flags.HasFlag MachFlag.MH_NO_HEAP_EXECUTION + +let translateAddr segMap addr = + match ARMap.tryFindByAddr addr segMap with + | Some s -> Convert.ToInt32 (addr - s.VMAddr + s.FileOff) + | None -> raise InvalidAddrReadException + +let private computeInvalidRanges toolBox segCmds getNextStartAddr = + segCmds + |> Array.filter (fun seg -> seg.SegCmdName <> "__PAGEZERO") + |> Array.sortBy (fun seg -> seg.VMAddr) + |> Array.fold (fun (set, saddr) seg -> + let n = getNextStartAddr seg + addInvalidRange set saddr seg.VMAddr, n) (IntervalSet.empty, 0UL) + |> addLastInvalidRange toolBox.Header.Class + +let invalidRangesByVM toolBox segCmds = + computeInvalidRanges toolBox segCmds (fun seg -> seg.VMAddr + seg.VMSize) + +let invalidRangesByFileBounds toolBox segCmds = + computeInvalidRanges toolBox segCmds (fun seg -> seg.VMAddr + seg.FileSize) + +let executableRanges segCmds = + segCmds + |> Array.filter (fun seg -> + let perm: Permission = seg.MaxProt |> LanguagePrimitives.EnumOfValue + perm &&& Permission.Executable = Permission.Executable) + |> Array.fold (fun set s -> + IntervalSet.add (AddrRange (s.VMAddr, s.VMAddr + s.VMSize - 1UL)) set + ) IntervalSet.empty + +let secFlagToSectionKind isExecutable = function + | SectionType.S_NON_LAZY_SYMBOL_POINTERS + | SectionType.S_LAZY_SYMBOL_POINTERS + | SectionType.S_SYMBOL_STUBS -> SectionKind.LinkageTableSection + | _ -> + if isExecutable then SectionKind.ExecutableSection + else SectionKind.ExtraSection + +let machSectionToSection segMap (sec: MachSection) = + let seg = ARMap.findByAddr sec.SecAddr segMap + let perm: MachVMProt = seg.InitProt |> LanguagePrimitives.EnumOfValue + let isExecutable = perm.HasFlag MachVMProt.Executable + { Address = sec.SecAddr + FileOffset = sec.SecOffset + Kind = secFlagToSectionKind isExecutable sec.SecType + Size = uint32 sec.SecSize + Name = sec.SecName } + +let getSectionsByAddr secs segMap addr = + secs + |> Array.tryFind (fun s -> addr >= s.SecAddr && addr < s.SecAddr + s.SecSize) + |> function + | Some s -> [| machSectionToSection segMap s |] + | None -> [||] + +let getSectionsByName secs segMap name = + match secs |> Array.tryFind (fun s -> s.SecName = name) with + | Some s -> [| machSectionToSection segMap s |] + | None -> [||] + +let getSections secs segMap = + secs + |> Array.map (machSectionToSection segMap) + +let getTextSection (secs: MachSection[]) segMap = + let secText = Section.getTextSectionIndex secs + secs[secText] + |> machSectionToSection segMap + +let getPLT symInfo = + symInfo.LinkageTable + |> List.sortBy (fun entry -> entry.TrampolineAddress) + |> List.toArray + +let isPLT symInfo addr = + symInfo.LinkageTable + |> List.exists (fun entry -> entry.TrampolineAddress = addr) + +let tryFindFuncSymb symInfo addr = + match Map.tryFind addr symInfo.SymbolMap with + | Some s -> Ok s.SymName + | None -> Error ErrorCase.SymbolNotFound + +let getDynamicSymbols excludeImported secs symInfo = + let secText = Section.getTextSectionIndex secs + let excludeImported = defaultArg excludeImported false + let filter = Array.filter (fun (s: MachSymbol) -> s.SymAddr > 0UL) + symInfo.Symbols + |> Array.filter Symbol.isDynamic + |> fun arr -> if excludeImported then filter arr else arr + |> Array.map (machSymbolToSymbol secText SymbolVisibility.DynamicSymbol) + +let getSymbols secs symInfo = + let s = getStaticSymbols secs symInfo + let d = getDynamicSymbols None secs symInfo + Array.append s d + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinFile/Mach/MachLoadCommands.fs b/src/FrontEnd/BinFile/Mach/MachLoadCommands.fs new file mode 100644 index 00000000..092c2e7b --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachLoadCommands.fs @@ -0,0 +1,446 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.FileHelper + +/// Load command type. +type LoadCmdType = + /// Defines a segment of this file to be mapped into the address space of the + /// process that loads this file. It also includes all the sections contained + /// by the segment. + | LC_SEGMENT = 0x01 + /// The symbol table for this file. + | LC_SYMTAB = 0x02 + /// The gdb symbol table info (obsolete). + | LC_SYMSEG = 0x03 + /// This command defines the initial thread state of the main thread of the + /// process. LC_THREAD is similar to LC_UNIXTHREAD but does not cause the + /// kernel to allocate a stack. + | LC_THREAD = 0x04 + /// This command defines the initial thread state of the main thread of the + /// process. + | LC_UNIXTHREAD = 0x05 + /// Load a specified fixed VM shared library. + | LC_LOADFVMLIB = 0x06 + /// Fixed VM shared library identification. + | LC_IDFVMLIB = 0x07 + /// Object identification info (obsolete). + | LC_IDENT = 0x08 + /// Fixed VM file inclusion (internal use). + | LC_FVMFILE = 0x09 + /// Prepage command (internal use). + | LC_PREPAGE = 0x0A + /// Dynamic link-edit symbol table info. + | LC_DYSYMTAB = 0x0B + /// Load a dynamically linked shared library. + | LC_LOAD_DYLIB = 0x0C + /// This command Specifies the install name of a dynamic shared library. + | LC_ID_DYLIB = 0x0D + /// Load a dynamic linker. + | LC_LOAD_DYLINKER = 0x0E + /// Dynamic linker identification. + | LC_ID_DYLINKER = 0x0F + /// Modules prebound for a dynamically linked shared library. + | LC_PREBOUND_DYLIB = 0x10 + /// Image routines. + | LC_ROUTINES = 0x11 + /// Sub framework. + | LC_SUB_FRAMEWORK = 0x12 + /// Sub umbrella. + | LC_SUB_UMBRELLA = 0x13 + /// Sub client. + | LC_SUB_CLIENT = 0x14 + /// Sub library. + | LC_SUB_LIBRARY = 0x15 + /// Two-level namespace lookup hints + | LC_TWOLEVEL_HINTS = 0x16 + /// Prebind checksum. + | LC_PREBIND_CKSUM = 0x17 + /// Load a dynamically linked shared library that is allowed to be missing. + | LC_LOAD_WEAK_DYLIB = 0x80000018 + /// 64-bit segment of this file to be mapped. + | LC_SEGMENT64 = 0x19 + /// 64-bit image routines. + | LC_ROUTINES64 = 0x1A + /// The uuid. + | LC_UUID = 0x1B + /// Runpath additions. + | LC_RPATH = 0x8000001C + /// Local of code signature. + | LC_CODE_SIGNATURE = 0x1D + /// Local of info to split segments + | LC_SEGMENT_SPLIT_INFO = 0x1E + /// Load and re-export dylib. + | LC_REEXPORT_DYLIB = 0x8000001F + /// Delay load of dylib until first use. + | LC_LAZY_LOAD_DYLIB = 0x20 + /// Encrypted segment information. + | LC_ENCRYPTION_INFO = 0x21 + /// Compressed dyld information. + | LC_DYLD_INFO = 0x22 + /// Compressed dyld information only. + | LC_DYLD_INFO_ONLY = 0x80000022 + /// Load upward dylib. + | LC_LOAD_UPWARD_DYLIB = 0x80000023 + /// Build for MacOSX min OS version. + | LC_VERSION_MIN_MACOSX = 0x24 + /// Build for iPhoneOS min OS version. + | LC_VERSION_MIN_IPHONEOS = 0x25 + /// Compressed table of function start addresses. + | LC_FUNCTION_STARTS = 0x26 + /// String for dyld to treat like environment variable. + | LC_DYLD_ENVIRONMENT = 0x27 + /// Replacement for LC_UNIXTHREAD. + | LC_MAIN = 0x80000028 + /// Table of non-instructions in __text. + | LC_DATA_IN_CODE = 0x29 + /// Source version used to build binary. + | LC_SOURCE_VERSION = 0x2A + /// Code signing DRs copied from linked dylibs. + | LC_DYLIB_CODE_SIGN_DRS = 0x2B + /// 64-bit encrypted segment information. + | LC_ENCRYPTION_INFO_64 = 0x2C + /// Linker options in MH_OBJECT files. + | LC_LINKER_OPTION = 0x2D + /// Optimization hints in MH_OBJECT files. + | LC_LINKER_OPTIMIZATION_HINT = 0x2E + /// Build for AppleTV min OS version. + | LC_VERSION_MIN_TVOS = 0x2F + /// Build for Watch min OS version + | LC_VERSION_MIN_WATCHOS = 0x30 + +/// The load command structures are located directly after the header of the +/// object file, and they specify both the logical structure of the file and the +/// layout of the file in virtual memory. +type LoadCommand = + | Segment of SegCmd + | SymTab of SymTabCmd + | DySymTab of DySymTabCmd + | DyLib of DyLibCmd + | DyLdInfo of DyLdInfoCmd + | FuncStarts of FuncStartsCmd + | Main of MainCmd + | Unhandled of UnhandledCommand + +/// Segment command. +and SegCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + /// The offset of the sections in the segment. If the segment has sections + /// then the section structures directly follow the segment command and their + /// size is in the size of the command. + SecOff: int + /// Segment name. + SegCmdName: string + /// The starting virtual memory address of this segment + VMAddr: Addr + /// The number of bytes of virtual memory occupied by this segment. + VMSize: uint64 + /// The offset in this file of the data to be mapped at VMAddr. + FileOff: Addr + /// The number of bytes occupied by this segment on disk + FileSize: uint64 + /// The maximum permitted virtual memory protections of this segment + MaxProt: int + /// The initial virtual memory protections of this segment. + InitProt: int + /// The number of section data structures following this load command. + NumSecs: uint32 + /// A set of flags that affect the loading of this segment. + SegFlag: uint32 +} + +/// Symbol table command. +and SymTabCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + /// An integer containing the byte offset from the start of the file to the + /// location of the symbol table entries. + SymOff: int + /// An integer indicating the number of entries in the symbol table. + NumOfSym: uint32 + /// An integer containing the byte offset from the start of the image to the + /// location of the string table. + StrOff: int + /// An integer indicating the size (in bytes) of the string table. + StrSize: uint32 +} + +/// Dynamic symbol table command. +and DySymTabCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + /// An integer indicating the index of the first symbol in the group of local + /// symbols. + IdxLocalSym: uint32 + /// An integer indicating the total number of symbols in the group of local + /// symbols. + NumLocalSym: uint32 + /// An integer indicating the index of the first symbol in the group of + /// defined external symbols. + IdxExtSym: uint32 + /// An integer indicating the total number of symbols in the group of defined + /// external symbols. + NumExtSym: uint32 + /// An integer indicating the index of the first symbol in the group of + /// undefined external symbols. + IdxUndefSym: uint32 + /// An integer indicating the total number of symbols in the group of + /// undefined external symbols. + NumUndefSym: uint32 + /// An integer indicating the byte offset from the start of the file to the + /// table of contents data. + TOCOffset: uint32 + /// An integer indicating the number of entries in the table of contents. + NumTOCContents: uint32 + /// An integer indicating the byte offset from the start of the file to the + /// module table data. + ModTabOff: uint32 + /// An integer indicating the number of entries in the module table. + NumModTab: uint32 + /// An integer indicating the byte offset from the start of the file to the + /// external reference table data. + ExtRefSymOff: uint32 + /// An integer indicating the number of entries in the external reference + /// table. + NumExtRefSym: uint32 + /// An integer indicating the byte offset from the start of the file to the + /// indirect symbol table data. + IndirectSymOff: uint32 + /// An integer indicating the number of entries in the indirect symbol table. + NumIndirectSym: uint32 + /// An integer indicating the byte offset from the start of the file to the + /// external relocation table data. + ExtRelOff: uint32 + /// An integer indicating the number of entries in the external relocation + /// table. + NumExtRel: uint32 + /// An integer indicating the byte offset from the start of the file to the + /// local relocation table data. + LocalRelOff: uint32 + /// An integer indicating the number of entries in the local relocation table. + NumLocalRel: uint32 +} + +/// DYLD information command (dyld_info_command). +and DyLdInfoCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + /// File offset to rebase info. + RebaseOff: int + /// The size of rebase info. + RebaseSize: uint32 + /// File offset to binding info + BindOff: int + /// The size of binding info. + BindSize: uint32 + /// File offset to weak binding info. + WeakBindOff: int + /// The size of weak binding info. + WeakBindSize: uint32 + /// File offset to lazy binding info. + LazyBindOff: int + /// The size of lazy binding info. + LazyBindSize: uint32 + /// File offset to export info. + ExportOff: int + /// The size of export info. + ExportSize: uint32 +} + +/// Function starts command (LC_FUNCTION_STARTS). +and FuncStartsCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + DataOffset: int + DataSize: uint32 +} + +/// Main command. +and MainCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + /// Offset of main(). + EntryOff: Addr + /// Initial stack size, if not zero. + StackSize: uint64 +} + +/// Dynamic library command: the data used by the dynamic linker to match a +/// shared library against the files that have linked to it. +and DyLibCmd = { + Cmd: LoadCmdType + CmdSize: uint32 + /// Library's path name. + DyLibName: string + /// Library's build time stamp. + DyLibTimeStamp: uint32 + /// Library's current version number. + DyLibCurVer: uint32 + /// Library's compatibility vers number. + DyLibCmpVer: uint32 +} + +/// This type represents a load command unhandled by B2R2. +and UnhandledCommand = { + Cmd: LoadCmdType + CmdSize: uint32 +} + +module internal LoadCommand = + let [] TextSegName = "__TEXT" + + let parseSegCmd toolBox cmdOffset cmdType cmdSize span = + let reader = toolBox.Reader + let cls = toolBox.Header.Class + { Cmd = cmdType + CmdSize = uint32 cmdSize + SecOff = cmdOffset + pickNum cls 56 72 + SegCmdName = readCString span 8 + VMAddr = readNative span reader cls 24 24 + toolBox.BaseAddress + VMSize = readNative span reader cls 28 32 + FileOff = readNative span reader cls 32 40 + FileSize = readNative span reader cls 36 48 + MaxProt = reader.ReadInt32 (span, pickNum cls 40 56) + InitProt = reader.ReadInt32 (span, pickNum cls 44 60) + NumSecs = reader.ReadUInt32 (span, pickNum cls 48 64) + SegFlag = reader.ReadUInt32 (span, pickNum cls 52 68) } + + let parseSymCmd toolBox cmdType cmdSize (span: ByteSpan) = + let reader = toolBox.Reader + { Cmd = cmdType + CmdSize = uint32 cmdSize + SymOff = reader.ReadInt32 (span, 8) + NumOfSym = reader.ReadUInt32 (span, 12) + StrOff = reader.ReadInt32 (span, 16) + StrSize = reader.ReadUInt32 (span, 20) } + + let parseDySymCmd toolBox cmdType cmdSize (span: ByteSpan) = + let reader = toolBox.Reader + { Cmd = cmdType + CmdSize = uint32 cmdSize + IdxLocalSym = reader.ReadUInt32 (span, 8) + NumLocalSym = reader.ReadUInt32 (span, 12) + IdxExtSym = reader.ReadUInt32 (span, 16) + NumExtSym = reader.ReadUInt32 (span, 20) + IdxUndefSym = reader.ReadUInt32 (span, 24) + NumUndefSym = reader.ReadUInt32 (span, 28) + TOCOffset = reader.ReadUInt32 (span, 32) + NumTOCContents = reader.ReadUInt32 (span, 36) + ModTabOff = reader.ReadUInt32 (span, 40) + NumModTab = reader.ReadUInt32 (span, 44) + ExtRefSymOff = reader.ReadUInt32 (span, 48) + NumExtRefSym = reader.ReadUInt32 (span, 52) + IndirectSymOff = reader.ReadUInt32 (span, 56) + NumIndirectSym = reader.ReadUInt32 (span, 60) + ExtRelOff = reader.ReadUInt32 (span, 64) + NumExtRel = reader.ReadUInt32 (span, 68) + LocalRelOff = reader.ReadUInt32 (span, 72) + NumLocalRel = reader.ReadUInt32 (span, 76) } + + let parseMainCmd toolBox cmdType cmdSize (span: ByteSpan) = + let reader = toolBox.Reader + { Cmd = cmdType + CmdSize = uint32 cmdSize + EntryOff = reader.ReadUInt64 (span, 8) + toolBox.BaseAddress + StackSize = reader.ReadUInt64 (span, 16) } + + /// Read lc_str string. + let readLCStr toolBox cmdSize (span: ByteSpan) = + let strOffset = toolBox.Reader.ReadInt32 (span, 8) + let strLen = cmdSize - strOffset + ByteArray.extractCStringFromSpan (span.Slice (strOffset, strLen)) 0 + + let parseDyLibCmd toolBox cmdType cmdSize (span: ByteSpan) = + let reader = toolBox.Reader + { Cmd = cmdType + CmdSize = uint32 cmdSize + DyLibName = readLCStr toolBox cmdSize span + DyLibTimeStamp = reader.ReadUInt32 (span, 12) + DyLibCurVer = reader.ReadUInt32 (span, 16) + DyLibCmpVer = reader.ReadUInt32 (span, 20) } + + let parseDyLdInfo toolBox cmdType cmdSize (span: ByteSpan) = + let reader = toolBox.Reader + { Cmd = cmdType + CmdSize = uint32 cmdSize + RebaseOff = reader.ReadInt32 (span, 8) + RebaseSize = reader.ReadUInt32 (span, 12) + BindOff = reader.ReadInt32 (span, 16) + BindSize = reader.ReadUInt32 (span, 20) + WeakBindOff = reader.ReadInt32 (span, 24) + WeakBindSize = reader.ReadUInt32 (span, 28) + LazyBindOff = reader.ReadInt32 (span, 32) + LazyBindSize = reader.ReadUInt32 (span, 36) + ExportOff = reader.ReadInt32 (span, 40) + ExportSize = reader.ReadUInt32 (span, 44) } + + let parseFuncStarts toolBox cmdType cmdSize (span: ByteSpan) = + let reader = toolBox.Reader + { Cmd = cmdType + CmdSize = uint32 cmdSize + DataOffset = reader.ReadInt32 (span, 8) + DataSize = reader.ReadUInt32 (span, 12) } + + let parseCmd ({ Bytes = bytes; Reader = reader } as toolBox) offset = + let cmdHdr = ReadOnlySpan (bytes, int offset, 8) + let cmdType = reader.ReadInt32 (cmdHdr, 0) |> LanguagePrimitives.EnumOfValue + let cmdSize = reader.ReadInt32 (cmdHdr, 4) + let cmdOffset = int (offset - toolBox.MachOffset) + let span = ReadOnlySpan (bytes, int offset, cmdSize) + let command = + match cmdType with + | LoadCmdType.LC_SEGMENT + | LoadCmdType.LC_SEGMENT64 -> + Segment (parseSegCmd toolBox cmdOffset cmdType cmdSize span) + | LoadCmdType.LC_SYMTAB -> + SymTab (parseSymCmd toolBox cmdType cmdSize span) + | LoadCmdType.LC_DYSYMTAB -> + DySymTab (parseDySymCmd toolBox cmdType cmdSize span) + | LoadCmdType.LC_MAIN -> + Main (parseMainCmd toolBox cmdType cmdSize span) + | LoadCmdType.LC_LOAD_DYLIB -> + DyLib (parseDyLibCmd toolBox cmdType cmdSize span) + | LoadCmdType.LC_DYLD_INFO + | LoadCmdType.LC_DYLD_INFO_ONLY -> + DyLdInfo (parseDyLdInfo toolBox cmdType cmdSize span) + | LoadCmdType.LC_FUNCTION_STARTS -> + FuncStarts (parseFuncStarts toolBox cmdType cmdSize span) + | _ -> + Unhandled { Cmd = cmdType; CmdSize = uint32 cmdSize } + struct (command, uint64 cmdSize) + + let parse ({ Header = hdr } as toolBox) = + let mutable cmdOffset = pickNum hdr.Class 28UL 32UL + toolBox.MachOffset + let numCmds = Convert.ToInt32 hdr.NumCmds + let cmds = Array.zeroCreate numCmds + for i = 0 to numCmds - 1 do + let struct (cmd, cmdSize) = parseCmd toolBox cmdOffset + cmds[i] <- cmd + cmdOffset <- cmdOffset + cmdSize + cmds diff --git a/src/FrontEnd/BinFile/Mach/MachMagic.fs b/src/FrontEnd/BinFile/Mach/MachMagic.fs new file mode 100644 index 00000000..7182d178 --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachMagic.fs @@ -0,0 +1,53 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open B2R2 + +/// Magic number for Mach-O header. +type Magic = + /// The file is intended for use on a CPU with the same endianness as the + /// computer on which the compiler is running (32-bit CPU). + | MH_MAGIC = 0xFEEDFACEu + /// The byte ordering scheme of the target machine is the reverse of the host + /// CPU (32-bit CPU). + | MH_CIGAM = 0xCEFAEDFEu + /// The file is intended for use on a CPU with the same endianness as the + /// computer on which the compiler is running (64-bit CPU). + | MH_MAGIC_64 = 0xFEEDFACFu + /// The byte ordering scheme of the target machine is the reverse of the host + /// CPU (64-bit CPU). + | MH_CIGAM_64 = 0xCFFAEDFEu + /// The file is intended for use on multiple architectures (FAT binary). This + /// value is used on a big-endian host. + | FAT_MAGIC = 0xCAFEBABEu + /// The file is intended for use on multiple architectures (FAT binary). This + /// value is used on a little-endian host. + | FAT_CIGAM = 0xBEBAFECAu + +module internal Magic = + let read (span: ByteSpan) (reader: IBinReader) = + if span.Length >= 4 then reader.ReadUInt32 (span, 0) else 0ul + |> LanguagePrimitives.EnumOfValue: Magic diff --git a/src/FrontEnd/BinFile/Mach/MachReloc.fs b/src/FrontEnd/BinFile/Mach/MachReloc.fs new file mode 100644 index 00000000..4ae0c318 --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachReloc.fs @@ -0,0 +1,106 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open System +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +type RelocSymbol = + | SymIndex of int (* Symbol table index *) + | SecOrdinal of int (* Section number *) + +/// Reloc info. +type RelocationInfo = { + /// Offset in the section to what is being relocated. + RelocAddr: int + /// RelocSymbol + RelocSymbol: RelocSymbol + /// Relocation length. + RelocLength: RegType + /// Parent section + RelocSection: MachSection + /// Is this address part of an instruction that uses PC-relative addressing? + IsPCRel: bool +} + +module internal Reloc = + let private parseRelocSymbol data = + let n = data &&& 0xFFFFFF + if (data >>> 27) &&& 1 = 1 then SymIndex (n) + else SecOrdinal (n) + + let private parseRelocLength data = + match (data >>> 25) &&& 3 with + | 0 -> 8 + | 1 -> 16 + | _ -> 32 + + let private countRelocs secs = + secs |> Array.fold (fun cnt sec -> cnt + sec.SecNumOfReloc) 0 + + let private parseReloc (span: ByteSpan) (reader: IBinReader) sec = + let addr = reader.ReadInt32 (span, 0) + let data = reader.ReadInt32 (span, 4) + let sym = parseRelocSymbol data + let len = parseRelocLength data + let rel = (data >>> 24) &&& 1 = 1 + { RelocAddr = addr + RelocSymbol = sym + RelocLength = len + RelocSection = sec + IsPCRel = rel } + + let private translateRelocAddr reloc = + reloc.RelocSection.SecAddr + uint64 reloc.RelocAddr + + let private translateRelocSymbol (symbols: _[]) (secs: MachSection[]) reloc = + match reloc.RelocSymbol with + | SymIndex (n) -> symbols[n].SymName + | SecOrdinal (n) -> secs[n - 1].SecName + + let private toSymbol symbols secs reloc = + { Address = translateRelocAddr reloc + Name = translateRelocSymbol symbols secs reloc + Kind = SymNoType (* FIXME *) + Visibility = SymbolVisibility.DynamicSymbol + LibraryName = "" + ArchOperationMode = ArchOperationMode.NoMode } + + let parse { Bytes = bytes; Reader = reader } symInfo secs = + let numRelocs = countRelocs secs + let relocs = Array.zeroCreate numRelocs + let mutable i = 0 + for sec in secs do + let relOffset, relSize = int sec.SecRelOff, int sec.SecNumOfReloc * 8 + let relSpan = ReadOnlySpan (bytes, relOffset, relSize) + for n = 0 to sec.SecNumOfReloc - 1 do + let offset = n * 8 + relocs[i] <- parseReloc (relSpan.Slice offset) reader sec + i <- i + 1 + relocs + |> Seq.toArray + |> Array.map (toSymbol symInfo.Symbols secs) diff --git a/src/FrontEnd/BinFile/Mach/MachSection.fs b/src/FrontEnd/BinFile/Mach/MachSection.fs new file mode 100644 index 00000000..5b640c2b --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachSection.fs @@ -0,0 +1,171 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.FileHelper + +/// Section type. +type SectionType = + /// Regular section. + | S_REGULAR = 0x0 + /// Zero fill on demand section. + | S_ZEROFILL = 0x1 + /// Section with only literal C strings. + | S_CSTRING_LITERALS = 0x2 + /// Section with only 4 byte literals. + | S_4BYTE_LITERALS = 0x3 + /// Section with only 8 byte literals. + | S_8BYTE_LITERALS = 0x4 + /// section with only pointers to literals. + | S_LITERAL_POINTERS = 0x5 + /// Section with only non-lazy symbol pointers . + | S_NON_LAZY_SYMBOL_POINTERS = 0x6 + /// Section with only lazy symbol pointers. + | S_LAZY_SYMBOL_POINTERS = 0x7 + /// Section with only symbol stubs, byte size of stub in the reserved2 field. + | S_SYMBOL_STUBS = 0x8 + /// Section with only function pointers for initialization. + | S_MOD_INIT_FUNC_POINTERS = 0x9 + /// Section with only function pointers for termination. + | S_MOD_TERM_FUNC_POINTERS = 0xa + /// Section contains symbols that are to be coalesced. + | S_COALESCED = 0xb + /// Zero fill on demand section (this can be larger than 4 gigabytes). + | S_GB_ZEROFILL = 0xc + /// Section with only pairs of function pointers for interposing. + | S_INTERPOSING = 0xd + /// Section with only 16 byte literals. + | S_16BYTE_LITERALS = 0xe + /// Section contains DTrace Object Format. + | S_DTRACE_DOF = 0xf + /// Section with only lazy symbol pointers to lazy loaded dylibs. + | S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10 + /// Template of initial values for TLVs. + | S_THREAD_LOCAL_REGULAR = 0x11 + /// Template of initial values for TLVs. + | S_THREAD_LOCAL_ZEROFILL = 0x12 + /// TLV descriptors. + | S_THREAD_LOCAL_VARIABLES = 0x13 + /// Pointers to TLV descriptors. + | S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14 + /// Functions to call to initialize TLV values . + | S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15 + +/// Section attribute. +[] +type SectionAttribute = + /// Section contains only true machine instructions. + | S_ATTR_PURE_INSTRUCTIONS = 0x80000000 + /// Section contains coalesced symbols that are not to be in a ranlib table of + /// contents. + | S_ATTR_NO_TOC = 0x40000000 + /// OK to strip static symbols in this section in files with the MH_DYLDLINK + /// flag. + | S_ATTR_STRIP_STATIC_SYMS = 0x20000000 + /// No dead stripping. + | S_ATTR_NO_DEAD_STRIP = 0x10000000 + /// Blocks are live if they reference live blocks. + | S_ATTR_LIVE_SUPPORT = 0x08000000 + /// Used with i386 code stubs written on by dyld. + | S_ATTR_SELF_MODIFYING_CODE = 0x04000000 + /// Debug section. + | S_ATTR_DEBUG = 0x02000000 + /// Section has external relocation entries. + | S_ATTR_EXT_RELOC = 0x00000200 + /// Section has local relocation entries. + | S_ATTR_LOC_RELOC = 0x00000100 + +/// Mach-O section. +type MachSection = { + /// Section name. + SecName: string + /// The name of the segment that should eventually contain this section. + SegName: string + /// The virtual memory address of this section. + SecAddr: Addr + /// The size of this section. + SecSize: uint64 + /// The offset to this section in the file. + SecOffset: uint32 + /// The section's byte alignment. + SecAlignment: uint32 + /// The file offset of the first relocation entry for this section. + SecRelOff: uint32 + /// The number of relocation entries located at SecRelOff for this section. + SecNumOfReloc: int + /// Section type. + SecType: SectionType + /// Section attributes. + SecAttrib: SectionAttribute + /// Reserved field 1. + SecReserved1: int + /// Reserved field 2. + SecReserved2: int +} + +module internal Section = + let [] SecText = "__text" + + let private parseSection toolBox (span: ByteSpan) offset = + let cls = toolBox.Header.Class + let reader = toolBox.Reader + let span = span.Slice offset + let secFlag = reader.ReadInt32 (span, pickNum cls 56 64) + { SecName = readCString span 0 + SegName = readCString span 16 + SecAddr = readUIntOfType span reader cls 32 + toolBox.BaseAddress + SecSize = readNative span reader cls 36 40 + SecOffset = reader.ReadUInt32 (span, pickNum cls 40 48) + SecAlignment = reader.ReadUInt32 (span, pickNum cls 44 52) + SecRelOff = reader.ReadUInt32 (span, pickNum cls 48 56) + SecNumOfReloc = reader.ReadInt32 (span, pickNum cls 52 60) + SecType = secFlag &&& 0xFF |> LanguagePrimitives.EnumOfValue + SecAttrib = secFlag &&& 0xFFFFFF00 |> LanguagePrimitives.EnumOfValue + SecReserved1 = reader.ReadInt32 (span, pickNum cls 60 68) + SecReserved2 = reader.ReadInt32 (span, pickNum cls 64 72) } + + let private countSections segCmds = + segCmds + |> Array.fold (fun cnt seg -> cnt + int seg.NumSecs) 0 + + let parse ({ Bytes = bytes; Header = hdr } as toolBox) segCmds = + let numSections = countSections segCmds + let sections = Array.zeroCreate numSections + let mutable idx = 0 + for seg in segCmds do + let entrySize = pickNum hdr.Class 68 80 + let sectionSize = entrySize * int seg.NumSecs + let sectionOffset = int toolBox.MachOffset + seg.SecOff + let sectionSpan = ReadOnlySpan (bytes, sectionOffset, sectionSize) + for i = 0 to int seg.NumSecs - 1 do + let offset = i * entrySize + sections[idx] <- parseSection toolBox sectionSpan offset + idx <- idx + 1 + sections + + let getTextSectionIndex secs = + secs |> Array.findIndex (fun s -> s.SecName = SecText) diff --git a/src/FrontEnd/BinFile/MachSegment.fs b/src/FrontEnd/BinFile/Mach/MachSegment.fs similarity index 76% rename from src/FrontEnd/BinFile/MachSegment.fs rename to src/FrontEnd/BinFile/Mach/MachSegment.fs index 9db5c23b..5e70b363 100644 --- a/src/FrontEnd/BinFile/MachSegment.fs +++ b/src/FrontEnd/BinFile/Mach/MachSegment.fs @@ -27,29 +27,28 @@ module internal B2R2.FrontEnd.BinFile.Mach.Segment open B2R2 open B2R2.FrontEnd.BinFile -let extract cmds = - let chooser = function - | Segment s -> Some s - | _ -> None - List.choose chooser cmds +let private chooser = function + | Segment s -> Some s + | _ -> None -let buildMap (segs: SegCmd list) = - segs - |> List.fold (fun map s -> - ARMap.addRange s.VMAddr (s.VMAddr + s.VMSize - 1UL) s map) ARMap.empty +let extract cmds = + Array.choose chooser cmds let segCmdToSegment seg = { Address = seg.VMAddr - Offset = seg.FileOff - Size = seg.VMSize - SizeInFile = seg.FileSize + Offset = uint32 seg.FileOff + Size = uint32 seg.VMSize + SizeInFile = uint32 seg.FileSize Permission = seg.MaxProt |> LanguagePrimitives.EnumOfValue } -let getSegments mach isLoadable = - mach.Segments - |> fun segs -> - if isLoadable then segs |> List.filter (fun s -> s.FileSize > 0UL) - else segs - |> List.map segCmdToSegment - |> List.toSeq +let toArray segCmds isLoadable = + if isLoadable then segCmds |> Array.filter (fun s -> s.FileSize > 0UL) + else segCmds + |> Array.map segCmdToSegment + +let buildMap segs = + segs + |> Array.fold (fun map s -> + ARMap.addRange s.VMAddr (s.VMAddr + s.VMSize - 1UL) s map + ) ARMap.empty diff --git a/src/FrontEnd/BinFile/Mach/MachSymbol.fs b/src/FrontEnd/BinFile/Mach/MachSymbol.fs new file mode 100644 index 00000000..a91164ff --- /dev/null +++ b/src/FrontEnd/BinFile/Mach/MachSymbol.fs @@ -0,0 +1,404 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile.Mach + +open System +open System.Collections.Generic +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper + +/// Symbol type (N_TYPE). +type SymbolType = + /// The symbol is undefined. + | N_UNDF = 0x0 + /// The symbol is absolute. The linker does not update the value of an + /// absolute symbol. + | N_ABS = 0x2 + /// The symbol is defined in the section number given in n_sect. + | N_SECT = 0xe + /// The symbol is undefined and the image is using a prebound value for the + /// symbol. + | N_PBUD = 0xc + /// The symbol is defined to be the same as another symbol. + | N_INDR = 0xa + /// Global symbol. + | N_GSYM = 0x20 + /// Procedure name (f77 kludge). + | N_FNAME = 0x22 + /// Procedure. + | N_FUN = 0x24 + /// Static symbol. + | N_STSYM = 0x26 + /// .lcomm symbol. + | N_LCSYM = 0x28 + /// Begin nsect sym. + | N_BNSYM = 0x2e + /// AST file path. + | N_AST = 0x32 + /// Emitted with gcc2_compiled and in gcc source. + | N_OPT = 0x3c + /// Register sym. + | N_RSYM = 0x40 + /// Source line. + | N_SLINE = 0x44 + /// End nsect sym. + | N_ENSYM = 0x4e + /// Structure element. + | N_SSYM = 0x60 + /// Source file name. + | N_SO = 0x64 + /// Object file name. + | N_OSO = 0x66 + /// Local symbol. + | N_LSYM = 0x80 + /// Include file beginning. + | N_BINCL = 0x82 + /// "#included" file name: name,,n_sect,0,address. + | N_SOL = 0x84 + /// Compiler parameters. + | N_PARAMS = 0x86 + /// Compiler version. + | N_VERSION= 0x88 + /// Compiler optimization level. + | N_OLEVEL = 0x8a + /// Parameter. + | N_PSYM = 0xa0 + /// Include file end. + | N_EINCL = 0xa2 + /// Alternate entry. + | N_ENTRY = 0xa4 + /// Left bracket. + | N_LBRAC = 0xc0 + /// Deleted include file. + | N_EXCL = 0xc2 + /// Right bracket. + | N_RBRAC = 0xe0 + /// Begin common. + | N_BCOMM = 0xe2 + /// End common. + | N_ECOMM = 0xe4 + /// End common (local name). + | N_ECOML = 0xe8 + /// Second stab entry with length information. + | N_LENG = 0xfe + /// Global pascal symbol. + | N_PC = 0x30 + +/// Mach-O symbol. +type MachSymbol = { + /// Symbol name. + SymName: string + /// Symbol type (N_TYPE field of n_type). + SymType: SymbolType + /// Is this an external symbol? + IsExternal: bool + /// The number of the section that this symbol can be found. + SecNum: int + /// Providing additional information about the nature of this symbol for + /// non-stab symbols. + SymDesc: int16 + /// External library version info. + VerInfo: DyLibCmd option + /// Address of the symbol. + SymAddr: Addr +} + +/// Export info. +type ExportInfo = { + /// Symbol name. + ExportSymName: string + /// Exported symbol address. + ExportAddr: Addr +} + +/// Symbol info +type SymInfo = { + /// All symbols. + Symbols: MachSymbol[] + /// Address to symbol mapping. + SymbolMap: Map + /// Linkage table. + LinkageTable: LinkageTableEntry list + /// Export info. + Exports: ExportInfo[] +} + +module internal Symbol = + let [] private IndirectSymbolLocal = 0x80000000 + + let [] private IndirectSymbolABS = 0x40000000 + + let private chooseDyLib = function + | DyLib c -> Some c + | _ -> None + + let private chooseSymTab = function + | SymTab c -> Some c + | _ -> None + + let private chooseDynSymTab = function + | DySymTab c -> Some c + | _ -> None + + let private chooseDyLdInfo = function + | DyLdInfo c -> Some c + | _ -> None + + let private chooseFuncStarts = function + | FuncStarts c -> Some c + | _ -> None + + let private parseFuncStarts toolBox cmds = + let bytes, reader = toolBox.Bytes, toolBox.Reader + let addrSet = HashSet () + for cmd in cmds do + let dataSpan = ReadOnlySpan (bytes, cmd.DataOffset, int cmd.DataSize) + let saddr, count = reader.ReadUInt64LEB128 (dataSpan, 0) + let saddr = saddr + toolBox.BaseAddress + addrSet.Add saddr |> ignore + let mutable offset = count + let mutable fnAddr = saddr + while offset < int cmd.DataSize do + let data, count = reader.ReadUInt64LEB128 (dataSpan, offset) + fnAddr <- fnAddr + data + addrSet.Add fnAddr |> ignore + offset <- offset + count + addrSet + + let private countSymbols symtabs = + symtabs |> Array.fold (fun cnt symtab -> int symtab.NumOfSym + cnt) 0 + + let private getLibraryVerInfo (flags: MachFlag) libs nDesc = + if flags.HasFlag (MachFlag.MH_TWOLEVEL) then + let ord = nDesc >>> 8 &&& 0xffs |> int + if ord = 0 || ord = 254 then None + else Some <| Array.get libs (ord - 1) + else None + + let private adjustSymVal toolBox addr = (* TODO: needs to consider n_type *) + if addr = 0UL then 0UL + else toolBox.BaseAddress + uint64 addr + + let private parseNList toolBox libs strTab symTab offset = + let reader = toolBox.Reader + let strIdx = reader.ReadInt32 (span=symTab, offset=offset) (* n_strx *) + let nDesc = reader.ReadInt16 (symTab, offset + 6) (* n_desc *) + let nType = symTab[offset + 4] |> int (* n_type *) + { SymName = ByteArray.extractCStringFromSpan strTab strIdx + SymType = nType |> LanguagePrimitives.EnumOfValue + IsExternal = nType &&& 0x1 = 0x1 + SecNum = symTab[offset + 5] |> int (* n_sect *) + SymDesc = nDesc + VerInfo = getLibraryVerInfo toolBox.Header.Flags libs nDesc + SymAddr = readUIntOfType symTab reader toolBox.Header.Class (offset + 8) + |> adjustSymVal toolBox } + + let private parseSymTable ({ Bytes = bytes } as toolBox) libs symTabCmds = + let numSymbols = countSymbols symTabCmds + let symbols = Array.zeroCreate numSymbols + let mutable idx = 0 + for symTabCmd in symTabCmds do + let strOff, strSize = symTabCmd.StrOff, int symTabCmd.StrSize + let strTab = ReadOnlySpan (bytes, strOff, strSize) + let entrySize = 8 + WordSize.toByteWidth toolBox.Header.Class + let symTabSize = int symTabCmd.NumOfSym * entrySize + let symTab = ReadOnlySpan (bytes, symTabCmd.SymOff, symTabSize) + for n = 0 to int symTabCmd.NumOfSym - 1 do + let offset = n * entrySize + symbols[idx] <- parseNList toolBox libs strTab symTab offset + idx <- idx + 1 + symbols + + let private addFuncs secText (starts: HashSet) symbols = + let symbolAddrs = symbols |> Array.map (fun s -> s.SymAddr) |> HashSet + starts.ExceptWith symbolAddrs + starts + |> Seq.toArray + |> Array.map (fun addr -> + { SymName = Addr.toFuncName addr + SymType = SymbolType.N_SECT + IsExternal = false + SecNum = secText + 1 + SymDesc = -1s (* To indicate this is B2R2-created symbols. *) + VerInfo = None + SymAddr = addr }) + |> Array.append symbols + + let isStatic s = + let isDebuggingInfo s = int s.SymType &&& 0xe0 <> 0 + (* REFERENCED_DYNAMICALLY field of n_desc is set. This means this symbol + will not be stripped (thus, this symbol is dynamic). *) + let isReferrencedDynamically s = s.SymDesc &&& 0x10s <> 0s + isDebuggingInfo s + || (s.SecNum > 0 && s.SymAddr > 0UL && s.VerInfo = None + && (isReferrencedDynamically s |> not)) + + let isDynamic s = isStatic s |> not + + let private obtainStaticSymbols symbols = + symbols |> Array.filter isStatic + + let private countDynSymbs dyntabs = + dyntabs + |> Array.fold (fun cnt dyntab -> int dyntab.NumIndirectSym + cnt) 0 + + /// DynSym table contains indices to the symbol table. + let private parseDynSymTable toolBox dyntabs = + let reader = toolBox.Reader + let numSymbs = countDynSymbs dyntabs + let indices = Array.zeroCreate numSymbs + let mutable i = 0 + for dyntab in dyntabs do + let tabOffset = int dyntab.IndirectSymOff + let tabSize = int dyntab.NumIndirectSym * 4 + let tabBuf = ReadOnlySpan (toolBox.Bytes, tabOffset, tabSize) + for n = 0 to int dyntab.NumIndirectSym - 1 do + let offset = n * 4 + let symidx = reader.ReadInt32 (tabBuf, offset) + indices[i] <- symidx + i <- i + 1 + indices + + let private isUndefinedEntry entry = + entry = IndirectSymbolLocal || entry = IndirectSymbolABS + + let rec private parseSymbStub map symbols dynsymtbl sec idx len cnt = + if cnt = 0UL then map + else + let entry = Array.get dynsymtbl (sec.SecReserved1 + idx) + if isUndefinedEntry entry then + parseSymbStub map symbols dynsymtbl sec (idx + 1) len (cnt - 1UL) + else + let symbol = Array.get symbols entry + let map' = Map.add (sec.SecAddr + uint64 (idx * len)) symbol map + parseSymbStub map' symbols dynsymtbl sec (idx + 1) len (cnt - 1UL) + + /// __stubs section is similar to PLT in ELF. + let private parseSymbolStubs secs symbols dynsymtbl = + let folder acc sec = + match sec.SecType with + | SectionType.S_SYMBOL_STUBS -> + let entryLen = sec.SecReserved2 + let entryCnt = sec.SecSize / uint64 entryLen + parseSymbStub acc symbols dynsymtbl sec 0 entryLen entryCnt + | _ -> acc + secs |> Array.fold folder Map.empty + + /// Symbol pointer tables are similar to GOT in ELF. + let private parseSymbolPtrs macHdr secs symbols dynsymtbl = + let folder acc sec = + match sec.SecType with + | SectionType.S_LAZY_SYMBOL_POINTERS + | SectionType.S_NON_LAZY_SYMBOL_POINTERS -> + let entryLen = WordSize.toByteWidth macHdr.Class + let entryCnt = sec.SecSize / uint64 entryLen + parseSymbStub acc symbols dynsymtbl sec 0 entryLen entryCnt + | _ -> acc + secs |> Array.fold folder Map.empty + + let getSymbolLibName symbol = + match symbol.VerInfo with + | None -> "" + | Some v -> v.DyLibName + + let private accumulateLinkageInfo nameMap lst addr symbol = + match Map.tryFind symbol.SymName nameMap with + | None -> lst + | Some stubAddr -> + let lib = getSymbolLibName symbol + { FuncName = symbol.SymName + LibraryName = lib + TrampolineAddress = stubAddr + TableAddress = addr } :: lst + + let private createLinkageTable stubs ptrtbls = + let nameMap = Map.fold (fun m a s -> Map.add s.SymName a m) Map.empty stubs + ptrtbls |> Map.fold (accumulateLinkageInfo nameMap) [] + + let rec readStr (span: ByteSpan) pos acc = + match span[pos] with + | 0uy -> + List.rev acc |> List.toArray |> Text.Encoding.ASCII.GetString, pos + 1 + | b -> readStr span (pos + 1) (b :: acc) + + let buildExportEntry name addr = + { ExportSymName = name; ExportAddr = addr } + + let rec private parseTrie toolBox (span: ByteSpan) offset str acc = + let reader = toolBox.Reader + if span[offset] = 0uy then (* non-terminal *) + let nChilds, len = reader.ReadUInt64LEB128 (span, offset + 1) + parseChildren toolBox span (offset + 1 + len) nChilds str acc + else + let _, shift = reader.ReadUInt64LEB128 (span, offset) + let flagOffset = offset + shift + let _flag = span[flagOffset] + let symbOffset, _ = reader.ReadUInt64LEB128 (span, flagOffset + 1) + buildExportEntry str (symbOffset + toolBox.BaseAddress) :: acc + and private parseChildren toolBox span offset nChilds str acc = + if nChilds = 0UL then acc + else + let pref, nextOffset = readStr span offset [] + let reader = toolBox.Reader + let nextNode, len = reader.ReadUInt64LEB128 (span, nextOffset) + let acc = parseTrie toolBox span (int nextNode) (str + pref) acc + parseChildren toolBox span (nextOffset + len) (nChilds - 1UL) str acc + + /// The symbols exported by a dylib are encoded in a trie. + let private parseExportTrieHead toolBox exportSpan = + parseTrie toolBox exportSpan 0 "" [] + + let private parseExports toolBox dyldinfo = + match Array.tryHead dyldinfo with + | None -> [||] + | Some info -> + let exportSize = int info.ExportSize + let exportSpan = ReadOnlySpan (toolBox.Bytes, info.ExportOff, exportSize) + parseExportTrieHead toolBox exportSpan + |> List.toArray + + let private buildSymbolMap stubs ptrtbls staticsymbs = + let map = Map.fold (fun map k v -> Map.add k v map) stubs ptrtbls + Array.fold (fun map s -> Map.add s.SymAddr s map) map staticsymbs + + let parse toolBox cmds secs = + let secText = Section.getTextSectionIndex secs + let libs = Array.choose chooseDyLib cmds + let symtabs = Array.choose chooseSymTab cmds + let dyntabs = Array.choose chooseDynSymTab cmds + let dyldinfo = Array.choose chooseDyLdInfo cmds + let fnStarts = parseFuncStarts toolBox (Array.choose chooseFuncStarts cmds) + let symbs = parseSymTable toolBox libs symtabs |> addFuncs secText fnStarts + let staticsymbs = obtainStaticSymbols symbs + let dynsymIndices = parseDynSymTable toolBox dyntabs + let stubs = parseSymbolStubs secs symbs dynsymIndices + let ptrtbls = parseSymbolPtrs toolBox.Header secs symbs dynsymIndices + let linkage = createLinkageTable stubs ptrtbls + let exports = parseExports toolBox dyldinfo + { Symbols = symbs |> Array.filter (fun s -> s.SymType <> SymbolType.N_OPT) + SymbolMap = buildSymbolMap stubs ptrtbls staticsymbs + LinkageTable = linkage + Exports = exports } diff --git a/src/FrontEnd/BinFile/MachFat.fs b/src/FrontEnd/BinFile/MachFat.fs deleted file mode 100644 index 88b76a53..00000000 --- a/src/FrontEnd/BinFile/MachFat.fs +++ /dev/null @@ -1,64 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.FrontEnd.BinFile.Mach.Fat - -open System -open B2R2 - -type FatArch = { - CPUType: CPUType - CPUSubType: CPUSubType - Offset: int - Size: int - Align: int -} - -let private readFatArch (span: ByteSpan) (r: IBinReader) pos = - { CPUType = r.ReadInt32 (span, pos) |> LanguagePrimitives.EnumOfValue - CPUSubType = r.ReadInt32 (span, pos + 4) |> LanguagePrimitives.EnumOfValue - Offset = r.ReadInt32 (span, pos + 8) - Size = r.ReadInt32 (span, pos + 12) - Align = r.ReadInt32 (span, pos + 16) } - -let rec private loadFatAux acc span reader pos cnt = - if cnt = 0 then acc - else - let arch = readFatArch span reader pos - loadFatAux (arch :: acc) span reader (pos + 20) (cnt - 1) - -let loadFats (span: ByteSpan) (reader: IBinReader) = - let nArch = reader.ReadInt32 (span, 4) - loadFatAux [] span reader 8 nArch - -let private matchISA isa fatArch = - let arch = Header.cpuTypeToArch fatArch.CPUType fatArch.CPUSubType - isa.Arch = arch - -let rec findMatchingFatRecord isa fats = - match fats with - | fatArch :: tl -> - if matchISA isa fatArch then fatArch - else findMatchingFatRecord isa tl - | [] -> raise InvalidISAException \ No newline at end of file diff --git a/src/FrontEnd/BinFile/MachHeader.fs b/src/FrontEnd/BinFile/MachHeader.fs deleted file mode 100644 index ec3c6513..00000000 --- a/src/FrontEnd/BinFile/MachHeader.fs +++ /dev/null @@ -1,98 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.FrontEnd.BinFile.Mach.Header - -open System -open B2R2 -open B2R2.FrontEnd.BinFile - -let internal peekMagic (span: ByteSpan) reader = - if span.Length > 4 - then (reader: IBinReader).ReadUInt32 (span, 0) - else 0ul - |> LanguagePrimitives.EnumOfValue - -let isFat span reader = - match peekMagic span reader with - | Magic.FATCigam | Magic.FATMagic -> true - | _ -> false - -let isMach span reader = - match peekMagic span reader with - | Magic.MHCigam | Magic.MHCigam64 | Magic.MHMagic | Magic.MHMagic64 -> true - | _ -> isFat span reader - -let internal peekCPUType (span: ByteSpan) (reader: IBinReader) = - reader.ReadInt32 (span, 4) |> LanguagePrimitives.EnumOfValue - -let internal peekCPUSubType (span: ByteSpan) (reader: IBinReader) = - reader.ReadInt32 (span, 8) |> LanguagePrimitives.EnumOfValue - -let internal getMIPSArch = function - | CPUSubType.MIPSAll - | CPUSubType.MIPSR2300 - | CPUSubType.MIPSR2600 - | CPUSubType.MIPSR2800 - | CPUSubType.MIPSR2000A -> Arch.MIPS32R2 - | _ -> raise InvalidISAException - -let cpuTypeToArch cputype subtype = - match cputype with - | CPUType.I386 -> Arch.IntelX86 - | CPUType.X64 -> Arch.IntelX64 - | CPUType.ARM -> Arch.ARMv7 - | CPUType.ARM64 -> Arch.AARCH64 - | CPUType.MIPS -> getMIPSArch subtype - | _ -> Arch.UnknownISA - -let internal peekArch span reader = - let cputype = peekCPUType span reader - let subtype = peekCPUSubType span reader - cpuTypeToArch cputype subtype - -let internal peekClass span reader = - match peekMagic span reader with - | Magic.MHMagic | Magic.MHCigam -> WordSize.Bit32 - | Magic.MHMagic64 | Magic.MHCigam64 -> WordSize.Bit64 - | _ -> raise FileFormatMismatchException - -let internal magicToEndian = function - | Magic.MHMagic | Magic.MHMagic64 -> Endian.Little - | Magic.MHCigam | Magic.MHCigam64 -> Endian.Big - | _ -> raise FileFormatMismatchException - -let internal peekEndianness span reader = - peekMagic span reader - |> magicToEndian - -let internal parse span reader = - { Magic = peekMagic span reader - Class = peekClass span reader - CPUType = peekCPUType span reader - CPUSubType = peekCPUSubType span reader - FileType = reader.ReadInt32 (span, 12) |> LanguagePrimitives.EnumOfValue - NumCmds = reader.ReadUInt32 (span, 16) - SizeOfCmds = reader.ReadUInt32 (span, 20) - Flags = reader.ReadInt32 (span, 24) |> LanguagePrimitives.EnumOfValue } \ No newline at end of file diff --git a/src/FrontEnd/BinFile/MachHelper.fs b/src/FrontEnd/BinFile/MachHelper.fs deleted file mode 100644 index 757145fd..00000000 --- a/src/FrontEnd/BinFile/MachHelper.fs +++ /dev/null @@ -1,184 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.Mach.Helper - -open System -open B2R2 -open B2R2.FrontEnd.BinFile - -/// Mach-specific virtual memory permission (for maxprot and initprot). Note -/// that these values are different than the B2R2.Permission type. -[] -type MachVMProt = - /// File is readable. - | Readable = 1 - /// File is writable. - | Writable = 2 - /// File is executable. - | Executable = 4 - -let getISA mach = - let cputype = mach.MachHdr.CPUType - let cpusubtype = mach.MachHdr.CPUSubType - let arch = Header.cpuTypeToArch cputype cpusubtype - let endian = Header.magicToEndian mach.MachHdr.Magic - ISA.Init arch endian - -let convFileType = function - | MachFileType.MHExecute -> FileType.ExecutableFile - | MachFileType.MHObject -> FileType.ObjFile - | MachFileType.MHDylib - | MachFileType.MHFvmlib -> FileType.LibFile - | MachFileType.MHCore -> FileType.CoreFile - | _ -> FileType.UnknownFile - -let machTypeToSymbKind sym secText = - if (sym.SymType = SymbolType.NFun && sym.SymName.Length > 0) - || (sym.SymType.HasFlag SymbolType.NSect - && sym.SecNum = (secText + 1) - && sym.SymDesc = 0s) then - SymFunctionType - elif sym.SymType = SymbolType.NSO - || sym.SymType = SymbolType.NOSO then - SymFileType - else - NoType - -let machSymbolToSymbol secText target sym = - { Address = sym.SymAddr - Name = sym.SymName - Kind = machTypeToSymbKind sym secText - Target = target - LibraryName = Symbol.getSymbolLibName sym - ArchOperationMode = ArchOperationMode.NoMode } - -let getStaticSymbols mach = - mach.SymInfo.Symbols - |> Array.filter Symbol.isStatic - |> Array.map (machSymbolToSymbol mach.SecText TargetKind.StaticSymbol) - -let isStripped mach = - getStaticSymbols mach - |> Array.exists (fun s -> s.Kind = SymFunctionType) - |> not - -let isNXEnabled mach = - not (mach.MachHdr.Flags.HasFlag MachFlag.MHAllowStackExecution) - || mach.MachHdr.Flags.HasFlag MachFlag.MHNoHeapExecution - -let inline getTextStartAddr mach = - (Map.find "__text" mach.Sections.SecByName).SecAddr - -let inline translateAddr mach addr = - match ARMap.tryFindByAddr addr mach.SegmentMap with - | Some s -> Convert.ToInt32 (addr - s.VMAddr + s.FileOff) - | None -> raise InvalidAddrReadException - -let getDynamicSymbols excludeImported mach = - let excludeImported = defaultArg excludeImported false - let filter = Array.filter (fun (s: MachSymbol) -> s.SymAddr > 0UL) - mach.SymInfo.Symbols - |> Array.filter Symbol.isDynamic - |> fun arr -> if excludeImported then filter arr else arr - |> Array.map (machSymbolToSymbol mach.SecText TargetKind.DynamicSymbol) - -let getSymbols mach = - let s = getStaticSymbols mach - let d = getDynamicSymbols None mach - Array.append s d |> Array.toSeq - -let secFlagToSectionKind isExecutable = function - | SectionType.NonLazySymbolPointers - | SectionType.LazySymbolPointers - | SectionType.SymbolStubs -> SectionKind.LinkageTableSection - | _ -> - if isExecutable then SectionKind.ExecutableSection - else SectionKind.ExtraSection - -let machSectionToSection segMap (sec: MachSection) = - let seg = ARMap.findByAddr sec.SecAddr segMap - let perm: MachVMProt = seg.InitProt |> LanguagePrimitives.EnumOfValue - let isExecutable = perm.HasFlag MachVMProt.Executable - { Address = sec.SecAddr - FileOffset = uint64 sec.SecOffset - Kind = secFlagToSectionKind isExecutable sec.SecType - Size = sec.SecSize - Name = sec.SecName } - -let getSections mach = - mach.Sections.SecByNum - |> Array.map (machSectionToSection mach.SegmentMap) - |> Array.toSeq - -let getSectionsByAddr mach addr = - match ARMap.tryFindByAddr addr mach.Sections.SecByAddr with - | Some s -> Seq.singleton (machSectionToSection mach.SegmentMap s) - | None -> Seq.empty - -let getSectionsByName mach name = - match Map.tryFind name mach.Sections.SecByName with - | Some s -> Seq.singleton (machSectionToSection mach.SegmentMap s) - | None -> Seq.empty - -let getTextSections mach = - mach.Sections.SecByNum[mach.SecText] - |> machSectionToSection mach.SegmentMap - |> Seq.singleton - -let getPLT mach = - mach.SymInfo.LinkageTable - |> List.sortBy (fun entry -> entry.TrampolineAddress) - |> List.toSeq - -let isPLT mach addr = - mach.SymInfo.LinkageTable - |> List.exists (fun entry -> entry.TrampolineAddress = addr) - -let inline tryFindFuncSymb mach addr = - match Map.tryFind addr mach.SymInfo.SymbolMap with - | Some s -> Ok s.SymName - | None -> Error ErrorCase.SymbolNotFound - -let inline isValidAddr mach addr = - IntervalSet.containsAddr addr mach.InvalidAddrRanges |> not - -let inline isValidRange mach range = - IntervalSet.findAll range mach.InvalidAddrRanges |> List.isEmpty - -let inline isInFileAddr mach addr = - IntervalSet.containsAddr addr mach.NotInFileRanges |> not - -let inline isInFileRange mach range = - IntervalSet.findAll range mach.NotInFileRanges |> List.isEmpty - -let inline isExecutableAddr mach addr = - IntervalSet.containsAddr addr mach.ExecutableRanges - -let inline getNotInFileIntervals mach range = - IntervalSet.findAll range mach.NotInFileRanges - |> List.map (FileHelper.trimByRange range) - |> List.toSeq - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinFile/MachLoadCommands.fs b/src/FrontEnd/BinFile/MachLoadCommands.fs deleted file mode 100644 index 42ac72ae..00000000 --- a/src/FrontEnd/BinFile/MachLoadCommands.fs +++ /dev/null @@ -1,150 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.Mach.LoadCommands - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.FileHelper - -let parseSegCmd span (reader: IBinReader) baseAddr cls offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - SecOff = offset + if cls = WordSize.Bit64 then 72 else 56 - SegCmdName = peekCString span (offset + 8) - VMAddr = peekHeaderNative span reader cls offset 24 24 + baseAddr - VMSize = peekHeaderNative span reader cls offset 28 32 - FileOff = peekHeaderNative span reader cls offset 32 40 - FileSize = peekHeaderNative span reader cls offset 36 48 - MaxProt = peekHeaderI32 span reader cls offset 40 56 - InitProt = peekHeaderI32 span reader cls offset 44 60 - NumSecs = peekHeaderU32 span reader cls offset 48 64 - SegFlag = peekHeaderU32 span reader cls offset 52 68 } - -let parseSymCmd (span: ByteSpan) reader offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - SymOff = (reader: IBinReader).ReadInt32 (span, offset + 8) - NumOfSym = reader.ReadUInt32 (span, offset + 12) - StrOff = reader.ReadInt32 (span, offset + 16) - StrSize = reader.ReadUInt32 (span, offset + 20) } - -let parseDySymCmd (span: ByteSpan) reader offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - IdxLocalSym = (reader: IBinReader).ReadUInt32 (span, offset + 8) - NumLocalSym = reader.ReadUInt32 (span, offset + 12) - IdxExtSym = reader.ReadUInt32 (span, offset + 16) - NumExtSym = reader.ReadUInt32 (span, offset + 20) - IdxUndefSym = reader.ReadUInt32 (span, offset + 24) - NumUndefSym = reader.ReadUInt32 (span, offset + 28) - TOCOffset = reader.ReadUInt32 (span, offset + 32) - NumTOCContents = reader.ReadUInt32 (span, offset + 36) - ModTabOff = reader.ReadUInt32 (span, offset + 40) - NumModTab = reader.ReadUInt32 (span, offset + 44) - ExtRefSymOff = reader.ReadUInt32 (span, offset + 48) - NumExtRefSym = reader.ReadUInt32 (span, offset + 52) - IndirectSymOff = reader.ReadUInt32 (span, offset + 56) - NumIndirectSym = reader.ReadUInt32 (span, offset + 60) - ExtRelOff = reader.ReadUInt32 (span, offset + 64) - NumExtRel = reader.ReadUInt32 (span, offset + 68) - LocalRelOff = reader.ReadUInt32 (span, offset + 72) - NumLocalRel = reader.ReadUInt32 (span, offset + 76) } - -let parseMainCmd (span: ByteSpan) reader baseAddr offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - EntryOff = ((reader: IBinReader).ReadUInt64 (span, offset + 8)) + baseAddr - StackSize = reader.ReadUInt64 (span, offset + 16) } - -/// Read lc_str string. -let readLCStr (span: ByteSpan) reader (size: uint32) offset = - let strOffset = (reader: IBinReader).ReadInt32 (span, offset + 8) - let strLen = Convert.ToInt32 size - strOffset - ByteArray.extractCStringFromSpan (span.Slice (offset + strOffset, strLen)) 0 - -let parseDyLibCmd span reader offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - DyLibName = readLCStr span reader cmdSize offset - DyLibTimeStamp = reader.ReadUInt32 (span, offset + 12) - DyLibCurVer = reader.ReadUInt32 (span, offset + 16) - DyLibCmpVer = reader.ReadUInt32 (span, offset + 20) } - -let parseDyLdInfo (span: ByteSpan) reader offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - RebaseOff = (reader: IBinReader).ReadInt32 (span, offset + 8) - RebaseSize = reader.ReadUInt32 (span, offset + 12) - BindOff = reader.ReadInt32 (span, offset + 16) - BindSize = reader.ReadUInt32 (span, offset + 20) - WeakBindOff = reader.ReadInt32 (span, offset + 24) - WeakBindSize = reader.ReadUInt32 (span, offset + 28) - LazyBindOff = reader.ReadInt32 (span, offset + 32) - LazyBindSize = reader.ReadUInt32 (span, offset + 36) - ExportOff = reader.ReadInt32 (span, offset + 40) - ExportSize = reader.ReadUInt32 (span, offset + 44) } - -let parseFuncStarts (span: ByteSpan) reader offset cmdType cmdSize = - { Cmd = cmdType - CmdSize = cmdSize - DataOffset = (reader: IBinReader).ReadInt32 (span, offset + 8) - DataSize = reader.ReadUInt32 (span, offset + 12) } - -let parseCmd baddr (span: ByteSpan) (reader: IBinReader) cls offset = - let cmdType = - reader.ReadInt32 (span, offset) |> LanguagePrimitives.EnumOfValue - let cmdSize = reader.ReadUInt32 (span, offset + 4) - let command = - match cmdType with - | LoadCmdType.LCSegment - | LoadCmdType.LCSegment64 -> - Segment (parseSegCmd span reader baddr cls offset cmdType cmdSize) - | LoadCmdType.LCSymTab -> - SymTab (parseSymCmd span reader offset cmdType cmdSize) - | LoadCmdType.LCDySymTab -> - DySymTab (parseDySymCmd span reader offset cmdType cmdSize) - | LoadCmdType.LCMain -> - Main (parseMainCmd span reader baddr offset cmdType cmdSize) - | LoadCmdType.LCLoadDyLib -> - DyLib (parseDyLibCmd span reader offset cmdType cmdSize) - | LoadCmdType.LCDyLDInfo - | LoadCmdType.LCDyLDInfoOnly -> - DyLdInfo (parseDyLdInfo span reader offset cmdType cmdSize) - | LoadCmdType.LCFunStarts -> - FuncStarts (parseFuncStarts span reader offset cmdType cmdSize) - | _ -> Unhandled { Cmd = cmdType; CmdSize = cmdSize } - struct (command, Convert.ToInt32 cmdSize) - -let rec private cmdLoop baseAddr span reader machHdr cNum acc offset = - if cNum = 0u then List.rev acc - else - let struct (cmd, cmdSize) = - parseCmd baseAddr span reader machHdr.Class offset - cmdLoop baseAddr span reader machHdr - (cNum - 1u) (cmd :: acc) (offset + cmdSize) - -let parse baseAddr span reader machHdr = - let cmdOffset = if machHdr.Class = WordSize.Bit32 then 28 else 32 - cmdLoop baseAddr span reader machHdr machHdr.NumCmds [] cmdOffset diff --git a/src/FrontEnd/BinFile/MachParser.fs b/src/FrontEnd/BinFile/MachParser.fs deleted file mode 100644 index 3f49c021..00000000 --- a/src/FrontEnd/BinFile/MachParser.fs +++ /dev/null @@ -1,119 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.Mach.Parser - -open System -open B2R2 -open B2R2.FrontEnd.BinFile - -let isMainCmd = function - | Main _ -> true - | _ -> false - -let getMainOffset cmds = - match cmds |> List.tryFind isMainCmd with - | Some (Main m) -> m.EntryOff - | _ -> 0UL - -let getTextSegOffset segs = - let isTextSegment s = s.SegCmdName = "__TEXT" - match segs |> List.tryFind isTextSegment with - | Some s -> s.VMAddr - | _ -> raise FileFormatMismatchException - -let computeEntryPoint segs cmds = - let mainOffset = getMainOffset cmds - if mainOffset = 0UL then None - else Some (mainOffset + getTextSegOffset segs) - -let invRanges wordSize segs getNextStartAddr = - segs - |> List.filter (fun seg -> seg.SegCmdName <> "__PAGEZERO") - |> List.sortBy (fun seg -> seg.VMAddr) - |> List.fold (fun (set, saddr) seg -> - let n = getNextStartAddr seg - FileHelper.addInvRange set saddr seg.VMAddr, n) (IntervalSet.empty, 0UL) - |> FileHelper.addLastInvRange wordSize - -let execRanges segs = - segs - |> List.filter (fun seg -> - let perm: Permission = seg.MaxProt |> LanguagePrimitives.EnumOfValue - perm &&& Permission.Executable = Permission.Executable) - |> List.fold (fun set s -> - IntervalSet.add (AddrRange (s.VMAddr, s.VMAddr + s.VMSize - 1UL)) set - ) IntervalSet.empty - -let computeBaseAddr machHdr baseAddr = - if machHdr.Flags.HasFlag MachFlag.MHPIE then defaultArg baseAddr 0UL - else 0UL - -let parseMach baseAddr span reader = - let machHdr = Header.parse span reader - let baseAddr = computeBaseAddr machHdr baseAddr - let cls = machHdr.Class - let cmds = LoadCommands.parse baseAddr span reader machHdr - let segs = Segment.extract cmds - let segmap = Segment.buildMap segs - let secs = Section.parseSections baseAddr span reader cls segs - let secText = Section.getTextSectionIndex secs.SecByNum - let symInfo = Symbol.parse baseAddr span reader machHdr cmds secs secText - let relocs = - Reloc.parseRelocs span reader secs.SecByNum - |> Array.map (Reloc.toSymbol symInfo.Symbols secs.SecByNum) - { EntryPoint = computeEntryPoint segs cmds - BaseAddr = baseAddr - SymInfo = symInfo - MachHdr = machHdr - Segments = segs - SegmentMap = segmap - Sections = secs - SecText = secText - Relocations = relocs - Cmds = cmds - InvalidAddrRanges = invRanges cls segs (fun s -> s.VMAddr + s.VMSize) - NotInFileRanges = invRanges cls segs (fun s -> s.VMAddr + s.FileSize) - ExecutableRanges = execRanges segs - BinReader = reader } - -let private computeOffsetAndSize span reader isa = - let fatArch = Fat.loadFats span reader |> Fat.findMatchingFatRecord isa - struct (fatArch.Offset, fatArch.Size) - -let updateSpanForFat isa span reader = - if Header.isFat span reader then - let struct (offset, size) = computeOffsetAndSize span reader isa - span.Slice (offset, size) - else span - -let parse baseAddr (bytes: byte[]) isa = - let span = ReadOnlySpan bytes - let span = updateSpanForFat isa span BinReader.binReaderBE - if Header.isMach span BinReader.binReaderLE then () - else raise FileFormatMismatchException - match Header.peekEndianness span BinReader.binReaderLE with - | Endian.Little -> parseMach baseAddr span BinReader.binReaderLE - | Endian.Big -> parseMach baseAddr span BinReader.binReaderBE - | _ -> Utils.impossible () \ No newline at end of file diff --git a/src/FrontEnd/BinFile/MachReloc.fs b/src/FrontEnd/BinFile/MachReloc.fs deleted file mode 100644 index eb0b15a3..00000000 --- a/src/FrontEnd/BinFile/MachReloc.fs +++ /dev/null @@ -1,85 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.Mach.Reloc - -open System -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile - -let parseRelocSymbol data = - let n = data &&& 0xFFFFFF - if (data >>> 27) &&& 1 = 1 then SymIndex (n) - else SecOrdinal (n) - -let parseRelocLength data = - match (data >>> 25) &&& 3 with - | 0 -> 8 - | 1 -> 16 - | _ -> 32 - -let rec updateReloc relocs (span: ByteSpan) reader sec off endOffset = - if off >= endOffset then () - else - let addr = (reader: IBinReader).ReadInt32 (span, off) - let data = reader.ReadInt32 (span, off + 4) - let sym = parseRelocSymbol data - let len = parseRelocLength data - let rel = (data >>> 24) &&& 1 = 1 - let r = - { RelocAddr = addr - RelocSymbol = sym - RelocLength = len - RelocSection = sec - IsPCRel = rel } - (relocs: List).Add r - updateReloc relocs span reader sec (off + 8) endOffset - -let translateRelocAddr reloc = - reloc.RelocSection.SecAddr + uint64 reloc.RelocAddr - -let translateRelocSymbol (symbols: MachSymbol []) (secs: MachSection []) reloc = - match reloc.RelocSymbol with - | SymIndex (n) -> symbols[n].SymName - | SecOrdinal (n) -> secs[n - 1].SecName - -let toSymbol symbols secs reloc = - { Address = translateRelocAddr reloc - Name = translateRelocSymbol symbols secs reloc - Kind = SymbolKind.NoType (* FIXME *) - Target = TargetKind.DynamicSymbol - LibraryName = "" - ArchOperationMode = ArchOperationMode.NoMode } - -let parseRelocs span reader secs = - let relocs = List () - for sec in secs do - if sec.SecNumOfReloc = 0 then () - else - let startOffset = sec.SecRelOff |> Convert.ToInt32 - let endOffset = startOffset + (8 * int sec.SecNumOfReloc) - updateReloc relocs span reader sec startOffset endOffset - relocs - |> Seq.toArray diff --git a/src/FrontEnd/BinFile/MachSection.fs b/src/FrontEnd/BinFile/MachSection.fs deleted file mode 100644 index 2d1b0f03..00000000 --- a/src/FrontEnd/BinFile/MachSection.fs +++ /dev/null @@ -1,65 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.Mach.Section - -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile.FileHelper - -let parseSection baseAddr span reader cls pos = - let secFlag = peekHeaderI32 span reader cls pos 56 64 - { SecName = peekCString span pos - SegName = peekCString span (pos + 16) - SecAddr = peekUIntOfType span reader cls (pos + 32) + baseAddr - SecSize = peekHeaderNative span reader cls pos 36 40 - SecOffset = peekHeaderU32 span reader cls pos 40 48 - SecAlignment = peekHeaderU32 span reader cls pos 44 52 - SecRelOff = peekHeaderU32 span reader cls pos 48 56 - SecNumOfReloc = peekHeaderI32 span reader cls pos 52 60 - SecType = secFlag &&& 0xFF |> LanguagePrimitives.EnumOfValue - SecAttrib = secFlag &&& 0xFFFFFF00 |> LanguagePrimitives.EnumOfValue - SecReserved1 = peekHeaderI32 span reader cls pos 60 68 - SecReserved2 = peekHeaderI32 span reader cls pos 64 72 } - -let foldSecInfo acc sec = - let secEnd = sec.SecAddr + sec.SecSize - 1UL - let secByAddr = ARMap.addRange sec.SecAddr secEnd sec acc.SecByAddr - let secByName = Map.add sec.SecName sec acc.SecByName - { acc with SecByAddr = secByAddr; SecByName = secByName } - -let parseSections baseAddr span reader cls segs = - let sections = List () - for seg in segs do - let mutable pos = seg.SecOff - for _ = 1 to int seg.NumSecs do - let sec = parseSection baseAddr span reader cls pos - sections.Add sec - pos <- pos + if cls = WordSize.Bit64 then 80 else 68 - let acc = { SecByAddr = ARMap.empty; SecByName = Map.empty; SecByNum = [||] } - let secInfo = Seq.fold foldSecInfo acc sections - { secInfo with SecByNum = Array.ofSeq sections } - -let getTextSectionIndex secs = - secs |> Array.findIndex (fun s -> s.SecName = "__text") diff --git a/src/FrontEnd/BinFile/MachSymbol.fs b/src/FrontEnd/BinFile/MachSymbol.fs deleted file mode 100644 index c803031e..00000000 --- a/src/FrontEnd/BinFile/MachSymbol.fs +++ /dev/null @@ -1,278 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinFile.Mach.Symbol - -open System -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinFile.FileHelper - -let [] IndirectSymbolLocal = 0x80000000 -let [] IndirectSymbolABS = 0x40000000 - -let chooseDyLib = function - | DyLib c -> Some c - | _ -> None - -let chooseSymTab = function - | SymTab c -> Some c - | _ -> None - -let chooseDynSymTab = function - | DySymTab c -> Some c - | _ -> None - -let chooseDyLdInfo = function - | DyLdInfo c -> Some c - | _ -> None - -let chooseFuncStarts = function - | FuncStarts c -> Some c - | _ -> None - -let parseFuncStarts baseAddr (span: ByteSpan) reader cmds = - let set = HashSet () - for cmd in cmds do - let offset = cmd.DataOffset - let saddr, count = (reader: IBinReader).ReadUInt64LEB128 (span, offset) - let saddr = saddr + baseAddr - set.Add saddr |> ignore - let lastOffset = offset + int cmd.DataSize - let mutable offset = offset + count - let mutable fnAddr = saddr - while offset < lastOffset do - let data, count = (reader: IBinReader).ReadUInt64LEB128 (span, offset) - fnAddr <- fnAddr + data - set.Add fnAddr |> ignore - offset <- offset + count - set |> Set - -let getLibraryVerInfo (flags: MachFlag) libs nDesc = - if flags.HasFlag (MachFlag.MHTwoLevel) then - let ord = nDesc >>> 8 &&& 0xffs |> int - if ord = 0 || ord = 254 then None - else Some <| Array.get libs (ord - 1) - else None - -let adjustSymAddr baseAddr addr = - if addr = 0UL then 0UL - else baseAddr + addr - -let parseNList baseAddr (span: ByteSpan) reader macHdr libs strtab offset = - let strIdx = (reader: IBinReader).ReadInt32 (span, offset) - let nDesc = reader.ReadInt16 (span, offset + 6) - let nType = reader.ReadByte (span, offset + 4) |> int - { SymName = ByteArray.extractCStringFromSpan strtab strIdx - SymType = nType |> LanguagePrimitives.EnumOfValue - IsExternal = nType &&& 0x1 = 0x1 - SecNum = reader.ReadByte (span, offset + 5) |> int - SymDesc = nDesc - VerInfo = getLibraryVerInfo macHdr.Flags libs nDesc - SymAddr = peekUIntOfType span reader macHdr.Class (offset + 8) - |> adjustSymAddr baseAddr } - -/// Parse SymTab, which is essentially an array of n_list. -let rec symTab lst baseAddr span reader macHdr libs strtab offset numSymbs = - if numSymbs = 0u then () - else - let symb = parseNList baseAddr span reader macHdr libs strtab offset - (lst: List).Add symb - let offset' = offset + 8 + WordSize.toByteWidth macHdr.Class - symTab lst baseAddr span reader macHdr libs strtab offset' (numSymbs - 1u) - -let parseSymTable baseAddr (span: ByteSpan) reader macHdr libs symtabs = - let lst = List () - for symtab in symtabs do - let strtabSize = Convert.ToInt32 symtab.StrSize - let strtab = span.Slice (symtab.StrOff, strtabSize) - symTab lst baseAddr span reader macHdr libs strtab - symtab.SymOff symtab.NumOfSym - lst |> Seq.toArray - -let addFuncs secTxt starts symbols = - let symbolAddrs = symbols |> Array.map (fun s -> s.SymAddr) |> Set.ofArray - Set.difference starts symbolAddrs - |> Set.toArray - |> Array.map (fun addr -> - { SymName = Addr.toFuncName addr - SymType = SymbolType.NSect - IsExternal = false - SecNum = secTxt + 1 - SymDesc = -1s (* To indicate this is B2R2-created symbols. *) - VerInfo = None - SymAddr = addr }) - |> Array.append symbols - -let isStatic s = - let isDebuggingInfo s = int s.SymType &&& 0xe0 <> 0 - /// REFERENCED_DYNAMICALLY field of n_desc is set. This means this symbol - /// will not be stripped (thus, this symbol is dynamic). - let isReferrencedDynamically s = s.SymDesc &&& 0x10s <> 0s - isDebuggingInfo s - || (s.SecNum > 0 && s.SymAddr > 0UL && s.VerInfo = None - && (isReferrencedDynamically s |> not)) - -let isDynamic s = isStatic s |> not - -let obtainStaticSymbols symbols = - symbols |> Array.filter isStatic - -let rec parseDynTab lst (span: ByteSpan) reader offset numSymbs = - if numSymbs = 0u then () - else - let idx = (reader: IBinReader).ReadInt32 (span, offset) - (lst: List).Add idx - parseDynTab lst span reader (offset + 4) (numSymbs- 1u) - -/// DynSym table contains indices to the symbol table. -let parseDynSymTable span reader dyntabs = - let lst = List () - for dyntab in dyntabs do - let tabOffset = Convert.ToInt32 dyntab.IndirectSymOff - parseDynTab lst span reader tabOffset dyntab.NumIndirectSym - lst |> Seq.toArray - -let isUndefinedEntry entry = - entry = IndirectSymbolLocal || entry = IndirectSymbolABS - -let rec parseSymbStub map symbols dynsymtbl sec idx len cnt = - if cnt = 0UL then map - else - let entry = Array.get dynsymtbl (sec.SecReserved1 + idx) - if isUndefinedEntry entry then - parseSymbStub map symbols dynsymtbl sec (idx + 1) len (cnt - 1UL) - else - let symbol = Array.get symbols entry - let map' = Map.add (sec.SecAddr + uint64 (idx * len)) symbol map - parseSymbStub map' symbols dynsymtbl sec (idx + 1) len (cnt - 1UL) - -/// __stubs section is similar to PLT in ELF. -let parseSymbolStubs secs symbols dynsymtbl = - let folder acc sec = - match sec.SecType with - | SectionType.SymbolStubs -> - let entryLen = sec.SecReserved2 - let entryCnt = sec.SecSize / uint64 entryLen - parseSymbStub acc symbols dynsymtbl sec 0 entryLen entryCnt - | _ -> acc - secs.SecByNum |> Array.fold folder Map.empty - -/// Symbol pointer tables are similar to GOT in ELF. -let parseSymbolPtrs macHdr secs symbols dynsymtbl = - let folder acc sec = - match sec.SecType with - | SectionType.LazySymbolPointers - | SectionType.NonLazySymbolPointers -> - let entryLen = WordSize.toByteWidth macHdr.Class - let entryCnt = sec.SecSize / uint64 entryLen - parseSymbStub acc symbols dynsymtbl sec 0 entryLen entryCnt - | _ -> acc - secs.SecByNum |> Array.fold folder Map.empty - -let getSymbolLibName symbol = - match symbol.VerInfo with - | None -> "" - | Some v -> v.DyLibName - -let accumulateLinkageInfo nameMap lst addr symbol = - match Map.tryFind symbol.SymName nameMap with - | None -> lst - | Some stubAddr -> - let lib = getSymbolLibName symbol - { FuncName = symbol.SymName - LibraryName = lib - TrampolineAddress = stubAddr - TableAddress = addr } :: lst - -let createLinkageTable stubs ptrtbls = - let nameMap = Map.fold (fun m a s -> Map.add s.SymName a m) Map.empty stubs - ptrtbls |> Map.fold (accumulateLinkageInfo nameMap) [] - -let rec readStr (span: ByteSpan) pos acc = - match span[pos] with - | 0uy -> - List.rev acc |> List.toArray |> Text.Encoding.ASCII.GetString, pos + 1 - | b -> readStr span (pos + 1) (b :: acc) - -let buildExportEntry name addr = - { ExportSymName = name; ExportAddr = addr } - -let rec parseExportTrie bAddr span reader trieOfs ofs str acc = - let b = (span: ByteSpan)[ofs] - if b = 0uy then (* non-terminal *) - let nChilds, len = - (reader: IBinReader).ReadUInt64LEB128 (span, ofs + 1) - parseChildren bAddr span reader trieOfs (ofs + 1 + len) nChilds str acc - else - let _, shift= reader.ReadUInt64LEB128 (span, ofs) - let _flag = reader.ReadByte (span, ofs + shift) - let symbOffset, _ = reader.ReadUInt64LEB128 (span, ofs + shift + 1) - buildExportEntry str (symbOffset + bAddr) :: acc -and parseChildren bAddr span reader trieOfs ofs nChilds str acc = - if nChilds = 0UL then acc - else - let pref, nextOffset = readStr span ofs [] - let nextNode, len = reader.ReadUInt64LEB128 (span, nextOffset) - let acc = - parseExportTrie bAddr span reader trieOfs - (int nextNode + trieOfs) (str + pref) acc - parseChildren bAddr span reader trieOfs - (nextOffset + len) (nChilds - 1UL) str acc - -/// The symbols exported by a dylib are encoded in a trie. -let parseExportTrieHead baseAddr span reader trieOffset = - parseExportTrie baseAddr span reader trieOffset trieOffset "" [] - -let parseExports baseAddr span reader dyldinfo = - match List.tryHead dyldinfo with - | None -> [] - | Some info -> - parseExportTrieHead baseAddr span reader info.ExportOff - -let buildSymbolMap stubs ptrtbls staticsymbs = - let map = Map.fold (fun map k v -> Map.add k v map) stubs ptrtbls - Array.fold (fun map s -> Map.add s.SymAddr s map) map staticsymbs - -let parse baseAddr span reader macHdr cmds secs secTxt = - let libs = List.choose chooseDyLib cmds |> List.toArray - let symtabs = List.choose chooseSymTab cmds - let dyntabs = List.choose chooseDynSymTab cmds - let dyldinfo = List.choose chooseDyLdInfo cmds - let fnStarts = - parseFuncStarts baseAddr span reader (List.choose chooseFuncStarts cmds) - let symbs = - parseSymTable baseAddr span reader macHdr libs symtabs - |> addFuncs secTxt fnStarts - let staticsymbs = obtainStaticSymbols symbs - let dynsymIndices = parseDynSymTable span reader dyntabs - let stubs = parseSymbolStubs secs symbs dynsymIndices - let ptrtbls = parseSymbolPtrs macHdr secs symbs dynsymIndices - let linkage = createLinkageTable stubs ptrtbls - let exports = parseExports baseAddr span reader dyldinfo - { Symbols = symbs |> Array.filter (fun s -> s.SymType <> SymbolType.NOpt) - SymbolMap = buildSymbolMap stubs ptrtbls staticsymbs - LinkageTable = linkage - Exports = exports } diff --git a/src/FrontEnd/BinFile/MachTypes.fs b/src/FrontEnd/BinFile/MachTypes.fs deleted file mode 100644 index c51bb497..00000000 --- a/src/FrontEnd/BinFile/MachTypes.fs +++ /dev/null @@ -1,758 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile.Mach - -open System -open B2R2 -open B2R2.FrontEnd.BinFile - -/// Magic number for Mach-O header. -type Magic = - /// The file is intended for use on a CPU with the same endianness as the - /// computer on which the compiler is running (32-bit CPU). - | MHMagic = 0xFEEDFACEu - /// The byte ordering scheme of the target machine is the reverse of the host - /// CPU (32-bit CPU). - | MHCigam = 0xCEFAEDFEu - /// The file is intended for use on a CPU with the same endianness as the - /// computer on which the compiler is running (64-bit CPU). - | MHMagic64 = 0xFEEDFACFu - /// The byte ordering scheme of the target machine is the reverse of the host - /// CPU (64-bit CPU). - | MHCigam64 = 0xCFFAEDFEu - /// The file is intended for use on multiple architectures (FAT binary). This - /// value is used on a big-endian host. - | FATMagic = 0xCAFEBABEu - /// The file is intended for use on multiple architectures (FAT binary). This - /// value is used on a little-endian host. - | FATCigam = 0xBEBAFECAu - -/// CPUType indicates the architecture. -type CPUType = - | Any = 0xFFFFFFFF - | VAX = 0x00000001 - | ROMP = 0x00000002 - | NS32032 = 0x00000004 - | NS32332 = 0x00000005 - | MC680x0 = 0x00000006 - | I386 = 0x00000007 - | X64 = 0x01000007 - | MIPS = 0x00000008 - | NS32532 = 0x00000009 - | HPPA = 0x0000000B - | ARM = 0x0000000C - | MC88000 = 0x0000000D - | SPARC = 0x0000000E - | I860 = 0x0000000F - | I860LITTLE = 0x00000010 - | RS6000 = 0x00000011 - | POWERPC = 0x00000012 - | ABI64 = 0x01000000 - | POWERPC64 = 0x01000012 - | VEO = 0x000000FF - | ARM64 = 0x0100000C - -/// CPUSubType specifies the exact model of the CPU. -type CPUSubType = - | MIPSAll = 0 - | MIPSR2300 = 1 - | MIPSR2600 = 2 - | MIPSR2800 = 3 - | MIPSR2000A = 4 - -/// Usage of the file. -type MachFileType = - /// Intermediate object files. - | MHObject = 0x1 - /// Standard executable programs. - | MHExecute = 0x2 - /// Fixed VM shared library file. - | MHFvmlib = 0x3 - /// Core file. - | MHCore = 0x4 - /// Preloaded executable file. - | MHPreload = 0x5 - /// Dynamically bound shared library file. - | MHDylib = 0x6 - /// Dynamically bound shared library file. - | MHDylinker = 0x7 - /// Dynamically bound bundle file. - | MHDybundle = 0x8 - /// Shared library stub for static linking only, no section contents. - | MHDylibStub = 0x9 - /// Companion file with only debug sections. - | MHDsym = 0xa - /// x86_64 kexts. - | MHKextBundle = 0xb - -/// Attribute of the file. -[] -type MachFlag = - /// The object file has no undefined references. - | MHNoUndefs = 0x1 - /// The object file is the output of an incremental link against a base file - /// and can't be linked against a base file and can't be link edited again. - | MHIncrLink = 0x2 - /// The object file is input for the dynamic linker and can't be statically - /// link edited again. - | MHDYLDLink = 0x4 - /// The object file's undefined references are bound by the dynamic linker - /// when loaded. - | MHBinDatLoad = 0x8 - /// The file has its dynamic undefined references prebound. - | MHPreBound = 0x10 - /// The file has its read-only and read-write segments split. - | MHSplitSegs = 0x20 - /// the shared library init routine is to be run lazily via catching memory - /// faults to its writeable segments (obsolete). - | MHLazyInit = 0x40 - /// The image is using two-level name space bindings. - | MHTwoLevel = 0x80 - /// The executable is forcing all images to use flat name space bindings. - | MHForceFlat = 0x100 - /// This umbrella guarantees no multiple defintions of symbols in its - /// sub-images so the two-level namespace hints can always be used. - | MHNoMultiDefs = 0x200 - /// Do not have dyld notify the prebinding agent about this executable. - | MHNoFixPrebinding = 0x400 - /// the binary is not prebound but can have its prebinding redone. only used - /// when MHPreBound is not set. - | MHPrebindable = 0x800 - /// Indicates that this binary binds to all two-level namespace modules of - /// its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL - /// are both set. - | MHAllModsBound = 0x1000 - /// Safe to divide up the sections into sub-sections via symbols for dead code - /// stripping. - | MHSubsectionsViaSymbols = 0x2000 - /// The binary has been canonicalized via the unprebind operation. - | MHCanonical = 0x4000 - /// The final linked image contains external weak symbols. - | MHWeakDefines = 0x8000 - /// The final linked image uses weak symbols. - | MHBindsToWeak = 0x10000 - /// When this bit is set, all stacks in the task will be given stack execution - /// privilege. Only used in MHExecute filetypes. - | MHAllowStackExecution = 0x20000 - /// When this bit is set, the binary declares it is safe for use in processes - /// with uid zero. - | MHRootSafe = 0x40000 - /// When this bit is set, the binary declares it is safe for use in processes - /// when issetugid() is true. - | MHSetUIDSafe = 0x80000 - /// When this bit is set on a dylib, the static linker does not need to - /// examine dependent dylibs to see if any are re-exported. - | MHNoReexportedDylibs = 0x100000 - /// When this bit is set, the OS will load the main executable at a random - /// address. - | MHPIE = 0x200000 - /// Only for use on dylibs. When linking against a dylib that has this bit - /// set, the static linker will automatically not create a LCLoadDyLib load - /// command to the dylib if no symbols are being referenced from the dylib. - | MHDeadStrippableDYLIB = 0x400000 - /// Contains a section of type ThreadLocalVariables. - | MHHasTLVDescriptors = 0x800000 - /// When this bit is set, the OS will run the main executable with a - /// non-executable heap even on platforms (e.g. i386) that don't require it. - /// Only used in MHExecute filetypes. - | MHNoHeapExecution = 0x1000000 - /// The code was linked for use in an application extension. - | MHAppExtensionSafe = 0x02000000 - -/// Mach-O file format header. -type MachHeader = { - /// Magic number. - Magic: Magic - /// Word size. - Class: WordSize - /// CPU type. - CPUType: CPUType - /// CPU subtype. - CPUSubType: CPUSubType - /// File type. - FileType: MachFileType - /// The number of load commands. - NumCmds: uint32 - /// The number of bytes occupied by the load commands following the header - /// structure. - SizeOfCmds: uint32 - /// A set of bit flags indicating the state of certain optional features of - /// the Mach-O file format. - Flags: MachFlag -} - -/// Load command type. -type LoadCmdType = - /// Defines a segment of this file to be mapped into the address space of the - /// process that loads this file. It also includes all the sections contained - /// by the segment. - | LCSegment = 0x01 - /// The symbol table for this file. - | LCSymTab = 0x02 - /// The gdb symbol table info (obsolete). - | LCSymSeg = 0x03 - /// This command defines the initial thread state of the main thread of the - /// process. LCThread is similar to LCUnixThread but does not cause the kernel - /// to allocate a stack. - | LCThread = 0x04 - /// This command defines the initial thread state of the main thread of the - /// process. - | LCUnixThread = 0x05 - /// Load a specified fixed VM shared library. - | LCLoadFVMLib = 0x06 - /// Fixed VM shared library identification. - | LCIDFVMLib = 0x07 - /// Object identification info (obsolete). - | LCIdent = 0x08 - /// Fixed VM file inclusion (internal use). - | LCFVMFile = 0x09 - /// Prepage command (internal use). - | LCPrepage = 0x0A - /// Dynamic link-edit symbol table info. - | LCDySymTab = 0x0B - /// Load a dynamically linked shared library. - | LCLoadDyLib = 0x0C - /// This command Specifies the install name of a dynamic shared library. - | LCIDDyLib = 0x0D - /// Load a dynamic linker. - | LCLoadDyLink = 0x0E - /// Dynamic linker identification. - | LCIDDyLink = 0x0F - /// Modules prebound for a dynamically linked shared library. - | LCPreboundDyLib = 0x10 - /// Image routines. - | LCRoutines = 0x11 - /// Sub framework. - | LCSubFramework = 0x12 - /// Sub umbrella. - | LCSubUmbrella = 0x13 - /// Sub client. - | LCSubClient = 0x14 - /// Sub library. - | LCSubLib = 0x15 - /// Two-level namespace lookup hints - | LCTwoLevelHints = 0x16 - /// Prebind checksum. - | LCPrebindCksum = 0x17 - /// Load a dynamically linked shared library that is allowed to be missing. - | LCLoadWeakDyLib = 0x80000018 - /// 64-bit segment of this file to be mapped. - | LCSegment64 = 0x19 - /// 64-bit image routines. - | LCRoutines64 = 0x1A - /// The uuid. - | LCUUID = 0x1B - /// Runpath additions. - | LCRunPath = 0x8000001C - /// Local of code signature. - | LCCodeSign = 0x1D - /// Local of info to split segments - | LCSegSplitInfo = 0x1E - /// Load and re-export dylib. - | LCReExportDyLib = 0x1F - /// Delay load of dylib until first use. - | LCLazyLoadDyLib = 0x20 - /// Encrypted segment information. - | LCEncSegInfo = 0x21 - /// Compressed dyld information. - | LCDyLDInfo = 0x22 - /// Compressed dyld information only. - | LCDyLDInfoOnly = 0x80000022 - /// Load upward dylib. - | LCLoadUpwardDyLib = 0x80000023 - /// Build for MacOSX min OS version. - | LCVerMinMacOSX = 0x24 - /// Build for iPhoneOS min OS version. - | LCVerMinIphoneOS = 0x25 - /// Compressed table of function start addresses. - | LCFunStarts = 0x26 - /// String for dyld to treat like environment variable. - | LCDyLDEnv = 0x27 - /// Replacement for LC_UNIXTHREAD. - | LCMain = 0x80000028 - /// Table of non-instructions in __text. - | LCDataInCode = 0x29 - /// Source version used to build binary. - | LCSourceVer = 0x2A - /// Code signing DRs copied from linked dylibs. - | LCDyLibCodeSigDRS = 0x2B - /// 64-bit encrypted segment information. - | LCEncInfo64 = 0x2C - /// Linker options in MH_OBJECT files. - | LCLinkOpt = 0x2D - /// Optimization hints in MH_OBJECT files. - | LCLinkOptimizeHint = 0x2E - /// Build for Watch min OS version - | LCVerMinWatchOS = 0x30 - -/// The load command structures are located directly after the header of the -/// object file, and they specify both the logical structure of the file and the -/// layout of the file in virtual memory. -type LoadCommand = - | Segment of SegCmd - | SymTab of SymTabCmd - | DySymTab of DySymTabCmd - | DyLib of DyLibCmd - | DyLdInfo of DyLdInfoCmd - | FuncStarts of FuncStartsCmd - | Main of MainCmd - | Unhandled of UnhandledCommand - -/// Segment command. -and SegCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - /// The offset of the sections in the segment. If the segment has sections - /// then the section structures directly follow the segment command and their - /// size is in the size of the command. - SecOff: int - /// Segment name. - SegCmdName: string - /// The starting virtual memory address of this segment - VMAddr: Addr - /// The number of bytes of virtual memory occupied by this segment. - VMSize: uint64 - /// The offset in this file of the data to be mapped at VMAddr. - FileOff: Addr - /// The number of bytes occupied by this segment on disk - FileSize: uint64 - /// The maximum permitted virtual memory protections of this segment - MaxProt: int - /// The initial virtual memory protections of this segment. - InitProt: int - /// The number of section data structures following this load command. - NumSecs: uint32 - /// A set of flags that affect the loading of this segment. - SegFlag: uint32 -} - -/// Symbol table command. -and SymTabCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - /// An integer containing the byte offset from the start of the file to the - /// location of the symbol table entries. - SymOff: int - /// An integer indicating the number of entries in the symbol table. - NumOfSym: uint32 - /// An integer containing the byte offset from the start of the image to the - /// location of the string table. - StrOff: int - /// An integer indicating the size (in bytes) of the string table. - StrSize: uint32 -} - -/// Dynamic symbol table command. -and DySymTabCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - /// An integer indicating the index of the first symbol in the group of local - /// symbols. - IdxLocalSym: uint32 - /// An integer indicating the total number of symbols in the group of local - /// symbols. - NumLocalSym: uint32 - /// An integer indicating the index of the first symbol in the group of - /// defined external symbols. - IdxExtSym: uint32 - /// An integer indicating the total number of symbols in the group of defined - /// external symbols. - NumExtSym: uint32 - /// An integer indicating the index of the first symbol in the group of - /// undefined external symbols. - IdxUndefSym: uint32 - /// An integer indicating the total number of symbols in the group of - /// undefined external symbols. - NumUndefSym: uint32 - /// An integer indicating the byte offset from the start of the file to the - /// table of contents data. - TOCOffset: uint32 - /// An integer indicating the number of entries in the table of contents. - NumTOCContents: uint32 - /// An integer indicating the byte offset from the start of the file to the - /// module table data. - ModTabOff: uint32 - /// An integer indicating the number of entries in the module table. - NumModTab: uint32 - /// An integer indicating the byte offset from the start of the file to the - /// external reference table data. - ExtRefSymOff: uint32 - /// An integer indicating the number of entries in the external reference - /// table. - NumExtRefSym: uint32 - /// An integer indicating the byte offset from the start of the file to the - /// indirect symbol table data. - IndirectSymOff: uint32 - /// An integer indicating the number of entries in the indirect symbol table. - NumIndirectSym: uint32 - /// An integer indicating the byte offset from the start of the file to the - /// external relocation table data. - ExtRelOff: uint32 - /// An integer indicating the number of entries in the external relocation - /// table. - NumExtRel: uint32 - /// An integer indicating the byte offset from the start of the file to the - /// local relocation table data. - LocalRelOff: uint32 - /// An integer indicating the number of entries in the local relocation table. - NumLocalRel: uint32 -} - -/// DYLD information command (dyld_info_command). -and DyLdInfoCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - /// File offset to rebase info. - RebaseOff: int - /// The size of rebase info. - RebaseSize: uint32 - /// File offset to binding info - BindOff: int - /// The size of binding info. - BindSize: uint32 - /// File offset to weak binding info. - WeakBindOff: int - /// The size of weak binding info. - WeakBindSize: uint32 - /// File offset to lazy binding info. - LazyBindOff: int - /// The size of lazy binding info. - LazyBindSize: uint32 - /// File offset to export info. - ExportOff: int - /// The size of export info. - ExportSize: uint32 -} - -/// Function starts command (LC_FUNCTION_STARTS). -and FuncStartsCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - DataOffset: int - DataSize: uint32 -} - -/// Main command. -and MainCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - /// Offset of main(). - EntryOff: Addr - /// Initial stack size, if not zero. - StackSize: uint64 -} - -/// Dynamic library command: the data used by the dynamic linker to match a -/// shared library against the files that have linked to it. -and DyLibCmd = { - Cmd: LoadCmdType - CmdSize: uint32 - /// Library's path name. - DyLibName: string - /// Library's build time stamp. - DyLibTimeStamp: uint32 - /// Library's current version number. - DyLibCurVer: uint32 - /// Library's compatibility vers number. - DyLibCmpVer: uint32 -} - -/// This type represents a load command unhandled by B2R2. -and UnhandledCommand = { - Cmd: LoadCmdType - CmdSize: uint32 -} - -/// Section type. -type SectionType = - /// Regular section. - | Regular = 0x0 - /// Zero fill on demand section. - | ZeroFill = 0x1 - /// Section with only literal C strings. - | CStringLiterals = 0x2 - /// Section with only 4 byte literals. - | FourByteLiterals = 0x3 - /// Section with only 8 byte literals. - | EightByteLiterals = 0x4 - /// section with only pointers to literals. - | LiteralPointers = 0x5 - /// Section with only non-lazy symbol pointers . - | NonLazySymbolPointers = 0x6 - /// Section with only lazy symbol pointers. - | LazySymbolPointers = 0x7 - /// Section with only symbol stubs, byte size of stub in the reserved2 field. - | SymbolStubs = 0x8 - /// Section with only function pointers for initialization. - | ModInitFuncPointers = 0x9 - /// Section with only function pointers for termination. - | ModTermFuncPointers = 0xa - /// Section contains symbols that are to be coalesced. - | Coalesced = 0xb - /// Zero fill on demand section (this can be larger than 4 gigabytes). - | GBZeroFill = 0xc - /// Section with only pairs of function pointers for interposing. - | Interposing = 0xd - /// Section with only 16 byte literals. - | SixteenByteLiterals = 0xe - /// Section contains DTrace Object Format. - | DTraceDOF = 0xf - /// Section with only lazy symbol pointers to lazy loaded dylibs. - | LazyDyLibSymbolPointers = 0x10 - /// Template of initial values for TLVs. - | ThreadLocalRegular = 0x11 - /// Template of initial values for TLVs. - | ThreadLocalZeroFill = 0x12 - /// TLV descriptors. - | ThreadLocalVariables = 0x13 - /// Pointers to TLV descriptors. - | ThreadLocalVariablePointers = 0x14 - /// Functions to call to initialize TLV values . - | ThreadLocalInitFunctionPointers = 0x15 - -/// Section attribute. -[] -type SectionAttribute = - /// Section contains only true machine instructions. - | AttrPureInstructions = 0x80000000 - /// Section contains coalesced symbols that are not to be in a ranlib table of - /// contents. - | AttrNoTOC = 0x40000000 - /// OK to strip static symbols in this section in files with the MH_DYLDLINK - /// flag. - | AttrStripStaticSyms = 0x20000000 - /// No dead stripping. - | AttrNoDeadStrip = 0x10000000 - /// Blocks are live if they reference live blocks. - | AttrLiveSupport = 0x08000000 - /// Used with i386 code stubs written on by dyld. - | AttrSelfModifyingCode = 0x04000000 - /// Debug section. - | AttrDebug = 0x02000000 - /// Section has external relocation entries. - | AttrExtReloc = 0x00000200 - /// Section has local relocation entries. - | AttrLocReloc = 0x00000100 - -/// Mach-O section. -type MachSection = { - /// Section name. - SecName: string - /// The name of the segment that should eventually contain this section. - SegName: string - /// The virtual memory address of this section. - SecAddr: Addr - /// The size of this section. - SecSize: uint64 - /// The offset to this section in the file. - SecOffset: uint32 - /// The section’s byte alignment. - SecAlignment: uint32 - /// The file offset of the first relocation entry for this section. - SecRelOff: uint32 - /// The number of relocation entries located at SecRelOff for this section. - SecNumOfReloc: int - /// Section type. - SecType: SectionType - /// Section attributes. - SecAttrib: SectionAttribute - /// Reserved field 1. - SecReserved1: int - /// Reserved field 2. - SecReserved2: int -} - -/// Section information. -type SectionInfo = { - SecByAddr: ARMap - SecByName: Map - SecByNum: MachSection [] -} - -/// Symbol type (N_TYPE). -type SymbolType = - /// The symbol is undefined. - | NUndef = 0x0 - /// The symbol is absolute. The linker does not update the value of an - /// absolute symbol. - | NAbs = 0x2 - /// The symbol is defined in the section number given in n_sect. - | NSect = 0xe - /// The symbol is undefined and the image is using a prebound value for the - /// symbol. - | NPreBnd = 0xc - /// The symbol is defined to be the same as another symbol. - | NIndirect = 0xa - /// Global symbol. - | NGSym = 0x20 - /// Procedure name (f77 kludge). - | NFName = 0x22 - /// Procedure. - | NFun = 0x24 - /// Static symbol. - | NStSym = 0x26 - /// .lcomm symbol. - | NLCSym = 0x28 - /// Begin nsect sym. - | NBnSym = 0x2e - /// AST file path. - | NAST = 0x32 - /// Emitted with gcc2_compiled and in gcc source. - | NOpt = 0x3c - /// Register sym. - | NRSym = 0x40 - /// Source line. - | NSLine = 0x44 - /// End nsect sym. - | NEnSym = 0x4e - /// Structure element. - | NSSym = 0x60 - /// Source file name. - | NSO = 0x64 - /// Object file name. - | NOSO = 0x66 - /// Local symbol. - | NLSym = 0x80 - /// Include file beginning. - | NBIncl = 0x82 - /// "#included" file name: name,,n_sect,0,address. - | NSOL = 0x84 - /// Compiler parameters. - | NParams = 0x86 - /// Compiler version. - | NVersion = 0x88 - /// Compiler optimization level. - | NOLevel = 0x8a - /// Parameter. - | NPSym = 0xa0 - /// Include file end. - | NEIncl = 0xa2 - /// Alternate entry. - | NEntry = 0xa4 - /// Left bracket. - | NLBrac = 0xc0 - /// Deleted include file. - | NExcl = 0xc2 - /// Right bracket. - | NRBrac = 0xe0 - /// Begin common. - | NBComm = 0xe2 - /// End common. - | NEComm = 0xe4 - /// End common (local name). - | NEComL = 0xe8 - /// Second stab entry with length information. - | NLeng = 0xfe - /// Global pascal symbol. - | NPC = 0x30 - -/// Mach-O symbol. -type MachSymbol = { - /// Symbol name. - SymName: string - /// Symbol type (N_TYPE field of n_type). - SymType: SymbolType - /// Is this an external symbol? - IsExternal: bool - /// The number of the section that this symbol can be found. - SecNum: int - /// Providing additional information about the nature of this symbol for - /// non-stab symbols. - SymDesc: int16 - /// External library version info. - VerInfo: DyLibCmd option - /// Address of the symbol. - SymAddr: Addr -} - -/// Export info. -type ExportInfo = { - /// Symbol name. - ExportSymName: string - /// Exported symbol address. - ExportAddr: Addr -} - -type RelocSymbol = - | SymIndex of int (* Symbol table index *) - | SecOrdinal of int (* Section number *) - -/// Reloc info. -type RelocationInfo = { - /// Offset in the section to what is being relocated. - RelocAddr: int - /// RelocSymbol - RelocSymbol: RelocSymbol - /// Relocation length. - RelocLength: RegType - /// Parent section - RelocSection: MachSection - /// Is this address part of an instruction that uses PC-relative addressing? - IsPCRel: bool -} - -/// Symbol info -type SymInfo = { - /// All symbols. - Symbols: MachSymbol [] - /// Address to symbol mapping. - SymbolMap: Map - /// Linkage table. - LinkageTable: LinkageTableEntry list - /// Export info. - Exports: ExportInfo list -} - -/// Main Mach-o file structure. -type Mach = { - /// Entry point. - EntryPoint: Addr option - /// Preferred base address. - BaseAddr: Addr - /// Header. - MachHdr: MachHeader - /// Segments. - Segments: SegCmd list - /// Segment address map. - SegmentMap: ARMap - /// Sections. - Sections: SectionInfo - /// Load Commands - Cmds: LoadCommand list - /// Symbol info. - SymInfo: SymInfo - /// Text section index. - SecText: int - /// Relocation information. - Relocations: Symbol [] - /// Invalid address ranges. - InvalidAddrRanges: IntervalSet - /// Not-in-file address ranges. - NotInFileRanges: IntervalSet - /// Executable address ranges. - ExecutableRanges: IntervalSet - /// BinReader. - BinReader: IBinReader -} \ No newline at end of file diff --git a/src/FrontEnd/BinFile/PE.fs b/src/FrontEnd/BinFile/PE.fs deleted file mode 100644 index eab48d47..00000000 --- a/src/FrontEnd/BinFile/PE.fs +++ /dev/null @@ -1,83 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.PE.Helper - -/// -/// This class represents a PE binary file. -/// -type PEFileInfo (bytes, path, baseAddr, rawpdb) = - inherit FileInfo () - let pe = PE.Parser.parse bytes path baseAddr rawpdb - let isa = getISA pe - - new (bytes, path) = PEFileInfo (bytes, path, None, [||]) - new (bytes, path, baseAddr) = PEFileInfo (bytes, path, baseAddr, [||]) - new (bytes, path, rawpdb) = PEFileInfo (bytes, path, None, rawpdb) - - override __.Span = ReadOnlySpan bytes - override __.FileFormat = FileFormat.PEBinary - override __.ISA = isa - override __.FileType = getFileType pe - override __.FilePath = path - override __.WordSize = getWordSize pe - override __.IsStripped = Array.length pe.SymbolInfo.SymbolArray = 0 - override __.IsNXEnabled = isNXEnabled pe - override __.IsRelocatable = isRelocatable pe - override __.BaseAddress = pe.BaseAddr - override __.EntryPoint = getEntryPoint pe - override __.TextStartAddr = getTextStartAddr pe - override __.TranslateAddress addr = translateAddr pe addr - override __.AddSymbol addr symbol = Utils.futureFeature () - override __.GetSymbols () = getSymbols pe - override __.GetStaticSymbols () = getStaticSymbols pe - override __.GetDynamicSymbols (?exc) = getDynamicSymbols pe exc - override __.GetRelocationSymbols () = getRelocationSymbols pe - override __.GetSections () = getSections pe - override __.GetSections (addr) = getSectionsByAddr pe addr - override __.GetSections (name) = getSectionsByName pe name - override __.GetTextSections () = getTextSections pe - override __.GetSegments (_isLoadable) = getSegments pe - override __.GetLinkageTableEntries () = getImportTable pe - override __.IsLinkageTable addr = isImportTable pe addr - override __.TryFindFunctionSymbolName (addr) = tryFindFuncSymb pe addr - override __.ExceptionTable = ARMap.empty - override __.ToBinaryPointer addr = - BinaryPointer.OfSectionOpt (getSectionsByAddr pe addr |> Seq.tryHead) - override __.ToBinaryPointer name = - BinaryPointer.OfSectionOpt (getSectionsByName pe name |> Seq.tryHead) - override __.IsValidAddr addr = isValidAddr pe addr - override __.IsValidRange range = isValidRange pe range - override __.IsInFileAddr addr = isInFileAddr pe addr - override __.IsInFileRange range = isInFileRange pe range - override __.IsExecutableAddr addr = isExecutableAddr pe addr - override __.GetNotInFileIntervals range = getNotInFileIntervals pe range - member __.PE with get() = pe - member __.RawPDB = rawpdb - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinFile/PE/PEBinFile.fs b/src/FrontEnd/BinFile/PE/PEBinFile.fs new file mode 100644 index 00000000..155d4459 --- /dev/null +++ b/src/FrontEnd/BinFile/PE/PEBinFile.fs @@ -0,0 +1,171 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.PE +open B2R2.FrontEnd.BinFile.PE.Helper + +/// This class represents a PE binary file. +type PEBinFile (path, bytes: byte[], baseAddrOpt, rawpdb) = + let pe = Parser.parse path bytes baseAddrOpt rawpdb + + new (path, bytes) = PEBinFile (path, bytes, None, [||]) + + new (path, bytes, rawpdb) = PEBinFile (path, bytes, None, rawpdb) + + member __.PE with get() = pe + + member __.RawPDB = rawpdb + + interface IBinFile with + member __.Path with get() = path + + member __.Format with get() = FileFormat.PEBinary + + member __.ISA with get() = getISA pe + + member __.Type with get() = getFileType pe + + member __.EntryPoint = getEntryPoint pe + + member __.BaseAddress with get() = pe.BaseAddr + + member __.IsStripped = Array.isEmpty pe.SymbolInfo.SymbolArray + + member __.IsNXEnabled = isNXEnabled pe + + member __.IsRelocatable = isRelocatable pe + + member __.GetOffset addr = translateAddr pe addr + + member __.Slice (addr, size) = + let offset = translateAddr pe addr |> Convert.ToInt32 + (__ :> IBinFile).Slice (offset=offset, size=size) + + member __.Slice (addr) = + let offset = translateAddr pe addr |> Convert.ToInt32 + (__ :> IBinFile).Slice (offset=offset) + + member __.Slice (offset: int, size) = + ReadOnlySpan (bytes, offset, size) + + member __.Slice (offset: int) = + ReadOnlySpan(bytes).Slice offset + + member __.Slice (ptr: BinFilePointer, size) = + ReadOnlySpan (bytes, ptr.Offset, size) + + member __.Slice (ptr: BinFilePointer) = + ReadOnlySpan(bytes).Slice ptr.Offset + + member __.ReadByte (addr: Addr) = + let offset = translateAddr pe addr |> Convert.ToInt32 + bytes[offset] + + member __.ReadByte (offset: int) = + bytes[offset] + + member __.ReadByte (ptr: BinFilePointer) = + bytes[ptr.Offset] + + member __.IsValidAddr addr = isValidAddr pe addr + + member __.IsValidRange range = isValidRange pe range + + member __.IsInFileAddr addr = isInFileAddr pe addr + + member __.IsInFileRange range = isInFileRange pe range + + member __.IsExecutableAddr addr = isExecutableAddr pe addr + + member __.GetNotInFileIntervals range = getNotInFileIntervals pe range + + member __.ToBinFilePointer addr = + BinFilePointer.OfSectionOpt (getSectionsByAddr pe addr |> Seq.tryHead) + + member __.ToBinFilePointer name = + BinFilePointer.OfSectionOpt (getSectionsByName pe name |> Seq.tryHead) + + member __.GetRelocatedAddr _relocAddr = Utils.futureFeature () + + member __.TryFindFunctionName (addr) = tryFindFuncSymb pe addr + + member __.GetSymbols () = getSymbols pe + + member __.GetStaticSymbols () = getStaticSymbols pe + + member __.GetFunctionSymbols () = + let self = __ :> IBinFile + let staticSymbols = + self.GetStaticSymbols () + |> Array.filter (fun s -> s.Kind = SymFunctionType) + let dynamicSymbols = + self.GetDynamicSymbols (true) + |> Array.filter (fun s -> s.Kind = SymFunctionType) + Array.append staticSymbols dynamicSymbols + + member __.GetDynamicSymbols (?exc) = getDynamicSymbols pe exc + + member __.GetRelocationSymbols () = getRelocationSymbols pe + + member __.AddSymbol _addr _symbol = Utils.futureFeature () + + member __.GetSections () = getSections pe + + member __.GetSections (addr) = getSectionsByAddr pe addr + + member __.GetSections (name) = getSectionsByName pe name + + member __.GetTextSection () = getTextSection pe + + member __.GetSegments (_isLoadable: bool) = getSegments pe + + member __.GetSegments (addr) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (addr >= s.Address) + && (addr < s.Address + uint64 s.Size)) + + member __.GetSegments (perm) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (s.Permission &&& perm = perm) && s.Size > 0u) + + member __.GetLinkageTableEntries () = getImportTable pe + + member __.IsLinkageTable addr = isImportTable pe addr + + member __.GetFunctionAddresses () = + (__ :> IBinFile).GetFunctionSymbols () + |> Array.map (fun s -> s.Address) + + member __.GetFunctionAddresses (_) = + (__ :> IBinFile).GetFunctionAddresses () + + member __.Reader with get() = pe.BinReader + + member __.RawBytes = bytes + + member __.Length = bytes.Length \ No newline at end of file diff --git a/src/FrontEnd/BinFile/PECoff.fs b/src/FrontEnd/BinFile/PE/PECoff.fs similarity index 89% rename from src/FrontEnd/BinFile/PECoff.fs rename to src/FrontEnd/BinFile/PE/PECoff.fs index a1181d6f..b4f0d81d 100644 --- a/src/FrontEnd/BinFile/PECoff.fs +++ b/src/FrontEnd/BinFile/PE/PECoff.fs @@ -25,7 +25,7 @@ module internal B2R2.FrontEnd.BinFile.PE.Coff open System -open System.Collections.Generic +open System.IO open System.Reflection.PortableExecutable open System.Runtime.InteropServices open B2R2 @@ -99,7 +99,7 @@ let getWordSize = function | _ -> WordSize.Bit32 let parseLongSymbolName (span: ByteSpan) stroff offset = - peekCString span (stroff + offset) + readCString span (stroff + offset) let parseSymbName (span: ByteSpan) offset stroff = let bs = span.Slice (offset, 8) @@ -140,26 +140,27 @@ let buildSymbolMaps arr = Map.add symb.Name symb byName ) (Map.empty, Map.empty) -let getSymbols (span: ByteSpan) reader (coff: CoffHeader) = +let getSymbols bytes reader (coff: CoffHeader) = let maxCnt = coff.NumberOfSymbols - 1 - let tbloff = coff.PointerToSymbolTable - let stroff = tbloff + coff.NumberOfSymbols * 18 - let symbs = List () + let tblOff = coff.PointerToSymbolTable + let strOff = tblOff + coff.NumberOfSymbols * 18 + let symbs = Array.zeroCreate coff.NumberOfSymbols + let span = ReadOnlySpan (bytes, tblOff, coff.NumberOfSymbols * 18) let mutable auxcnt = 0 - let mutable cnt = if tbloff = 0 then maxCnt else 0 + let mutable cnt = if tblOff = 0 then maxCnt else 0 while cnt < maxCnt do if auxcnt > 0 then (* TODO *) auxcnt <- auxcnt - 1 cnt <- cnt + 1 else - let offset = tbloff + cnt * 18 - let name = parseSymbName span offset stroff + let offset = tblOff + cnt * 18 + let name = parseSymbName span offset strOff let v = (reader: IBinReader).ReadInt32 (span, offset + 8) let secnum = reader.ReadInt16 (span, offset + 12) |> int let typ = reader.ReadInt16 (span, offset + 14) |> parseSymType - let storage = reader.ReadByte (span, offset + 16) |> parseStorageClass - symbs.Add (getCoffSymbol name v secnum typ storage) - auxcnt <- reader.ReadByte (span, offset + 17) |> int + let storage = span[offset + 16] |> parseStorageClass + symbs[cnt] <- getCoffSymbol name v secnum typ storage + auxcnt <- span[offset + 17] |> int cnt <- cnt + 1 Seq.choose toPESymbol symbs |> fun lst -> diff --git a/src/FrontEnd/BinFile/PEHelper.fs b/src/FrontEnd/BinFile/PE/PEHelper.fs similarity index 81% rename from src/FrontEnd/BinFile/PEHelper.fs rename to src/FrontEnd/BinFile/PE/PEHelper.fs index 81d40d62..cdb31076 100644 --- a/src/FrontEnd/BinFile/PEHelper.fs +++ b/src/FrontEnd/BinFile/PE/PEHelper.fs @@ -25,12 +25,13 @@ module internal B2R2.FrontEnd.BinFile.PE.Helper open System +open System.IO open B2R2 open B2R2.Monads open B2R2.FrontEnd.BinFile open System.Reflection.PortableExecutable -let [] secText = ".text" +let [] SecText = ".text" let getFileType pe = let c = pe.PEHeaders.CoffHeader.Characteristics @@ -38,18 +39,6 @@ let getFileType pe = elif c.HasFlag Characteristics.ExecutableImage then FileType.ExecutableFile else FileType.ObjFile -let getWordSize pe = - if isNull pe.PEHeaders.PEHeader then - match pe.PEHeaders.CoffHeader.Machine with - | Machine.I386 | Machine.Arm -> WordSize.Bit32 - | Machine.Amd64 | Machine.IA64 | Machine.Arm64 -> WordSize.Bit64 - | _ -> raise InvalidWordSizeException - else - match pe.PEHeaders.PEHeader.Magic with - | PEMagic.PE32 -> WordSize.Bit32 - | PEMagic.PE32Plus -> WordSize.Bit64 - | _ -> raise InvalidWordSizeException - let isNXEnabled pe = let hdrs = pe.PEHeaders if hdrs.IsCoffOnly then false @@ -88,20 +77,15 @@ let getVirtualSectionSize (sec: SectionHeader) = let secHdrToSection pe (sec: SectionHeader) = { Address = addrFromRVA pe.BaseAddr sec.VirtualAddress - FileOffset = uint64 sec.PointerToRawData + FileOffset = uint32 sec.PointerToRawData Kind = secFlagToSectionKind sec.SectionCharacteristics - Size = uint64 sec.SizeOfRawData + Size = uint32 sec.SizeOfRawData Name = sec.Name } let getSectionsByName pe name = match pe.SectionHeaders |> Seq.tryFind (fun sec -> sec.Name = name) with - | None -> Seq.empty - | Some sec -> secHdrToSection pe sec |> Seq.singleton - -let getTextStartAddr pe = - match getSectionsByName pe secText |> Seq.tryHead with - | None -> 0UL - | Some sec -> sec.Address + | None -> [||] + | Some sec -> [| secHdrToSection pe sec |] let inline translateAddr pe addr = let rva = int (addr - pe.BaseAddr) @@ -113,20 +97,19 @@ let inline translateAddr pe addr = let pdbTypeToSymbKind = function | SymFlags.Function -> SymFunctionType - | _ -> NoType + | _ -> SymNoType let pdbSymbolToSymbol (sym: PESymbol) = { Address = sym.Address Name = sym.Name Kind = pdbTypeToSymbKind sym.Flags - Target = TargetKind.StaticSymbol + Visibility = SymbolVisibility.StaticSymbol LibraryName = "" ArchOperationMode = ArchOperationMode.NoMode } let inline getStaticSymbols pe = pe.SymbolInfo.SymbolArray |> Array.map pdbSymbolToSymbol - |> Array.toSeq let getSymbolKindBySectionIndex pe idx = let ch = pe.SectionHeaders[idx].SectionCharacteristics @@ -140,14 +123,14 @@ let getImportSymbols pe = { Address = addrFromRVA pe.BaseAddr rva Name = "#" + ord.ToString() Kind = SymExternFunctionType - Target = TargetKind.DynamicSymbol + Visibility = SymbolVisibility.DynamicSymbol LibraryName = dllname ArchOperationMode = ArchOperationMode.NoMode } :: acc | ImportByName (_, funname, dllname) -> { Address = addrFromRVA pe.BaseAddr rva Name = funname Kind = SymExternFunctionType - Target = TargetKind.DynamicSymbol + Visibility = SymbolVisibility.DynamicSymbol LibraryName = dllname ArchOperationMode = ArchOperationMode.NoMode } :: acc pe.ImportMap @@ -159,14 +142,14 @@ let getExportSymbols pe = { Address = addr Name = name Kind = kind - Target = TargetKind.DynamicSymbol + Visibility = SymbolVisibility.DynamicSymbol LibraryName = "" ArchOperationMode = ArchOperationMode.NoMode } let makeForwardedExportSymbol name (fwdBin, fwdFunc) = { Address = 0UL Name = name Kind = SymForwardType (fwdBin, fwdFunc) - Target = TargetKind.DynamicSymbol + Visibility = SymbolVisibility.DynamicSymbol LibraryName = "" ArchOperationMode = ArchOperationMode.NoMode } let localExportFolder accSymbols addr names = @@ -181,48 +164,52 @@ let getExportSymbols pe = makeForwardedExportSymbol name (fwdBin, fwdFunc) :: accSymbols Map.fold localExportFolder [] pe.ExportMap |> Map.fold forwardedExportFolder <| pe.ForwardMap + |> List.toArray let getAllDynamicSymbols pe = let isym = getImportSymbols pe let esym = getExportSymbols pe - List.append isym esym + Seq.append isym esym + |> Seq.toArray let getDynamicSymbols pe excludeImported = let excludeImported = defaultArg excludeImported false - if excludeImported then getExportSymbols pe else getAllDynamicSymbols pe - |> List.toSeq + if excludeImported then getExportSymbols pe + else getAllDynamicSymbols pe let getSymbols pe = let s = getStaticSymbols pe let d = getAllDynamicSymbols pe - Seq.append s d + Array.append s d let getRelocationSymbols pe = pe.RelocBlocks |> Seq.collect (fun block -> - block.Entries |> Seq.map(fun entry -> (block, entry))) + block.Entries |> Seq.map (fun entry -> (block, entry))) |> Seq.map (fun (block, entry) -> { Address = uint64 (block.PageRVA + uint32 entry.Offset) Name = String.Empty - Kind = SymbolKind.NoType - Target = TargetKind.DynamicSymbol + Kind = SymNoType + Visibility = SymbolVisibility.DynamicSymbol LibraryName = String.Empty ArchOperationMode = ArchOperationMode.NoMode }) + |> Seq.toArray let getSections pe = pe.SectionHeaders |> Array.map (secHdrToSection pe) - |> Array.toSeq let getSectionsByAddr pe addr = let rva = int (addr - pe.BaseAddr) match pe.FindSectionIdxFromRVA rva with - | -1 -> Seq.empty + | -1 -> [||] | idx -> - pe.SectionHeaders[idx] |> secHdrToSection pe |> Seq.singleton + [| pe.SectionHeaders[idx] |> secHdrToSection pe |] -let getTextSections pe = - getSectionsByName pe secText +let getTextSection pe = + match pe.SectionHeaders |> Seq.tryFind (fun sec -> sec.Name = SecText) with + | Some sec -> secHdrToSection pe sec + | None -> raise SectionNotFoundException let getImportTable pe = pe.ImportMap @@ -239,7 +226,7 @@ let getImportTable pe = TrampolineAddress = 0UL TableAddress = addrFromRVA pe.BaseAddr addr } :: acc) [] |> List.sortBy (fun entry -> entry.TableAddress) - |> List.toSeq + |> List.toArray let isImportTable pe addr = let rva = int (addr - pe.BaseAddr) @@ -254,12 +241,12 @@ let getSecPermission (chr: SectionCharacteristics) = let getSegments pe = let secToSegment (sec: SectionHeader) = { Address = uint64 sec.VirtualAddress + pe.BaseAddr - Offset = uint64 sec.PointerToRawData - Size = getVirtualSectionSize sec |> uint64 - SizeInFile = uint64 sec.SizeOfRawData + Offset = uint32 sec.PointerToRawData + Size = getVirtualSectionSize sec |> uint32 + SizeInFile = uint32 sec.SizeOfRawData Permission = getSecPermission sec.SectionCharacteristics } pe.SectionHeaders - |> Seq.map secToSegment + |> Array.map secToSegment let private findSymFromIAT addr pe = let rva = int (addr - pe.BaseAddr) @@ -304,14 +291,14 @@ let inline isExecutableAddr pe addr = let inline getNotInFileIntervals pe range = IntervalSet.findAll range pe.NotInFileRanges - |> List.map (FileHelper.trimByRange range) - |> List.toSeq + |> List.toArray + |> Array.map range.Slice let machineToArch = function - | Machine.I386 -> Arch.IntelX86 - | Machine.Amd64 | Machine.IA64 -> Arch.IntelX64 - | Machine.Arm -> Arch.ARMv7 - | Machine.Arm64 -> Arch.AARCH64 + | Machine.I386 -> Architecture.IntelX86 + | Machine.Amd64 | Machine.IA64 -> Architecture.IntelX64 + | Machine.Arm -> Architecture.ARMv7 + | Machine.Arm64 -> Architecture.AARCH64 | _ -> raise InvalidISAException let peHeadersToArch (peHeaders: PEHeaders) = @@ -319,23 +306,22 @@ let peHeadersToArch (peHeaders: PEHeaders) = if isNull corHeader then peHeaders.CoffHeader.Machine |> machineToArch else - if corHeader.Flags = CorFlags.ILOnly then Arch.CILOnly + if corHeader.Flags = CorFlags.ILOnly then Architecture.CILOnly else match peHeaders.CoffHeader.Machine with - | Machine.I386 -> Arch.CILIntel32 - | Machine.Amd64 | Machine.IA64 -> Arch.CILIntel64 + | Machine.I386 -> Architecture.CILIntel32 + | Machine.Amd64 | Machine.IA64 -> Architecture.CILIntel64 | _ -> raise InvalidISAException /// Return Architecture from the PE header. If the given binary is invalid, /// return an Error. -let getPEArch bytes offset = +let getPEArch (bytes: byte[]) = try - let bs = Array.sub bytes offset (Array.length bytes - offset) - use stream = new IO.MemoryStream (bs) + use stream = new MemoryStream (bytes) use reader = new PEReader (stream, PEStreamOptions.Default) peHeadersToArch reader.PEHeaders |> Ok with _ -> - Error ErrorCase.InvalidFileFormat + Error ErrorCase.InvalidFormat let getISA pe = let arch = peHeadersToArch pe.PEHeaders diff --git a/src/FrontEnd/BinFile/PEPDB.fs b/src/FrontEnd/BinFile/PE/PEPDB.fs similarity index 97% rename from src/FrontEnd/BinFile/PEPDB.fs rename to src/FrontEnd/BinFile/PE/PEPDB.fs index 9ba1baec..4307d210 100644 --- a/src/FrontEnd/BinFile/PEPDB.fs +++ b/src/FrontEnd/BinFile/PE/PEPDB.fs @@ -60,8 +60,8 @@ let readStream (span: ByteSpan) reader blockSize blockMapAddrs = let mutable idx = 0 for blockMapAddr in blockMapAddrs do let offset = blockMapAddr * blockSize - let blk = (reader: IBinReader).ReadBytes (span, offset, blockSize) - Array.blit blk 0 buf (idx * blockSize) blockSize + let blk = span.Slice (offset, blockSize) + blk.CopyTo (buf.AsSpan (idx * blockSize)) idx <- idx + 1 buf @@ -125,13 +125,13 @@ let rec parseSymbolRecord (bs: byte[]) reader offset modules streamMap = { Flags = flg Address = reader.ReadUInt32 (sp, offset + 8) |> uint64 Segment = reader.ReadUInt16 (sp, offset + 12) - Name = peekCString sp (offset + 14) } |> Some + Name = readCString sp (offset + 14) } |> Some | SymType.SLPROC32 | SymType.SGPROC32 -> (* PROCSYM32 *) { Flags = SymFlags.Function Address = reader.ReadUInt32 (sp, offset + 32) |> uint64 Segment = reader.ReadUInt16 (sp, offset + 36) - Name = peekCString sp (offset + 39) } |> Some + Name = readCString sp (offset + 39) } |> Some | SymType.SPROCREF | SymType.SLPROCREF -> (* REFSYM2 *) let modnum = reader.ReadUInt16 (sp, offset + 12) |> int diff --git a/src/FrontEnd/BinFile/PEParser.fs b/src/FrontEnd/BinFile/PE/PEParser.fs similarity index 71% rename from src/FrontEnd/BinFile/PEParser.fs rename to src/FrontEnd/BinFile/PE/PEParser.fs index 3787d56a..e33ed416 100644 --- a/src/FrontEnd/BinFile/PEParser.fs +++ b/src/FrontEnd/BinFile/PE/PEParser.fs @@ -28,6 +28,7 @@ open System open System.Reflection.PortableExecutable open B2R2 open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.FileHelper open B2R2.FrontEnd.BinFile.PE.Helper /// This is equivalent to GetContainingSectionIndex function except that we are @@ -50,9 +51,9 @@ let getRawOffset secs rva = let sHdr = secs[idx] rva + sHdr.PointerToRawData - sHdr.VirtualAddress -let readStr secs (bs: byte[]) rva = +let readStr secs (bytes: byte[]) rva = if rva = 0 then "" - else FileHelper.peekCString (ReadOnlySpan bs) (getRawOffset secs rva) + else readCString (ReadOnlySpan bytes) (getRawOffset secs rva) let isNULLImportDir tbl = tbl.ImportLookupTableRVA = 0 @@ -65,103 +66,40 @@ let decodeForwardInfo (str: string) = let dllName, funcName = strInfo[0], strInfo[1] (dllName, funcName) -let readIDTEntry (bs: byte[]) (reader: IBinReader) secs pos = - { ImportLookupTableRVA = reader.ReadInt32 (bs, pos) - ForwarderChain = reader.ReadInt32 (bs, pos + 8) - ImportDLLName = reader.ReadInt32 (bs, pos + 12) |> readStr secs bs - ImportAddressTableRVA = reader.ReadInt32 (bs, pos + 16) - DelayLoad = false } - -let readDelayIDTEntry (bs: byte[]) (reader: IBinReader) secs pos = - { ImportLookupTableRVA = reader.ReadInt32 (bs, pos + 16) - ForwarderChain = 0 - ImportDLLName = reader.ReadInt32 (bs, pos + 4) |> readStr secs bs - ImportAddressTableRVA = reader.ReadInt32 (bs, pos + 12) - DelayLoad = true } - -let parseImportDirectoryTableAux bytes reader secs readFn nextPos = function - | 0 -> [||] - | rva -> - let rec loop acc pos = - let tbl = readFn bytes reader secs pos - if isNULLImportDir tbl then acc else loop (tbl :: acc) (nextPos pos) - getRawOffset secs rva |> loop [] |> List.rev |> List.toArray - -let parseImportDirectoryTable bytes reader (headers: PEHeaders) secs = - let nextPos pos = pos + 20 - headers.PEHeader.ImportTableDirectory.RelativeVirtualAddress - |> parseImportDirectoryTableAux bytes reader secs readIDTEntry nextPos - -let parseDelayImportDirectoryTable bytes reader (headers: PEHeaders) secs = - let nextPos pos = pos + 32 - headers.PEHeader.DelayImportTableDirectory.RelativeVirtualAddress - |> parseImportDirectoryTableAux bytes reader secs readDelayIDTEntry nextPos - -let parseILTEntry (bs: byte[]) (reader: IBinReader) secs idt mask rva = - let dllname = idt.ImportDLLName - if rva &&& mask <> 0UL then - ImportByOrdinal (uint16 rva |> int16, dllname) - else - let rva = 0x7fffffffUL &&& rva |> int - let hint = reader.ReadInt16 (bs, getRawOffset secs rva) - let funname = readStr secs bs (rva + 2) - ImportByName (hint, funname, dllname) - -let computeRVAMaskForILT wordSize = - if wordSize = WordSize.Bit32 then 0x80000000UL - else 0x8000000000000000UL +let readExportDirectoryTableEntry bytes (reader: IBinReader) tbl secs = + { ExportDLLName = readStr secs bytes (reader.ReadInt32 (span=tbl, offset=12)) + OrdinalBase = reader.ReadInt32 (tbl, 16) + AddressTableEntries = reader.ReadInt32 (tbl, 20) + NumNamePointers = reader.ReadInt32 (tbl, 24) + ExportAddressTableRVA = reader.ReadInt32 (tbl, 28) + NamePointerRVA = reader.ReadInt32 (tbl, 32) + OrdinalTableRVA = reader.ReadInt32 (tbl, 36) } -let parseILT (bs: byte[]) reader secs wordSize map idt = - let skip = if wordSize = WordSize.Bit32 then 4 else 8 - let mask = computeRVAMaskForILT wordSize - let rec loop map rvaOffset pos = - let rva = FileHelper.peekUIntOfType (ReadOnlySpan bs) reader wordSize pos - if rva = 0UL then map - else - let entry = parseILTEntry bs reader secs idt mask rva - let map = Map.add (idt.ImportAddressTableRVA + rvaOffset) entry map - loop map (rvaOffset + skip) (pos + skip) - if idt.ImportLookupTableRVA <> 0 then idt.ImportLookupTableRVA - else idt.ImportAddressTableRVA - |> getRawOffset secs - |> loop map 0 +let inline getEATEntry (lowerBound, upperBound) rva = + if rva < lowerBound || rva > upperBound then ExportRVA rva + else ForwarderRVA rva -let parseImports bs reader (headers: PEHeaders) secs wordSize = - let mainImportTable = parseImportDirectoryTable bs reader headers secs - let delayImportTable = parseDelayImportDirectoryTable bs reader headers secs - Array.append mainImportTable delayImportTable - |> Array.toList - |> List.fold (parseILT bs reader secs wordSize) Map.empty - -let readExportDirectoryTableEntry (bs: byte[]) (reader: IBinReader) secs pos = - { ExportDLLName = readStr secs bs (reader.ReadInt32 (bs, pos + 12)) - OrdinalBase = reader.ReadInt32 (bs, pos + 16) - AddressTableEntries = reader.ReadInt32 (bs, pos + 20) - NumNamePointers = reader.ReadInt32 (bs, pos + 24) - ExportAddressTableRVA = reader.ReadInt32 (bs, pos + 28) - NamePointerRVA = reader.ReadInt32 (bs, pos + 32) - OrdinalTableRVA = reader.ReadInt32 (bs, pos + 36) } - -let parseEAT (bs: byte[]) (reader: IBinReader) secs range edt = - let lowerbound, upperbound = range - let getEntry rva = - if rva < lowerbound || rva > upperbound then ExportRVA rva - else ForwarderRVA rva - let rec loop acc cnt pos = - if cnt = 0 then List.rev acc |> List.toArray - else let rva = reader.ReadInt32 (bs, pos) - loop (getEntry rva :: acc) (cnt - 1) (pos + 4) +let parseEAT bytes (reader: IBinReader) secs range edt = match edt.ExportAddressTableRVA with | 0 -> [||] - | rva -> getRawOffset secs rva |> loop [] edt.AddressTableEntries + | rva -> + let offset = getRawOffset secs rva + let span = ReadOnlySpan (bytes, offset, edt.AddressTableEntries * 4) + let addrTbl = Array.zeroCreate edt.AddressTableEntries + for i = 0 to edt.AddressTableEntries - 1 do + let rva = reader.ReadInt32 (span, i * 4) + addrTbl[i] <- getEATEntry range rva + addrTbl /// Parse Export Name Pointer Table (ENPT). -let parseENPT (bs: byte[]) (reader: IBinReader) secs edt = +let parseENPT (bytes: byte[]) (reader: IBinReader) secs edt = let rec loop acc cnt pos1 pos2 = if cnt = 0 then acc - else let str = readStr secs bs (reader.ReadInt32 (bs, pos1)) - let ord = reader.ReadInt16 (bs, pos2) - loop ((str, ord) :: acc) (cnt - 1) (pos1 + 4) (pos2 + 2) + else + let rva = reader.ReadInt32 (bytes, pos1) + let str = readStr secs bytes rva + let ord = reader.ReadInt16 (bytes, pos2) + loop ((str, ord) :: acc) (cnt - 1) (pos1 + 4) (pos2 + 2) if edt.NamePointerRVA = 0 then [] else let offset1 = edt.NamePointerRVA |> getRawOffset secs @@ -176,9 +114,9 @@ let private decideNameWithTable nameTbl ordBase idx = | None -> sprintf "#%d" (int16 idx + ordBase) // Exported with an ordinal. | Some (name, _) -> name // ENTP has a corresponding name for this entry. -let buildExportTable bs reader baseAddr secs range edt = - let addrTbl = parseEAT bs reader secs range edt - let nameTbl = parseENPT bs reader secs edt +let buildExportTable bytes reader baseAddr secs range edt = + let addrTbl = parseEAT bytes reader secs range edt + let nameTbl = parseENPT bytes reader secs edt let ordinalBase = int16 edt.OrdinalBase let folder (expMap, forwMap) idx = function | ExportRVA rva -> @@ -190,7 +128,7 @@ let buildExportTable bs reader baseAddr secs range edt = expMap, forwMap | ForwarderRVA rva -> let name = decideNameWithTable nameTbl ordinalBase idx - let forwardStr = readStr secs bs rva + let forwardStr = readStr secs bytes rva let forwardInfo = decodeForwardInfo forwardStr let forwMap = Map.add name forwardInfo forwMap expMap, forwMap @@ -202,26 +140,94 @@ let parseExports baseAddr bytes reader (headers: PEHeaders) secs = | rva -> let size = headers.PEHeader.ExportTableDirectory.Size let range = (rva, rva + size) - getRawOffset secs rva - |> readExportDirectoryTableEntry bytes reader secs + let offset = getRawOffset secs rva + let tbl = ReadOnlySpan (bytes, offset, size) + readExportDirectoryTableEntry bytes reader tbl secs |> buildExportTable bytes reader baseAddr secs range -let buildRelocBlock (bs: byte[]) (reader: IBinReader) headerOffset = - let blockSize = reader.ReadInt32 (bs, headerOffset + 4) +let readIDTEntry (bs: byte[]) (reader: IBinReader) secs pos = + { ImportLookupTableRVA = reader.ReadInt32 (bs, pos) + ForwarderChain = reader.ReadInt32 (bs, pos + 8) + ImportDLLName = reader.ReadInt32 (bs, pos + 12) |> readStr secs bs + ImportAddressTableRVA = reader.ReadInt32 (bs, pos + 16) + DelayLoad = false } + +let readDelayIDTEntry (bs: byte[]) (reader: IBinReader) secs pos = + { ImportLookupTableRVA = reader.ReadInt32 (bs, pos + 16) + ForwarderChain = 0 + ImportDLLName = reader.ReadInt32 (bs, pos + 4) |> readStr secs bs + ImportAddressTableRVA = reader.ReadInt32 (bs, pos + 12) + DelayLoad = true } + +let parseImportDirectoryTblAux bytes reader secs entrySize rva readFn = + if rva = 0 then [||] + else + let rec loop acc offset = + let tbl = readFn bytes reader secs offset + if isNULLImportDir tbl then acc + else loop (tbl :: acc) (offset + entrySize) + getRawOffset secs rva |> loop [] |> List.rev |> List.toArray + +let parseImportDirectoryTable bytes reader (headers: PEHeaders) secs = + let rva = headers.PEHeader.ImportTableDirectory.RelativeVirtualAddress + parseImportDirectoryTblAux bytes reader secs 20 rva readIDTEntry + +let parseDelayImportDirectoryTable bytes reader (headers: PEHeaders) secs = + let rva = headers.PEHeader.DelayImportTableDirectory.RelativeVirtualAddress + parseImportDirectoryTblAux bytes reader secs 32 rva readDelayIDTEntry + +let parseILTEntry (bytes: byte[]) (reader: IBinReader) secs idt mask rva = + let dllname = idt.ImportDLLName + if rva &&& mask <> 0UL then + ImportByOrdinal (uint16 rva |> int16, dllname) + else + let rva = 0x7fffffffUL &&& rva |> int + let hint = reader.ReadInt16 (bytes, getRawOffset secs rva) + let funname = readStr secs bytes (rva + 2) + ImportByName (hint, funname, dllname) + +let computeRVAMaskForILT wordSize = + if wordSize = WordSize.Bit32 then 0x80000000UL + else 0x8000000000000000UL + +let parseILT (bytes: byte[]) (reader: IBinReader) secs wordSize map idt = + let skip = if wordSize = WordSize.Bit32 then 4 else 8 + let mask = computeRVAMaskForILT wordSize + let rec loop map rvaOffset pos = + let rva = readUIntOfType (ReadOnlySpan bytes) reader wordSize pos + if rva = 0UL then map + else + let entry = parseILTEntry bytes reader secs idt mask rva + let map = Map.add (idt.ImportAddressTableRVA + rvaOffset) entry map + loop map (rvaOffset + skip) (pos + skip) + if idt.ImportLookupTableRVA <> 0 then idt.ImportLookupTableRVA + else idt.ImportAddressTableRVA + |> getRawOffset secs + |> loop map 0 + +let parseImports bytes reader (headers: PEHeaders) secs wordSize = + let mainImportTbl = parseImportDirectoryTable bytes reader headers secs + let delayImportTbl = parseDelayImportDirectoryTable bytes reader headers secs + Array.append mainImportTbl delayImportTbl + |> Array.toList + |> List.fold (parseILT bytes reader secs wordSize) Map.empty + +let buildRelocBlock (bytes: byte[]) (reader: IBinReader) headerOffset = + let blockSize = reader.ReadInt32 (bytes, headerOffset + 4) let upperBound = headerOffset + blockSize let rec parseBlock offset entries = if offset < upperBound then - let buffer = reader.ReadUInt16(bs, offset) + let buffer = reader.ReadUInt16 (bytes, offset) { Type = buffer >>> 12 |> int32 |> LanguagePrimitives.EnumOfValue; Offset = buffer &&& 0xFFFus }::entries |> parseBlock (offset + 2) else entries |> List.toArray - { PageRVA = reader.ReadUInt32 (bs, headerOffset) + { PageRVA = reader.ReadUInt32 (bytes, headerOffset) BlockSize = blockSize Entries = parseBlock (headerOffset + 8) List.empty } -let parseRelocation bs (reader: IBinReader) (headers: PEHeaders) secs = +let parseRelocation bytes (reader: IBinReader) (headers: PEHeaders) secs = let peHdr = headers.PEHeader match peHdr.BaseRelocationTableDirectory.RelativeVirtualAddress with | 0 -> List.empty @@ -230,7 +236,7 @@ let parseRelocation bs (reader: IBinReader) (headers: PEHeaders) secs = let upperBound = hdrOffset + peHdr.BaseRelocationTableDirectory.Size let rec parseRelocDirectory offset blks = if offset < upperBound then - let relocBlk = buildRelocBlock bs reader offset + let relocBlk = buildRelocBlock bytes reader offset parseRelocDirectory (offset + relocBlk.BlockSize) (relocBlk :: blks) else blks parseRelocDirectory hdrOffset List.empty @@ -243,7 +249,7 @@ let magicToWordSize = function let parsePDB reader (pdbBytes: byte[]) = let span = ReadOnlySpan pdbBytes if PDB.isPDBHeader span reader then () - else raise FileFormatMismatchException + else raise InvalidFileFormatException PDB.parse span reader let getPDBSymbols reader (execpath: string) = function @@ -282,8 +288,8 @@ let invRanges wordSize baseAddr secs getNextStartAddr = |> Array.fold (fun (set, saddr) s -> let myaddr = uint64 s.VirtualAddress + baseAddr let n = getNextStartAddr myaddr s - FileHelper.addInvRange set saddr myaddr, n) (IntervalSet.empty, 0UL) - |> FileHelper.addLastInvRange wordSize + addInvalidRange set saddr myaddr, n) (IntervalSet.empty, 0UL) + |> addLastInvalidRange wordSize let computeInvalidAddrRanges wordSize baseAddr secs = invRanges wordSize baseAddr secs (fun a s -> @@ -303,29 +309,9 @@ let execRanges baseAddr secs = IntervalSet.add (AddrRange (saddr, eaddr - 1UL)) set ) IntervalSet.empty -let parseImage execpath rawpdb baseAddr bytes reader (hdrs: PEHeaders) = - let wordSize = magicToWordSize hdrs.PEHeader.Magic - let baseAddr = defaultArg baseAddr hdrs.PEHeader.ImageBase - let secs = hdrs.SectionHeaders |> Seq.toArray - let exportMap, forwardMap = parseExports baseAddr bytes reader hdrs secs - { PEHeaders = hdrs - BaseAddr = baseAddr - SectionHeaders = secs - ImportMap= parseImports bytes reader hdrs secs wordSize - ExportMap = exportMap - ForwardMap = forwardMap - RelocBlocks = parseRelocation bytes reader hdrs secs - WordSize = wordSize - SymbolInfo = getPDBSymbols reader execpath rawpdb |> buildPDBInfo baseAddr secs - InvalidAddrRanges = computeInvalidAddrRanges wordSize baseAddr secs - NotInFileRanges = computeNotInFileRanges wordSize baseAddr secs - ExecutableRanges = execRanges baseAddr secs - FindSectionIdxFromRVA = findSectionIndex hdrs secs - BinReader = reader } - -let parseCoff baseAddr bytes reader (hdrs: PEHeaders) = +let parseCoff baseAddrOpt bytes reader (hdrs: PEHeaders) = let coff = hdrs.CoffHeader - let baseAddr = defaultArg baseAddr 0UL + let baseAddr = defaultArg baseAddrOpt 0UL let wordSize = Coff.getWordSize coff.Machine let secs = hdrs.SectionHeaders |> Seq.toArray let idx = secs |> Array.findIndex (fun s -> s.Name.StartsWith ".text") @@ -338,20 +324,41 @@ let parseCoff baseAddr bytes reader (hdrs: PEHeaders) = ForwardMap = Map.empty RelocBlocks = [] WordSize = wordSize - SymbolInfo = Coff.getSymbols (ReadOnlySpan bytes) reader coff + SymbolInfo = Coff.getSymbols bytes reader coff InvalidAddrRanges = IntervalSet.empty NotInFileRanges = IntervalSet.empty ExecutableRanges = execRanges baseAddr secs FindSectionIdxFromRVA = findSectionIdxFromRVA BinReader = reader } -let parsePE execpath baseAddr rawpdb bytes reader (peReader: PEReader) = +let parseImage execpath rawpdb baseAddr bytes reader (hdrs: PEHeaders) = + let wordSize = magicToWordSize hdrs.PEHeader.Magic + let baseAddr = defaultArg baseAddr hdrs.PEHeader.ImageBase + let secs = hdrs.SectionHeaders |> Seq.toArray + let exportMap, forwardMap = parseExports baseAddr bytes reader hdrs secs + { PEHeaders = hdrs + BaseAddr = baseAddr + SectionHeaders = secs + ImportMap = parseImports bytes reader hdrs secs wordSize + ExportMap = exportMap + ForwardMap = forwardMap + RelocBlocks = parseRelocation bytes reader hdrs secs + WordSize = wordSize + SymbolInfo = + getPDBSymbols reader execpath rawpdb |> buildPDBInfo baseAddr secs + InvalidAddrRanges = computeInvalidAddrRanges wordSize baseAddr secs + NotInFileRanges = computeNotInFileRanges wordSize baseAddr secs + ExecutableRanges = execRanges baseAddr secs + FindSectionIdxFromRVA = findSectionIndex hdrs secs + BinReader = reader } + +let parsePE execpath baseAddrOpt rawpdb bytes reader (peReader: PEReader) = let hdrs = peReader.PEHeaders - if hdrs.IsCoffOnly then parseCoff baseAddr bytes reader hdrs - else parseImage execpath rawpdb baseAddr bytes reader hdrs + if hdrs.IsCoffOnly then parseCoff baseAddrOpt bytes reader hdrs + else parseImage execpath rawpdb baseAddrOpt bytes reader hdrs -let parse (bytes: byte[]) execpath baseAddr rawpdb = - let reader = BinReader.binReaderLE +let parse execpath (bytes: byte[]) baseAddrOpt rawpdb = + let reader = BinReader.Init Endian.Little use stream = new IO.MemoryStream (bytes) use peReader = new PEReader (stream, PEStreamOptions.Default) - parsePE execpath baseAddr rawpdb bytes reader peReader + parsePE execpath baseAddrOpt rawpdb bytes reader peReader diff --git a/src/FrontEnd/BinFile/PETypes.fs b/src/FrontEnd/BinFile/PE/PETypes.fs similarity index 98% rename from src/FrontEnd/BinFile/PETypes.fs rename to src/FrontEnd/BinFile/PE/PETypes.fs index 8635c596..65bc245e 100644 --- a/src/FrontEnd/BinFile/PETypes.fs +++ b/src/FrontEnd/BinFile/PE/PETypes.fs @@ -222,8 +222,8 @@ type SymFlags = | Managed = 0b0100 | MSIL = 0b1000 -/// PE symbol. We separate B2R2.FrontEnd.BinFile.Symbol from format-specific symbol type -/// for ease of analysis. +/// PE symbol. We separate B2R2.FrontEnd.BinFile.Symbol from format-specific +/// symbol type for ease of analysis. type PESymbol = { Flags: SymFlags Address: Addr @@ -245,7 +245,7 @@ type PE = { /// Image base address. BaseAddr: Addr /// Section headers. - SectionHeaders: SectionHeader [] + SectionHeaders: SectionHeader[] /// RVA to import information. ImportMap: Map /// Address (VA) to exported function name. diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSParser.fsi b/src/FrontEnd/BinFile/Permission.fs similarity index 65% rename from src/FrontEnd/BinLifter/MIPS/MIPSParser.fsi rename to src/FrontEnd/BinFile/Permission.fs index c492982e..ae57372c 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSParser.fsi +++ b/src/FrontEnd/BinFile/Permission.fs @@ -22,20 +22,26 @@ SOFTWARE. *) -/// MIPS instruction parser. -module B2R2.FrontEnd.BinLifter.MIPS.Parser +namespace B2R2.FrontEnd.BinFile open System -open B2R2 - -/// Read in bytes and return a parsed instruction for MIPS. This function -/// returns MIPSInstruction, which is a specialized type for MIPS. If you want -/// to handle instructions in a platform-agnostic manner, you'd better use the -/// MIPS class. -val parse: - ByteSpan - -> IBinReader - -> Arch - -> WordSize - -> Addr - -> MIPSInstruction + +/// File permission. Each permission corresponds to a bit, and thus, multiple +/// permissions can be OR-ed. +[] +type Permission = + /// File is readable. + | Readable = 4 + /// File is writable. + | Writable = 2 + /// File is executable. + | Executable = 1 + +module Permission = + /// Permission to string. + [] + let toString (p: Permission) = + let r = if p.HasFlag Permission.Readable then "r" else "-" + let w = if p.HasFlag Permission.Writable then "w" else "-" + let x = if p.HasFlag Permission.Executable then "x" else "-" + r + w + x diff --git a/src/FrontEnd/BinFile/RawBinFile.fs b/src/FrontEnd/BinFile/RawBinFile.fs new file mode 100644 index 00000000..4421fd92 --- /dev/null +++ b/src/FrontEnd/BinFile/RawBinFile.fs @@ -0,0 +1,188 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open System +open System.Collections.Generic +open B2R2 + +/// This class represents a raw binary file (containing only binary code and +/// data without file format). +type RawBinFile (path, bytes: byte[], isa, baseAddrOpt) = + let size = bytes.Length + let baseAddr = defaultArg baseAddrOpt 0UL + let symbolMap = Dictionary () + let reader = BinReader.Init isa.Endian + + interface IBinFile with + member __.Path with get() = path + + member __.Format with get() = FileFormat.RawBinary + + member __.ISA with get() = isa + + member __.Type with get() = FileType.UnknownFile + + member __.EntryPoint = Some baseAddr + + member __.BaseAddress with get() = baseAddr + + member __.IsStripped = false + + member __.IsNXEnabled = false + + member __.IsRelocatable = false + + member __.GetOffset addr = Convert.ToInt32 (addr - baseAddr) + + member __.Slice (addr, size) = + let offset = (__ :> IContentAddressable).GetOffset addr + let span = ReadOnlySpan bytes + span.Slice (offset, size) + + member __.Slice (addr) = + let offset = (__ :> IContentAddressable).GetOffset addr + let span = ReadOnlySpan bytes + span.Slice offset + + member __.Slice (offset: int, size) = + let span = ReadOnlySpan bytes + span.Slice (offset, size) + + member __.Slice (offset: int) = + let span = ReadOnlySpan bytes + span.Slice offset + + member __.Slice (ptr: BinFilePointer, size) = + let span = ReadOnlySpan bytes + span.Slice (ptr.Offset, size) + + member __.Slice (ptr: BinFilePointer) = + let span = ReadOnlySpan bytes + span.Slice ptr.Offset + + member __.ReadByte (addr: Addr) = + let offset = (__ :> IContentAddressable).GetOffset addr + bytes[offset] + + member __.ReadByte (offset: int) = + bytes[offset] + + member __.ReadByte (ptr: BinFilePointer) = + bytes[ptr.Offset] + + member __.IsValidAddr addr = + addr >= baseAddr && addr < (baseAddr + uint64 size) + + member __.IsValidRange range = + (__ :> IContentAddressable).IsValidAddr range.Min + && (__ :> IContentAddressable).IsValidAddr range.Max + + member __.IsInFileAddr addr = + (__ :> IContentAddressable).IsValidAddr addr + + member __.IsInFileRange range = + (__ :> IContentAddressable).IsValidRange range + + member __.IsExecutableAddr addr = + (__ :> IContentAddressable).IsValidAddr addr + + member __.GetNotInFileIntervals range = + FileHelper.getNotInFileIntervals baseAddr (uint64 size) range + + member __.ToBinFilePointer addr = + if addr = baseAddr then BinFilePointer (baseAddr, 0, size - 1) + else BinFilePointer.Null + + member __.ToBinFilePointer (_name: string) = BinFilePointer.Null + + member __.GetRelocatedAddr _relocAddr = Utils.impossible () + + member __.TryFindFunctionName (_addr) = + if symbolMap.ContainsKey(_addr) then Ok symbolMap[_addr].Name + else Error ErrorCase.SymbolNotFound + + member __.GetSymbols () = + Seq.map (fun (KeyValue(k, v)) -> v) symbolMap |> Seq.toArray + + member __.GetStaticSymbols () = (__ :> IBinFile).GetSymbols () + + member __.GetFunctionSymbols () = (__ :> IBinFile).GetStaticSymbols () + + member __.GetDynamicSymbols (?_excludeImported) = [||] + + member __.GetRelocationSymbols () = [||] + + member __.AddSymbol addr symbol = symbolMap[addr] <- symbol + + member __.GetSections () = + [| { Address = baseAddr + FileOffset = 0u + Kind = SectionKind.ExecutableSection + Size = uint32 size + Name = "" } |] + + member __.GetSections (addr: Addr) = + if addr >= baseAddr && addr < (baseAddr + uint64 size) then + (__ :> IBinFile).GetSections () + else [||] + + member __.GetSections (_: string): Section[] = [||] + + member __.GetTextSection () = raise SectionNotFoundException + + member __.GetSegments (_isLoadable: bool) = + [| { Address = baseAddr + Offset = 0u + Size = uint32 size + SizeInFile = uint32 size + Permission = Permission.Readable ||| Permission.Executable } |] + + member __.GetSegments (addr: Addr) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (addr >= s.Address) + && (addr < s.Address + uint64 s.Size)) + + member __.GetSegments (perm: Permission) = + (__ :> IBinFile).GetSegments () + |> Array.filter (fun s -> (s.Permission &&& perm = perm) && s.Size > 0u) + + member __.GetLinkageTableEntries () = [||] + + member __.IsLinkageTable _ = false + + member __.GetFunctionAddresses () = + (__ :> IBinFile).GetFunctionSymbols () + |> Array.filter (fun s -> s.Kind = SymFunctionType) + |> Array.map (fun s -> s.Address) + + member __.GetFunctionAddresses (_) = + (__ :> IBinFile).GetFunctionAddresses () + + member __.Reader with get() = reader + + member __.RawBytes = bytes + + member __.Length = bytes.Length \ No newline at end of file diff --git a/src/FrontEnd/BinFile/RawBinary.fs b/src/FrontEnd/BinFile/RawBinary.fs deleted file mode 100644 index fb5fcf16..00000000 --- a/src/FrontEnd/BinFile/RawBinary.fs +++ /dev/null @@ -1,136 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open System.Collections.Generic -open B2R2 - -/// -/// This class represents a raw binary file (containing only binary code and -/// data without file format) -/// -type RawFileInfo (bytes: byte [], path, isa, baseAddr) = - inherit FileInfo () - let baseAddr = defaultArg baseAddr 0UL - let size = bytes.Length - let usize = uint64 size - - let symbolMap = Dictionary () - - override __.Span = ReadOnlySpan bytes - - override __.FileFormat = FileFormat.RawBinary - - override __.ISA = isa - - override __.FileType = FileType.UnknownFile - - override __.FilePath = path - - override __.WordSize = isa.WordSize - - override __.IsStripped = false - - override __.IsNXEnabled = false - - override __.IsRelocatable = false - - override __.BaseAddress = baseAddr - - override __.EntryPoint = Some baseAddr - - override __.TextStartAddr = baseAddr - - override __.TranslateAddress addr = System.Convert.ToInt32 (addr - baseAddr) - - override __.AddSymbol addr symbol = - symbolMap[addr] <- symbol - - override __.GetSymbols () = - Seq.map (fun (KeyValue(k, v)) -> v) symbolMap - - override __.GetStaticSymbols () = __.GetSymbols () - - override __.GetDynamicSymbols (?_excludeImported) = Seq.empty - - override __.GetRelocationSymbols () = Seq.empty - - override __.GetSections () = - Seq.singleton { Address = baseAddr - FileOffset = 0UL - Kind = SectionKind.ExecutableSection - Size = usize - Name = "" } - - override __.GetSections (addr: Addr) = - if addr >= baseAddr && addr < (baseAddr + usize) then - __.GetSections () - else - Seq.empty - - override __.GetSections (_: string): seq
= Seq.empty - - override __.GetTextSections () = Seq.empty - - override __.GetSegments (_isLoadable) = - Seq.singleton { Address = baseAddr - Offset = 0UL - Size = usize - SizeInFile = usize - Permission = Permission.Readable ||| Permission.Executable } - - override __.GetLinkageTableEntries () = Seq.empty - - override __.IsLinkageTable _ = false - - override __.TryFindFunctionSymbolName (_addr) = - if symbolMap.ContainsKey(_addr) then Ok symbolMap[_addr].Name - else Error ErrorCase.SymbolNotFound - - override __.ExceptionTable = ARMap.empty - - override __.ToBinaryPointer addr = - if addr = baseAddr then BinaryPointer (baseAddr, 0, size) - else BinaryPointer.Null - - override __.ToBinaryPointer (_name: string) = BinaryPointer.Null - - override __.IsValidAddr (addr) = - addr >= baseAddr && addr < (baseAddr + usize) - - override __.IsValidRange (range) = - __.IsValidAddr range.Min && __.IsValidAddr range.Max - - override __.IsInFileAddr (addr) = __.IsValidAddr (addr) - - override __.IsInFileRange range = __.IsValidRange range - - override __.IsExecutableAddr addr = __.IsValidAddr addr - - override __.GetNotInFileIntervals range = - FileHelper.getNotInFileIntervals baseAddr usize range - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMRegisterSet.fs b/src/FrontEnd/BinFile/Section.fs similarity index 55% rename from src/FrontEnd/BinLifter/EVM/EVMRegisterSet.fs rename to src/FrontEnd/BinFile/Section.fs index 34e2387e..9b04ec45 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMRegisterSet.fs +++ b/src/FrontEnd/BinFile/Section.fs @@ -22,40 +22,42 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.EVM +namespace B2R2.FrontEnd.BinFile open B2R2 -module private RegisterSetLiteral = - let [] ArrLen = 2 - -open RegisterSetLiteral - -type EVMRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = EVMRegisterSet (RegisterSet.MakeInternalBitArray ArrLen, Set.empty) - - override __.Tag = RegisterSetTag.EVM - - override __.ArrSize = ArrLen - - override __.New arr s = new EVMRegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | R.GAS -> 1 - | _ -> -1 - - override __.IndexToRegID index = - match index with - | 1 -> R.GAS |> Register.toRegID - | _ -> Utils.impossible () +/// Kinds of sections. +type SectionKind = + /// Executable section. + | ExecutableSection = 1 + /// Writable section. + | WritableSection = 2 + /// Linkage table, such as PLT, section. + | LinkageTableSection = 3 + /// Extra section. + | ExtraSection = 4 + +/// A section object defined in a file-format-agnostic way. A Section in B2R2 +/// should be located inside a segment. +type Section = { + /// Address of the section. + Address: Addr + /// File offset of the section. + FileOffset: uint32 + /// Section kind. + Kind: SectionKind + /// Size of the section. + Size: uint32 + /// Name of the section. + Name: string +} +with + /// Convert the section into an AddrRange based on its starting address and + /// the size. + member __.ToAddrRange () = + AddrRange (__.Address, __.Address + uint64 __.Size - 1UL) override __.ToString () = - sprintf "EVMReisterSet<%x, %x>" __.BitArray[0] __.BitArray[1] - -[] -module EVMRegisterSet = - let singleton rid = EVMRegisterSet().Add(rid) - let empty = EVMRegisterSet () :> RegisterSet + $"Section [{__.Name}] ({__.Kind}) \ + @ {__.Address:x}-{(__.Address + uint64 __.Size):x} \ + @ {__.FileOffset:x}" diff --git a/src/MiddleEnd/ControlFlowAnalysis/ICFGBuildable.fs b/src/FrontEnd/BinFile/Segment.fs similarity index 71% rename from src/MiddleEnd/ControlFlowAnalysis/ICFGBuildable.fs rename to src/FrontEnd/BinFile/Segment.fs index 326d0128..95eebd1e 100644 --- a/src/MiddleEnd/ControlFlowAnalysis/ICFGBuildable.fs +++ b/src/FrontEnd/BinFile/Segment.fs @@ -22,11 +22,22 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.ControlFlowAnalysis +namespace B2R2.FrontEnd.BinFile -/// The main interface for building a CFG. -type ICFGBuildable = - /// Update CFGs based on the given CFGEvents. This function will run our CFG - /// analysis by consuming the CFGEvents until there's no more event to - /// consume. When everything is done well, this function returns "Ok ()". - abstract Update: CFGEvents -> Result +open B2R2 + +/// A segment is a block of code/data that is loaded in the real memory at +/// runtime. A segment can contain multiple sections in it. +type Segment = { + /// Address of the segment. + Address: Addr + /// Offset in the file. + Offset: uint32 + /// Size of the segment. + Size: uint32 + /// Size of the corresponding segment in file. This can be smaller than + /// `Size` in which case the missing part is filled with zeros. + SizeInFile: uint32 + /// Permission of the segment. + Permission: Permission +} diff --git a/src/FrontEnd/BinFile/Symbol.fs b/src/FrontEnd/BinFile/Symbol.fs new file mode 100644 index 00000000..e9ec6d95 --- /dev/null +++ b/src/FrontEnd/BinFile/Symbol.fs @@ -0,0 +1,71 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open B2R2 + +/// Kinds of a symbol. +type SymbolKind = + /// The symbol type is not specified. + | SymNoType + /// The symbol is associated with a data object, such as a variable. + | SymObjectType + /// The symbol is associated with a general function. + | SymFunctionType + /// The symbol is associated with an external (imported) function. + | SymExternFunctionType + /// The symbol is associated with a trampoline instruction, such as PLT. + | SymTrampolineType + /// The symbol is associated with a section. + | SymSectionType + /// The symbol gives the name of the source file associated with the obj file. + | SymFileType + /// The symbol is associated with a forwarding entry. + | SymForwardType of bin: string * func: string + +/// Does the symbol need to be visible by external modules? +type SymbolVisibility = + /// Static symbols do not need to be visible by external modules, and can be + /// stripped off. + | StaticSymbol = 1 + /// Dynamic symbols cannot be stripped off. This should be visible to externs. + | DynamicSymbol = 2 + +/// A symbol object defined in a file-format-agnostic way. +type Symbol = { + /// Address of the symbol. + Address: Addr + /// Symbol name. + Name: string + /// Symbol kind. + Kind: SymbolKind + /// Symbol visibility (static or dynamic). + Visibility: SymbolVisibility + /// Corresponding library name. + LibraryName: string + /// Corresponding ArchOperationMode for this symbol, which is only meaningful + /// for ARM. + ArchOperationMode: ArchOperationMode +} diff --git a/src/FrontEnd/BinFile/Wasm.fs b/src/FrontEnd/BinFile/Wasm.fs deleted file mode 100644 index 12bbacc5..00000000 --- a/src/FrontEnd/BinFile/Wasm.fs +++ /dev/null @@ -1,82 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinFile - -open System -open B2R2 -open B2R2.FrontEnd.BinFile.Wasm -open B2R2.FrontEnd.BinFile.Wasm.Helper - -/// -/// This class represents a Web Assembly -/// (Wasm Module) binary file. -/// -type WasmFileInfo (bytes, path, baseAddr) = - inherit FileInfo () - let wm = Parser.parse bytes - let baseAddr = defaultArg baseAddr 0UL - - new (bytes, path) = WasmFileInfo (bytes, path, None) - override __.Span = ReadOnlySpan bytes - override __.FileFormat = FileFormat.WasmBinary - override __.ISA = defaultISA - override __.FileType = fileTypeOf wm - override __.FilePath = path - override __.WordSize = WordSize.Bit32 - override __.IsStripped = List.length wm.CustomSections = 0 - override __.IsNXEnabled = true - override __.IsRelocatable = false - override __.BaseAddress = baseAddr - override __.EntryPoint = entryPointOf wm - override __.TextStartAddr = textStartAddrOf wm - override __.TranslateAddress addr = int addr - override __.AddSymbol addr symbol = Utils.futureFeature () - override __.GetSymbols () = getSymbols wm - override __.GetStaticSymbols () = Seq.empty - override __.GetDynamicSymbols (?exc) = getDynamicSymbols wm exc - override __.GetRelocationSymbols () = Seq.empty - override __.GetSections () = getSections wm - override __.GetSections (addr) = getSectionsByAddr wm addr - override __.GetSections (name) = getSectionsByName wm name - override __.GetTextSections () = Utils.futureFeature () // FIXME - override __.GetSegments (_isLoadable) = Seq.empty - override __.GetLinkageTableEntries () = getImports wm - override __.IsLinkageTable _addr = Utils.futureFeature () // FIXME - override __.TryFindFunctionSymbolName (addr) = tryFindFunSymName wm addr - override __.ExceptionTable = ARMap.empty - override __.ToBinaryPointer addr = - BinaryPointer.OfSectionOpt (getSectionsByAddr wm addr |> Seq.tryHead) - override __.ToBinaryPointer name = - BinaryPointer.OfSectionOpt (getSectionsByName wm name |> Seq.tryHead) - override __.IsValidAddr (addr) = - addr >= 0UL && addr < (uint64 bytes.LongLength) - override __.IsValidRange range = - __.IsValidAddr range.Min && __.IsValidAddr range.Max - override __.IsInFileAddr addr = __.IsValidAddr addr - override __.IsInFileRange range = __.IsValidRange range - override __.IsExecutableAddr _addr = Utils.futureFeature () // FIXME - override __.GetNotInFileIntervals range = - FileHelper.getNotInFileIntervals 0UL (uint64 bytes.LongLength) range - member __.WASM with get() = wm diff --git a/src/FrontEnd/BinFile/Wasm/WasmBinFile.fs b/src/FrontEnd/BinFile/Wasm/WasmBinFile.fs new file mode 100644 index 00000000..ef0f6dbf --- /dev/null +++ b/src/FrontEnd/BinFile/Wasm/WasmBinFile.fs @@ -0,0 +1,171 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinFile + +open System +open B2R2 +open B2R2.FrontEnd.BinFile.Wasm +open B2R2.FrontEnd.BinFile.Wasm.Helper + +/// This class represents a Web Assembly (Wasm Module) binary file. +type WasmBinFile (path, bytes, baseAddrOpt) = + let wm = Parser.parse bytes + let baseAddr = defaultArg baseAddrOpt 0UL + let reader = BinReader.Init Endian.Little + + new (path, bytes) = WasmBinFile (path, bytes, None) + + member __.WASM with get() = wm + + interface IBinFile with + member __.Path with get() = path + + member __.Format with get() = FileFormat.WasmBinary + + member __.ISA with get() = defaultISA + + member __.Type with get() = fileTypeOf wm + + member __.EntryPoint = entryPointOf wm + + member __.BaseAddress with get() = baseAddr + + member __.IsStripped = List.isEmpty wm.CustomSections + + member __.IsNXEnabled = true + + member __.IsRelocatable = false + + member __.GetOffset addr = int addr + + member __.Slice (addr: Addr, size) = + let span = ReadOnlySpan bytes + span.Slice (int addr, size) + + member __.Slice (addr: Addr) = + let span = ReadOnlySpan bytes + span.Slice (int addr) + + member __.Slice (offset: int, size) = + let span = ReadOnlySpan bytes + span.Slice (offset, size) + + member __.Slice (offset: int) = + let span = ReadOnlySpan bytes + span.Slice offset + + member __.Slice (ptr: BinFilePointer, size) = + let span = ReadOnlySpan bytes + span.Slice (ptr.Offset, size) + + member __.Slice (ptr: BinFilePointer) = + let span = ReadOnlySpan bytes + span.Slice ptr.Offset + + member __.ReadByte (addr: Addr) = + let offset = (__ :> IContentAddressable).GetOffset addr + bytes[offset] + + member __.ReadByte (offset: int) = + bytes[offset] + + member __.ReadByte (ptr: BinFilePointer) = + bytes[ptr.Offset] + + member __.IsValidAddr (addr) = + addr >= 0UL && addr < (uint64 bytes.LongLength) + + member __.IsValidRange range = + (__ :> IContentAddressable).IsValidAddr range.Min + && (__ :> IContentAddressable).IsValidAddr range.Max + + member __.IsInFileAddr addr = + (__ :> IContentAddressable).IsValidAddr addr + + member __.IsInFileRange range = + (__ :> IContentAddressable).IsValidRange range + + member __.IsExecutableAddr _addr = Utils.futureFeature () + + member __.GetNotInFileIntervals range = + FileHelper.getNotInFileIntervals 0UL (uint64 bytes.LongLength) range + + member __.ToBinFilePointer addr = + BinFilePointer.OfSectionOpt (getSectionsByAddr wm addr |> Seq.tryHead) + + member __.ToBinFilePointer name = + BinFilePointer.OfSectionOpt (getSectionsByName wm name |> Seq.tryHead) + + member __.GetRelocatedAddr _relocAddr = Utils.futureFeature () + + member __.TryFindFunctionName (addr) = tryFindFunSymName wm addr + + member __.GetSymbols () = getSymbols wm + + member __.GetStaticSymbols () = [||] + + member __.GetFunctionSymbols () = Utils.futureFeature () + + member __.GetDynamicSymbols (?exc) = getDynamicSymbols wm exc + + member __.GetRelocationSymbols () = [||] + + member __.AddSymbol _addr _symbol = Utils.futureFeature () + + member __.GetSections () = getSections wm + + member __.GetSections (addr) = getSectionsByAddr wm addr + + member __.GetSections (name) = getSectionsByName wm name + + member __.GetTextSection () = + wm.CodeSection + |> Option.map (fun sec -> + { Address = uint64 sec.Offset + FileOffset = uint32 sec.Offset + Kind = sectionIdToKind SectionId.Code + Size = sec.Size + Name = "" }) + |> function Some s -> s | None -> raise SectionNotFoundException + + member __.GetSegments (_isLoadable: bool): Segment[] = [||] + + member __.GetSegments (_addr: Addr): Segment[] = [||] + + member __.GetSegments (_perm: Permission): Segment[] = [||] + + member __.GetLinkageTableEntries () = getImports wm + + member __.IsLinkageTable _addr = Utils.futureFeature () + + member __.GetFunctionAddresses () = Utils.futureFeature () + + member __.GetFunctionAddresses (_) = Utils.futureFeature () + + member __.Reader with get() = reader + + member __.RawBytes = bytes + + member __.Length = bytes.Length \ No newline at end of file diff --git a/src/FrontEnd/BinFile/WasmExpression.fs b/src/FrontEnd/BinFile/Wasm/WasmExpression.fs similarity index 87% rename from src/FrontEnd/BinFile/WasmExpression.fs rename to src/FrontEnd/BinFile/Wasm/WasmExpression.fs index 1799c568..0ab252c2 100644 --- a/src/FrontEnd/BinFile/WasmExpression.fs +++ b/src/FrontEnd/BinFile/Wasm/WasmExpression.fs @@ -34,18 +34,18 @@ let peekConstExpr (span: ByteSpan) (reader: IBinReader) offset = |> LanguagePrimitives.EnumOfValue let offset' = offset + 1 match evt with - | ConstExprValueType.i32 -> + | ConstExprValueType.I32 -> let v, len = reader.ReadUInt32LEB128 (span, offset') I32 (v), offset' + len + 1 - | ConstExprValueType.i64 -> + | ConstExprValueType.I64 -> let v, len = reader.ReadUInt64LEB128 (span, offset') I64 (v), offset' + len + 1 - | ConstExprValueType.f32 -> - let b = reader.ReadBytes (span, offset', 4) + | ConstExprValueType.F32 -> + let b = span.Slice(offset', 4).ToArray () let v = BitConverter.ToSingle (b, 0) F32 (v), offset' + 4 + 1 - | ConstExprValueType.f64 -> - let b = reader.ReadBytes (span, offset', 8) + | ConstExprValueType.F64 -> + let b = span.Slice(offset', 8).ToArray () let v = BitConverter.ToDouble (b, 0) F64 (v), offset' + 8 + 1 - | _ -> raise InvalidFileTypeException \ No newline at end of file + | _ -> raise InvalidFileFormatException \ No newline at end of file diff --git a/src/FrontEnd/BinFile/WasmHeader.fs b/src/FrontEnd/BinFile/Wasm/WasmHeader.fs similarity index 91% rename from src/FrontEnd/BinFile/WasmHeader.fs rename to src/FrontEnd/BinFile/Wasm/WasmHeader.fs index 93e913b7..81d8ebe7 100644 --- a/src/FrontEnd/BinFile/WasmHeader.fs +++ b/src/FrontEnd/BinFile/Wasm/WasmHeader.fs @@ -24,13 +24,12 @@ module internal B2R2.FrontEnd.BinFile.Wasm.Header -open System open B2R2 let wasmMagic = 0x6D736100u -let isWasm (span: ByteSpan) (reader: IBinReader) = - if span.Length >= 8 then reader.ReadUInt32 (span, 0) = wasmMagic +let isWasm (bytes: byte[]) (reader: IBinReader) = + if bytes.Length >= 8 then reader.ReadUInt32 (bytes, 0) = wasmMagic else false let peekFormatVersion (span: ByteSpan) (reader: IBinReader) offset = diff --git a/src/FrontEnd/BinFile/WasmHelper.fs b/src/FrontEnd/BinFile/Wasm/WasmHelper.fs similarity index 81% rename from src/FrontEnd/BinFile/WasmHelper.fs rename to src/FrontEnd/BinFile/Wasm/WasmHelper.fs index aae9cb1f..aff4c3c0 100644 --- a/src/FrontEnd/BinFile/WasmHelper.fs +++ b/src/FrontEnd/BinFile/Wasm/WasmHelper.fs @@ -51,12 +51,6 @@ let entryPointOf wm = | None -> None | None -> None -let textStartAddrOf wm = - match wm.CodeSection with - | Some cs -> - uint64 cs.Offset - | None -> 0UL - let importDescToSymKind desc = match desc with | ImpFunc _ -> SymExternFunctionType @@ -68,7 +62,7 @@ let importEntryToSymbol (importEntry: Import) = { Address = uint64 importEntry.Offset Name = importEntry.Name Kind = importDescToSymKind importEntry.Desc - Target = TargetKind.DynamicSymbol + Visibility = SymbolVisibility.DynamicSymbol LibraryName = importEntry.ModuleName ArchOperationMode = ArchOperationMode.NoMode } @@ -83,7 +77,7 @@ let exportEntryToSymbol (exportEntry: Export) = { Address = uint64 exportEntry.Offset Name = exportEntry.Name Kind = exportDescToSymKind exportEntry.Desc - Target = TargetKind.DynamicSymbol + Visibility = SymbolVisibility.DynamicSymbol LibraryName = "" ArchOperationMode = ArchOperationMode.NoMode } @@ -94,9 +88,7 @@ let getDynamicSymbols wm excludeImported = match wm.ImportSection with | Some is -> match is.Contents with - | Some iv -> - iv.Elements - |> Array.map (fun ie -> importEntryToSymbol ie) + | Some iv -> iv.Elements |> Array.map importEntryToSymbol | None -> [||] | None -> [||] else [||] @@ -104,12 +96,10 @@ let getDynamicSymbols wm excludeImported = match wm.ExportSection with | Some es -> match es.Contents with - | Some ev -> - ev.Elements - |> Array.map (fun ee -> exportEntryToSymbol ee) + | Some ev -> ev.Elements |> Array.map exportEntryToSymbol | None -> [||] | None -> [||] - Seq.append imports exports + Array.append imports exports let getSymbols wm = getDynamicSymbols wm None @@ -124,33 +114,30 @@ let sectionIdToKind id = let secSummaryToGenericSection (secSumm: SectionSummary) = { Address = uint64 secSumm.Offset - FileOffset = uint64 secSumm.Offset + FileOffset = uint32 secSumm.Offset Kind = sectionIdToKind secSumm.Id - Size = uint64 (secSumm.HeaderSize + secSumm.ContentsSize) + Size = secSumm.HeaderSize + secSumm.ContentsSize Name = secSumm.Name } let getSections wm = wm.SectionsInfo.SecArray |> Array.map secSummaryToGenericSection - |> Array.toSeq let getSectionsByAddr wm addr = match ARMap.tryFindByAddr addr wm.SectionsInfo.SecByAddr with - | Some s -> secSummaryToGenericSection s |> Seq.singleton - | None -> Seq.empty + | Some s -> [| secSummaryToGenericSection s |] + | None -> [||] let getSectionsByName wm name = match Map.tryFind name wm.SectionsInfo.SecByName with - | Some s -> secSummaryToGenericSection s |> Seq.singleton - | None -> Seq.empty + | Some s -> [| secSummaryToGenericSection s |] + | None -> [||] let importToLinkageTableEntry (entry: Import) = - { - FuncName = entry.Name + { FuncName = entry.Name LibraryName = entry.ModuleName TrampolineAddress = 0UL - TableAddress = uint64 entry.Offset - } + TableAddress = uint64 entry.Offset } let getImports wm = match wm.ImportSection with @@ -158,16 +145,13 @@ let getImports wm = match sec.Contents with | Some conts -> conts.Elements - |> Array.filter - (fun ie -> + |> Array.filter (fun ie -> match ie.Desc with | ImpFunc _ -> true - | _ -> false - ) - |> Array.map (fun ie -> importToLinkageTableEntry ie) - |> Seq.ofArray - | None -> Seq.empty - | None -> Seq.empty + | _ -> false) + |> Array.map importToLinkageTableEntry + | None -> [||] + | None -> [||] let tryFindFunSymName wm addr = let sym = diff --git a/src/FrontEnd/BinFile/WasmParser.fs b/src/FrontEnd/BinFile/Wasm/WasmParser.fs similarity index 96% rename from src/FrontEnd/BinFile/WasmParser.fs rename to src/FrontEnd/BinFile/Wasm/WasmParser.fs index 3b023c54..9366f5fd 100644 --- a/src/FrontEnd/BinFile/WasmParser.fs +++ b/src/FrontEnd/BinFile/Wasm/WasmParser.fs @@ -24,10 +24,11 @@ module internal B2R2.FrontEnd.BinFile.Wasm.Parser +open System +open System.IO open B2R2 open B2R2.FrontEnd.BinFile open B2R2.FrontEnd.BinFile.Wasm.Section -open System let sectionIdToName (secId: SectionId) (off: int) = match secId with @@ -76,8 +77,7 @@ let private peekSecSummPair (secsSumm: SectionSummary list) = let validateSectionsOrder secsSummary = let rec validationLoop secsSumm isValid = - if List.length secsSumm = 0 - then isValid + if List.isEmpty secsSumm then isValid else let sec1, sec2, secsSumm' = peekSecSummPair secsSumm match sec2 with @@ -206,11 +206,11 @@ let private parseWasmModule (bs: byte[]) (reader: IBinReader) offset = let contOff = offset + 8 let secsSummary = summerizeSections bs reader contOff if not (validateSectionsOrder secsSummary) - then raise InvalidFileTypeException + then raise InvalidFileFormatException else let rec parsingLoop wasmModule info (secsSummary: SectionSummary list) = - if List.length secsSummary = 0 - then { wasmModule with SectionsInfo = info } + if List.isEmpty secsSummary then + { wasmModule with SectionsInfo = info } else let secSumm = List.head secsSummary let info' = @@ -329,13 +329,11 @@ let buildFuncIndexMap (wm: WasmModule) = other index maps maybe added in the future as needed. *) let buildModuleIndexMap wm = - { - wm with - IndexMap = buildFuncIndexMap wm - } + { wm with IndexMap = buildFuncIndexMap wm } let parse (bs: byte[]) = - if Header.isWasm (ReadOnlySpan bs) BinReader.binReaderLE then () - else raise FileFormatMismatchException - parseWasmModule bs BinReader.binReaderLE 0 + let reader = BinReader.Init Endian.Little + if Header.isWasm bs reader then () + else raise InvalidFileFormatException + parseWasmModule bs reader 0 |> buildModuleIndexMap \ No newline at end of file diff --git a/src/FrontEnd/BinFile/WasmSection.fs b/src/FrontEnd/BinFile/Wasm/WasmSection.fs similarity index 96% rename from src/FrontEnd/BinFile/WasmSection.fs rename to src/FrontEnd/BinFile/Wasm/WasmSection.fs index ff79af08..1656105f 100644 --- a/src/FrontEnd/BinFile/WasmSection.fs +++ b/src/FrontEnd/BinFile/Wasm/WasmSection.fs @@ -47,8 +47,8 @@ let peekVector bs (reader: IBinReader) offset pe = Size = size } let peekByteVector (bs: byte[]) reader offset = - let pb (bs: byte[]) (r: IBinReader) (o: int) = - r.ReadByte (bs, o), o + 1 + let pb (bs: byte[]) (_: IBinReader) (o: int) = + bs[o], o + 1 peekVector bs reader offset pb let peekName bs reader offset = @@ -125,7 +125,7 @@ let peekLimits (bs: byte[]) (reader: IBinReader) offset = let mn, mnLen = reader.ReadUInt32LEB128 (bs, offset') let mx, mxLen = reader.ReadUInt32LEB128 (bs, offset' + mnLen) MinMax (mn, mx), (offset' + mnLen + mxLen) - | _ -> raise InvalidFileTypeException + | _ -> raise InvalidFileFormatException let peekTableType (bs: byte[]) (reader: IBinReader) offset = let elemType = @@ -162,7 +162,7 @@ let peekImportDesc (bs: byte[]) (reader: IBinReader) offset = | ImportDescKind.Global -> let glob, size = peekGlobalType bs reader (offset + 1) ImpGlobal (glob), (offset + 1 + size) - | _ -> raise InvalidFileTypeException + | _ -> raise InvalidFileFormatException let peekImportEntry bs reader offset = let modName, rawLen = peekName bs reader offset @@ -228,7 +228,7 @@ let peekExportDesc (bs: byte[]) (reader: IBinReader) offset = | ExportDescKind.Global -> let globalIdx, len = reader.ReadUInt32LEB128 (bs, offset + 1) ExpGlobal (globalIdx), offset + 1 + len - | _ -> raise InvalidFileTypeException + | _ -> raise InvalidFileFormatException let peekExportEntry bs reader offset = let name, rawLen = peekName bs reader offset @@ -272,7 +272,7 @@ let rec parseLocalDecls (bs: byte[]) (reader: IBinReader) locals len pos = if len = 0 then locals else let localDeclCnt, rawLen = reader.ReadUInt32LEB128 (bs, pos) - let localDeclType = reader.ReadByte (bs, pos + rawLen) + let localDeclType = bs[pos + rawLen] let local = { LocalDeclCount = localDeclCnt; LocalDeclType = localDeclType; @@ -285,12 +285,10 @@ let peekCodeEntry (bs: byte[]) (reader: IBinReader) offset = let pos = offset + len let localsCnt, rawLen = reader.ReadUInt32LEB128 (bs, pos) let locals = parseLocalDecls bs reader [] (int localsCnt) (pos + rawLen) - { - Offset = offset + { Offset = offset LenFieldSize = len CodeSize = codeSize - Locals = locals - }, offset + len + int codeSize + Locals = locals }, offset + len + int codeSize let peekCodeSecContents bs reader offset = peekVector bs reader offset peekCodeEntry diff --git a/src/FrontEnd/BinFile/WasmTypes.fs b/src/FrontEnd/BinFile/Wasm/WasmTypes.fs similarity index 97% rename from src/FrontEnd/BinFile/WasmTypes.fs rename to src/FrontEnd/BinFile/Wasm/WasmTypes.fs index 0a9b5603..1aaba713 100644 --- a/src/FrontEnd/BinFile/WasmTypes.fs +++ b/src/FrontEnd/BinFile/Wasm/WasmTypes.fs @@ -37,16 +37,16 @@ type Vector<'TElement> = { } type ValueType = - | i32 = 0x7Fuy - | i64 = 0x7Euy - | f32 = 0x7Duy - | f64 = 0x7Cuy + | I32 = 0x7Fuy + | I64 = 0x7Euy + | F32 = 0x7Duy + | F64 = 0x7Cuy type ConstExprValueType = - | i32 = 0x41uy - | i64 = 0x42uy - | f32 = 0x43uy - | f64 = 0x44uy + | I32 = 0x41uy + | I64 = 0x42uy + | F32 = 0x43uy + | F64 = 0x44uy type ConstExpr = | I32 of uint32 diff --git a/src/FrontEnd/BinInterface/Basis.fs b/src/FrontEnd/BinInterface/Basis.fs deleted file mode 100644 index 73cfac23..00000000 --- a/src/FrontEnd/BinInterface/Basis.fs +++ /dev/null @@ -1,50 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -[] -module B2R2.FrontEnd.BinInterface.Basis - -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Establish the basis for lifting. This function returns a pair of -/// TranslationContext and RegisterBay. -[] -let init isa = - match isa.Arch with - | Arch.IntelX64 - | Arch.IntelX86 -> Intel.Basis.init isa - | Arch.ARMv7 | Arch.AARCH32 -> ARM32.Basis.init isa - | Arch.AARCH64 -> ARM64.Basis.init isa - | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 - | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 - | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> MIPS.Basis.init isa - | Arch.EVM -> EVM.Basis.init isa - | Arch.TMS320C6000 -> TMS320C6000.Basis.init isa - | Arch.CILOnly -> CIL.Basis.init isa - | Arch.AVR -> AVR.Basis.init isa - | Arch.SH4 -> SH4.Basis.init isa - | Arch.PPC32 -> PPC32.Basis.init isa - | Arch.RISCV64 -> RISCV.Basis.init isa - | _ -> Utils.futureFeature () diff --git a/src/FrontEnd/BinInterface/BinHandle.fs b/src/FrontEnd/BinInterface/BinHandle.fs deleted file mode 100644 index 32b07f46..00000000 --- a/src/FrontEnd/BinInterface/BinHandle.fs +++ /dev/null @@ -1,287 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinInterface - -open System -open B2R2 -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface.Helper - -type BinHandle = { - ISA: ISA - FileInfo: FileInfo - DisasmHelper: DisasmHelper - TranslationContext: TranslationContext - Parser: Parser - RegisterBay: RegisterBay - BinReader: IBinReader - OS: OS -} -with - static member private Init (isa, mode, autoDetect, baseAddr, bs, path, os) = - let struct (fmt, isa, os) = identifyFormatAndISAAndOS bs isa os autoDetect - let struct (ctxt, regbay) = Basis.init isa - let fi = newFileInfo bs baseAddr path fmt isa regbay - assert (isa = fi.ISA) - let parser = Parser.init isa mode fi.EntryPoint - { ISA = isa - FileInfo = fi - DisasmHelper = DisasmHelper (fi.TryFindFunctionSymbolName) - TranslationContext = ctxt - Parser = parser - RegisterBay = regbay - BinReader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - OS = os } - - static member Init (isa, archMode, autoDetect, baseAddr, bytes) = - BinHandle.Init (isa, archMode, autoDetect, baseAddr, bytes, "", None) - - static member Init (isa, archMode, autoDetect, baseAddr, fileName) = - let bytes = IO.File.ReadAllBytes fileName - let fileName = IO.Path.GetFullPath fileName - BinHandle.Init (isa, archMode, autoDetect, baseAddr, bytes, fileName, None) - - static member Init (isa, baseAddr, fileName) = - let bytes = IO.File.ReadAllBytes fileName - let fileName = IO.Path.GetFullPath fileName - let defaultMode = ArchOperationMode.NoMode - BinHandle.Init (isa, defaultMode, true, baseAddr, bytes, fileName, None) - - static member Init (isa, fileName) = - BinHandle.Init (isa=isa, baseAddr=None, fileName=fileName) - - static member Init (isa, baseAddr, bytes) = - let defaultMode = ArchOperationMode.NoMode - BinHandle.Init (isa, defaultMode, false, baseAddr, bytes, "", None) - - static member Init (isa, bytes) = - BinHandle.Init (isa=isa, baseAddr=None, bytes=bytes) - - static member Init (isa, archMode) = - BinHandle.Init (isa, archMode, false, None, [||], "", None) - - static member Init (isa, os) = - let defaultMode = ArchOperationMode.NoMode - BinHandle.Init (isa, defaultMode, false, None, [||], "", Some os) - - static member Init (isa: ISA) = BinHandle.Init (isa, ([||]: byte [])) - - static member UpdateCode hdl addr bs = - { hdl with FileInfo = RawFileInfo (bs, "", hdl.ISA, Some addr) :> FileInfo } - - static member private UpdateFileInfo h fi = - { h with FileInfo = fi } - - static member PatchCode hdl addr (bs: byte []) = - let fi = hdl.FileInfo - let idx = int <| addr - fi.BaseAddress - let lastIdx = idx + bs.Length - 1 - if fi.Span.Length <= idx || fi.Span.Length <= lastIdx then - Error ErrorCase.InvalidMemoryRead - else - let dup = fi.Span.ToArray () - Buffer.BlockCopy (bs, 0, dup, idx, bs.Length) - match fi with - | :? RawFileInfo -> - RawFileInfo (dup, fi.FilePath, fi.ISA, Some fi.BaseAddress) :> FileInfo - |> BinHandle.UpdateFileInfo hdl - |> Ok - | :? ELFFileInfo as fi -> - ELFFileInfo (dup, fi.FilePath, Some fi.BaseAddress, fi.RegisterBay) - :> FileInfo - |> BinHandle.UpdateFileInfo hdl - |> Ok - | :? MachFileInfo -> - MachFileInfo (dup, fi.FilePath, fi.ISA, Some fi.BaseAddress) :> FileInfo - |> BinHandle.UpdateFileInfo hdl - |> Ok - | :? PEFileInfo as fi -> - PEFileInfo (dup, fi.FilePath, Some fi.BaseAddress, fi.RawPDB) - :> FileInfo - |> BinHandle.UpdateFileInfo hdl - |> Ok - | :? WasmFileInfo -> - WasmFileInfo (dup, fi.FilePath, Some fi.BaseAddress) :> FileInfo - |> BinHandle.UpdateFileInfo hdl - |> Ok - | _ -> Error ErrorCase.InvalidFileFormat - - member __.ReadBytes (addr: Addr, nBytes) = - BinHandle.ReadBytes (__, addr, nBytes) - - member __.ReadBytes (bp: BinaryPointer, nBytes) = - BinHandle.ReadBytes (__, bp, nBytes) - - static member TryReadBytes ({ FileInfo = fi; BinReader = r }, addr, nBytes) = - let range = AddrRange (addr, addr + uint64 nBytes - 1UL) - if fi.IsInFileRange range then - r.ReadBytes (fi.Span, fi.TranslateAddress addr, nBytes) |> Ok - elif fi.IsValidRange range then - fi.GetNotInFileIntervals range - |> classifyRanges range - |> List.fold (fun bs (range, isInFile) -> - let len = (range.Max - range.Min |> int) + 1 - if isInFile then - let offset = fi.TranslateAddress range.Min - r.ReadBytes (fi.Span, offset, len) - |> Array.append bs - else Array.create len 0uy |> Array.append bs - ) [||] - |> Ok - else Error ErrorCase.InvalidMemoryRead - - static member TryReadBytes ({ FileInfo = fi; BinReader = r }, bp, nBytes) = - if BinaryPointer.IsValidAccess bp nBytes then - r.ReadBytes (fi.Span, bp.Offset, nBytes) |> Ok - else Error ErrorCase.InvalidMemoryRead - - static member ReadBytes (hdl, addr: Addr, nBytes) = - match BinHandle.TryReadBytes (hdl, addr, nBytes) with - | Ok bs -> bs - | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) - - static member ReadBytes (hdl, bp: BinaryPointer, nBytes) = - match BinHandle.TryReadBytes (hdl, bp, nBytes) with - | Ok bs -> bs - | Error e -> invalidArg (nameof bp) (ErrorCase.toString e) - - member __.ReadInt (addr: Addr, size) = - BinHandle.ReadInt (__, addr, size) - - member __.ReadInt (bp: BinaryPointer, size) = - BinHandle.ReadInt (__, bp, size) - - static member TryReadInt ({ FileInfo = fi; BinReader = r }, addr, size) = - let pos = fi.TranslateAddress addr - if (pos + size) > fi.Span.Length || (pos < 0) then - Error ErrorCase.InvalidMemoryRead - else readIntBySize r fi pos size - - static member TryReadInt ({ FileInfo = fi; BinReader = r }, bp, size) = - if BinaryPointer.IsValidAccess bp size then - readIntBySize r fi bp.Offset size - else Error ErrorCase.InvalidMemoryRead - - static member ReadInt (hdl, addr: Addr, size) = - match BinHandle.TryReadInt (hdl, addr, size) with - | Ok i -> i - | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) - - static member ReadInt (hdl, bp: BinaryPointer, size) = - match BinHandle.TryReadInt (hdl, bp, size) with - | Ok i -> i - | Error e -> invalidArg (nameof bp) (ErrorCase.toString e) - - member __.ReadUInt (addr: Addr, size) = - BinHandle.ReadUInt (__, addr, size) - - member __.ReadUInt (bp: BinaryPointer, size) = - BinHandle.ReadUInt (__, bp, size) - - static member TryReadUInt ({ FileInfo = fi; BinReader = r }, addr, size) = - let pos = fi.TranslateAddress addr - if (pos + size) > fi.Span.Length || (pos < 0) then - Error ErrorCase.InvalidMemoryRead - else readUIntBySize r fi pos size - - static member TryReadUInt ({ FileInfo = fi; BinReader = r }, bp, size) = - if BinaryPointer.IsValidAccess bp size then - readUIntBySize r fi bp.Offset size - else Error ErrorCase.InvalidMemoryRead - - static member ReadUInt (hdl, addr: Addr, size) = - match BinHandle.TryReadUInt (hdl, addr, size) with - | Ok i -> i - | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) - - static member ReadUInt (hdl, bp: BinaryPointer, size) = - match BinHandle.TryReadUInt (hdl, bp, size) with - | Ok i -> i - | Error e -> invalidArg (nameof bp) (ErrorCase.toString e) - - member __.ReadASCII (addr: Addr) = - BinHandle.ReadASCII (__, addr) - - member __.ReadASCII (bp: BinaryPointer) = - BinHandle.ReadASCII (__, bp) - - static member ReadASCII ({ FileInfo = fi }, addr) = - let bs = fi.TranslateAddress addr |> readASCII fi - ByteArray.extractCString bs 0 - - static member ReadASCII ({ FileInfo = fi }, bp: BinaryPointer) = - let bs = readASCII fi bp.Offset - ByteArray.extractCString bs 0 - - static member ParseInstr (hdl: BinHandle, addr) = - parseInstrFromAddr hdl.FileInfo hdl.Parser addr - - static member ParseInstr (hdl: BinHandle, bp: BinaryPointer) = - parseInstrFromBinPtr hdl.FileInfo hdl.Parser bp - - static member TryParseInstr (hdl, addr) = - tryParseInstrFromAddr hdl.FileInfo hdl.Parser addr - - static member TryParseInstr (hdl, bp: BinaryPointer) = - tryParseInstrFromBinPtr hdl.FileInfo hdl.Parser bp - - static member ParseBBlock (hdl, addr) = - parseBBLFromAddr hdl.FileInfo hdl.Parser addr - - static member ParseBBlock (hdl, bp) = - parseBBLFromBinPtr hdl.FileInfo hdl.Parser bp - - static member inline LiftInstr (hdl: BinHandle) (ins: Instruction) = - ins.Translate hdl.TranslationContext - - static member LiftOptimizedInstr hdl (ins: Instruction) = - BinHandle.LiftInstr hdl ins |> LocalOptimizer.Optimize - - static member LiftBBlock (hdl: BinHandle, addr: Addr) = - liftBBLFromAddr hdl.FileInfo hdl.Parser hdl.TranslationContext addr - - static member LiftBBlock (hdl: BinHandle, bp: BinaryPointer) = - liftBBLFromBinPtr hdl.FileInfo hdl.Parser hdl.TranslationContext bp - - static member inline DisasmInstr hdl showAddr resolveSymbol ins = - (ins: Instruction).Disasm (showAddr, resolveSymbol, hdl.DisasmHelper) - - static member inline DisasmInstrSimple (ins: Instruction) = - ins.Disasm () - - static member DisasmBBlock (hdl, showAddr, resolveSymbol, addr) = - disasmBBLFromAddr - hdl.FileInfo hdl.Parser hdl.DisasmHelper showAddr resolveSymbol addr - - static member DisasmBBlock (hdl, showAddr, resolveSymbol, bp) = - disasmBBLFromBinPtr - hdl.FileInfo hdl.Parser hdl.DisasmHelper showAddr resolveSymbol bp - - static member Optimize stmts = LocalOptimizer.Optimize stmts - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinInterface/BinHandle.fsi b/src/FrontEnd/BinInterface/BinHandle.fsi deleted file mode 100644 index 2b0c4ba3..00000000 --- a/src/FrontEnd/BinInterface/BinHandle.fsi +++ /dev/null @@ -1,632 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinInterface - -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinLifter - -/// The main handle for reading/parsing a binary code. BinHandle essentially -/// provides a low-level interface for a chunk of binary code. One can use -/// BinHandle to parse/lift/disassemble instructions at a specific address or to -/// access file-specific data. -type BinHandle = { - ISA: ISA - FileInfo: FileInfo - DisasmHelper: DisasmHelper - TranslationContext: TranslationContext - Parser: Parser - RegisterBay: RegisterBay - BinReader: IBinReader - OS: OS -} -with - /// - /// Return the byte array of size (nBytes) at the addr from the current - /// binary. - /// - /// The address. - /// The size of the byte array (in bytes). - /// - /// Return the byte array if succeed. Otherwise, raise an exception. - /// - member ReadBytes: addr: Addr * nBytes: int -> byte [] - - /// - /// Return the byte array of size (nBytes) pointed to by the binary pointer - /// (bp). - /// - /// BInaryPointer. - /// The size of the byte array (in bytes). - /// - /// Return the byte array if succeed. Otherwise, raise an exception. - /// - member ReadBytes: bp: BinaryPointer * nBytes: int -> byte [] - - /// - /// Return the corresponding integer value at the addr of the size from the - /// current binary. - /// - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding integer (int64). - /// - member ReadInt: addr: Addr * size: int -> int64 - - /// - /// Return the corresponding integer value of the size from the current - /// binary, which is pointed to by the binary pointer (bp). - /// - /// The binary pointer. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding integer (int64). - /// - member ReadInt: bp: BinaryPointer * size: int -> int64 - - /// - /// Return the corresponding unsigned integer value at the addr of the size - /// from the binary. - /// - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64). - /// - member ReadUInt: addr: Addr * size: int -> uint64 - - /// - /// Return the corresponding unsigned integer value of the size from the - /// binary, which is pointed to by the binary pointer (bp). - /// - /// BinaryPointer. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64). - /// - member ReadUInt: bp: BinaryPointer * size: int -> uint64 - - /// - /// Return the ASCII string at the addr from the given BinHandle. - /// - /// The address. - /// - /// Return the corresponding ASCII string. - /// - member ReadASCII: addr: Addr -> string - - /// - /// Return the ASCII string pointed to by the binary pointer from the given - /// BinHandle. - /// - /// BinaryPointer. - /// - /// Return the corresponding ASCII string. - /// - member ReadASCII: bp: BinaryPointer -> string - - /// - /// Initialize a BInHnalder from a given binary byte sequence. This function - /// will read the byte sequence and automatically detect its binary format - /// if autoDetect is true. Otherwise, it will consider the given binary - /// sequence as a raw binary (just a series of machine instructions without - /// specific file format). - /// - /// ISA. - /// ArchOperationMode. - /// Perform auto format detection or not. - /// Base address for calculating instruction - /// addresses. - /// Raw binary sequence. - /// BinHandle. - static member Init: - isa: ISA - * archMode: ArchOperationMode - * autoDetect: bool - * baseAddr: Addr option - * bytes: byte [] - -> BinHandle - - /// - /// Initialize a BinHandle from a given binary file (fileName). This - /// function will read the file and parse it. It will automatically detect - /// the file format if autoDetect is true. Otherwise, it will cnosider the - /// file as a raw binary. - /// - /// ISA. - /// ArchOperatinoMode. - /// Whether to perform auto format detection. - /// Base address for calculating instruction - /// addresses. - /// Binary file. - /// BinHandle. - static member Init: - isa: ISA - * archMode: ArchOperationMode - * autoDetect: bool - * baseAddr: Addr option - * fileName: string - -> BinHandle - - /// - /// Initialize a BinHandle from an ISA and a binary file path, assuming - /// that the archMode is NoMode. This function behaves the same as the - /// 2-argument constructor Init (isa, fileName), with a difference of using - /// the specified base address when initializing the BinHandle. - /// - /// ISA. - /// Base address. - /// Binary file path. - /// BinHandle. - static member Init: - isa: ISA * baseAddr: Addr option * fileName: string -> BinHandle - - /// - /// Initialize a BinHandle from an ISA and a byte sequence, assuming that - /// the archMode is NoMode. This function behaves the same as the 2-argument - /// constructor Init (isa, bytes), with a difference of using the specified - /// base address when initializing the BinHandle. - /// - /// ISA. - /// Base address. - /// Byte sequence. - /// BinHandle. - static member Init: - isa: ISA * baseAddr: Addr option * bytes: byte [] -> BinHandle - - /// - /// Initialize a BinHandle from an ISA and a binary file path, assuming - /// that the archMode is NoMode. B2R2 will automatically detect the file - /// format of the given binary file, but it will refer to the given ISA - /// parameter either when the binary has multiple architectures, e.g., a fat - /// binary on macOS, or when B2R2 cannot recognize the given file format. If - /// the given binary file does not follow the known formats, then B2R2 - /// consider it as a raw binary with base address at 0. - /// - /// ISA. - /// Binary file path. - /// BinHandle. - static member Init: isa: ISA * fileName: string -> BinHandle - - /// - /// Initialize a BinHandle from an ISA and a byte sequence, assuming that - /// the archMode is NoMode, and the format is RawBinary. - /// - /// ISA. - /// Byte sequence. - /// BinHandle. - static member Init: isa: ISA * bytes: byte [] -> BinHandle - - /// - /// Initialize an empty BinHandle. This function is useful when you want to - /// delay loading the actual body of your binary blob. - /// - /// ISA. - /// ArchOperatinoMode. - /// BinHandle. - static member Init: isa: ISA * archMode: ArchOperationMode -> BinHandle - - /// - /// Initialize an empty BinHandle solely from an ISA, assuming that the - /// archMode is NoMode, and the format is RawBinary. This function is useful - /// when you want to delay loading the actual body of your binary blob. - /// - /// ISA. - /// BinHandle. - static member Init: isa: ISA -> BinHandle - - /// - /// Initialize an empty BinHandle. This function is useful when you want to - /// delay loading the actual body of your binary blob but also want to - /// specify the os. - /// - /// ISA. - /// OS. - /// BinHandle. - static member Init: isa: ISA * os: OS -> BinHandle - - /// - /// Update BinHandle to have new code at a new address (addr). BinHandle - /// is *immutable*. - /// - /// The BinHandle to update. - /// The new address to use. - /// The new code in bytes. - /// New BinHandle. - static member UpdateCode: - hdl: BinHandle -> addr: Addr -> bs: byte [] -> BinHandle - - /// - /// Update BinHandle by patching the code at the address (addr). Note that - /// BinHandle itself is *immutable*, and thus, this function returns a new - /// BinHandle. - /// - /// The BinHandle to update. - /// The new address to use. - /// The new code in bytes. - /// - /// Return (BinHandle) if succeeded, (ErrorCase) otherwise. - /// - static member PatchCode: - hdl: BinHandle -> addr: Addr -> bs: byte [] -> Result - - /// - /// Return the byte array of size (nBytes) at the addr from the given - /// BinHandle (hdl). The return value is an option type. When the given - /// address is invalid, this function returns None. - /// - /// BinHandle. - /// The address. - /// The size of the byte array (in bytes). - /// - /// Return (byte []) if succeeded, (ErrorCase) otherwise. - /// - static member TryReadBytes: - hdl: BinHandle * addr: Addr * nBytes: int -> Result - - /// - /// Return the byte array of size (nBytes) from the BinHandler (hdl), which - /// is pointed to by the BinaryPointer (bp). The return value is an option - /// type. When the given address is invalid, this function returns None. - /// - /// BinHandle. - /// BinaryPointer. - /// The size of the byte array (in bytes). - /// - /// Return (byte []) if succeeded, (ErrorCase) otherwise. - /// - static member TryReadBytes: - hdl: BinHandle * bp: BinaryPointer * nBytes: int - -> Result - - /// - /// Return the byte array of size (nBytes) at the addr from the given - /// BinHandle. - /// - /// BinHandle. - /// The address. - /// The size of the byte array (in bytes). - /// - /// Return the byte array if succeed. Otherwise, raise an exception. - /// - static member ReadBytes: - hdl: BinHandle * addr: Addr * nBytes: int -> byte [] - - /// - /// Return the byte array of size (nBytes) from the given BinHandle, which - /// is pointed to by the BinaryPointer (bp). - /// - /// BinHandle. - /// BinaryPointer. - /// The size of the byte array (in bytes). - /// - /// Return the byte array if succeed. Otherwise, raise an exception. - /// - static member ReadBytes: - hdl: BinHandle * bp: BinaryPointer * nBytes: int -> byte [] - - /// - /// Return the corresponding integer option value at the addr of the size - /// from the given BinHandle. - /// - /// BinHandle. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding value (int64) if the address and the size is - /// valid. Otherwise ErrorCase. - /// - static member TryReadInt: - hdl: BinHandle * addr: Addr * size: int -> Result - - /// - /// Return the corresponding integer option value of the size from the given - /// BinHandle (hdl), which is pointed to by the binary pointer (bp). - /// - /// BinHandle. - /// BinaryPointer. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding value (int64) if the address and the size is - /// valid. Otherwise ErrorCase. - /// - static member TryReadInt: - hdl: BinHandle * bp: BinaryPointer * size: int -> Result - - /// - /// Return the corresponding integer value at the addr of the size from the - /// given BinHandle. - /// - /// BinHandle. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding integer (int64). - /// - static member ReadInt: - hdl: BinHandle * addr: Addr * size: int -> int64 - - /// - /// Return the corresponding integer value of the size from the given - /// BinHandle (hdl), which is pointed to by the binary pointer (bp). - /// - /// BinHandle. - /// BinaryPointer. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding integer (int64). - /// - static member ReadInt: - hdl: BinHandle * bp: BinaryPointer * size: int -> int64 - - /// - /// Return the corresponding unsigned integer option value at the addr of - /// the size from the given BinHandle. - /// - /// BinHandle. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64) if the address and - /// the size is valid. Otherwise, ErrorCase. - /// - static member TryReadUInt: - hdl: BinHandle * addr: Addr * size: int -> Result - - /// - /// Return the corresponding unsigned integer option value of the size from - /// the given BinHandle (hdl), which is pointed to by the binary pointer - /// (bp). - /// - /// BinHandle. - /// BinaryPointer. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64) if the address and - /// the size is valid. Otherwise, ErrorCase. - /// - static member TryReadUInt: - hdl: BinHandle * bp: BinaryPointer * size: int -> Result - - /// - /// Return the corresponding unsigned integer value at the addr of the size - /// from the given BinHandle. - /// - /// BinHandle. - /// The address. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64). - /// - static member ReadUInt: - hdl: BinHandle * addr: Addr * size: int -> uint64 - - /// - /// Return the corresponding unsigned integer value of the size from the - /// given BinHandle (hdl), which is pointed to by the binary pointer (bp). - /// - /// BinHandle. - /// BinaryPointer. - /// The size of the integer in bytes. Maximum 8 bytes is - /// possible. - /// - /// Return the corresponding unsigned integer (uint64). - /// - static member ReadUInt: - hdl: BinHandle * bp: BinaryPointer * size: int -> uint64 - - /// - /// Return the ASCII string at the addr from the given BinHandle. - /// - /// BinHandle. - /// The address. - /// - /// Return the corresponding ASCII string. - /// - static member ReadASCII: - hdl: BinHandle * addr: Addr -> string - - /// - /// Return the ASCII string pointed to by the binary pointer from the given - /// BinHandle. - /// - /// BinHandle. - /// BinaryPointer. - /// - /// Return the corresponding ASCII string. - /// - static member ReadASCII: - hdl: BinHandle * bp: BinaryPointer -> string - - /// - /// Parse one instruction at the given address (addr) from the BinHandle, - /// and return the corresponding instruction. This function raises an - /// exception if the parsing process failed. - /// - /// BinHandle. - /// The address. - /// - /// Parsed instruction. - /// - static member ParseInstr: - hdl: BinHandle * addr: Addr -> Instruction - - /// - /// Parse one instruction pointed to by binary pointer (bp) from the - /// BinHandle, and return the corresponding instruction. This function - /// raises an exception if the parsing process failed. - /// - /// BinHandle. - /// BinaryPointer. - /// - /// Parsed instruction. - /// - static member ParseInstr: - hdl: BinHandle * bp: BinaryPointer -> Instruction - - /// - /// Parse one instruction at the given address (addr) from the BinHandle, - /// and return the corresponding instruction. This function does not raise - /// an exception, but returns an option type. - /// - /// BinHandle. - /// The address. - /// - /// Parsed instruction (option type). - /// - static member TryParseInstr: - hdl: BinHandle * addr: Addr -> Result - - /// - /// Parse one instruction pointed to by the binary pointer (bp) from the - /// BinHandle, and return the corresponding instruction. This function does - /// not raise an exception, but returns an option type. - /// - /// BinHandle. - /// BinaryPointer. - /// - /// Parsed instruction (option type). - /// - static member TryParseInstr: - hdl: BinHandle * bp: BinaryPointer -> Result - - /// Parse a basic block from the given address, and return the sequence of the - /// instructions of the basic block. This function may return an incomplete - /// basic block as an Error type. This function can be safely used for any - /// ISAs, and thus, this should be the main parsing function. - static member ParseBBlock: - BinHandle * addr: Addr - -> Result - - /// Parse a basic block pointed to by the binary pointer (bp), and return the - /// sequence of the instructions of the basic block. This function may return - /// an incomplete basic block as an Error type. This function can be safely - /// used for any ISAs, and thus, this should be the main parsing function. - static member ParseBBlock: - BinHandle * bp: BinaryPointer - -> Result - - /// Lift a parsed instruction (Instruction) to produce an array of IR - /// statements from a given BinHandle. - static member inline LiftInstr: - hdl: BinHandle -> ins: Instruction -> LowUIR.Stmt [] - - /// Lift a parsed instruction (Instruction) to produce an array of optimized - /// IR statements from a given BinHandle. - static member LiftOptimizedInstr: - hdl: BinHandle -> ins: Instruction -> LowUIR.Stmt [] - - /// Return the lifted IR (an array of statements) of a basic block at the - /// given address. This function returns a partial bblock with Error, if the - /// parsing of the bblock was not successful. - static member LiftBBlock: - hdl: BinHandle * addr: Addr - -> Result<(LowUIR.Stmt [] * Addr), - (LowUIR.Stmt [] * Addr)> - - /// Return the lifted IR (an array of statements) of a basic block pointed to - /// by the binary pointer (bp). This function returns a partial bblock with - /// Error, if the parsing of the bblock was not successful. - static member LiftBBlock: - hdl: BinHandle * bp: BinaryPointer - -> Result<(LowUIR.Stmt [] * BinaryPointer), - (LowUIR.Stmt [] * BinaryPointer)> - - /// - /// Return a disassembled string from the parsed instruction. - /// - /// BinHandle. - /// Whether to show the instruction address or - /// not. - /// Whether to resolve symbols while disassembling - /// the instruction. - /// The instruction to disassemble. - /// - /// Disassembled string. - /// - static member inline DisasmInstr: - hdl: BinHandle - -> showAddr: bool - -> resolveSymbol: bool - -> ins: Instruction - -> string - - /// - /// Return a disassembled string from the parsed instruction. This function - /// returns a simplified disassembly, which does not contain the instruction - /// address nor symbols. - /// - /// The instruction to disassemble. - /// - /// Disassembled string. - /// - static member inline DisasmInstrSimple: ins: Instruction -> string - - /// - /// Return the disassembled string for a basic block starting at the given - /// address along with the fall-through address of the block. This function - /// returns a partial disassembly if parsing of the bblock was not - /// successful. - /// - static member DisasmBBlock: - hdl: BinHandle - * showAddr:bool - * resolveSymbol: bool - * addr: Addr - -> Result<(string * Addr), (string * Addr)> - - /// - /// Return the disassembled string for a basic block starting at address - /// pointed to by the binary pointer (bp) along with the fall-through - /// address of the block. This function returns a partial disassembly if - /// parsing of the bblock was not successful. - /// - static member DisasmBBlock: - hdl: BinHandle - * showAddr:bool - * resolveSymbol: bool - * bp: BinaryPointer - -> Result<(string * BinaryPointer), - (string * BinaryPointer)> - - /// - /// Return optimized statements from the given statements. - /// - static member Optimize: stmts: LowUIR.Stmt [] -> LowUIR.Stmt [] - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinInterface/Helper.fs b/src/FrontEnd/BinInterface/Helper.fs deleted file mode 100644 index 4c99dd78..00000000 --- a/src/FrontEnd/BinInterface/Helper.fs +++ /dev/null @@ -1,201 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.FrontEnd.BinInterface.Helper - -open System.Text -open B2R2 -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinLifter - -let private appendOSInfo fmt isa = - match fmt with - | FileFormat.ELFBinary -> struct (fmt, isa, OS.Linux) - | FileFormat.PEBinary -> struct (fmt, isa, OS.Windows) - | FileFormat.MachBinary -> struct (fmt, isa, OS.MacOSX) - | FileFormat.WasmBinary -> struct (fmt, isa, OS.UnknownOS) - | _ -> Utils.impossible () - -let identifyFormatAndISAAndOS bytes isa os autoDetect = - if autoDetect then FormatDetector.identify bytes isa ||> appendOSInfo - else struct (FileFormat.RawBinary, isa, Option.defaultValue OS.UnknownOS os) - -let newFileInfo bytes (baddr: Addr option) path fmt isa regbay = - match fmt with - | FileFormat.ELFBinary -> - ELFFileInfo (bytes, path, baddr, Some regbay) :> FileInfo - | FileFormat.PEBinary -> - PEFileInfo (bytes, path, baddr) :> FileInfo - | FileFormat.MachBinary -> - MachFileInfo (bytes, path, isa, baddr) :> FileInfo - | FileFormat.WasmBinary -> - WasmFileInfo (bytes, path, baddr) :> FileInfo - | _ -> RawFileInfo (bytes, path, isa, baddr) :> FileInfo - -/// Classify ranges to be either in-file or not-in-file. The second parameter -/// (notinfiles) is a sequence of (exclusive) ranges within the myrange, which -/// represent the not-in-file ranges. This function will simply divide the -/// myrange into subranges where each subrange is labeled with either true or -/// false, where true means in-file, and false means not-in-file. -let classifyRanges myrange notinfiles = - notinfiles - |> Seq.fold (fun (infiles, saddr) r -> - let l = AddrRange.GetMin r - let h = AddrRange.GetMax r - if saddr = l then (r, false) :: infiles, h - else (r, false) :: ((AddrRange (saddr, l), true) :: infiles), h - ) ([], AddrRange.GetMin myrange) - |> (fun (infiles, saddr) -> - if saddr = myrange.Max then infiles - else ((AddrRange (saddr, myrange.Max), true) :: infiles)) - |> List.rev - -let inline readIntBySize (r: IBinReader) (fi: FileInfo) pos size = - match size with - | 1 -> r.ReadInt8 (fi.Span, pos) |> int64 |> Ok - | 2 -> r.ReadInt16 (fi.Span, pos) |> int64 |> Ok - | 4 -> r.ReadInt32 (fi.Span, pos) |> int64 |> Ok - | 8 -> r.ReadInt64 (fi.Span, pos) |> Ok - | _ -> Error ErrorCase.InvalidMemoryRead - -let inline readUIntBySize (r: IBinReader) (fi: FileInfo) pos size = - match size with - | 1 -> r.ReadUInt8 (fi.Span, pos) |> uint64 |> Ok - | 2 -> r.ReadUInt16 (fi.Span, pos) |> uint64 |> Ok - | 4 -> r.ReadUInt32 (fi.Span, pos) |> uint64 |> Ok - | 8 -> r.ReadUInt64 (fi.Span, pos) |> Ok - | _ -> Error ErrorCase.InvalidMemoryRead - -let inline readASCII (fi: FileInfo) pos = - let rec loop acc pos = - let b = fi.Span[pos] - if b = 0uy then List.rev (b :: acc) |> List.toArray - else loop (b :: acc) (pos + 1) - loop [] pos - -let inline parseInstrFromAddr (fi: FileInfo) (parser: Parser) addr = - let offset = fi.TranslateAddress addr - parser.Parse (fi.Span.Slice offset, addr) - -let inline tryParseInstrFromAddr (fi: FileInfo) (parser: Parser) addr = - try parseInstrFromAddr fi parser addr |> Ok - with _ -> Error ErrorCase.ParsingFailure - -let inline tryParseInstrFromBinPtr fi (p: Parser) (bp: BinaryPointer) = - try - let ins = p.Parse ((fi: FileInfo).Span.Slice bp.Offset, bp.Addr) - if BinaryPointer.IsValidAccess bp (int ins.Length) then Ok ins - else Error ErrorCase.ParsingFailure - with _ -> - Error ErrorCase.ParsingFailure - -let inline parseInstrFromBinPtr (fi: FileInfo) parser (bp: BinaryPointer) = - match tryParseInstrFromBinPtr fi parser bp with - | Ok ins -> ins - | Error _ -> raise ParsingFailureException - -let advanceAddr addr len = - addr + uint64 len - -let rec parseLoopByAddr fi parser addr acc = - match tryParseInstrFromAddr fi parser addr with - | Ok ins -> - if ins.IsBBLEnd () then Ok (List.rev (ins :: acc)) - else - let addr = addr + (uint64 ins.Length) - parseLoopByAddr fi parser addr (ins :: acc) - | Error _ -> Error <| List.rev acc - -let inline parseBBLFromAddr (fi: FileInfo) (parser: Parser) addr = - parseLoopByAddr fi parser addr [] - -let rec parseLoopByPtr fi parser bp acc = - match tryParseInstrFromBinPtr fi parser bp with - | Ok (ins: Instruction) -> - if ins.IsBBLEnd () then Ok (List.rev (ins :: acc)) - else - let bp = BinaryPointer.Advance bp (int ins.Length) - parseLoopByPtr fi parser bp (ins :: acc) - | Error _ -> Error <| List.rev acc - -let inline parseBBLFromBinPtr (fi: FileInfo) (parser: Parser) bp = - parseLoopByPtr fi parser bp [] - -let rec liftBBLAux acc advanceFn trctxt pos = function - | (ins: Instruction) :: rest -> - let pos = advanceFn pos (int ins.Length) - liftBBLAux (ins.Translate trctxt :: acc) advanceFn trctxt pos rest - | [] -> struct (List.rev acc |> Array.concat, pos) - -let inline liftBBLFromAddr fi parser trctxt addr = - match parseBBLFromAddr fi parser addr with - | Ok bbl -> - let struct (stmts, addr) = liftBBLAux [] advanceAddr trctxt addr bbl - Ok (stmts, addr) - | Error bbl -> - let struct (stmts, addr) = liftBBLAux [] advanceAddr trctxt addr bbl - Error (stmts, addr) - -let inline liftBBLFromBinPtr fi parser trctxt bp = - match parseBBLFromBinPtr fi parser bp with - | Ok bbl -> - let struct (stmts, bp) = liftBBLAux [] BinaryPointer.Advance trctxt bp bbl - Ok (stmts, bp) - | Error bbl -> - let struct (stmts, bp) = liftBBLAux [] BinaryPointer.Advance trctxt bp bbl - Error (stmts, bp) - -let rec disasmBBLAux sb advanceFn showAddr resolve hlp pos = function - | (ins: Instruction) :: rest -> - let s = ins.Disasm (showAddr, resolve, hlp) - let s = - if (sb: StringBuilder).Length = 0 then s - else System.Environment.NewLine + s - let pos = advanceFn pos (int ins.Length) - disasmBBLAux (sb.Append (s)) advanceFn showAddr resolve hlp pos rest - | [] -> struct (sb.ToString (), pos) - -let disasmBBLFromAddr fi parser hlp showAddr resolve addr = - match parseBBLFromAddr fi parser addr with - | Ok bbl -> - let struct (str, addr) = - disasmBBLAux (StringBuilder ()) advanceAddr showAddr resolve hlp addr bbl - Ok (str, addr) - | Error bbl -> - let struct (str, addr) = - disasmBBLAux (StringBuilder ()) advanceAddr showAddr resolve hlp addr bbl - Error (str, addr) - -let disasmBBLFromBinPtr fi parser hlp showAddr resolve bp = - match parseBBLFromBinPtr fi parser bp with - | Ok bbl -> - let struct (str, addr) = - disasmBBLAux (StringBuilder ()) - BinaryPointer.Advance showAddr resolve hlp bp bbl - Ok (str, addr) - | Error bbl -> - let struct (str, addr) = - disasmBBLAux (StringBuilder ()) - BinaryPointer.Advance showAddr resolve hlp bp bbl - Error (str, addr) diff --git a/src/FrontEnd/BinLifter.Tests/ARM32.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/ARM32.Lifter.Tests.fs new file mode 100644 index 00000000..5f241797 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/ARM32.Lifter.Tests.fs @@ -0,0 +1,105 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.ARM32Lifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.BinIR.LowUIR.AST.InfixOp +open type Register + +[] +module TestHelper = + let num v = BitVector.OfUInt32 v 32 |> AST.num + + let t32 id = AST.tmpvar 32 id + + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) + + let isa = ISA.Init Architecture.ARMv7 Endian.Big + + let ctxt = ARM32TranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + let inline ( ++ ) (byteStr: string) givenStmts = + ByteArray.ofHexString byteStr, givenStmts + + let test mode (bytes: byte[]) (givenStmts: Stmt[]) = + let parser = ARM32Parser (isa, mode, None) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) + let liftInstr = BinHandle(isa).LiftInstr ins + CollectionAssert.AreEqual (givenStmts, unwrapStmts liftInstr) + + let testARM (bytes: byte[], givenStmts: Stmt[]) = + test ArchOperationMode.ARMMode bytes givenStmts + + let testThumb (bytes: byte[], givenStmts: Stmt[]) = + test ArchOperationMode.ThumbMode bytes givenStmts + +[] +type ARMUnitTest () = + [] + member __.``[ARMv7] ADD (shifted register) lift test`` () = + let shiftAmt = AST.zext 32 (AST.xtlo 8 !.R8) + "e080285e" + ++ [| t32 1 := + !.R0 .+ (AST.ite (shiftAmt == num 0x0u) !.LR (!.LR ?>> shiftAmt)) + .+ num 0x0u + !.R2 := t32 1 |] + |> testARM + + [] + member __.``[ARMv7] ADD (immedate) lift test`` () = + "e28f0ff0" + ++ [| t32 1 := !.PC .+ num 0x8u .+ num 0x3c0u .+ num 0x0u + !.R0 := t32 1 |] + |> testARM + +[] +type ThumbUnitTest () = + [] + member __.``[Thumb] ADD (Two Reg Operands) lift test`` () = + "448b" + ++ [| t32 1 := !.FP .+ !.R1 .+ num 0u + !.FP := t32 1 |] + |> testThumb + + [] + member __.``[Thumb] ADD (Three Reg Operands) lift test`` () = + "44ec" + ++ [| t32 1 := !.SP .+ !.IP .+ num 0u + !.IP := t32 1 |] + |> testThumb + + [] + member __.``[Thumb] ADD (Immediate) lift test`` () = + "b066" + ++ [| t32 1 := !.SP .+ num 0x198u .+ num 0u + !.SP := t32 1 |] + |> testThumb diff --git a/src/FrontEnd/BinLifter.Tests/ARM32.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/ARM32.Parser.Tests.fs new file mode 100644 index 00000000..fb9e23b4 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/ARM32.Parser.Tests.fs @@ -0,0 +1,866 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.ARM32 + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.FrontEnd.BinLifter.ARM32.OperandHelper +open type Opcode +open type Register + +type O = + static member Reg (r) = + OprReg r + + static member Imm (v) = + OprImm v + + static member RegShift (srType, r) = + OprRegShift (srType, r) + + static member Shift (srType, v) = + OprShift (srType, Imm v) + + static member SpecReg (r, psfFlag) = + OprSpecReg (r, Some psfFlag) + + static member Iflag (flag) = + OprIflag flag + + static member RegList (lst) = + OprRegList lst + + static member Option (barrier) = + OprOption barrier + + static member Endian (endian) = + OprEndian endian + + static member Cond (cond) = + OprCond cond + + static member SimdScalarReg (r, elem) = + toSSReg (r, elem) + + static member SimdVectorReg (r) = + toSVReg r + + static member MemLabel (v) = + memLabel v + + static member MemUnIdx (r, v) = + memUnIdxImm (r, v) + + static member MemOffsetImm (offset) = + memOffsetImm offset + + static member MemOffsetReg (r1, signOpt, r2, srType, v) = + memOffsetReg (r1, signOpt, r2, Some (srType, Imm v)) + + static member MemOffsetReg (r1, signOpt, r2) = + memOffsetReg (r1, signOpt, r2, None) + + static member MemOffsetAlign (offset) = + memOffsetAlign offset + + static member MemPreIdxImm (offset) = + memPreIdxImm offset + + static member MemPreIdxReg (r1, signOpt, r2, srType, v) = + memPreIdxReg (r1, signOpt, r2, Some (srType, Imm v)) + + static member MemPreIdxReg (r1, signOpt, r2) = + memPreIdxReg (r1, signOpt, r2, None) + + static member MemPreIdxAlign (offset) = + memPreIdxAlign offset + + static member MemPostIdxImm (offset) = + memPostIdxImm offset + + static member MemPostIdxReg (r1, signOpt, r2, srType, v) = + memPostIdxReg (r1, signOpt, r2, Some (srType, Imm v)) + + static member MemPostIdxReg (r1, signOpt, r2) = + memPostIdxReg (r1, signOpt, r2, None) + + static member MemPostIdxAlign (offset) = + memPostIdxAlign offset + + static member SimdScalarRegs (regList, elem) = + getSIMDScalar elem regList + + static member SimdVectorRegs (regList) = + getSIMDVector regList + +let private test cond op w simd oprs (bytes: byte[]) = + let mode = ArchOperationMode.ARMMode + let isa = ISA.Init Architecture.ARMv7 Endian.Big + let parser = ARM32Parser (isa, mode, None) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) :?> ARM32Instruction + let cond' = ins.Condition + let opcode' = ins.Opcode + let wback' = ins.WriteBack + let simd' = ins.SIMDTyp + let oprs' = ins.Operands + Assert.AreEqual (cond', cond) + Assert.AreEqual (opcode', op) + Assert.AreEqual (wback', w) + Assert.AreEqual (simd', simd) + Assert.AreEqual (oprs', oprs) + +let private testNoWbackNoQNoSimd pref (bytes: byte[]) (opcode, operands) = + test pref opcode false None operands bytes + +let private testNoWbackNoQ pref simd (bytes: byte[]) (opcode, operands) = + test pref opcode false simd operands bytes + +let private testNoQNoSimd pref wback (bytes: byte[]) (opcode, operands) = + test pref opcode wback None operands bytes + +let private testNoQ pref wback simd (bytes: byte[]) (opcode, operands) = + test pref opcode wback simd operands bytes + +let private operandsFromArray oprList = + let oprs = Array.ofList oprList + match oprs.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprs[0] + | 2 -> TwoOperands (oprs[0], oprs[1]) + | 3 -> ThreeOperands (oprs[0], oprs[1], oprs[2]) + | 4 -> FourOperands (oprs[0], oprs[1], oprs[2], oprs[3]) + | 5 -> FiveOperands (oprs[0], oprs[1], oprs[2], oprs[3], oprs[4]) + | 6 -> SixOperands (oprs[0], oprs[1], oprs[2], oprs[3], oprs[4], oprs[5]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +/// A4.3 Branch instructions +[] +type BranchClass () = + [] + member __.``[ARMv7] Branch Parse Test (1)`` () = + "ea0000ff" + ++ B ** [ O.MemLabel 1020L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Branch Parse Test (2)`` () = + "fa000010" + ++ BLX ** [ O.MemLabel 64L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Branch Parse Test (3)`` () = + "e12fff10" + ++ BX ** [ O.Reg R0 ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.4 Data-processing instructions +[] +type DataProcessingClass () = + /// A4.4.1 Standard data-processing instructions + [] + member __.``[ARMv7] Standard data-processing Parse Test (1)`` () = + "e080285e" + ++ ADD ** [ O.Reg R2; O.Reg R0; O.Reg LR; O.RegShift (SRTypeASR, R8) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (2)`` () = + "e28f0ff0" + ++ ADD ** [ O.Reg R0; O.Reg PC; O.Imm 960L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (3)`` () = + "e0000000" + ++ AND ** [ O.Reg R0; O.Reg R0; O.Reg R0; O.Shift (SRTypeLSL, 0u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (4)`` () = + "e15c0262" + ++ CMP ** [ O.Reg IP; O.Reg R2; O.Shift (SRTypeROR, 4u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (5)`` () = + "e23010fc" + ++ EORS ** [ O.Reg R1; O.Reg R0; O.Imm 252L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (6)`` () = + "e300a00f" + ++ MOVW ** [ O.Reg SL; O.Imm 15L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (7)`` () = + "e1b0800c" + ++ MOVS ** [ O.Reg R8; O.Reg IP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (8)`` () = + "e1e00819" + ++ MVN ** [ O.Reg R0; O.Reg SB; O.RegShift (SRTypeLSL, R8) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (9)`` () = + "e13a0c16" + ++ TEQ ** [ O.Reg SL; O.Reg R6; O.RegShift (SRTypeLSL, IP) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Standard data-processing Parse Test (10)`` () = + "e3130004" + ++ TST ** [ O.Reg R3; O.Imm 4L ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.2 Shift instructions + [] + member __.``[ARMv7] Shift Parse Test (1)`` () = + "e1b00113" + ++ LSLS ** [ O.Reg R0; O.Reg R3; O.Reg R1 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Shift Parse Test (2)`` () = + "e1a00e65" + ++ ROR ** [ O.Reg R0; O.Reg R5; O.Imm 28L ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.3 Multiply instructions + [] + member __.``[ARMv7] Multiply Parse Test (1)`` () = + "e0100c99" + ++ MULS ** [ O.Reg R0; O.Reg SB; O.Reg IP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Multiply Parse Test (2)`` () = + "e100cac5" + ++ SMLABT ** [ O.Reg R0; O.Reg R5; O.Reg SL; O.Reg IP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Multiply Parse Test (3)`` () = + "e14012e8" + ++ SMLALTT ** [ O.Reg R1; O.Reg R0; O.Reg R8; O.Reg R2 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Multiply Parse Test (4)`` () = + "e700f112" + ++ SMUAD ** [ O.Reg R0; O.Reg R2; O.Reg R1 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Multiply Parse Test (5)`` () = + "e1600e8c" + ++ SMULBB ** [ O.Reg R0; O.Reg IP; O.Reg LR ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.4 Saturating instructions + [] + member __.``[ARMv7] Saturating Parse Test (1)`` () = + "e6bc03d2" + ++ SSAT ** [ O.Reg R0; O.Imm 29L; O.Reg R2; O.Shift (SRTypeASR, 7u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.5 Saturating addition and subtraction instructions + [] + member __.``[ARMv7] Saturating addition and subtraction Parse Test (1)`` () = + "e1001052" + ++ QADD ** [ O.Reg R1; O.Reg R2; O.Reg R0 ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.6 Packing and unpacking instructions + [] + member __.``[ARMv7] Packing and unpacking Parse Test (1)`` () = + "e6801ad8" + ++ PKHTB ** [ O.Reg R1; O.Reg R0; O.Reg R8; O.Shift (SRTypeASR, 21u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Packing and unpacking Parse Test (2)`` () = + "e6a01c70" + ++ SXTAB ** [ O.Reg R1; O.Reg R0; O.Reg R0; O.Shift (SRTypeROR, 24u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Packing and unpacking Parse Test (3)`` () = + "e6bf0073" + ++ SXTH ** [ O.Reg R0; O.Reg R3; O.Shift (SRTypeROR, 0u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.7 Parallel addition and subtraction instructions + [] + member __.``[ARMv7] Parallel addition and subtraction Parse Test (1)`` () = + "e6101f37" + ++ SASX ** [ O.Reg R1; O.Reg R0; O.Reg R7 ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.9 Miscellaneous data-processing instructions + [] + member __.``[ARMv7] Miscellaneous data-processing Parse Test (1)`` () = + "e7df019f" + ++ BFC ** [ O.Reg R0; O.Imm 3L; O.Imm 29L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Miscellaneous data-processing Parse Test (2)`` () = + "e7ca0290" + ++ BFI ** [ O.Reg R0; O.Reg R0; O.Imm 5L; O.Imm 6L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Miscellaneous data-processing Parse Test (3)`` () = + "e16f0f11" + ++ CLZ ** [ O.Reg R0; O.Reg R1 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Miscellaneous data-processing Parse Test (4)`` () = + "e7a20e52" + ++ SBFX ** [ O.Reg R0; O.Reg R2; O.Imm 28L; O.Imm 3L ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.5 Status register access instructions +[] +type StatusOprRegAccessClass () = + [] + member __.``[ARMv7] Status register access Parse Test (1)`` () = + "e32cf0f0" + ++ MSR ** [ O.SpecReg (CPSR, PSRfs); O.Imm 240L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Status register access Parse Test (2)`` () = + "e12cf002" + ++ MSR ** [ O.SpecReg (CPSR, PSRfs); O.Reg R2 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Status register access Parse Test (3)`` () = + "f10a0142" + ++ CPSIE ** [ O.Iflag AF; O.Imm 2L ] + ||> testNoWbackNoQNoSimd Condition.UN + +/// A4.6 Load/store instructions +[] +type LoadStoreClass () = + [] + member __.``[ARMv7] Load/store (Lord) Parse test (1)`` () = + "e59f000f" + ++ LDR ** [ O.Reg R0; O.MemLabel 15L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Load/store (Lord) Parse test (2)`` () = + "e09010bc" + ++ LDRH ** [ O.Reg R1; O.MemPostIdxReg (R0, Some Plus, IP) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[ARMv7] Load/store (Lord) Parse test (3)`` () = + "e75010c2" + ++ LDRB ** [ O.Reg R1; O.MemOffsetReg (R0, Some Minus, R2, SRTypeASR, 1u) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[ARMv7] Load/store (Lord) Parse test (4)`` () = + "e1701cd3" + ++ LDRSB ** [ O.Reg R1; O.MemPreIdxImm (R0, Some Minus, Some 195L) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[ARMv7] Load/store (Store) Parse test (1)`` () = + "e50010f3" + ++ STR ** [ O.Reg R1; O.MemOffsetImm (R0, Some Minus, Some 243L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[ARMv7] Load/store (Store) Parse test (2)`` () = + "e640122c" + ++ STRB ** [ O.Reg R1; O.MemPostIdxReg (R0, Some Minus, IP, SRTypeLSR, 4u) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[ARMv7] Load/store (Store) Parse test (3)`` () = + "e1a0c0f8" + ++ STRD ** [ O.Reg IP; O.Reg SP; O.MemPreIdxReg (R0, Some Plus, R8) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[ARMv7] Load/store (Load unprivileged) Parse test (1)`` () = + "e070e0fe" + ++ LDRSHT ** [ O.Reg LR; O.MemPostIdxImm (R0, Some Minus, Some 14L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Load/store (Store unprivileged) Parse test (1)`` () = + "e4a0100f" + ++ STRT ** [ O.Reg R1; O.MemPostIdxImm (R0, Some Plus, Some 15L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Load/store (Store unprivileged) Parse test (2)`` () = + "e02010b4" + ++ STRHT ** [ O.Reg R1; O.MemPostIdxReg (R0, Some Minus, R4) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Load/store (Load-Exclusive) Parse test (1)`` () = + "e190ef9f" + ++ LDREX ** [ O.Reg LR; O.MemOffsetImm (R0, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Load/store (Store-Exclusive) Parse test (1)`` () = + "e1a01f92" + ++ STREXD ** [ O.Reg R1; O.Reg R2; O.Reg R3; + O.MemOffsetImm (R0, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.7 Load/store multiple instructions +[] +type LoadStoreMultipleClass () = + [] + member __.``[ARMv7] Load/store multiple Parse Test (1)`` () = + "e8100f0c" + ++ LDMDA ** [ O.Reg R0; O.RegList [ R2; R3; R8; SB; SL; FP ] ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[ARMv7] Load/store multiple Parse Test (2)`` () = + "e8300f0c" + ++ LDMDA ** [ O.Reg R0; O.RegList [ R2; R3; R8; SB; SL; FP ] ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[ARMv7] Load/store multiple Parse Test (3)`` () = + "e8bd000f" + ++ POP ** [ O.RegList [ R0; R1; R2; R3 ] ] + ||> testNoWbackNoQNoSimd Condition.AL + + (* + "e52d0004" + ++ STR ** [ O.Reg R0; O.MemPreIdxImm (SP, Some Minus, Some 4L) ] + ||> testNoQNoSimd Condition.AL (Some true) + *) + + [] + member __.``[ARMv7] Load/store multiple Parse Test (4)`` () = + "e52d0004" + ++ PUSH ** [ O.RegList [ R0 ] ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[ARMv7] Load/store multiple Parse Test (5)`` () = + "e8c9e000" + ++ STMIA ** [ O.Reg SB; O.RegList [ SP; LR; PC ] ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.8 Miscellaneous instructions +[] +type MiscellaneousClass () = + [] + member __.``[ARMv7] Miscellaneous Parse test (1)`` () = + "f57ff01f" + ++ CLREX ** [ ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Miscellaneous Parse test (2)`` () = + "f57ff05f" + ++ DMB ** [ O.Option BarrierOption.SY ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Miscellaneous Parse test (3)`` () = + "e320f000" + ++ NOP ** [ ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Miscellaneous Parse test (4)`` () = + "f55fff00" + ++ PLD ** [ O.MemLabel -3840L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Miscellaneous Parse test (5)`` () = + "f790f1c0" + ++ PLDW ** [ O.MemOffsetReg (R0, Some Plus, R0, SRTypeASR, 3u) ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Miscellaneous Parse test (6)`` () = + "f450f0f0" + ++ PLI ** [ O.MemLabel -240L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Miscellaneous Parse test (7)`` () = + "f1010200" + ++ SETEND ** [ O.Endian Endian.Big ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Miscellaneous Parse test (8)`` () = + "e100c09e" + ++ SWP ** [ O.Reg IP; O.Reg LR; O.MemOffsetImm (R0, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.9 Exception-generating and exception-handling instructions +[] +type ExcepGenAndExcepHandlClass () = + [] + member __.``[ARMv7] Exception-gen and exception-handling Parse Test (1)`` () = + "e120f07c" + ++ BKPT ** [ O.Imm 3852L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Exception-gen and exception-handling Parse Test (2)`` () = + "e160007f" + ++ SMC ** [ O.Imm 15L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Exception-gen and exception-handling Parse Test (3)`` () = + "f9bc0a00" + ++ RFEIB ** [ O.Reg IP ] + ||> testNoQNoSimd Condition.UN true + + [] + member __.``[ARMv7] Exception-gen and exception-handling Parse Test (4)`` () = + "f96d0504" + ++ SRSDB ** [ O.Reg SP; O.Imm 4L ] + ||> testNoQNoSimd Condition.UN true + +/// A4.10 Co-processor instructions +[] +type CoprocessorClass () = + [] + member __.``[ARMv7] Co-processor Parse test (1)`` () = + (* Only ARMv7 *) + "ee0123e8" + ++ CDP ** [ O.Reg P3; O.Imm 0L; O.Reg C2; O.Reg C1; O.Reg C8; O.Imm 7L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Co-processor Parse test (2)`` () = + "ec401fe3" + ++ MCRR ** [ O.Reg P15; O.Imm 14L; O.Reg R1; O.Reg R0; O.Reg C3 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Co-processor Parse test (3)`` () = + "ee9e9e32" + ++ MRC ** [ O.Reg P14; O.Imm 4L; O.Reg SB; O.Reg C14; O.Reg C2; O.Imm 1L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[ARMv7] Co-processor Parse test (4)`` () = + "ed9f5e30" + ++ LDC ** [ O.Reg P14; O.Reg C5; O.MemLabel 192L ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[ARMv7] Co-processor Parse test (5)`` () = + "ec905e80" + ++ LDC ** [ O.Reg P14; O.Reg C5; O.MemUnIdx (R0, 128L) ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.11 Advanced SIMD and Floating-point load/store instructions +[] +type AdvSIMDAndFPLoadStoreClass () = + /// A4.11.1 Element and structure load/store instructions + [] + member __.``[ARMv7] Element and structure load/store Parse Test (1)`` () = + "f4e02f70" + ++ VLD4 ** [ O.SimdScalarRegs ([ D18; D20; D22; D24 ], None); + O.MemPostIdxAlign (R0, Some 64L, Some R0) ] + ||> testNoQ Condition.UN true (Some (OneDT SIMDTyp16)) + + [] + member __.``[ARMv7] Element and structure load/store Parse test (2)`` () = + "f402c690" + ++ VST1 ** [ O.SimdVectorRegs ([ D12; D13; D14 ]); + O.MemPostIdxAlign (R2, Some 64L, Some R0) ] + ||> testNoQ Condition.UN true (Some (OneDT SIMDTyp32)) + + [] + member __.``[ARMv7] Element and structure load/store Parse test (3)`` () = + "f48eeac3" + ++ VST3 ** [ O.SimdScalarRegs ([ D14; D16; D18 ], Some 1uy); + O.MemPostIdxReg (LR, None, R3) ] + ||> testNoQ Condition.UN true (Some (OneDT SIMDTyp32)) + +/// A4.12 Advanced SIMD and Floating-point register transfer instructions +[] +type AdvSIMDAndFPRegTransClass () = + [] + member __.``[ARMv7] Advanced SIMD and FP register transfer Parse test (1)`` () + = + "ee82ebb0" + ++ VDUP ** [ O.SimdVectorReg D18; O.Reg LR ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTyp16)) + + [] + member __.``[ARMv7] Advanced SIMD and FP register transfer Parse test (2)`` () + = + "ee42cbb0" + ++ VMOV ** [ O.SimdScalarReg (D18, Some 1uy); O.Reg IP ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTyp8)) + + [] + member __.``[ARMv7] Advanced SIMD and FP register transfer Parse test (3)`` () + = + "ee108bb0" + ++ VMOV ** [ O.Reg R8; O.SimdScalarReg (D16, Some 0uy) ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTypS16)) + +/// A4.13 Advanced SIMD data-processing instructions +[] +type AdvSIMDDataProcessingClass () = + /// A4.13.1 Advanced SIMD parallel addition and subtraction + [] + member __.``[ARMv7] Advanced SIMD parallel add and sub Parse test (1)`` () = + "f2c0c18a" + ++ VADDW ** [ O.SimdVectorReg Q14; O.SimdVectorReg Q8; O.SimdVectorReg D10 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypS8)) + + [] + member __.``[ARMv7] Advanced SIMD parallel add and sub Parse test (2)`` () = + "f320122c" + ++ VHSUB ** [ O.SimdVectorReg D1; O.SimdVectorReg D0; O.SimdVectorReg D28 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypU32)) + + [] + member __.``[ARMv7] Advanced SIMD parallel add and sub Parse test (3)`` () = + "f3b0028e" + ++ VPADDL ** [ O.SimdVectorReg D0; O.SimdVectorReg D14 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypU8)) + + [] + member __.``[ARMv7] Advanced SIMD parallel add and sub Parse test (4)`` () = + "f290c682" + ++ VSUBHN ** [ O.SimdVectorReg D12; O.SimdVectorReg Q8; O.SimdVectorReg Q1 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypI32)) + + /// A4.13.2 Bitwise Advanced SIMD data-processing instructions + [] + member __.``[ARMv7] Bitwise Advanced SIMD data-processing Parse test (1)`` () + = + "f242c1f8" + ++ VAND ** [ O.SimdVectorReg Q14; O.SimdVectorReg Q9; O.SimdVectorReg Q12 ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[ARMv7] Bitwise Advanced SIMD data-processing Parse test (2)`` () + = + "f3c1e57b" + ++ VBIC ** [ O.SimdVectorReg Q15; O.Imm 0x9B0000L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypI32)) + + [] + member __.``[ARMv7] Bitwise Advanced SIMD data-processing Parse test (3)`` () + = + "ee12ca10" + ++ VMOV ** [ O.Reg IP; O.SimdVectorReg S4 ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.13.3 Advanced SIMD comparison instructions + [] + member __.``[ARMv7] Advanced SIMD comparison Parse test (1)`` () = + "f24c8e40" + ++ VCEQ ** [ O.SimdVectorReg Q12; O.SimdVectorReg Q6; O.SimdVectorReg Q0 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypF32)) + + /// A4.13.4 Advanced SIMD shift instructions + [] + member __.``[ARMv7] Advanced SIMD shift Parse test (1)`` () = + "f3a00950" + ++ VQRSHRN ** [ O.SimdVectorReg D0; O.SimdVectorReg Q0; O.Imm 32L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypU64)) + + [] + member __.``[ARMv7] Advanced SIMD shift Parse test (2)`` () = + "f3b80830" + ++ VQSHRUN ** [ O.SimdVectorReg D0; O.SimdVectorReg Q8; O.Imm 8L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypS64)) + + [] + member __.``[ARMv7] Advanced SIMD shift Parse test (3)`` () = + "f2b825d8" + ++ VSHL ** [ O.SimdVectorReg Q1; O.SimdVectorReg Q4; O.Imm 56L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypI64)) + + [] + member __.``[ARMv7] Advanced SIMD shift Parse test (4)`` () = + "f2a00832" + ++ VSHRN ** [ O.SimdVectorReg D0; O.SimdVectorReg Q9; O.Imm 32L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypI64)) + + [] + member __.``[ARMv7] Advanced SIMD shift Parse test (5)`` () = + "f3e801f0" + ++ VSRA ** [ O.SimdVectorReg Q8; O.SimdVectorReg Q8; O.Imm 24L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypU64)) + + [] + member __.``[ARMv7] Advanced SIMD shift Parse test (6)`` () = + "f3b9943a" + ++ VSRI ** [ O.SimdVectorReg D9; O.SimdVectorReg D26; O.Imm 7L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTyp32)) + + /// A4.13.5 Advanced SIMD multiply instructions + [] + member __.``[ARMv7] Advanced SIMD multiply Parse test (1)`` () = + "f3a02a28" + ++ VMLSL ** [ O.SimdVectorReg Q1; O.SimdVectorReg D0; O.SimdVectorReg D24 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypU32)) + + [] + member __.``[ARMv7] Advanced SIMD multiply Parse test (2)`` () = + "ee202aa8" + ++ VMUL ** [ O.SimdVectorReg S4; O.SimdVectorReg S1; O.SimdVectorReg S17 ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTypF32)) + + [] + member __.``[ARMv7] Advanced SIMD multiply Parse test (3)`` () = + "f2c28ca0" + ++ VMULL ** [ O.SimdVectorReg Q12; O.SimdVectorReg D18; + O.SimdVectorReg D16 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypS8)) + + [] + member __.``[ARMv7] Advanced SIMD multiply Parse test (4)`` () = + "f3e24a4a" + ++ VMULL ** [ O.SimdVectorReg Q10; O.SimdVectorReg D2; + O.SimdScalarReg (D10, Some 0uy) ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypU32)) + + [] + member __.``[ARMv7] Advanced SIMD multiply Parse test (5)`` () = + "f3d02ce8" + ++ VQDMULH ** [ O.SimdVectorReg Q9; O.SimdVectorReg Q8; + O.SimdScalarReg (D0, Some 3uy) ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypS16)) + + /// A4.13.6 Miscellaneous Advanced SIMD data-processing instructions + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (1)`` () = + "f3aa0f30" + ++ VCVT ** [ O.SimdVectorReg D0; O.SimdVectorReg D16; O.Imm 22L ] + ||> testNoWbackNoQ Condition.UN (Some (TwoDT (SIMDTypU32, SIMDTypF32))) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (2)`` () = + "eebf0b62" + ++ VCVT ** [ O.SimdVectorReg D0; O.SimdVectorReg D0; O.Imm 11L ] + ||> testNoWbackNoQ Condition.AL (Some (TwoDT (SIMDTypU16, SIMDTypF64))) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (3)`` () = + "f3f0a56e" + ++ VCNT ** [ O.SimdVectorReg Q13; O.SimdVectorReg Q15 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTyp8)) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (4)`` () = + "f2b003ce" + ++ VEXT ** [ O.SimdVectorReg Q0; O.SimdVectorReg Q8; O.SimdVectorReg Q7; + O.Imm 3L ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTyp8)) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (5)`` () = + "eef10b62" + ++ VNEG ** [ O.SimdVectorReg D16; O.SimdVectorReg D18 ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTypF64)) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (6)`` () = + "f3409f0f" + ++ VPMAX ** [ O.SimdVectorReg D25; O.SimdVectorReg D0; O.SimdVectorReg D15 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypF32)) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (7)`` () = + "f3b400c2" + ++ VREV32 ** [ O.SimdVectorReg Q0; O.SimdVectorReg Q1 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTyp16)) + + [] + member __.``[ARMv7] Misc Advanced SIMD data-processing Parse test (8)`` () = + "f3b35b43" + ++ VTBX ** [ O.SimdVectorReg D5; O.SimdVectorRegs [ D3; D4; D5; D6; ]; + O.SimdVectorReg D3 ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTyp8)) + +/// A4.14 Floating-point data-processing instructions +[] +type FPDataProcessingClass () = + [] + member __.``[ARMv7] Floating-point data-processing Parse test (1)`` () = + "eeb50bc0" + ++ VCMPE ** [ O.SimdVectorReg D0; O.Imm 0L ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTypF64)) + + [] + member __.``[ARMv7] Floating-point data-processing Parse test (2)`` () = + "eeb82a68" + ++ VCVT ** [ O.SimdVectorReg S4; O.SimdVectorReg S17 ] + ||> testNoWbackNoQ Condition.AL (Some (TwoDT (SIMDTypF32, SIMDTypU32))) + + [] + member __.``[ARMv7] Floating-point data-processing Parse test (3)`` () = + "eeb30a43" + ++ VCVTB ** [ O.SimdVectorReg S0; O.SimdVectorReg S6 ] + ||> testNoWbackNoQ Condition.AL (Some (TwoDT (SIMDTypF16, SIMDTypF32))) + + [] + member __.``[ARMv7] Floating-point data-processing Parse test (4)`` () = + "eeb23a02" + ++ VMOV ** [ O.SimdVectorReg S6; O.Imm 1091567616L ] + ||> testNoWbackNoQ Condition.AL (Some (OneDT SIMDTypF32)) + + [] + member __.``[ARMv7] Floating-point data-processing Parse test (5)`` () = + "f3d2c460" + ++ VMLS ** [ O.SimdVectorReg Q14; O.SimdVectorReg Q1; + O.SimdScalarReg (D0, Some 2uy) ] + ||> testNoWbackNoQ Condition.UN (Some (OneDT SIMDTypI16)) \ No newline at end of file diff --git a/src/FrontEnd/BinLifter.Tests/ARM64.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/ARM64.Lifter.Tests.fs new file mode 100644 index 00000000..97bba24f --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/ARM64.Lifter.Tests.fs @@ -0,0 +1,77 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.ARM64Lifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM64 +open B2R2.BinIR.LowUIR.AST.InfixOp +open type Register + +[] +module TestHelper = + let num v = BitVector.OfUInt32 v 32 |> AST.num + + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) + + let isa = ISA.Init Architecture.AARCH64 Endian.Big + + let ctxt = ARM64TranslationContext isa + + let inline ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + let inline ( ++ ) (byteStr: string) (givenStmts: Stmt[]) = + ByteArray.ofHexString byteStr, givenStmts + + let test (bytes: byte[], givenStmts) = + let parser = ARM64Parser (isa) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) + CollectionAssert.AreEqual (givenStmts, unwrapStmts <| ins.Translate ctxt) + +[] +type ARM64UnitTest () = + [] + member __.``[AArch64] ADD (immedate) lift test`` () = + "114dc4ba" + ++ [| !.X26 := AST.zext 64 + ((AST.xtlo 32 !.X5 .+ num 0x371000u .+ num 0x0u)) |] + |> test + + [] + member __.``[AArch64] ADD (extended register) lift test`` () = + "0b3f43ff" + ++ [| !.SP := AST.zext 64 + (AST.xtlo 32 !.SP .+ AST.xtlo 32 !.XZR .+ num 0x0u) |] + |> test + + [] + member __.``[AArch64] ADD (shifted register) lift test`` () = + "0b8e5f9b" + ++ [| !.X27 := AST.zext 64 + (AST.xtlo 32 !.X28 .+ (AST.xtlo 32 !.X14 ?>> num 0x17u) + .+ num 0x0u) |] + |> test diff --git a/src/FrontEnd/BinLifter.Tests/ARM64.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/ARM64.Parser.Tests.fs new file mode 100644 index 00000000..ece61b87 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/ARM64.Parser.Tests.fs @@ -0,0 +1,4375 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.ARM64 + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter.ARM64 +open B2R2.FrontEnd.BinLifter.ARM64.OperandHelper +open type Opcode +open type Register + +/// Shortcut for creating operands. +type O = + static member Reg (r) = + OprRegister r + + static member RegOffset (r) = + OprExtReg r + + static member MemBaseReg (baseReg, offsetReg, typ: ExtendType, imm) = + memBaseReg (baseReg, offsetReg, Some <| ExtRegOffset (typ, imm)) + + static member MemBaseReg (baseReg, offsetReg, typ: SRType, imm) = + memBaseReg (baseReg, offsetReg, Some <| ShiftOffset (typ, imm)) + + static member MemBaseImm (register, imm) = + memBaseImm (register, Some imm) + + static member MemBaseImm register = + memBaseImm (register, None) + + static member MemPreIdxImm (register, imm) = + memPreIdxImm (register, Some imm) + + static member MemPreIdxReg (baseReg, offsetReg, imm) = + memPreIdxReg (baseReg, offsetReg, Some imm) + + static member MemPostIdxImm (register, imm) = + memPostIdxImm (register, Some imm) + + static member MemPostIdxReg (baseReg, offsetReg, imm) = + memPostIdxReg (baseReg, offsetReg, Some imm) + + static member MemPostIdxReg (baseReg, offsetReg) = + memPostIdxReg (baseReg, offsetReg, None) + + static member MemLabel label = + memLabel label + + static member Imm (v) = + OprImm v + + static member Shift (srType, v: int64) = + OprShift (srType, Imm v) + + static member Shift (srType, r: Register) = + OprShift (srType, Reg r) + + static member LSB v = + OprLSB v + + static member Pstate st = + OprPstate st + + static member SIMDVecReg (reg: Register, typ: SIMDVector) = + SIMDVecReg (reg, typ) |> OprSIMD + + static member SIMDVecRegWithIdx (reg: Register, typ: SIMDVector, idx: Index) = + (reg, typ, idx) |> SIMDVecRegWithIdx |> OprSIMD + + static member SIMDList (lst: Register list, typ: SIMDVector) = + lst |> List.map (fun r -> SIMDVecReg (r, typ)) |> OprSIMDList + + static member SIMDList (lst: Register list, typ: SIMDVector, idx: Index) = + OprSIMDList <| List.map (fun reg -> SIMDVecRegWithIdx (reg, typ, idx)) lst + + static member Prefetch v = + OprPrfOp v + + static member ScalarReg r = + scalReg r + +let private test (bytes: byte[]) (opcode, oprs) = + let reader = BinReader.Init Endian.Big + let span = System.ReadOnlySpan bytes + let ins = ParsingMain.parse span reader 0UL + let opcode' = ins.Info.Opcode + let oprs' = ins.Info.Operands + Assert.AreEqual (opcode', opcode) + Assert.AreEqual (oprs', oprs) + +let private operandsFromArray oprList = + let oprs = Array.ofList oprList + match oprs.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprs[0] + | 2 -> TwoOperands (oprs[0], oprs[1]) + | 3 -> ThreeOperands (oprs[0], oprs[1], oprs[2]) + | 4 -> FourOperands (oprs[0], oprs[1], oprs[2], oprs[3]) + | 5 -> FiveOperands (oprs[0], oprs[1], oprs[2], oprs[3], oprs[4]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +/// C4.2 Data processing - immediate +[] +type DataProcessingImmClass () = + /// C4.2.1 Add/subtract (immediate) + [] + member __.``[AArch64] Add/subtract (immedate) Parse Test`` () = + "114dc4ba" + ++ ADD ** [ O.Reg W26; O.Reg W5; O.Imm 0x371L; O.Shift (SRTypeLSL, 12L) ] + ||> test + + [] + member __.``C4.2.2 Bit Field (1)`` () = + "13010401" + ++ SBFX ** [ O.Reg W1; O.Reg W0; O.Imm 0x1L; O.Imm 0x1L ] + ||> test + + [] + member __.``C4.2.3 Extract (1)`` () = + "93c00422" + ++ EXTR ** [ O.Reg X2; O.Reg X1; O.Reg X0; O.LSB 0x1uy ] + ||> test + + [] + member __.``C4.2.4 Logical (immediate) (1)`` () = + "12010401" + ++ AND ** [ O.Reg W1; O.Reg W0; O.Imm 0x80000001L ] + ||> test + + [] + member __.``C4.2.4 Logical (immediate) (2)`` () = + "12030c01" + ++ AND ** [ O.Reg W1; O.Reg W0; O.Imm 0xE0000001L ] + ||> test + + [] + member __.``C4.2.4 Logical (immediate) (3)`` () = + "12200401" + ++ AND ** [ O.Reg W1; O.Reg W0; O.Imm 0x3L ] + ||> test + + [] + member __.``C4.2.4 Logical (immediate) (4)`` () = + "121a7821" + ++ AND ** [ O.Reg W1; O.Reg W1; O.Imm 0xffffffdfL ] + ||> test + + [] + member __.``C4.2.4 Logical (immediate) (5)`` () = + "92200401" + ++ AND ** [ O.Reg X1; O.Reg X0; O.Imm 0x300000003L ] + ||> test + + [] + member __.``C4.2.5 Move wide (immediate) (1)`` () = + "92a00015" + ++ MOVN ** [ O.Reg X21; O.Imm 0x0L; O.Shift (SRTypeLSL, 0x10L) ] + ||> test + + [] + member __.``C4.2.5 Move wide (immediate) (2)`` () = + "92e3ffbf" + ++ MOV ** [ O.Reg XZR; O.Imm 0xE002FFFFFFFFFFFFL ] + ||> test + + [] + member __.``C4.2.5 Move wide (immediate) (3)`` () = + "12b0001a" + ++ MOV ** [ O.Reg W26; O.Imm 0x7FFFFFFFL ] + ||> test + + [] + member __.``C4.2.6 PC-rel. addressing (1)`` () = + "707ff067" + ++ ADR ** [ O.Reg X7; O.MemLabel 0xffe0fL ] + ||> test + +/// C4.3 Branches, exception generating and system instructions +[] +type BranchesAndExcepGenAndSystemClass () = + [] + member __.``C4.3.1 Compare & branch (immediate) (1)`` () = + "b4041023" + ++ CBZ ** [ O.Reg X3; O.MemLabel 0x8204L ] + ||> test + + [] + member __.``C4.3.2 Conditional branch (immediate) (1)`` () = + "54000021" + ++ BNE ** [ O.MemLabel 0x4L ] + ||> test + + [] + member __.``C4.3.3 Exception generation (1)`` () = + "d4000061" + ++ SVC ** [ O.Imm 0x3L ] + ||> test + + [] + member __.``C4.3.4 System (1)`` () = + "d50042bf" + ++ MSR ** [ O.Pstate SPSEL; O.Imm 0x2L ] + ||> test + + [] + member __.``C4.3.4 System (2)`` () = + "d50342df" + ++ MSR ** [ O.Pstate DAIFSET; O.Imm 0x2L ] + ||> test + + [] + member __.``C4.3.4 System (3)`` () = + "d50320df" + ++ HINT ** [ O.Imm 0x6L ] + ||> test + + [] + member __.``C4.3.4 System (4)`` () = + "d50320bf" + ++ SEVL ** [] + ||> test + + [] + member __.``C4.3.4 System (5)`` () = + "d50b7423" + ++ DCZVA ** [ O.Reg X3 ] + ||> test + + [] + member __.``C4.3.4 System (6)`` () = + "d528f4d8" + ++ SYSL ** [ O.Reg X24; O.Imm 0L; O.Reg C15; O.Reg C4; O.Imm 6L ] + ||> test + + [] + member __.``C4.3.4 System (7)`` () = + "d51c6080" + ++ MSR ** [ O.Reg HPFAREL2; O.Reg X0 ] + ||> test + + [] + member __.``C4.3.4 System (8)`` () = + "d5181020" + ++ MSR ** [ O.Reg ACTLREL1; O.Reg X0 ] + ||> test + + [] + member __.``C4.3.4 System (9)`` () = + "d5381020" + ++ MRS ** [ O.Reg X0; O.Reg ACTLREL1 ] + ||> test + + [] + member __.``C4.3.5 Test & branch (immediate) (1)`` () = + "b6080043" + ++ TBZ ** [ O.Reg X3; O.Imm 0x21L; O.MemLabel 0x8L ] + ||> test + + [] + member __.``C4.3.6 Unconditional branch (immediate) (1)`` () = + "14082a09" + ++ B ** [ O.MemLabel 0x20a824L ] + ||> test + + [] + member __.``C4.3.7 Unconditional branch (register) (1)`` () = + "d61f03e0" + ++ BR ** [ O.Reg XZR ] + ||> test + +/// C4.4 Loads and stores +[] +type LoadAndStoreClass () = + [] + member __.``C4.4.1 load/store multiple structures (1)`` () = + "0c0001c5" + ++ ST4 ** [ O.SIMDList ([ V5; V6; V7; V8 ], EightB); O.MemBaseImm X14 ] + ||> test + + [] + member __.``C4.4.1 load/store multiple structures (2)`` () = + "0c0081f8" + ++ ST2 ** [ O.SIMDList ([ V24; V25 ], EightB); O.MemBaseImm X15 ] + ||> test + + [] + member __.``C4.4.1 load/store multiple structures (3)`` () = + "0c402f3d" + ++ LD1 ** [ O.SIMDList ([ V29; V30; V31; V0 ], OneD); O.MemBaseImm X25 ] + ||> test + + [] + member __.``C4.4.2 load/store multiple structures (post-indexed) (1)`` () = + "0c800421" + ++ ST4 ** [ O.SIMDList ([ V1; V2; V3; V4 ], FourH) + O.MemPostIdxReg (X1, X0) ] + ||> test + + [] + member __.``C4.4.2 load/store multiple structures (post-indexed) (2)`` () = + "0c950539" + ++ ST4 ** [ O.SIMDList ([ V25; V26; V27; V28 ], FourH) + O.MemPostIdxReg (X9, X21) ] + ||> test + + [] + member __.``C4.4.2 load/store multiple structures (post-indexed) (3)`` () = + "4c9f0684" + ++ ST4 ** [ O.SIMDList ([ V4; V5; V6; V7 ], EightH) + O.MemPostIdxImm (X20, 0x40L) ] + ||> test + + [] + member __.``C4.4.2 load/store multiple structures (post-indexed) (4)`` () = + "4cca46be" + ++ LD3 ** [ O.SIMDList ([ V30; V31; V0 ], EightH) + O.MemPostIdxReg (X21, X10) ] + ||> test + + [] + member __.``C4.4.2 load/store multiple structures (post-indexed) (5)`` () = + "4cdf0684" + ++ LD4 ** [ O.SIMDList ([ V4; V5; V6; V7 ], EightH) + O.MemPostIdxImm (X20, 0x40L) ] + ||> test + + [] + member __.``C4.4.3 load/store single structure (1)`` () = + "0d00147e" + ++ ST1 ** [ O.SIMDList ([ V30 ], VecB, 5uy); O.MemBaseImm X3 ] + ||> test + + [] + member __.``C4.4.3 load/store single structure (2)`` () = + "0d0025c3" + ++ ST3 ** [ O.SIMDList ([ V3; V4; V5 ], VecB, 1uy); O.MemBaseImm X14 ] + ||> test + + [] + member __.``C4.4.3 load/store single structure (3)`` () = + "4d20b2bd" + ++ ST4 ** [ O.SIMDList ([ V29; V30; V31; V0 ], VecS, 3uy) + O.MemBaseImm X21 ] + ||> test + + [] + member __.``C4.4.3 load/store single structure (4)`` () = + "4d601d4a" + ++ LD2 ** [ O.SIMDList ([ V10; V11 ], VecB, 0xfuy); O.MemBaseImm X10 ] + ||> test + + [] + member __.``C4.4.3 load/store single structure (5)`` () = + "4d40e6b5" + ++ LD3R ** [ O.SIMDList ([ V21; V22; V23 ], EightH); O.MemBaseImm X21 ] + ||> test + + [] + member __.``C4.4.4 load/store single structure (post-indexed) (1)`` () = + "0d8a06be" + ++ ST1 ** [ O.SIMDList ([ V30 ], VecB, 1uy); O.MemPostIdxReg (X21, X10) ] + ||> test + + [] + member __.``C4.4.4 load/store single structure (post-indexed) (2)`` () = + "4d9f597e" + ++ ST1 ** [ O.SIMDList ([ V30 ], VecH, 7uy) + O.MemPostIdxImm (X11, 0x2L) ] + ||> test + + [] + member __.``C4.4.4 load/store single structure (post-indexed) (3)`` () = + "4db581bd" + ++ ST2 ** [ O.SIMDList ([ V29; V30 ], VecS, 2uy) + O.MemPostIdxReg (X13, X21) ] + ||> test + + [] + member __.``C4.4.4 load/store single structure (post-indexed) (4)`` () = + "0dca06be" + ++ LD1 ** [ O.SIMDList ([ V30 ], VecB, 1uy); O.MemPostIdxReg (X21, X10) ] + ||> test + + [] + member __.``C4.4.4 load/store single structure (post-indexed) (5)`` () = + "4dff39fd" + ++ LD4 ** [ O.SIMDList ([ V29; V30; V31; V0 ], VecB, 0xeuy) + O.MemPostIdxImm (X15, 0x4L) ] + ||> test + + [] + member __.``C4.4.5 Load register (literal) (1)`` () = + "58531c49" + ++ LDR ** [ O.Reg X9; O.MemLabel 0xa6388L ] + ||> test + + [] + member __.``C4.4.5 Load register (literal) (2)`` () = + "9880001e" + ++ LDRSW ** [ O.Reg X30; O.MemLabel 0xfffffffffff00000L ] + ||> test + + [] + member __.``C4.4.5 Load register (literal) (3)`` () = + "d800802b" + ++ PRFM ** [ O.Prefetch PLIL2STRM; O.MemLabel 0x1004L ] + ||> test + + [] + member __.``C4.4.6 Load/store exclusive (1)`` () = + "08147cb5" + ++ STXRB ** [ O.Reg W20; O.Reg W21; O.MemBaseImm X5 ] + ||> test + + [] + member __.``C4.4.6 Load/store exclusive (2)`` () = + "882b04c2" + ++ STXP ** [ O.Reg W11; O.Reg W2; O.Reg W1; O.MemBaseImm X6 ] + ||> test + + [] + member __.``C4.4.6 Load/store exclusive (3)`` () = + "085f7d7a" + ++ LDXRB ** [ O.Reg W26; O.MemBaseImm X11 ] + ||> test + + [] + member __.``C4.4.7 Load/store no-allocate pair (offset) (1)`` () = + "280c2aa3" + ++ STNP ** [ O.Reg W3; O.Reg W10; O.MemBaseImm (X21, 0x60L) ] + ||> test + + [] + member __.``C4.4.7 Load/store no-allocate pair (offset) (2)`` () = + "ac1505b5" + ++ STNP ** [ O.ScalarReg Q21; O.ScalarReg Q1; O.MemBaseImm (X13, 0x2a0L) ] + ||> test + + [] + member __.``C4.4.8 Load/store register (immediate post-indexed) (1)`` () = + "3810a423" + ++ STRB ** [ O.Reg W3; O.MemPostIdxImm (X1, 0xffffffffffffff0aL) ] + ||> test + + [] + member __.``C4.4.8 Load/store register (immediate post-indexed) (2)`` () = + "38cea4b2" + ++ LDRSB ** [ O.Reg W18; O.MemPostIdxImm (X5, 0xeaL) ] + ||> test + + [] + member __.``C4.4.8 Load/store register (immediate post-indexed) (3)`` () = + "7c0ca422" + ++ STR ** [ O.ScalarReg H2; O.MemPostIdxImm (X1, 0xcaL) ] + ||> test + + [] + member __.``C4.4.8 Load/store register (immediate post-indexed) (4)`` () = + "781004f5" + ++ STRH ** [ O.Reg W21; O.MemPostIdxImm (X7, 0xffffffffffffff00L) ] + ||> test + + [] + member __.``C4.4.8 Load/store register (immediate post-indexed) (5)`` () = + "b8803555" + ++ LDRSW ** [ O.Reg X21; O.MemPostIdxImm (X10, 0x3L) ] + ||> test + + [] + member __.``C4.4.9 Load/store register (immediate pre-indexed) (1)`` () = + "3800fcb1" + ++ STRB ** [ O.Reg W17; O.MemPreIdxImm (X5, 0xfL) ] + ||> test + + [] + member __.``C4.4.9 Load/store register (immediate pre-indexed) (2)`` () = + "7c00fc6a" + ++ STR ** [ O.ScalarReg H10; O.MemPreIdxImm (X3, 0xfL) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (1)`` () = + "38214867" + ++ STRB ** [ O.Reg W7; O.MemBaseReg (X3, W1, ExtUXTW, None) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (2)`` () = + "38235867" + ++ STRB ** [ O.Reg W7; O.MemBaseReg (X3, W3, ExtUXTW, Some 0x0L) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (3)`` () = + "3820782c" + ++ STRB ** [ O.Reg W12; O.MemBaseReg (X1, X0, SRTypeLSL, Imm 0x0L) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (4)`` () = + "7867cabf" + ++ LDRH ** [ O.Reg WZR; O.MemBaseReg (X21, W7, ExtSXTW, None) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (5)`` () = + "78e37871" + ++ LDRSH ** [ O.Reg W17; O.MemBaseReg (X3, X3, SRTypeLSL, Imm 0x1L) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (6)`` () = + "f8a35867" + ++ PRFM ** [ O.Imm 0x7L; O.MemBaseReg (X3, W3, ExtUXTW, Some 0x3L) ] + ||> test + + [] + member __.``C4.4.10 Load/store register (register offset) (7)`` () = + "f8a3586c" + ++ PRFM ** [ O.Prefetch PLIL3KEEP + O.MemBaseReg (X3, W3, ExtUXTW, Some 0x3L) ] + ||> test + + [] + member __.``C4.4.11 Load/store register (unprivileged) (1)`` () = + "380198ee" + ++ STTRB ** [ O.Reg W14; O.MemBaseImm (X7, 0x19L) ] + ||> test + + [] + member __.``C4.4.11 Load/store register (unprivileged) (2)`` () = + "781188ba" + ++ STTRH ** [ O.Reg W26; O.MemBaseImm (X5, 0xffffffffffffff18L) ] + ||> test + + [] + member __.``C4.4.11 Load/store register (unprivileged) (3)`` () = + "b881f86a" + ++ LDTRSW ** [ O.Reg X10; O.MemBaseImm (X3, 0x1fL) ] + ||> test + + [] + member __.``C4.4.12 Load/store register (unscaled immediate) (1)`` () = + "3806a0f8" + ++ STURB ** [ O.Reg W24; O.MemBaseImm (X7, 0x6aL) ] + ||> test + + [] + member __.``C4.4.12 Load/store register (unscaled immediate) (2)`` () = + "3cce0283" + ++ LDUR ** [ O.ScalarReg Q3; O.MemBaseImm (X20, 0xe0L) ] + ||> test + + [] + member __.``C4.4.12 Load/store register (unscaled immediate) (3)`` () = + "f881f07c" + ++ PRFUM ** [ O.Imm 0x1cL; O.MemBaseImm (X3, 0x1fL) ] + ||> test + + [] + member __.``C4.4.13 Load/store register (unsigned immediate) (1)`` () = + "391557ff" + ++ STRB ** [ O.Reg WZR; O.MemBaseImm (SP, 0x555L) ] + ||> test + + [] + member __.``C4.4.13 Load/store register (unsigned immediate) (2)`` () = + "bd1fffff" + ++ STR ** [ O.ScalarReg S31; O.MemBaseImm (SP, 0x1ffcL) ] + ||> test + + [] + member __.``C4.4.13 Load/store register (unsigned immediate) (3)`` () = + "f9be01f2" + ++ PRFM ** [ O.Prefetch PSTL2KEEP; O.MemBaseImm (X15, 0x7c00L) ] + ||> test + + [] + member __.``C4.4.14 Load/store register pair (offset) (1)`` () = + "2961cbb9" + ++ LDP ** [ O.Reg W25; O.Reg W18; O.MemBaseImm (X29, 0xffffffffffffff0cL) ] + ||> test + + [] + member __.``C4.4.15 Load/store register pair (post-indexed) (1)`` () = + "a89fd7eb" + ++ STP ** [ O.Reg X11; O.Reg X21; O.MemPostIdxImm (SP, 0x1f8L) ] + ||> test + + [] + member __.``C4.4.15 Load/store register pair (post-indexed) (2)`` () = + "68cfdfdf" + ++ LDPSW ** [ O.Reg XZR; O.Reg X23; O.MemPostIdxImm (X30, 0x7cL) ] + ||> test + + [] + member __.``C4.4.16 Load/store register pair (pre-indexed) (1)`` () = + "a99fffff" + ++ STP ** [ O.Reg XZR; O.Reg XZR; O.MemPreIdxImm (SP, 0x1f8L) ] + ||> test + +/// C4.5 Data processing - register +[] +type DataPorcessingRegClass () = + [] + member __.``4.5.1 Add/subtract (extended register) (1)`` () = + "0b3f43ff" + ++ ADD ** [ O.Reg WSP; O.Reg WSP; O.Reg WZR; O.RegOffset None ] + ||> test + + [] + member __.``4.5.1 Add/subtract (extended register) (2)`` () = + "0b3f4bff" + ++ ADD ** [ O.Reg WSP; O.Reg WSP; O.Reg WZR + O.RegOffset (Some (ShiftOffset (SRTypeLSL, Imm 2L))) ] + ||> test + + [] + member __.``4.5.1 Add/subtract (extended register) (3)`` () = + "8b2a495f" + ++ ADD ** [ O.Reg SP; O.Reg X10; O.Reg W10 + O.RegOffset (Some (ExtRegOffset (ExtUXTW, Some 2L))) ] + ||> test + + [] + member __.``4.5.1 Add/subtract (extended register) (4)`` () = + "ab2e67ff" + ++ CMN ** [ O.Reg SP; O.Reg X14 + O.RegOffset (Some (ShiftOffset (SRTypeLSL, Imm 1L))) ] + ||> test + + [] + member __.``4.5.2 Add/subtract (shifted register) (1)`` () = + "0b8e5f9b" + ++ ADD ** [ O.Reg W27; O.Reg W28; O.Reg W14; O.Shift (SRTypeASR, 23L) ] + ||> test + + [] + member __.``4.5.2 Add/subtract (shifted register) (2)`` () = + "6b4e1fab" + ++ SUBS ** [ O.Reg W11; O.Reg W29; O.Reg W14; O.Shift (SRTypeLSR, 7L) ] + ||> test + + [] + member __.``4.5.2 Add/subtract (shifted register) (3)`` () = + "ab8e1fb2" + ++ ADDS ** [ O.Reg X18; O.Reg X29; O.Reg X14; O.Shift (SRTypeASR, 7L) ] + ||> test + + [] + member __.``4.5.3 Add/subtract (with carry) (1)`` () = + "ba0a02bf" + ++ ADCS ** [ O.Reg XZR; O.Reg X21; O.Reg X10 ] + ||> test + + [] + member __.``4.5.3 Add/subtract (with carry) (2)`` () = + "5a0b03fe" + ++ NGC ** [ O.Reg W30; O.Reg W11 ] + ||> test + + [] + member __.``4.5.4 Conditional compare (immediate) (1)`` () = + "ba55c868" + ++ CCMN ** [ O.Reg X3; O.Imm 0x15L; OprNZCV 8uy; OprCond GT ] + ||> test + + [] + member __.``4.5.5 Conditional compare (register) (1)`` () = + "ba5c51ef" + ++ CCMN ** [ O.Reg X15; O.Reg X28; OprNZCV 0xfuy; OprCond PL ] + ||> test + + [] + member __.``4.5.6 Conditional select (1)`` () = + "9a8692fc" + ++ CSEL ** [ O.Reg X28; O.Reg X23; O.Reg X6; OprCond LS ] + ||> test + + [] + member __.``4.5.6 Conditional select (2)`` () = + "1a902415" + ++ CSINC ** [ O.Reg W21; O.Reg W0; O.Reg W16; OprCond CS ] // HS + ||> test + + [] + member __.``4.5.6 Conditional select (3)`` () = + "1a902615" + ++ CINC ** [ O.Reg W21; O.Reg W16; OprCond CC ] // LO + ||> test + + [] + member __.``4.5.6 Conditional select (4)`` () = + "1a9fc7e7" + ++ CSET ** [ O.Reg W7; OprCond LE ] + ||> test + + [] + member __.``4.5.6 Conditional select (5)`` () = + "da87c0ea" + ++ CINV ** [ O.Reg X10; O.Reg X7; OprCond LE ] + ||> test + + [] + member __.``4.5.6 Conditional select (6)`` () = + "da9fc3ea" + ++ CSETM ** [ O.Reg X10; OprCond LE ] + ||> test + + [] + member __.``4.5.6 Conditional select (7)`` () = + "da9fc36a" + ++ CSINV ** [ O.Reg X10; O.Reg X27; O.Reg XZR; OprCond GT ] + ||> test + + [] + member __.``4.5.6 Conditional select (8)`` () = + "5a8ae6be" + ++ CSNEG ** [ O.Reg W30; O.Reg W21; O.Reg W10; OprCond AL ] + ||> test + + [] + member __.``4.5.6 Conditional select (9)`` () = + "5a95c6be" + ++ CNEG ** [ O.Reg W30; O.Reg W21; OprCond LE ] + ||> test + + [] + member __.``4.5.7 Data-processing (1 source) (1)`` () = + "5ac0017c" + ++ RBIT ** [ O.Reg W28; O.Reg W11 ] + ||> test + + [] + member __.``4.5.7 Data-processing (1 source) (2)`` () = + "dac0157f" + ++ CLS ** [ O.Reg XZR; O.Reg X11 ] + ||> test + + [] + member __.``4.5.7 Data-processing (1 source) (3)`` () = + "dac009fe" + ++ REV32 ** [ O.Reg X30; O.Reg X15 ] + ||> test + + [] + member __.``4.5.8 Data-processing (2 source) (1)`` () = + "1ac90afe" + ++ UDIV ** [ O.Reg W30; O.Reg W23; O.Reg W9 ] + ||> test + + [] + member __.``4.5.8 Data-processing (2 source) (2)`` () = + "9ada5c7d" + ++ CRC32CX ** [ O.Reg W29; O.Reg W3; O.Reg X26 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (1)`` () = + "9b0a2f87" + ++ MADD ** [ O.Reg X7; O.Reg X28; O.Reg X10; O.Reg X11 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (2)`` () = + "9b0a7f87" + ++ MUL ** [ O.Reg X7; O.Reg X28; O.Reg X10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (3)`` () = + "9b0aaf87" + ++ MSUB ** [ O.Reg X7; O.Reg X28; O.Reg X10; O.Reg X11 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (4)`` () = + "9b2a2f87" + ++ SMADDL ** [ O.Reg X7; O.Reg W28; O.Reg W10; O.Reg X11 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (5)`` () = + "9b2aaf87" + ++ SMSUBL ** [ O.Reg X7; O.Reg W28; O.Reg W10; O.Reg X11 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (6)`` () = + "9b4a2f87" + ++ SMULH ** [ O.Reg X7; O.Reg X28; O.Reg X10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (7)`` () = + "9baa2f87" + ++ UMADDL ** [ O.Reg X7; O.Reg W28; O.Reg W10; O.Reg X11 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (8)`` () = + "9baaaf87" + ++ UMSUBL ** [ O.Reg X7; O.Reg W28; O.Reg W10; O.Reg X11 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (9)`` () = + "9bca2f87" + ++ UMULH ** [ O.Reg X7; O.Reg X28; O.Reg X10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (10)`` () = + "9b0aff87" + ++ MNEG ** [ O.Reg X7; O.Reg X28; O.Reg X10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (11)`` () = + "9b2a7f87" + ++ SMULL ** [ O.Reg X7; O.Reg W28; O.Reg W10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (12)`` () = + "9b2aff87" + ++ SMNEGL ** [ O.Reg X7; O.Reg W28; O.Reg W10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (13)`` () = + "9baa7f87" + ++ UMULL ** [ O.Reg X7; O.Reg W28; O.Reg W10 ] + ||> test + + [] + member __.``4.5.9 Data-processing (3 source) (14)`` () = + "9baaff87" + ++ UMNEGL ** [ O.Reg X7; O.Reg W28; O.Reg W10 ] + ||> test + + [] + member __.``4.5.10 Logical (shifted register) (1)`` () = + "8a583945" + ++ AND ** [ O.Reg X5; O.Reg X10; O.Reg X24; O.Shift (SRTypeLSR, 14L) ] + ||> test + + [] + member __.``4.5.10 Logical (shifted register) (2)`` () = + "2af61fba" + ++ ORN ** [ O.Reg W26; O.Reg W29; O.Reg W22; O.Shift (SRTypeROR, 7L) ] + ||> test + + [] + member __.``4.5.10 Logical (shifted register) (3)`` () = + "2af61ffa" + ++ MVN ** [ O.Reg W26; O.Reg W22; O.Shift (SRTypeROR, 0x7L) ] + ||> test + +/// C4.6 Data processing - SIMD and floating point +[] +type DataProcessingSIMDAndFPClass () = + [] + member __.``4.6.1 Advanced SIMD across lanes (1)`` () = + "4eb03ac2" + ++ SADDLV ** [ O.ScalarReg D2; O.SIMDVecReg (V22, FourS) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (2)`` () = + "0e30a8d2" + ++ SMAXV ** [ O.ScalarReg B18; O.SIMDVecReg (V6, EightB) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (3)`` () = + "0e71aa0a" + ++ SMINV ** [ O.ScalarReg H10; O.SIMDVecReg (V16, FourH) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (4)`` () = + "4e71b89a" + ++ ADDV ** [ O.ScalarReg H26; O.SIMDVecReg (V4, EightH) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (5)`` () = + "6eb03931" + ++ UADDLV ** [ O.ScalarReg D17; O.SIMDVecReg (V9, FourS) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (6)`` () = + "2e70ab88" + ++ UMAXV ** [ O.ScalarReg H8; O.SIMDVecReg (V28, FourH) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (7)`` () = + "6eb1aaea" + ++ UMINV ** [ O.ScalarReg S10; O.SIMDVecReg (V23, FourS) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (8)`` () = + "6e30ca4b" + ++ FMAXNMV ** [ O.ScalarReg S11; O.SIMDVecReg (V18, FourS) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (9)`` () = + "6e30f948" + ++ FMAXV ** [ O.ScalarReg S8; O.SIMDVecReg (V10, FourS) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (10)`` () = + "6eb0cacc" + ++ FMINNMV ** [ O.ScalarReg S12; O.SIMDVecReg (V22, FourS) ] + ||> test + + [] + member __.``4.6.1 Advanced SIMD across lanes (11)`` () = + "6eb0fac2" + ++ FMINV ** [ O.ScalarReg S2; O.SIMDVecReg (V22, FourS) ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (1)`` () = + "4e180486" + ++ DUP ** [ O.SIMDVecReg (V6, TwoD); O.SIMDVecRegWithIdx (V4, VecD, 1uy) ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (2)`` () = + "4e080c61" + ++ DUP ** [ O.SIMDVecReg (V1, TwoD); O.Reg X3 ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (3)`` () = + // Online HEX To ARM Conv error + "0e1e0ffc" + ++ DUP ** [ O.SIMDVecReg (V28, FourH); O.Reg WZR ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (4)`` () = + "0e020ffc" + ++ DUP ** [ O.SIMDVecReg (V28, FourH); O.Reg WZR ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (5)`` () = + "0e022cfa" + ++ SMOV ** [ O.Reg W26; O.SIMDVecRegWithIdx (V7, VecH, 0uy) ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (6)`` () = + "0e013dc3" + ++ UMOV ** [ O.Reg W3; O.SIMDVecRegWithIdx (V14, VecB, 0uy) ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (7)`` () = + "0e043dc3" + ++ MOV ** [ O.Reg W3; O.SIMDVecRegWithIdx (V14, VecS, 0uy) ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (8)`` () = + "4e083dc3" + ++ MOV ** [ O.Reg X3; O.SIMDVecRegWithIdx (V14, VecD, 0uy) ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (9)`` () = + "4e041c29" + ++ INS ** [ O.SIMDVecRegWithIdx (V9, VecS, 0uy); O.Reg W1 ] + ||> test + + [] + member __.``4.6.2 Advanced SIMD copy (10)`` () = + "6e0274c5" + ++ INS ** [ O.SIMDVecRegWithIdx (V5, VecH, 0uy) + O.SIMDVecRegWithIdx (V6, VecH, 7uy) ] + ||> test + + [] + member __.``4.6.3 Advanced SIMD extract (1)`` () = + "6e064983" + ++ EXT ** [ O.SIMDVecReg (V3, SixteenB); O.SIMDVecReg (V12, SixteenB) + O.SIMDVecReg (V6, SixteenB); O.Imm 9L ] + ||> test + + [] + member __.``4.6.3 Advanced SIMD extract (2)`` () = + "2e0738fc" + ++ EXT ** [ O.SIMDVecReg (V28, EightB); O.SIMDVecReg (V7, EightB) + O.SIMDVecReg (V7, EightB); O.Imm 7L ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (1)`` () = + "4f056559" + ++ MOVI ** [ O.SIMDVecReg (V25, FourS); O.Imm 0xAAL + O.Shift (SRTypeLSL, 24L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (2)`` () = + "4f050559" + ++ MOVI ** [ O.SIMDVecReg (V25, FourS); O.Imm 0xAAL ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (3)`` () = + "4f0234c5" + ++ ORR ** [ O.SIMDVecReg (V5, FourS); O.Imm 0x46L; O.Shift (SRTypeLSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (4)`` () = + "4f01e5d9" + ++ MOVI ** [ O.SIMDVecReg (V25, SixteenB); O.Imm 0x2EL ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (5)`` () = + "0f06b4e5" + ++ ORR ** [ O.SIMDVecReg (V5, FourH); O.Imm 0xC7L; O.Shift (SRTypeLSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (6)`` () = + "4f04a759" + ++ MOVI ** [ O.SIMDVecReg (V25, EightH); O.Imm 0x9AL + O.Shift (SRTypeLSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (7)`` () = + "4f05c655" + ++ MOVI ** [ O.SIMDVecReg (V21, FourS); O.Imm 0xB2L + O.Shift (SRTypeMSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (8)`` () = + "4f05f4e5" + ++ FMOV ** [ O.SIMDVecReg (V5, FourS); OprFPImm -11.5 ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (9)`` () = + "6f0724d5" + ++ MVNI ** [ O.SIMDVecReg (V21, FourS); O.Imm 0xE6L + O.Shift (SRTypeLSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (10)`` () = + "2f0536a7" + ++ BIC ** [ O.SIMDVecReg (V7, TwoS); O.Imm 0xB5L; O.Shift (SRTypeLSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (11)`` () = + "6f07a4d5" + ++ MVNI ** [ O.SIMDVecReg (V21, EightH); O.Imm 0xE6L + O.Shift (SRTypeLSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (12)`` () = + "2f0596a7" + ++ BIC ** [ O.SIMDVecReg (V7, FourH); O.Imm 0xB5L ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (13)`` () = + "6f07c4d5" + ++ MVNI ** [ O.SIMDVecReg (V21, FourS); O.Imm 0xE6L + O.Shift (SRTypeMSL, 8L) ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (14)`` () = + "2f05e75b" + ++ MOVI ** [ O.ScalarReg D27; O.Imm 0xFF00FFFFFF00FF00L ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (15)`` () = + "6f05e757" + ++ MOVI ** [ O.SIMDVecReg (V23, TwoD); O.Imm 0xFF00FFFFFF00FF00L ] + ||> test + + [] + member __.``4.6.4 Advanced SIMD modified immediate (16)`` () = + "6f05f4e5" + ++ FMOV ** [ O.SIMDVecReg (V5, TwoD); OprFPImm -11.5 ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (1)`` () = + "4e4e1983" + ++ UZP1 ** [ O.SIMDVecReg (V3, EightH); O.SIMDVecReg (V12, EightH) + O.SIMDVecReg (V14, EightH) ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (2)`` () = + "0e8728fe" + ++ TRN1 ** [ O.SIMDVecReg (V30, TwoS); O.SIMDVecReg (V7, TwoS) + O.SIMDVecReg (V7, TwoS) ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (3)`` () = + "4e03383c" + ++ ZIP1 ** [ O.SIMDVecReg (V28, SixteenB); O.SIMDVecReg (V1, SixteenB) + O.SIMDVecReg (V3, SixteenB) ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (4)`` () = + "0e0738c1" + ++ ZIP1 ** [ O.SIMDVecReg (V1, EightB); O.SIMDVecReg (V6, EightB) + O.SIMDVecReg (V7, EightB) ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (5)`` () = + "4ec158c6" + ++ UZP2 ** [ O.SIMDVecReg (V6, TwoD); O.SIMDVecReg (V6, TwoD) + O.SIMDVecReg (V1, TwoD) ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (6)`` () = + "0e8768c3" + ++ TRN2 ** [ O.SIMDVecReg (V3, TwoS); O.SIMDVecReg (V6, TwoS) + O.SIMDVecReg (V7, TwoS) ] + ||> test + + [] + member __.``4.6.5 Advanced SIMD permute (7)`` () = + "4e017885" + ++ ZIP2 ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V4, SixteenB) + O.SIMDVecReg (V1, SixteenB) ] + ||> test + + [] + member __.``4.6.6 Advanced SIMD scalar copy (1)`` () = + "5e08054a" + ++ MOV ** [ O.ScalarReg D10; O.SIMDVecRegWithIdx (V10, VecD, 0uy) ] + ||> test + + [] + member __.``4.6.6 Advanced SIMD scalar copy (2)`` () = + "5e070541" + ++ MOV ** [ O.ScalarReg B1; O.SIMDVecRegWithIdx (V10, VecB, 3uy) ] + ||> test + + [] + member __.``4.6.7 Advanced SIMD scalar pairwise (1)`` () = + "5ef1b867" + ++ ADDP ** [ O.ScalarReg D7; O.SIMDVecReg (V3, TwoD) ] + ||> test + + [] + member __.``4.6.7 Advanced SIMD scalar pairwise (2)`` () = + "7e70c9cf" + ++ FMAXNMP ** [ O.ScalarReg D15; O.SIMDVecReg (V14, TwoD) ] + ||> test + + [] + member __.``4.6.7 Advanced SIMD scalar pairwise (3)`` () = + "7e30d9ff" + ++ FADDP ** [ O.ScalarReg S31; O.SIMDVecReg (V15, TwoS) ] + ||> test + + [] + member __.``4.6.7 Advanced SIMD scalar pairwise (4)`` () = + "7e70fa32" + ++ FMAXP ** [ O.ScalarReg D18; O.SIMDVecReg (V17, TwoD) ] + ||> test + + [] + member __.``4.6.7 Advanced SIMD scalar pairwise (5)`` () = + "7eb0c9c1" + ++ FMINNMP ** [ O.ScalarReg S1; O.SIMDVecReg (V14, TwoS) ] + ||> test + + [] + member __.``4.6.7 Advanced SIMD scalar pairwise (6)`` () = + "7ef0f827" + ++ FMINP ** [ O.ScalarReg D7; O.SIMDVecReg (V1, TwoD) ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (1)`` () = + "5f420541" + ++ SSHR ** [ O.ScalarReg D1; O.ScalarReg D10; O.Imm 0x3eL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (2)`` () = + "5f64147c" + ++ SSRA ** [ O.ScalarReg D28; O.ScalarReg D3; O.Imm 0x1cL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (3)`` () = + "5f5924e1" + ++ SRSHR ** [ O.ScalarReg D1; O.ScalarReg D7; O.Imm 0x27L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (4)`` () = + "5f7f34c3" + ++ SRSRA ** [ O.ScalarReg D3; O.ScalarReg D6; O.Imm 1L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (5)`` () = + "5f4254ed" + ++ SHL ** [ O.ScalarReg D13; O.ScalarReg D7; O.Imm 2L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (6)`` () = + "5f247619" + ++ SQSHL ** [ O.ScalarReg S25; O.ScalarReg S16; O.Imm 4L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (7)`` () = + "5f647619" + ++ SQSHL ** [ O.ScalarReg D25; O.ScalarReg D16; O.Imm 0x24L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (8)`` () = + "5f299587" + ++ SQSHRN ** [ O.ScalarReg S7; O.ScalarReg D12; O.Imm 0x17L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (9)`` () = + "5f1f9cf9" + ++ SQRSHRN ** [ O.ScalarReg H25; O.ScalarReg S7; O.Imm 1L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (10)`` () = + "5f61e4c1" + ++ SCVTF ** [ O.ScalarReg D1; O.ScalarReg D6; OprFbits 0x1fuy ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (11)`` () = + "5f5bfd0b" + ++ FCVTZS ** [ O.ScalarReg D11; O.ScalarReg D8; OprFbits 0x25uy ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (12)`` () = + "7f6905c7" + ++ USHR ** [ O.ScalarReg D7; O.ScalarReg D14; O.Imm 0x17L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (13)`` () = + "7f4a1431" + ++ USRA ** [ O.ScalarReg D17; O.ScalarReg D1; O.Imm 0x36L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (14)`` () = + "7f602449" + ++ URSHR ** [ O.ScalarReg D9; O.ScalarReg D2; O.Imm 0x20L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (15)`` () = + "7f4434c9" + ++ URSRA ** [ O.ScalarReg D9; O.ScalarReg D6; O.Imm 0x3cL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (16)`` () = + "7f6145c3" + ++ SRI ** [ O.ScalarReg D3; O.ScalarReg D14; O.Imm 0x1fL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (17)`` () = + "7f4e54c3" + ++ SLI ** [ O.ScalarReg D3; O.ScalarReg D6; O.Imm 0xeL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (18)`` () = + "7f2b6687" + ++ SQSHLU ** [ O.ScalarReg S7; O.ScalarReg S20; O.Imm 0xbL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (19)`` () = + "7f0b74f8" + ++ UQSHL ** [ O.ScalarReg B24; O.ScalarReg B7; O.Imm 3L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (20)`` () = + "7f2f858d" + ++ SQSHRUN ** [ O.ScalarReg S13; O.ScalarReg D12; O.Imm 0x11L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (21)`` () = + "7f3a8c30" + ++ SQRSHRUN ** [ O.ScalarReg S16; O.ScalarReg D1; O.Imm 6L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (22)`` () = + "7f1594cd" + ++ UQSHRN ** [ O.ScalarReg H13; O.ScalarReg S6; O.Imm 0xbL ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (23)`` () = + "7f0c9c46" + ++ UQRSHRN ** [ O.ScalarReg B6; O.ScalarReg H2; O.Imm 4L ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (24)`` () = + "7f24e4c1" + ++ UCVTF ** [ O.ScalarReg S1; O.ScalarReg S6; OprFbits 0x1cuy ] + ||> test + + [] + member __.``4.6.8 Advanced SIMD scalar shift by imm (25)`` () = + "7f51fc83" + ++ FCVTZU ** [ O.ScalarReg D3; O.ScalarReg D4; OprFbits 0x2fuy ] + ||> test + + [] + member __.``4.6.9 Advanced SIMD scalar three different (1)`` () = + "5ea693c2" + ++ SQDMLAL ** [ O.ScalarReg D2; O.ScalarReg S30; O.ScalarReg S6 ] + ||> test + + [] + member __.``4.6.9 Advanced SIMD scalar three different (2)`` () = + "5e61b006" + ++ SQDMLSL ** [ O.ScalarReg S6; O.ScalarReg H0; O.ScalarReg H1 ] + ||> test + + [] + member __.``4.6.9 Advanced SIMD scalar three different (3)`` () = + "5ea2d242" + ++ SQDMULL ** [ O.ScalarReg D2; O.ScalarReg S18; O.ScalarReg S2 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (1)`` () = + "5e210dfc" + ++ SQADD ** [ O.ScalarReg B28; O.ScalarReg B15; O.ScalarReg B1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (2)`` () = + "5e632fc5" + ++ SQSUB ** [ O.ScalarReg H5; O.ScalarReg H30; O.ScalarReg H3 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (3)`` () = + "5ee134c5" + ++ CMGT ** [ O.ScalarReg D5; O.ScalarReg D6; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (4)`` () = + "5ee73cca" + ++ CMGE ** [ O.ScalarReg D10; O.ScalarReg D6; O.ScalarReg D7 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (5)`` () = + "5eff441e" + ++ SSHL ** [ O.ScalarReg D30; O.ScalarReg D0; O.ScalarReg D31 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (6)`` () = + "5e294f0e" + ++ SQSHL ** [ O.ScalarReg B14; O.ScalarReg B24; O.ScalarReg B9 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (7)`` () = + "5efe5791" + ++ SRSHL ** [ O.ScalarReg D17; O.ScalarReg D28; O.ScalarReg D30 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (8)`` () = + "5e6e5e2e" + ++ SQRSHL ** [ O.ScalarReg H14; O.ScalarReg H17; O.ScalarReg H14 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (9)`` () = + "5ef88478" + ++ ADD ** [ O.ScalarReg D24; O.ScalarReg D3; O.ScalarReg D24 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (10)`` () = + "5efc8d8a" + ++ CMTST ** [ O.ScalarReg D10; O.ScalarReg D12; O.ScalarReg D28 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (11)`` () = + "5ea1b4f0" + ++ SQDMULH ** [ O.ScalarReg S16; O.ScalarReg S7; O.ScalarReg S1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (12)`` () = + "5e61df0c" + ++ FMULX ** [ O.ScalarReg D12; O.ScalarReg D24; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (13)`` () = + "5e38e4c1" + ++ FCMEQ ** [ O.ScalarReg S1; O.ScalarReg S6; O.ScalarReg S24 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (14)`` () = + "5e61fc44" + ++ FRECPS ** [ O.ScalarReg D4; O.ScalarReg D2; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (15)`` () = + "5ee1fe18" + ++ FRSQRTS ** [ O.ScalarReg D24; O.ScalarReg D16; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (16)`` () = + "7e610d12" + ++ UQADD ** [ O.ScalarReg H18; O.ScalarReg H8; O.ScalarReg H1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (17)`` () = + "7e2c2d81" + ++ UQSUB ** [ O.ScalarReg B1; O.ScalarReg B12; O.ScalarReg B12 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (18)`` () = + "7ee134be" + ++ CMHI ** [ O.ScalarReg D30; O.ScalarReg D5; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (19)`` () = + "7ee33f12" + ++ CMHS ** [ O.ScalarReg D18; O.ScalarReg D24; O.ScalarReg D3 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (20)`` () = + "7ee34541" + ++ USHL ** [ O.ScalarReg D1; O.ScalarReg D10; O.ScalarReg D3 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (21)`` () = + "7e274e11" + ++ UQSHL ** [ O.ScalarReg B17; O.ScalarReg B16; O.ScalarReg B7 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (22)`` () = + "7ee15703" + ++ URSHL ** [ O.ScalarReg D3; O.ScalarReg D24; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (23)`` () = + "7e675e38" + ++ UQRSHL ** [ O.ScalarReg H24; O.ScalarReg H17; O.ScalarReg H7 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (24)`` () = + "7eea84df" + ++ SUB ** [ O.ScalarReg D31; O.ScalarReg D6; O.ScalarReg D10 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (25)`` () = + "7ee08e24" + ++ CMEQ ** [ O.ScalarReg D4; O.ScalarReg D17; O.ScalarReg D0 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (26)`` () = + "7e61b4ca" + ++ SQRDMULH ** [ O.ScalarReg H10; O.ScalarReg H6; O.ScalarReg H1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (27)`` () = + "7ea7b501" + ++ SQRDMULH ** [ O.ScalarReg S1; O.ScalarReg S8; O.ScalarReg S7 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (28)`` () = + "7e61e606" + ++ FCMGE ** [ O.ScalarReg D6; O.ScalarReg D16; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (29)`` () = + "7e21ec41" + ++ FACGE ** [ O.ScalarReg S1; O.ScalarReg S2; O.ScalarReg S1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (30)`` () = + "7ea1d626" + ++ FABD ** [ O.ScalarReg S6; O.ScalarReg S17; O.ScalarReg S1 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (31)`` () = + "7ee4e687" + ++ FCMGT ** [ O.ScalarReg D7; O.ScalarReg D20; O.ScalarReg D4 ] + ||> test + + [] + member __.``4.6.10 Advanced SIMD scalar three same (32)`` () = + "7ea5ec73" + ++ FACGT ** [ O.ScalarReg S19; O.ScalarReg S3; O.ScalarReg S5 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (1)`` () = + "5ea03bb5" + ++ SUQADD ** [ O.ScalarReg S21; O.ScalarReg S29 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (2)`` () = + "5e607bc1" + ++ SQABS ** [ O.ScalarReg H1; O.ScalarReg H30 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (3)`` () = + "5ee089fe" + ++ CMGT ** [ O.ScalarReg D30; O.ScalarReg D15; O.Imm 0L ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (4)`` () = + "5ee09af4" + ++ CMEQ ** [ O.ScalarReg D20; O.ScalarReg D23; O.Imm 0L ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (5)`` () = + "5ee0abdc" + ++ CMLT ** [ O.ScalarReg D28; O.ScalarReg D30; O.Imm 0L ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (6)`` () = + "5ee0bb11" + ++ ABS ** [ O.ScalarReg D17; O.ScalarReg D24 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (7)`` () = + "5e614b87" + ++ SQXTN ** [ O.ScalarReg H7; O.ScalarReg S28 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (8)`` () = + "5e61ab01" + ++ FCVTNS ** [ O.ScalarReg D1; O.ScalarReg D24 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (9)`` () = + "5e21bb36" + ++ FCVTMS ** [ O.ScalarReg S22; O.ScalarReg S25 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (10)`` () = + "5e61caff" + ++ FCVTAS ** [ O.ScalarReg D31; O.ScalarReg D23 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (11)`` () = + "5e21daaa" + ++ SCVTF ** [ O.ScalarReg S10; O.ScalarReg S21 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (12)`` () = + "5ea0cabc" + ++ FCMGT ** [ O.ScalarReg S28; O.ScalarReg S21; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (13)`` () = + "5ee0da39" + ++ FCMEQ ** [ O.ScalarReg D25; O.ScalarReg D17; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (14)`` () = + "5ee0c9fe" + ++ FCMGT ** [ O.ScalarReg D30; O.ScalarReg D15; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (15)`` () = + "5ea1abfc" + ++ FCVTPS ** [ O.ScalarReg S28; O.ScalarReg S31 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (16)`` () = + "5ee1b9fe" + ++ FCVTZS ** [ O.ScalarReg D30; O.ScalarReg D15 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (17)`` () = + "5ea1daf6" + ++ FRECPE ** [ O.ScalarReg S22; O.ScalarReg S23 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (18)`` () = + "5ee1f9ff" + ++ FRECPX ** [ O.ScalarReg D31; O.ScalarReg D15 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (19)`` () = + "7ea03a7c" + ++ USQADD ** [ O.ScalarReg S28; O.ScalarReg S19 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (20)`` () = + "7e60795b" + ++ SQNEG ** [ O.ScalarReg H27; O.ScalarReg H10 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (21)`` () = + "7ee08a81" + ++ CMGE ** [ O.ScalarReg D1; O.ScalarReg D20; O.Imm 0L ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (22)`` () = + "7ee09a38" + ++ CMLE ** [ O.ScalarReg D24; O.ScalarReg D17; O.Imm 0L ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (23)`` () = + "7ee0b97f" + ++ NEG ** [ O.ScalarReg D31; O.ScalarReg D11 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (24)`` () = + "7ea12a11" + ++ SQXTUN ** [ O.ScalarReg S17; O.ScalarReg D16 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (25)`` () = + "7e214a81" + ++ UQXTN ** [ O.ScalarReg B1; O.ScalarReg H20 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (26)`` () = + "7e616af8" + ++ FCVTXN ** [ O.ScalarReg S24; O.ScalarReg D23 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (27)`` () = + "7e21aaf8" + ++ FCVTNU ** [ O.ScalarReg S24; O.ScalarReg S23 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (28)`` () = + "7e61b807" + ++ FCVTMU ** [ O.ScalarReg D7; O.ScalarReg D0 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (29)`` () = + "7e21ca11" + ++ FCVTAU ** [ O.ScalarReg S17; O.ScalarReg S16 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (30)`` () = + "7e61d844" + ++ UCVTF ** [ O.ScalarReg D4; O.ScalarReg D2 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (31)`` () = + "7ea0cafe" + ++ FCMGE ** [ O.ScalarReg S30; O.ScalarReg S23; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (32)`` () = + "7ee0d8c8" + ++ FCMLE ** [ O.ScalarReg D8; O.ScalarReg D6; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (33)`` () = + "7ea1aa21" + ++ FCVTPU ** [ O.ScalarReg S1; O.ScalarReg S17 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (34)`` () = + "7ee1b823" + ++ FCVTZU ** [ O.ScalarReg D3; O.ScalarReg D1 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (35)`` () = + "7ea1da35" + ++ FRSQRTE ** [ O.ScalarReg S21; O.ScalarReg S17 ] + ||> test + + [] + member __.``4.6.11 Advanced SIMD scalar two-reg misc (36)`` () = + "7ee1dabd" + ++ FRSQRTE ** [ O.ScalarReg D29; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (1)`` () = + "5f883a21" + ++ SQDMLAL ** [ O.ScalarReg D1; O.ScalarReg S17 + O.SIMDVecRegWithIdx (V8, VecS, 2uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (2)`` () = + "5f767b1a" + ++ SQDMLSL ** [ O.ScalarReg S26; O.ScalarReg H24 + O.SIMDVecRegWithIdx (V6, VecH, 7uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (3)`` () = + "5facba67" + ++ SQDMULL ** [ O.ScalarReg D7; O.ScalarReg S19 + O.SIMDVecRegWithIdx (V12, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (4)`` () = + "5f7ec203" + ++ SQDMULH ** [ O.ScalarReg H3; O.ScalarReg H16 + O.SIMDVecRegWithIdx (V14, VecH, 3uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (5)`` () = + "5fbfcb7b" + ++ SQDMULH ** [ O.ScalarReg S27; O.ScalarReg S27 + O.SIMDVecRegWithIdx (V31, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (6)`` () = + "5f7fda7c" + ++ SQRDMULH ** [ O.ScalarReg H28; O.ScalarReg H19 + O.SIMDVecRegWithIdx (V15, VecH, 7uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (7)`` () = + "5fd318c3" + ++ FMLA ** [ O.ScalarReg D3; O.ScalarReg D6 + O.SIMDVecRegWithIdx (V19, VecD, 1uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (8)`` () = + "5fb05822" + ++ FMLS ** [ O.ScalarReg S2; O.ScalarReg S1 + O.SIMDVecRegWithIdx (V16, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (9)`` () = + "5fd1987e" + ++ FMUL ** [ O.ScalarReg D30; O.ScalarReg D3 + O.SIMDVecRegWithIdx (V17, VecD, 1uy) ] + ||> test + + [] + member __.``4.6.12 Advanced SIMD scalar x indexed elem (10)`` () = + "7fbe90d9" + ++ FMULX ** [ O.ScalarReg S25; O.ScalarReg S6 + O.SIMDVecRegWithIdx (V30, VecS, 1uy) ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (1)`` () = + "4f0d05c5" + ++ SSHR ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (2)`` () = + "4f1505c5" + ++ SSHR ** [ O.SIMDVecReg (V5, EightH); O.SIMDVecReg (V14, EightH) + O.Imm 0xBL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (3)`` () = + "4f3505c5" + ++ SSHR ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, FourS) + O.Imm 0xBL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (4)`` () = + "4f5205c5" + ++ SSHR ** [ O.SIMDVecReg (V5, TwoD); O.SIMDVecReg (V14, TwoD) + O.Imm 0x2EL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (5)`` () = + "4f0d15c5" + ++ SSRA ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (6)`` () = + "4f1525c5" + ++ SRSHR ** [ O.SIMDVecReg (V5, EightH); O.SIMDVecReg (V14, EightH) + O.Imm 0xBL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (7)`` () = + "4f3535c5" + ++ SRSRA ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, FourS) + O.Imm 0xBL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (8)`` () = + "4f0d55c5" + ++ SHL ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (9)`` () = + "4f0d75c5" + ++ SQSHL ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (10)`` () = + "4f2e85c5" + ++ SHRN2 ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, TwoD) + O.Imm 0x12L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (11)`` () = + "4f0d8dc5" + ++ RSHRN2 ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, EightH) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (12)`` () = + "4f0d95c5" + ++ SQSHRN2 ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, EightH) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (13)`` () = + "4f0d9dc5" + ++ SQRSHRN2 ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, EightH) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (14)`` () = + "4f0da5c5" + ++ SSHLL2 ** [ O.SIMDVecReg (V5, EightH); O.SIMDVecReg (V14, SixteenB) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (15)`` () = + "4f4fe54d" + ++ SCVTF ** [ O.SIMDVecReg (V13, TwoD); O.SIMDVecReg (V10, TwoD) + OprFbits 0x31uy ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (16)`` () = + "4f4ffd4d" + ++ FCVTZS ** [ O.SIMDVecReg (V13, TwoD); O.SIMDVecReg (V10, TwoD) + OprFbits 0x31uy ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (17)`` () = + "6f0d05c5" + ++ USHR ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (18)`` () = + "6f0d15c5" + ++ USRA ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (19)`` () = + "6f0d25c5" + ++ URSHR ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (20)`` () = + "6f0d35c5" + ++ URSRA ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (21)`` () = + "6f0d45c5" + ++ SRI ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 3L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (22)`` () = + "6f0d55c5" + ++ SLI ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (23)`` () = + "6f0d65c5" + ++ SQSHLU ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (24)`` () = + "6f0d75c5" + ++ UQSHL ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V14, SixteenB) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (25)`` () = + "6f2985c5" + ++ SQSHRUN2 ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, TwoD) + O.Imm 0x17L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (26)`` () = + "6f1b8dc5" + ++ SQRSHRUN2 ** [ O.SIMDVecReg (V5, EightH); O.SIMDVecReg (V14, FourS) + O.Imm 5L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (27)`` () = + "6f2695c5" + ++ UQSHRN2 ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, TwoD) + O.Imm 0x1AL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (28)`` () = + "6f1f9dc5" + ++ UQRSHRN2 ** [ O.SIMDVecReg (V5, EightH); O.SIMDVecReg (V14, FourS) + O.Imm 1L ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (29)`` () = + "2f2da4bb" + ++ USHLL ** [ O.SIMDVecReg (V27, TwoD); O.SIMDVecReg (V5, TwoS) + O.Imm 0xDL ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (30)`` () = + "6f39e5c5" + ++ UCVTF ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, FourS) + OprFbits 7uy ] + ||> test + + [] + member __.``4.6.13 Advanced SIMD shift by immediate (31)`` () = + "6f26fdc5" + ++ FCVTZU ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, FourS) + OprFbits 0x1Auy ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (1)`` () = + "4e0320c1" + ++ TBL ** [ O.SIMDVecReg (V1, SixteenB); O.SIMDList ([ V6; V7 ], SixteenB) + O.SIMDVecReg (V3, SixteenB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (2)`` () = + "0e0342c9" + ++ TBL ** [ O.SIMDVecReg (V9, EightB) + O.SIMDList ([ V22; V23; V24 ], SixteenB) + O.SIMDVecReg (V3, EightB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (3)`` () = + "4e0363e5" + ++ TBL ** [ O.SIMDVecReg (V5, SixteenB) + O.SIMDList ([ V31; V0; V1; V2 ], SixteenB) + O.SIMDVecReg (V3, SixteenB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (4)`` () = + "0e030371" + ++ TBL ** [ O.SIMDVecReg (V17, EightB); O.SIMDList ([ V27 ], SixteenB) + O.SIMDVecReg (V3, EightB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (5)`` () = + "0e1930fc" + ++ TBX ** [ O.SIMDVecReg (V28, EightB); O.SIMDList ([ V7; V8 ], SixteenB) + O.SIMDVecReg (V25, EightB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (6)`` () = + "4e1950fc" + ++ TBX ** [ O.SIMDVecReg (V28, SixteenB) + O.SIMDList ([ V7; V8; V9], SixteenB) + O.SIMDVecReg (V25, SixteenB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (7)`` () = + "0e1970fc" + ++ TBX ** [ O.SIMDVecReg (V28, EightB) + O.SIMDList ([ V7; V8; V9; V10], SixteenB) + O.SIMDVecReg (V25, EightB) ] + ||> test + + [] + member __.``4.6.14 Advanced SIMD table lookup (8)`` () = + "4e1910fc" + ++ TBX ** [ O.SIMDVecReg (V28, SixteenB); O.SIMDList ([ V7 ], SixteenB) + O.SIMDVecReg (V25, SixteenB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (1)`` () = + "0e6b039a" + ++ SADDL ** [ O.SIMDVecReg (V26, FourS); O.SIMDVecReg (V28, FourH) + O.SIMDVecReg (V11, FourH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (2)`` () = + "4ea50325" + ++ SADDL2 ** [ O.SIMDVecReg (V5, TwoD); O.SIMDVecReg (V25, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (3)`` () = + "0e2712ba" + ++ SADDW ** [ O.SIMDVecReg (V26, EightH); O.SIMDVecReg (V21, EightH) + O.SIMDVecReg (V7, EightB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (4)`` () = + "4e631079" + ++ SADDW2 ** [ O.SIMDVecReg (V25, FourS); O.SIMDVecReg (V3, FourS) + O.SIMDVecReg (V3, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (5)`` () = + "4e632079" + ++ SSUBL2 ** [ O.SIMDVecReg (V25, FourS); O.SIMDVecReg (V3, EightH) + O.SIMDVecReg (V3, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (6)`` () = + "4e633079" + ++ SSUBW2 ** [ O.SIMDVecReg (V25, FourS); O.SIMDVecReg (V3, FourS) + O.SIMDVecReg (V3, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (7)`` () = + "4e634079" + ++ ADDHN2 ** [ O.SIMDVecReg (V25, EightH); O.SIMDVecReg (V3, FourS) + O.SIMDVecReg (V3, FourS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (8)`` () = + "4e635079" + ++ SABAL2 ** [ O.SIMDVecReg (V25, FourS); O.SIMDVecReg (V3, EightH) + O.SIMDVecReg (V3, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (9)`` () = + "4e636079" + ++ SUBHN2 ** [ O.SIMDVecReg (V25, EightH); O.SIMDVecReg (V3, FourS) + O.SIMDVecReg (V3, FourS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (10)`` () = + "4e637079" + ++ SABDL2 ** [ O.SIMDVecReg (V25, FourS); O.SIMDVecReg (V3, EightH) + O.SIMDVecReg (V3, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (11)`` () = + "0ea68258" + ++ SMLAL ** [ O.SIMDVecReg (V24, TwoD); O.SIMDVecReg (V18, TwoS) + O.SIMDVecReg (V6, TwoS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (12)`` () = + "4ea692fa" + ++ SQDMLAL2 ** [ O.SIMDVecReg (V26, TwoD); O.SIMDVecReg (V23, FourS) + O.SIMDVecReg (V6, FourS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (13)`` () = + "4e66a22c" + ++ SMLSL2 ** [ O.SIMDVecReg (V12, FourS); O.SIMDVecReg (V17, EightH) + O.SIMDVecReg (V6, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (14)`` () = + "4ea5b2c3" + ++ SQDMLSL2 ** [ O.SIMDVecReg (V3, TwoD); O.SIMDVecReg (V22, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (15)`` () = + "0e65c17c" + ++ SMULL ** [ O.SIMDVecReg (V28, FourS); O.SIMDVecReg (V11, FourH) + O.SIMDVecReg (V5, FourH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (16)`` () = + "0ea8d079" + ++ SQDMULL ** [ O.SIMDVecReg (V25, TwoD); O.SIMDVecReg (V3, TwoS) + O.SIMDVecReg (V8, TwoS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (17)`` () = + "4ee3e245" + ++ PMULL2 ** [ O.SIMDVecReg (V5, OneQ); O.SIMDVecReg (V18, TwoD) + O.SIMDVecReg (V3, TwoD) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (18)`` () = + "2e2e026b" + ++ UADDL ** [ O.SIMDVecReg (V11, EightH); O.SIMDVecReg (V19, EightB) + O.SIMDVecReg (V14, EightB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (19)`` () = + "6eae1252" + ++ UADDW2 ** [ O.SIMDVecReg (V18, TwoD); O.SIMDVecReg (V18, TwoD) + O.SIMDVecReg (V14, FourS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (20)`` () = + "2ea122bd" + ++ USUBL ** [ O.SIMDVecReg (V29, TwoD); O.SIMDVecReg (V21, TwoS) + O.SIMDVecReg (V1, TwoS) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (21)`` () = + "6e27339b" + ++ USUBW2 ** [ O.SIMDVecReg (V27, EightH); O.SIMDVecReg (V28, EightH) + O.SIMDVecReg (V7, SixteenB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (22)`` () = + "6e27439b" + ++ RADDHN2 ** [ O.SIMDVecReg (V27, SixteenB); O.SIMDVecReg (V28, EightH) + O.SIMDVecReg (V7, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (23)`` () = + "6e27539b" + ++ UABAL2 ** [ O.SIMDVecReg (V27, EightH); O.SIMDVecReg (V28, SixteenB) + O.SIMDVecReg (V7, SixteenB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (24)`` () = + "6e27639b" + ++ RSUBHN2 ** [ O.SIMDVecReg (V27, SixteenB); O.SIMDVecReg (V28, EightH) + O.SIMDVecReg (V7, EightH) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (25)`` () = + "6e27739b" + ++ UABDL2 ** [ O.SIMDVecReg (V27, EightH); O.SIMDVecReg (V28, SixteenB) + O.SIMDVecReg (V7, SixteenB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (26)`` () = + "6e27839b" + ++ UMLAL2 ** [ O.SIMDVecReg (V27, EightH); O.SIMDVecReg (V28, SixteenB) + O.SIMDVecReg (V7, SixteenB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (27)`` () = + "6e27a39b" + ++ UMLSL2 ** [ O.SIMDVecReg (V27, EightH); O.SIMDVecReg (V28, SixteenB) + O.SIMDVecReg (V7, SixteenB) ] + ||> test + + [] + member __.``4.6.15 Advanced SIMD three different (28)`` () = + "6e27c39b" + ++ UMULL2 ** [ O.SIMDVecReg (V27, EightH); O.SIMDVecReg (V28, SixteenB) + O.SIMDVecReg (V7, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (1)`` () = + "4e2504b5" + ++ SHADD ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (2)`` () = + "4e650cb5" + ++ SQADD ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (3)`` () = + "4ea514b5" + ++ SRHADD ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (4)`` () = + "4e2524b5" + ++ SHSUB ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (5)`` () = + "4e652cb5" + ++ SQSUB ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (6)`` () = + "4ea534b5" + ++ CMGT ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (7)`` () = + "4e253cb5" + ++ CMGE ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (8)`` () = + "4e6544b5" + ++ SSHL ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (9)`` () = + "4ea54cb5" + ++ SQSHL ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (10)`` () = + "4e2554b5" + ++ SRSHL ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (11)`` () = + "4e655cb5" + ++ SQRSHL ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (12)`` () = + "4ea564b5" + ++ SMAX ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (13)`` () = + "4e256cb5" + ++ SMIN ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (14)`` () = + "4e6574b5" + ++ SABD ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (15)`` () = + "4ea57cb5" + ++ SABA ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (16)`` () = + "4e2584b5" + ++ ADD ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (17)`` () = + "4e658cb5" + ++ CMTST ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (18)`` () = + "4ea594b5" + ++ MLA ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (19)`` () = + "4e259cb5" + ++ MUL ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (20)`` () = + "4e65a4b5" + ++ SMAXP ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (21)`` () = + "4ea5acb5" + ++ SMINP ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (22)`` () = + "4ea5b4b5" + ++ SQDMULH ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (23)`` () = + "4e65bcb5" + ++ ADDP ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (24)`` () = + "4e25c6b5" + ++ FMAXNM ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V21, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (25)`` () = + "4e65cdb5" + ++ FMLA ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V13, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (26)`` () = + "4e25d4b5" + ++ FADD ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (27)`` () = + "4e65dcb1" + ++ FMULX ** [ O.SIMDVecReg (V17, TwoD); O.SIMDVecReg (V5, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (28)`` () = + "4e25e455" + ++ FCMEQ ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V2, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (29)`` () = + "4e65f5b5" + ++ FMAX ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V13, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (30)`` () = + "4e25fdb5" + ++ FRECPS ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V13, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (31)`` () = + "4e251cb1" + ++ AND ** [ O.SIMDVecReg (V17, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (32)`` () = + "4e651eb9" + ++ BIC ** [ O.SIMDVecReg (V25, SixteenB); O.SIMDVecReg (V21, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (33)`` () = + "4ea5c43d" + ++ FMINNM ** [ O.SIMDVecReg (V29, FourS); O.SIMDVecReg (V1, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (34)`` () = + "4ee5cfb4" + ++ FMLS ** [ O.SIMDVecReg (V20, TwoD); O.SIMDVecReg (V29, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (35)`` () = + "4ea5d4b5" + ++ FSUB ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (36)`` () = + "4ee5f425" + ++ FMIN ** [ O.SIMDVecReg (V5, TwoD); O.SIMDVecReg (V1, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (37)`` () = + "4ea5fcbd" + ++ FRSQRTS ** [ O.SIMDVecReg (V29, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (38)`` () = + "4ea51cb5" + ++ MOV ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (39)`` () = + "4ee51da9" + ++ ORN ** [ O.SIMDVecReg (V9, SixteenB); O.SIMDVecReg (V13, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (40)`` () = + "6e2504b5" + ++ UHADD ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (41)`` () = + "6e650cb5" + ++ UQADD ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (42)`` () = + "6ea514b5" + ++ URHADD ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (43)`` () = + "6e2524b5" + ++ UHSUB ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (44)`` () = + "6e652cb5" + ++ UQSUB ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (45)`` () = + "6ea534b5" + ++ CMHI ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (46)`` () = + "6e253cb5" + ++ CMHS ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (47)`` () = + "6e6544b5" + ++ USHL ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (48)`` () = + "6ea54cb5" + ++ UQSHL ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (49)`` () = + "6e2554b5" + ++ URSHL ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (50)`` () = + "6e655cb5" + ++ UQRSHL ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (51)`` () = + "6ea564b5" + ++ UMAX ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (52)`` () = + "6e256cb5" + ++ UMIN ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (53)`` () = + "6e6574b5" + ++ UABD ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (54)`` () = + "6ea57cb5" + ++ UABA ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (55)`` () = + "6e2584b5" + ++ SUB ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (56)`` () = + "6e658cb5" + ++ CMEQ ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (57)`` () = + "6ea594b5" + ++ MLS ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (58)`` () = + "6e259cb5" + ++ PMUL ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (59)`` () = + "6e65a4b5" + ++ UMAXP ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (60)`` () = + "6ea5acb5" + ++ UMINP ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (61)`` () = + "6e65b4b5" + ++ SQRDMULH ** [ O.SIMDVecReg (V21, EightH); O.SIMDVecReg (V5, EightH) + O.SIMDVecReg (V5, EightH) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (62)`` () = + "6e25c4b5" + ++ FMAXNMP ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (63)`` () = + "6e65d4b5" + ++ FADDP ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V5, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (64)`` () = + "6e25dcb5" + ++ FMUL ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (65)`` () = + "6e65e4b5" + ++ FCMGE ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V5, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (66)`` () = + "6e25ecb5" + ++ FACGE ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (67)`` () = + "6e65f4b5" + ++ FMAXP ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V5, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (68)`` () = + "6e25fcb5" + ++ FDIV ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (69)`` () = + "6e251cb5" + ++ EOR ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (70)`` () = + "6e651cb5" + ++ BSL ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (71)`` () = + "6ea5c4b5" + ++ FMINNMP ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (72)`` () = + "6ee5d4b5" + ++ FABD ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V5, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (73)`` () = + "6ea5e4b5" + ++ FCMGT ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (74)`` () = + "6ee5ecb5" + ++ FACGT ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V5, TwoD) + O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (75)`` () = + "6ea5f4b5" + ++ FMINP ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (76)`` () = + "6ea51cb5" + ++ BIT ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.16 Advanced SIMD three same (77)`` () = + "6ee51cb5" + ++ BIF ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V5, SixteenB) + O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (1)`` () = + "4e600983" + ++ REV64 ** [ O.SIMDVecReg (V3, EightH); O.SIMDVecReg (V12, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (2)`` () = + "4e2018b2" + ++ REV16 ** [ O.SIMDVecReg (V18, SixteenB); O.SIMDVecReg (V5, SixteenB) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (3)`` () = + "4e602983" + ++ SADDLP ** [ O.SIMDVecReg (V3, FourS); O.SIMDVecReg (V12, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (4)`` () = + "4e603a33" + ++ SUQADD ** [ O.SIMDVecReg (V19, EightH); O.SIMDVecReg (V17, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (5)`` () = + "4ea0487c" + ++ CLS ** [ O.SIMDVecReg (V28, FourS); O.SIMDVecReg (V3, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (6)`` () = + "0ea028cd" + ++ SADDLP ** [ O.SIMDVecReg (V13, OneD); O.SIMDVecReg (V6, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (7)`` () = + "4ee07a46" + ++ SQABS ** [ O.SIMDVecReg (V6, TwoD); O.SIMDVecReg (V18, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (8)`` () = + "4e208867" + ++ CMGT ** [ O.SIMDVecReg (V7, SixteenB); O.SIMDVecReg (V3, SixteenB) + O.Imm 0L ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (9)`` () = + "0e609879" + ++ CMEQ ** [ O.SIMDVecReg (V25, FourH); O.SIMDVecReg (V3, FourH) + O.Imm 0L ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (10)`` () = + "4ea0a841" + ++ CMLT ** [ O.SIMDVecReg (V1, FourS); O.SIMDVecReg (V2, FourS) + O.Imm 0L ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (11)`` () = + "4e20bb7d" + ++ ABS ** [ O.SIMDVecReg (V29, SixteenB); O.SIMDVecReg (V27, SixteenB) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (12)`` () = + "0ea128b9" + ++ XTN ** [ O.SIMDVecReg (V25, TwoS); O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (13)`` () = + "4ea128f8" + ++ XTN2 ** [ O.SIMDVecReg (V24, FourS); O.SIMDVecReg (V7, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (14)`` () = + "0e2148c3" + ++ SQXTN ** [ O.SIMDVecReg (V3, EightB); O.SIMDVecReg (V6, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (15)`` () = + "4e214945" + ++ SQXTN2 ** [ O.SIMDVecReg (V5, SixteenB); O.SIMDVecReg (V10, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (16)`` () = + "0e616885" + ++ FCVTN ** [ O.SIMDVecReg (V5, TwoS); O.SIMDVecReg (V4, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (17)`` () = + "4e2168f8" + ++ FCVTN2 ** [ O.SIMDVecReg (V24, EightH); O.SIMDVecReg (V7, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (18)`` () = + "0e217a7c" + ++ FCVTL ** [ O.SIMDVecReg (V28, FourS); O.SIMDVecReg (V19, FourH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (19)`` () = + "4e617b43" + ++ FCVTL2 ** [ O.SIMDVecReg (V3, TwoD); O.SIMDVecReg (V26, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (20)`` () = + "4e6188b8" + ++ FRINTN ** [ O.SIMDVecReg (V24, TwoD); O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (21)`` () = + "0e219865" + ++ FRINTM ** [ O.SIMDVecReg (V5, TwoS); O.SIMDVecReg (V3, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (22)`` () = + "4e21a86d" + ++ FCVTNS ** [ O.SIMDVecReg (V13, FourS); O.SIMDVecReg (V3, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (23)`` () = + "0e21b87e" + ++ FCVTMS ** [ O.SIMDVecReg (V30, TwoS); O.SIMDVecReg (V3, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (24)`` () = + "4e61c876" + ++ FCVTAS ** [ O.SIMDVecReg (V22, TwoD); O.SIMDVecReg (V3, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (25)`` () = + "4e21d892" + ++ SCVTF ** [ O.SIMDVecReg (V18, FourS); O.SIMDVecReg (V4, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (26)`` () = + "4ea0c8bd" + ++ FCMGT ** [ O.SIMDVecReg (V29, FourS); O.SIMDVecReg (V5, FourS) + OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (27)`` () = + "0ea0d83e" + ++ FCMEQ ** [ O.SIMDVecReg (V30, TwoS); O.SIMDVecReg (V1, TwoS) + OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (28)`` () = + "4ee0e939" + ++ FCMLT ** [ O.SIMDVecReg (V25, TwoD); O.SIMDVecReg (V9, TwoD) + OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (29)`` () = + "4ea0f88e" + ++ FABS ** [ O.SIMDVecReg (V14, FourS); O.SIMDVecReg (V4, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (30)`` () = + "0ea18896" + ++ FRINTP ** [ O.SIMDVecReg (V22, TwoS); O.SIMDVecReg (V4, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (31)`` () = + "4ee19849" + ++ FRINTZ ** [ O.SIMDVecReg (V9, TwoD); O.SIMDVecReg (V2, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (32)`` () = + "4ea1aac3" + ++ FCVTPS ** [ O.SIMDVecReg (V3, FourS); O.SIMDVecReg (V22, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (33)`` () = + "0ea1ba7a" + ++ FCVTZS ** [ O.SIMDVecReg (V26, TwoS); O.SIMDVecReg (V19, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (34)`` () = + "0ea1c8c7" + ++ URECPE ** [ O.SIMDVecReg (V7, TwoS); O.SIMDVecReg (V6, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (35)`` () = + "4ee1d883" + ++ FRECPE ** [ O.SIMDVecReg (V3, TwoD); O.SIMDVecReg (V4, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (36)`` () = + "6e60083e" + ++ REV32 ** [ O.SIMDVecReg (V30, EightH); O.SIMDVecReg (V1, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (37)`` () = + "6ea028fc" + ++ UADDLP ** [ O.SIMDVecReg (V28, TwoD); O.SIMDVecReg (V7, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (38)`` () = + "6ee03883" + ++ USQADD ** [ O.SIMDVecReg (V3, TwoD); O.SIMDVecReg (V4, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (39)`` () = + "6ea048c9" + ++ CLZ ** [ O.SIMDVecReg (V9, FourS); O.SIMDVecReg (V6, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (40)`` () = + "6e60683e" + ++ UADALP ** [ O.SIMDVecReg (V30, FourS); O.SIMDVecReg (V1, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (41)`` () = + "2ea078ef" + ++ SQNEG ** [ O.SIMDVecReg (V15, TwoS); O.SIMDVecReg (V7, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (42)`` () = + "6e208874" + ++ CMGE ** [ O.SIMDVecReg (V20, SixteenB); O.SIMDVecReg (V3, SixteenB) + O.Imm 0L ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (43)`` () = + "2e2098fd" + ++ CMLE ** [ O.SIMDVecReg (V29, EightB); O.SIMDVecReg (V7, EightB) + O.Imm 0L ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (44)`` () = + "6e60b8ca" + ++ NEG ** [ O.SIMDVecReg (V10, EightH); O.SIMDVecReg (V6, EightH) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (45)`` () = + "0ea14887" + ++ SQXTN ** [ O.SIMDVecReg (V7, TwoS); O.SIMDVecReg (V4, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (46)`` () = + "4e6148b4" + ++ SQXTN2 ** [ O.SIMDVecReg (V20, EightH); O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (47)`` () = + "2ea13a75" + ++ SHLL ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V19, TwoS) + O.Shift (SRTypeLSL, 32L) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (48)`` () = + "6e613a7d" + ++ SHLL2 ** [ O.SIMDVecReg (V29, FourS); O.SIMDVecReg (V19, EightH) + O.Shift (SRTypeLSL, 16L) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (49)`` () = + "2ea148e9" + ++ UQXTN ** [ O.SIMDVecReg (V9, TwoS); O.SIMDVecReg (V7, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (50)`` () = + "6e6148c2" + ++ UQXTN2 ** [ O.SIMDVecReg (V2, EightH); O.SIMDVecReg (V6, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (51)`` () = + "2e6168ca" + ++ FCVTXN ** [ O.SIMDVecReg (V10, TwoS); O.SIMDVecReg (V6, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (52)`` () = + "6e6169c5" + ++ FCVTXN2 ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V14, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (53)`` () = + "6e2188ba" + ++ FRINTA ** [ O.SIMDVecReg (V26, FourS); O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (54)`` () = + "6e6198bc" + ++ FRINTX ** [ O.SIMDVecReg (V28, TwoD); O.SIMDVecReg (V5, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (55)`` () = + "2e21a8c5" + ++ FCVTNU ** [ O.SIMDVecReg (V5, TwoS); O.SIMDVecReg (V6, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (56)`` () = + "6e21bac6" + ++ FCVTMU ** [ O.SIMDVecReg (V6, FourS); O.SIMDVecReg (V22, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (57)`` () = + "2e21cb65" + ++ FCVTAU ** [ O.SIMDVecReg (V5, TwoS); O.SIMDVecReg (V27, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (58)`` () = + "6e21d896" + ++ UCVTF ** [ O.SIMDVecReg (V22, FourS); O.SIMDVecReg (V4, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (59)`` () = + "6e20593a" + ++ MVN ** [ O.SIMDVecReg (V26, SixteenB); O.SIMDVecReg (V9, SixteenB) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (60)`` () = + "2e6058f2" + ++ RBIT ** [ O.SIMDVecReg (V18, EightB); O.SIMDVecReg (V7, EightB) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (61)`` () = + "6ea0cae5" + ++ FCMGE ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V23, FourS) + OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (62)`` () = + "2ea0da4e" + ++ FCMLE ** [ O.SIMDVecReg (V14, TwoS); O.SIMDVecReg (V18, TwoS) + OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (63)`` () = + "6ee0fa75" + ++ FNEG ** [ O.SIMDVecReg (V21, TwoD); O.SIMDVecReg (V19, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (64)`` () = + "2ea19abe" + ++ FRINTI ** [ O.SIMDVecReg (V30, TwoS); O.SIMDVecReg (V21, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (65)`` () = + "6ee1a889" + ++ FCVTPU ** [ O.SIMDVecReg (V9, TwoD); O.SIMDVecReg (V4, TwoD) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (66)`` () = + "2ea1b9fe" + ++ FCVTZU ** [ O.SIMDVecReg (V30, TwoS); O.SIMDVecReg (V15, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (67)`` () = + "6ea1cba5" + ++ URSQRTE ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V29, FourS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (68)`` () = + "2ea1db32" + ++ FRSQRTE ** [ O.SIMDVecReg (V18, TwoS); O.SIMDVecReg (V25, TwoS) ] + ||> test + + [] + member __.``4.6.17 Advanced SIMD two-reg miscellaneous (69)`` () = + "6ea1f8a6" + ++ FSQRT ** [ O.SIMDVecReg (V6, FourS); O.SIMDVecReg (V5, FourS) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (1)`` () = + "4f6228da" + ++ SMLAL2 ** [ O.SIMDVecReg (V26, FourS); O.SIMDVecReg (V6, EightH) + O.SIMDVecRegWithIdx (V2, VecH, 6uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (2)`` () = + "4fb13b42" + ++ SQDMLAL2 ** [ O.SIMDVecReg (V2, TwoD); O.SIMDVecReg (V26, FourS) + O.SIMDVecRegWithIdx (V17, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (3)`` () = + "4f7961ca" + ++ SMLSL2 ** [ O.SIMDVecReg (V10, FourS); O.SIMDVecReg (V14, EightH) + O.SIMDVecRegWithIdx (V9, VecH, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (4)`` () = + "0f92702f" + ++ SQDMLSL ** [ O.SIMDVecReg (V15, TwoD); O.SIMDVecReg (V1, TwoS) + O.SIMDVecRegWithIdx (V18, VecS, 0uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (5)`` () = + "0f738342" + ++ MUL ** [ O.SIMDVecReg (V2, FourH); O.SIMDVecReg (V26, FourH) + O.SIMDVecRegWithIdx (V3, VecH, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (6)`` () = + "0f6ca8c5" + ++ SMULL ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V6, FourH) + O.SIMDVecRegWithIdx (V12, VecH, 6uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (7)`` () = + "4fbdbb42" + ++ SQDMULL2 ** [ O.SIMDVecReg (V2, TwoD); O.SIMDVecReg (V26, FourS) + O.SIMDVecRegWithIdx (V29, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (8)`` () = + "4f9dcb5d" + ++ SQDMULH ** [ O.SIMDVecReg (V29, FourS); O.SIMDVecReg (V26, FourS) + O.SIMDVecRegWithIdx (V29, VecS, 2uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (9)`` () = + "0f5dd3da" + ++ SQRDMULH ** [ O.SIMDVecReg (V26, FourH); O.SIMDVecReg (V30, FourH) + O.SIMDVecRegWithIdx (V13, VecH, 1uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (10)`` () = + "4fa31b5b" + ++ FMLA ** [ O.SIMDVecReg (V27, FourS); O.SIMDVecReg (V26, FourS) + O.SIMDVecRegWithIdx (V3, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (11)`` () = + "4fd3535b" + ++ FMLS ** [ O.SIMDVecReg (V27, TwoD); O.SIMDVecReg (V26, TwoD) + O.SIMDVecRegWithIdx (V19, VecD, 0uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (12)`` () = + "4f839b5b" + ++ FMUL ** [ O.SIMDVecReg (V27, FourS); O.SIMDVecReg (V26, FourS) + O.SIMDVecRegWithIdx (V3, VecS, 2uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (13)`` () = + "6fad08be" + ++ MLA ** [ O.SIMDVecReg (V30, FourS); O.SIMDVecReg (V5, FourS) + O.SIMDVecRegWithIdx (V13, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (14)`` () = + "6f7f2b56" + ++ UMLAL2 ** [ O.SIMDVecReg (V22, FourS); O.SIMDVecReg (V26, EightH) + O.SIMDVecRegWithIdx (V15, VecH, 7uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (15)`` () = + "6f97488a" + ++ MLS ** [ O.SIMDVecReg (V10, FourS); O.SIMDVecReg (V4, FourS) + O.SIMDVecRegWithIdx (V23, VecS, 2uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (16)`` () = + "2f6e60de" + ++ UMLSL ** [ O.SIMDVecReg (V30, FourS); O.SIMDVecReg (V6, FourH) + O.SIMDVecRegWithIdx (V14, VecH, 2uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (17)`` () = + "6fbfa8ea" + ++ UMULL2 ** [ O.SIMDVecReg (V10, TwoD); O.SIMDVecReg (V7, FourS) + O.SIMDVecRegWithIdx (V31, VecS, 3uy) ] + ||> test + + [] + member __.``4.6.18 Advanced SIMD vector x indexed elem (18)`` () = + "6fad92c5" + ++ FMULX ** [ O.SIMDVecReg (V5, FourS); O.SIMDVecReg (V22, FourS) + O.SIMDVecRegWithIdx (V13, VecS, 1uy) ] + ||> test + + [] + member __.``4.6.19 Cryptographic AES (1)`` () = + "4e284ab5" + ++ AESE ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V21, SixteenB) ] + ||> test + + [] + member __.``4.6.19 Cryptographic AES (2)`` () = + "4e285ab5" + ++ AESD ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V21, SixteenB) ] + ||> test + + [] + member __.``4.6.19 Cryptographic AES (3)`` () = + "4e286ab5" + ++ AESMC ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V21, SixteenB) ] + ||> test + + [] + member __.``4.6.19 Cryptographic AES (4)`` () = + "4e287ab5" + ++ AESIMC ** [ O.SIMDVecReg (V21, SixteenB); O.SIMDVecReg (V21, SixteenB) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (1)`` () = + "5e190378" + ++ SHA1C ** [ O.ScalarReg Q24; O.ScalarReg S27; O.SIMDVecReg (V25, FourS) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (2)`` () = + "5e1313ff" + ++ SHA1P ** [ O.ScalarReg Q31; O.ScalarReg S31; O.SIMDVecReg (V19, FourS) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (3)`` () = + "5e0e22bc" + ++ SHA1M ** [ O.ScalarReg Q28; O.ScalarReg S21; O.SIMDVecReg (V14, FourS) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (4)`` () = + "5e173207" + ++ SHA1SU0 ** [ O.SIMDVecReg (V7, FourS); O.SIMDVecReg (V16, FourS) + O.SIMDVecReg (V23, FourS) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (5)`` () = + "5e1143de" + ++ SHA256H ** [ O.ScalarReg Q30; O.ScalarReg Q30 + O.SIMDVecReg (V17, FourS) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (6)`` () = + "5e19531e" + ++ SHA256H2 ** [ O.ScalarReg Q30; O.ScalarReg Q24 + O.SIMDVecReg (V25, FourS) ] + ||> test + + [] + member __.``4.6.20 Cryptographic three-register SHA (7)`` () = + "5e1732bf" + ++ SHA1SU0 ** [ O.SIMDVecReg (V31, FourS); O.SIMDVecReg (V21, FourS) + O.SIMDVecReg (V23, FourS) ] + ||> test + + [] + member __.``4.6.21 Cryptographic two-register SHA (1)`` () = + "5e28095f" + ++ SHA1H ** [ O.ScalarReg S31; O.ScalarReg S10 ] + ||> test + + [] + member __.``4.6.21 Cryptographic two-register SHA (2)`` () = + "5e281bd7" + ++ SHA1SU1 ** [ O.SIMDVecReg (V23, FourS); O.SIMDVecReg (V30, FourS) ] + ||> test + + [] + member __.``4.6.21 Cryptographic two-register SHA (3)`` () = + "5e282955" + ++ SHA256SU0 ** [ O.SIMDVecReg (V21, FourS); O.SIMDVecReg (V10, FourS) ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (1)`` () = + "1e3520e0" + ++ FCMP ** [ O.ScalarReg S7; O.ScalarReg S21 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (2)`` () = + "1e312388" + ++ FCMP ** [ O.ScalarReg S28; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (3)`` () = + "1e2b22d0" + ++ FCMPE ** [ O.ScalarReg S22; O.ScalarReg S11 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (4)`` () = + "1e392238" + ++ FCMPE ** [ O.ScalarReg S17; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (5)`` () = + "1e6220c0" + ++ FCMP ** [ O.ScalarReg D6; O.ScalarReg D2 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (6)`` () = + "1e7921c8" + ++ FCMP ** [ O.ScalarReg D14; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (7)`` () = + "1e742170" + ++ FCMPE ** [ O.ScalarReg D11; O.ScalarReg D20 ] + ||> test + + [] + member __.``4.6.22 Floating-point compare (8)`` () = + "1e6323b8" + ++ FCMPE ** [ O.ScalarReg D29; OprFPImm 0.0 ] + ||> test + + [] + member __.``4.6.23 Floating-point conditional compare (1)`` () = + "1e2d274d" + ++ FCCMP ** [ O.ScalarReg S26; O.ScalarReg S13; OprNZCV 0xDuy; OprCond CS ] + ||> test + + [] + member __.``4.6.23 Floating-point conditional compare (2)`` () = + "1e2ae756" + ++ FCCMPE ** [ O.ScalarReg S26; O.ScalarReg S10; OprNZCV 6uy; OprCond AL ] + ||> test + + [] + member __.``4.6.23 Floating-point conditional compare (3)`` () = + "1e693649" + ++ FCCMP ** [ O.ScalarReg D18; O.ScalarReg D9; OprNZCV 9uy; OprCond CC ] + ||> test + + [] + member __.``4.6.23 Floating-point conditional compare (4)`` () = + "1e6ee752" + ++ FCCMPE ** [ O.ScalarReg D26; O.ScalarReg D14; OprNZCV 2uy; OprCond AL ] + ||> test + + [] + member __.``4.6.24 Floating-point conditional select (1)`` () = + "1e292c5b" + ++ FCSEL ** [ O.ScalarReg S27; O.ScalarReg S2; O.ScalarReg S9; OprCond CS ] + ||> test + + [] + member __.``4.6.24 Floating-point conditional select (2)`` () = + "1e7ced53" + ++ FCSEL ** [ O.ScalarReg D19; O.ScalarReg D10; O.ScalarReg D28 + OprCond AL ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (1)`` () = + "1e20423a" + ++ FMOV ** [ O.ScalarReg S26; O.ScalarReg S17 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (2)`` () = + "1e20c0ea" + ++ FABS ** [ O.ScalarReg S10; O.ScalarReg S7 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (3)`` () = + "1e21410e" + ++ FNEG ** [ O.ScalarReg S14; O.ScalarReg S8 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (4)`` () = + "1e21c178" + ++ FSQRT ** [ O.ScalarReg S24; O.ScalarReg S11 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (5)`` () = + "1e22c2ca" + ++ FCVT ** [ O.ScalarReg D10; O.ScalarReg S22 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (6)`` () = + "1e23c1f0" + ++ FCVT ** [ O.ScalarReg H16; O.ScalarReg S15 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (7)`` () = + "1e244261" + ++ FRINTN ** [ O.ScalarReg S1; O.ScalarReg S19 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (8)`` () = + "1e24c15c" + ++ FRINTP ** [ O.ScalarReg S28; O.ScalarReg S10 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (9)`` () = + "1e2541d8" + ++ FRINTM ** [ O.ScalarReg S24; O.ScalarReg S14 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (10)`` () = + "1e25c0ce" + ++ FRINTZ ** [ O.ScalarReg S14; O.ScalarReg S6 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (11)`` () = + "1e26414c" + ++ FRINTA ** [ O.ScalarReg S12; O.ScalarReg S10 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (12)`` () = + "1e274178" + ++ FRINTX ** [ O.ScalarReg S24; O.ScalarReg S11 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (13)`` () = + "1e27c1e2" + ++ FRINTI ** [ O.ScalarReg S2; O.ScalarReg S15 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (14)`` () = + "1e604234" + ++ FMOV ** [ O.ScalarReg D20; O.ScalarReg D17 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (15)`` () = + "1e60c222" + ++ FABS ** [ O.ScalarReg D2; O.ScalarReg D17 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (16)`` () = + "1e6142a2" + ++ FNEG ** [ O.ScalarReg D2; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (17)`` () = + "1e61c1a6" + ++ FSQRT ** [ O.ScalarReg D6; O.ScalarReg D13 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (18)`` () = + "1e6241cd" + ++ FCVT ** [ O.ScalarReg S13; O.ScalarReg D14 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (19)`` () = + "1e63c2aa" + ++ FCVT ** [ O.ScalarReg H10; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (20)`` () = + "1e6441e3" + ++ FRINTN ** [ O.ScalarReg D3; O.ScalarReg D15 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (21)`` () = + "1e64c2b2" + ++ FRINTP ** [ O.ScalarReg D18; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (22)`` () = + "1e654374" + ++ FRINTM ** [ O.ScalarReg D20; O.ScalarReg D27 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (23)`` () = + "1e65c2e2" + ++ FRINTZ ** [ O.ScalarReg D2; O.ScalarReg D23 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (24)`` () = + "1e664351" + ++ FRINTA ** [ O.ScalarReg D17; O.ScalarReg D26 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (25)`` () = + "1e6742b8" + ++ FRINTX ** [ O.ScalarReg D24; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (26)`` () = + "1e67c375" + ++ FRINTI ** [ O.ScalarReg D21; O.ScalarReg D27 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (27)`` () = + "1ee241d4" + ++ FCVT ** [ O.ScalarReg S20; O.ScalarReg H14 ] + ||> test + + [] + member __.``4.6.25 FP data-processing (1 source) (28)`` () = + "1ee2c388" + ++ FCVT ** [ O.ScalarReg D8; O.ScalarReg H28 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (1)`` () = + "1e210822" + ++ FMUL ** [ O.ScalarReg S2; O.ScalarReg S1; O.ScalarReg S1 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (2)`` () = + "1e221a88" + ++ FDIV ** [ O.ScalarReg S8; O.ScalarReg S20; O.ScalarReg S2 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (3)`` () = + "1e2228ae" + ++ FADD ** [ O.ScalarReg S14; O.ScalarReg S5; O.ScalarReg S2 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (4)`` () = + "1e233956" + ++ FSUB ** [ O.ScalarReg S22; O.ScalarReg S10; O.ScalarReg S3 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (5)`` () = + "1e244af4" + ++ FMAX ** [ O.ScalarReg S20; O.ScalarReg S23; O.ScalarReg S4 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (6)`` () = + "1e255915" + ++ FMIN ** [ O.ScalarReg S21; O.ScalarReg S8; O.ScalarReg S5 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (7)`` () = + "1e266932" + ++ FMAXNM ** [ O.ScalarReg S18; O.ScalarReg S9; O.ScalarReg S6 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (8)`` () = + "1e2778ba" + ++ FMINNM ** [ O.ScalarReg S26; O.ScalarReg S5; O.ScalarReg S7 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (9)`` () = + "1e288aba" + ++ FNMUL ** [ O.ScalarReg S26; O.ScalarReg S21; O.ScalarReg S8 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (10)`` () = + "1e690abb" + ++ FMUL ** [ O.ScalarReg D27; O.ScalarReg D21; O.ScalarReg D9 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (11)`` () = + "1e6a18a2" + ++ FDIV ** [ O.ScalarReg D2; O.ScalarReg D5; O.ScalarReg D10 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (12)`` () = + "1e6b2aba" + ++ FADD ** [ O.ScalarReg D26; O.ScalarReg D21; O.ScalarReg D11 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (13)`` () = + "1e6c39be" + ++ FSUB ** [ O.ScalarReg D30; O.ScalarReg D13; O.ScalarReg D12 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (14)`` () = + "1e6d48ba" + ++ FMAX ** [ O.ScalarReg D26; O.ScalarReg D5; O.ScalarReg D13 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (15)`` () = + "1e6e5abb" + ++ FMIN ** [ O.ScalarReg D27; O.ScalarReg D21; O.ScalarReg D14 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (16)`` () = + "1e726ae2" + ++ FMAXNM ** [ O.ScalarReg D2; O.ScalarReg D23; O.ScalarReg D18 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (17)`` () = + "1e7f7882" + ++ FMINNM ** [ O.ScalarReg D2; O.ScalarReg D4; O.ScalarReg D31 ] + ||> test + + [] + member __.``4.6.26 FP data-processing (2 source) (18)`` () = + "1e608bd4" + ++ FNMUL ** [ O.ScalarReg D20; O.ScalarReg D30; O.ScalarReg D0 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (1)`` () = + "1f1f0759" + ++ FMADD ** [ O.ScalarReg S25; O.ScalarReg S26; O.ScalarReg S31 + O.ScalarReg S1 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (2)`` () = + "1f1e8b44" + ++ FMSUB ** [ O.ScalarReg S4; O.ScalarReg S26; O.ScalarReg S30 + O.ScalarReg S2 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (3)`` () = + "1f3c1116" + ++ FNMADD ** [ O.ScalarReg S22; O.ScalarReg S8; O.ScalarReg S28 + O.ScalarReg S4 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (4)`` () = + "1f38a1d5" + ++ FNMSUB ** [ O.ScalarReg S21; O.ScalarReg S14; O.ScalarReg S24 + O.ScalarReg S8 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (5)`` () = + "1f504159" + ++ FMADD ** [ O.ScalarReg D25; O.ScalarReg D10; O.ScalarReg D16 + O.ScalarReg D16 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (6)`` () = + "1f48e1dd" + ++ FMSUB ** [ O.ScalarReg D29; O.ScalarReg D14; O.ScalarReg D8 + O.ScalarReg D24 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (7)`` () = + "1f647171" + ++ FNMADD ** [ O.ScalarReg D17; O.ScalarReg D11; O.ScalarReg D4 + O.ScalarReg D28 ] + ||> test + + [] + member __.``4.6.27 FP data-processing (3 source) (8)`` () = + "1f62f871" + ++ FNMSUB ** [ O.ScalarReg D17; O.ScalarReg D3; O.ScalarReg D2 + O.ScalarReg D30 ] + ||> test + + [] + member __.``4.6.28 Floating-point immediate (1)`` () = + "1e201015" + ++ FMOV ** [ O.ScalarReg S21; OprFPImm 2.0 ] + ||> test + + [] + member __.``4.6.28 Floating-point immediate (2)`` () = + "1e64b019" + ++ FMOV ** [ O.ScalarReg D25; OprFPImm 10.5 ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (1)`` () = + "1e02a8bc" + ++ SCVTF ** [ O.ScalarReg S28; O.Reg W5; OprFbits 0x16uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (2)`` () = + "1e03f8a5" + ++ UCVTF ** [ O.ScalarReg S5; O.Reg W5; OprFbits 2uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (3)`` () = + "1e18fc91" + ++ FCVTZS ** [ O.Reg W17; O.ScalarReg S4; OprFbits 1uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (4)`` () = + "1e1985c5" + ++ FCVTZU ** [ O.Reg W5; O.ScalarReg S14; OprFbits 0x1Fuy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (5)`` () = + "1e42c5c5" + ++ SCVTF ** [ O.ScalarReg D5; O.Reg W14; OprFbits 0xFuy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (6)`` () = + "1e43a5c5" + ++ UCVTF ** [ O.ScalarReg D5; O.Reg W14; OprFbits 0x17uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (7)`` () = + "1e5895c5" + ++ FCVTZS ** [ O.Reg W5; O.ScalarReg D14; OprFbits 0x1Buy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (8)`` () = + "1e59ab45" + ++ FCVTZU ** [ O.Reg W5; O.ScalarReg D26; OprFbits 0x16uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (9)`` () = + "9e02c4d1" + ++ SCVTF ** [ O.ScalarReg S17; O.Reg X6; OprFbits 0xFuy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (10)`` () = + "9e03b5a5" + ++ UCVTF ** [ O.ScalarReg S5; O.Reg X13; OprFbits 0x13uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (11)`` () = + "9e18f0cd" + ++ FCVTZS ** [ O.Reg X13; O.ScalarReg S6; OprFbits 4uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (12)`` () = + "9e1995cd" + ++ FCVTZU ** [ O.Reg X13; O.ScalarReg S14; OprFbits 0x1Buy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (13)`` () = + "9e428b85" + ++ SCVTF ** [ O.ScalarReg D5; O.Reg X28; OprFbits 0x1Euy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (14)`` () = + "9e43c5c5" + ++ UCVTF ** [ O.ScalarReg D5; O.Reg X14; OprFbits 0xFuy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (15)`` () = + "9e58e6d1" + ++ FCVTZS ** [ O.Reg X17; O.ScalarReg D22; OprFbits 7uy ] + ||> test + + [] + member __.``4.6.29 Conversion between FP and fixed-pt (16)`` () = + "9e59d1d2" + ++ FCVTZU ** [ O.Reg X18; O.ScalarReg D14; OprFbits 0xCuy ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (1)`` () = + "1e200154" + ++ FCVTNS ** [ O.Reg W20; O.ScalarReg S10 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (2)`` () = + "1e60034a" + ++ FCVTNS ** [ O.Reg W10; O.ScalarReg D26 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (3)`` () = + "9e200162" + ++ FCVTNS ** [ O.Reg X2; O.ScalarReg S11 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (4)`` () = + "9e600257" + ++ FCVTNS ** [ O.Reg X23; O.ScalarReg D18 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (5)`` () = + "1e2100b8" + ++ FCVTNU ** [ O.Reg W24; O.ScalarReg S5 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (6)`` () = + "1e6102b2" + ++ FCVTNU ** [ O.Reg W18; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (7)`` () = + "9e2100bb" + ++ FCVTNU ** [ O.Reg X27; O.ScalarReg S5 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (8)`` () = + "9e6101bc" + ++ FCVTNU ** [ O.Reg X28; O.ScalarReg D13 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (9)`` () = + "1e2200ba" + ++ SCVTF ** [ O.ScalarReg S26; O.Reg W5 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (10)`` () = + "1e6201e8" + ++ SCVTF ** [ O.ScalarReg D8; O.Reg W15 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (11)`` () = + "9e2201c2" + ++ SCVTF ** [ O.ScalarReg S2; O.Reg X14 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (12)`` () = + "9e6201dd" + ++ SCVTF ** [ O.ScalarReg D29; O.Reg X14 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (13)`` () = + "1e2302bd" + ++ UCVTF ** [ O.ScalarReg S29; O.Reg W21 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (14)`` () = + "1e6301c7" + ++ UCVTF ** [ O.ScalarReg D7; O.Reg W14 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (15)`` () = + "9e2301de" + ++ UCVTF ** [ O.ScalarReg S30; O.Reg X14 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (16)`` () = + "9e6302b9" + ++ UCVTF ** [ O.ScalarReg D25; O.Reg X21 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (17)`` () = + "1e24018a" + ++ FCVTAS ** [ O.Reg W10; O.ScalarReg S12 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (18)`` () = + "1e640299" + ++ FCVTAS ** [ O.Reg W25; O.ScalarReg D20 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (19)`` () = + "9e240255" + ++ FCVTAS ** [ O.Reg X21; O.ScalarReg S18 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (20)`` () = + "9e640338" + ++ FCVTAS ** [ O.Reg X24; O.ScalarReg D25 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (21)`` () = + "1e25035d" + ++ FCVTAU ** [ O.Reg W29; O.ScalarReg S26 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (22)`` () = + "1e650345" + ++ FCVTAU ** [ O.Reg W5; O.ScalarReg D26 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (23)`` () = + "9e250311" + ++ FCVTAU ** [ O.Reg X17; O.ScalarReg S24 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (24)`` () = + "9e650374" + ++ FCVTAU ** [ O.Reg X20; O.ScalarReg D27 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (25)`` () = + "1e26032e" + ++ FMOV ** [ O.Reg W14; O.ScalarReg S25 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (26)`` () = + "1e2701c3" + ++ FMOV ** [ O.ScalarReg S3; O.Reg W14 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (27)`` () = + "9e6602ab" + ++ FMOV ** [ O.Reg X11; O.ScalarReg D21 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (28)`` () = + "9e6701e3" + ++ FMOV ** [ O.ScalarReg D3; O.Reg X15 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (29)`` () = + "9eae021d" + ++ FMOV ** [ O.Reg X29; O.SIMDVecRegWithIdx (V16, VecD, 1uy) ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (30)`` () = + "9eaf02f8" + ++ FMOV ** [ O.SIMDVecRegWithIdx (V24, VecD, 1uy); O.Reg X23 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (31)`` () = + "1e2800ce" + ++ FCVTPS ** [ O.Reg W14; O.ScalarReg S6 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (32)`` () = + "1e680066" + ++ FCVTPS ** [ O.Reg W6; O.ScalarReg D3 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (33)`` () = + "9e280223" + ++ FCVTPS ** [ O.Reg X3; O.ScalarReg S17 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (34)`` () = + "9e68037a" + ++ FCVTPS ** [ O.Reg X26; O.ScalarReg D27 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (35)`` () = + "1e29021c" + ++ FCVTPU ** [ O.Reg W28; O.ScalarReg S16 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (36)`` () = + "1e690133" + ++ FCVTPU ** [ O.Reg W19; O.ScalarReg D9 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (37)`` () = + "9e290069" + ++ FCVTPU ** [ O.Reg X9; O.ScalarReg S3 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (38)`` () = + "9e690275" + ++ FCVTPU ** [ O.Reg X21; O.ScalarReg D19 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (39)`` () = + "1e3001dd" + ++ FCVTMS ** [ O.Reg W29; O.ScalarReg S14 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (40)`` () = + "1e700362" + ++ FCVTMS ** [ O.Reg W2; O.ScalarReg D27 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (41)`` () = + "9e300079" + ++ FCVTMS ** [ O.Reg X25; O.ScalarReg S3 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (42)`` () = + "9e700086" + ++ FCVTMS ** [ O.Reg X6; O.ScalarReg D4 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (43)`` () = + "1e310185" + ++ FCVTMU ** [ O.Reg W5; O.ScalarReg S12 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (44)`` () = + "1e71027d" + ++ FCVTMU ** [ O.Reg W29; O.ScalarReg D19 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (45)`` () = + "9e3103ff" + ++ FCVTMU ** [ O.Reg XZR; O.ScalarReg S31 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (46)`` () = + "9e710000" + ++ FCVTMU ** [ O.Reg X0; O.ScalarReg D0 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (47)`` () = + "1e380343" + ++ FCVTZS ** [ O.Reg W3; O.ScalarReg S26 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (48)`` () = + "1e7800cd" + ++ FCVTZS ** [ O.Reg W13; O.ScalarReg D6 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (49)`` () = + "9e380279" + ++ FCVTZS ** [ O.Reg X25; O.ScalarReg S19 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (50)`` () = + "9e780146" + ++ FCVTZS ** [ O.Reg X6; O.ScalarReg D10 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (51)`` () = + "1e390261" + ++ FCVTZU ** [ O.Reg W1; O.ScalarReg S19 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (52)`` () = + "1e79033b" + ++ FCVTZU ** [ O.Reg W27; O.ScalarReg D25 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (53)`` () = + "9e390053" + ++ FCVTZU ** [ O.Reg X19; O.ScalarReg S2 ] + ||> test + + [] + member __.``4.6.30 Conversion between FP and integer (54)`` () = + "9e790262" + ++ FCVTZU ** [ O.Reg X2; O.ScalarReg D19 ] + ||> test diff --git a/src/FrontEnd/BinLifter.Tests/ARMThumb.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/ARMThumb.Parser.Tests.fs new file mode 100644 index 00000000..cbf732ac --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/ARMThumb.Parser.Tests.fs @@ -0,0 +1,975 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.ARMThumb + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.ARM32 +open B2R2.FrontEnd.Tests.ARM32 +open type Opcode +open type Register + +let private test c op w q (s: SIMDDataTypes option) oprs (b: byte[]) = + let mode = ArchOperationMode.ThumbMode + let isa = ISA.Init Architecture.ARMv7 Endian.Big + let parser = ARM32Parser (isa, mode, None) :> IInstructionParsable + let ins = parser.Parse (b, 0UL) :?> ARM32Instruction + let cond' = ins.Condition + let opcode' = ins.Opcode + let wback' = ins.WriteBack + let q' = ins.Qualifier + let q = if Option.isSome q then W else N + let simd' = ins.SIMDTyp + let oprs' = ins.Operands + Assert.AreEqual (cond', c) + Assert.AreEqual (opcode', op) + Assert.AreEqual (wback', w) + Assert.AreEqual (q', q) + Assert.AreEqual (simd', s) + Assert.AreEqual (oprs', oprs) + +let private testNoWbackNoQNoSimd pref (bytes: byte[]) (opcode, operands) = + test pref opcode false None None operands bytes + +let private testNoWbackNoSimd pref q (bytes: byte[]) (opcode, operands) = + test pref opcode false q None operands bytes + +let private testNoQNoSimd pref wback (bytes: byte[]) (opcode, operands) = + test pref opcode wback None None operands bytes + +let private testNoSimd pref wback q (bytes: byte[]) (opcode, operands) = + test pref opcode wback q None operands bytes + +let private operandsFromArray oprList = + let oprs = Array.ofList oprList + match oprs.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprs[0] + | 2 -> TwoOperands (oprs[0], oprs[1]) + | 3 -> ThreeOperands (oprs[0], oprs[1], oprs[2]) + | 4 -> FourOperands (oprs[0], oprs[1], oprs[2], oprs[3]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +/// A4.3 Branch instructions +[] +type BranchClass () = + [] + member __.``[Thumb] Branch Parse test (1)`` () = + "d826" + ++ B ** [ O.MemLabel 76L ] + ||> testNoWbackNoQNoSimd Condition.HI + + [] + member __.``[Thumb] Branch Parse test (2)`` () = + "e184" + ++ B ** [ O.MemLabel 776L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Branch Parse test (3)`` () = + "f6738866" + ++ B ** [ O.MemLabel 4294652108L ] + ||> testNoWbackNoSimd Condition.LS (Some W) + + [] + member __.``[Thumb] Branch Parse test (4)`` () = + "f0309194" + ++ B ** [ O.MemLabel 12780328L ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Branch Parse test (5)`` () = + "b91a" + ++ CBNZ ** [ O.Reg R2; O.MemLabel 6L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Branch Parse test (6)`` () = + "47c8" + ++ BLX ** [ O.Reg SB ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Branch Parse test (7)`` () = + "f436e184" + ++ BLX ** [ O.MemLabel 4286800648L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Branch Parse test (8)`` () = + "4718" + ++ BX ** [ O.Reg R3 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Branch Parse test (9)`` () = + "f3c58f00" + ++ BXJ ** [ O.Reg R5 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Branch Parse test (10)`` () = + "e8def017" + ++ TBH ** [ O.MemOffsetReg (LR, None, R7, SRTypeLSL, 1u) ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.4 Data-processing instructions +[] +type DataProcessingClass () = + /// A4.4.1 Standard data-processing instructions + [] + member __.``[Thumb] Standard data-processing Parse test (1)`` () = + "f1526318" + ++ ADCS ** [ O.Reg R3; O.Reg R2; O.Imm 159383552L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (2)`` () = + "44ec" + ++ ADD ** [ O.Reg IP; O.Reg SP; O.Reg IP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (3)`` () = + "44d5" + ++ ADD ** [ O.Reg SP; O.Reg SP; O.Reg SL ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (4)`` () = + "448b" + ++ ADD ** [ O.Reg FP; O.Reg R1 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (5)`` () = + "b066" + ++ ADD ** [ O.Reg SP; O.Reg SP; O.Imm 408L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (6)`` () = + "ac28" + ++ ADD ** [ O.Reg R4; O.Reg SP; O.Imm 160L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (7)`` () = + "f1040e01" + ++ ADD ** [ O.Reg LR; O.Reg R4; O.Imm 1L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (8)`` () = + "180c" + ++ ADDS ** [ O.Reg R4; O.Reg R1; O.Reg R0 ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Standard data-processing Parse test (9)`` () = + "1c77" + ++ ADDS ** [ O.Reg R7; O.Reg R6; O.Imm 1L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Standard data-processing Parse test (10)`` () = + "f20b0001" + ++ ADDW ** [ O.Reg R0; O.Reg FP; O.Imm 1L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (11)`` () = + "f20f0001" + ++ ADR ** [ O.Reg R0; O.MemLabel 1L ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Standard data-processing Parse test (12)`` () = + "a20f" + ++ ADR ** [ O.Reg R2; O.MemLabel 60L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (13)`` () = + "403e" + ++ ANDS ** [ O.Reg R6; O.Reg R6; O.Reg R7 ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Standard data-processing Parse test (14)`` () = + "ea3c7605" + ++ BICS ** [ O.Reg R6; O.Reg IP; O.Reg R5; O.Shift (SRTypeLSL, 28u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (15)`` () = + "2df3" + ++ CMP ** [ O.Reg R5; O.Imm 243L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (16)`` () = + "45c8" + ++ CMP ** [ O.Reg R8; O.Reg SB ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (17)`` () = + "4544" + ++ CMP ** [ O.Reg R4; O.Reg R8 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (18)`` () = + "f04f1708" + ++ MOV ** [ O.Reg R7; O.Imm 524296L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (19)`` () = + "000e" + ++ MOVS ** [ O.Reg R6; O.Reg R1; O.Shift (SRTypeLSL, 0u) ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Standard data-processing Parse test (20)`` () = + "f6420b02" + ++ MOVW ** [ O.Reg FP; O.Imm 10242L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (21)`` () = + "ea6ff49e" + ++ MVN ** [ O.Reg R4; O.Reg LR; O.Shift (SRTypeLSR, 30u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (22)`` () = + "f5d90308" + ++ RSBS ** [ O.Reg R3; O.Reg SB; O.Imm 8912896L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (23)`` () = + "424b" + ++ RSBS ** [ O.Reg R3; O.Reg R1; O.Imm 0L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Standard data-processing Parse test (24)`` () = + "f4914f88" + ++ TEQ ** [ O.Reg R1; O.Imm 17408L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Standard data-processing Parse test (25)`` () = + "ea125f6b" + ++ TST ** [ O.Reg R2; O.Reg FP; O.Shift (SRTypeASR, 21u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.2 Shift instructions + [] + member __.``[Thumb] Shift Parse test (1)`` () = + "fa5afb07" + ++ ASRS ** [ O.Reg FP; O.Reg SL; O.Reg R7 ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Shift Parse test (2)`` () = + "0431" + ++ LSLS ** [ O.Reg R1; O.Reg R6; O.Imm 16L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Shift Parse test (3)`` () = + "080a" + ++ LSRS ** [ O.Reg R2; O.Reg R1; O.Imm 32L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Shift Parse test (4)`` () = + "ea5f0cda" + ++ LSRS ** [ O.Reg IP; O.Reg SL; O.Imm 3L ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Shift Parse test (5)`` () = + "ea5f0039" + ++ RRXS ** [ O.Reg R0; O.Reg SB ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.3 Multiply instructions + [] + member __.``[Thumb] Multiply Parse test (1)`` () = + "fb00c901" + ++ MLA ** [ O.Reg SB; O.Reg R0; O.Reg R1; O.Reg IP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (2)`` () = + "fb03fc0b" + ++ MUL ** [ O.Reg IP; O.Reg R3; O.Reg FP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (3)`` () = + "4366" + ++ MULS ** [ O.Reg R6; O.Reg R4; O.Reg R6 ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Multiply Parse test (4)`` () = + "fb2a5c14" + ++ SMLADX ** [ O.Reg IP; O.Reg SL; O.Reg R4; O.Reg R5 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (5)`` () = + "fb1e5c21" + ++ SMLATB ** [ O.Reg IP; O.Reg LR; O.Reg R1; O.Reg R5 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (6)`` () = + "fbc18aa3" + ++ SMLALTB ** [ O.Reg R8; O.Reg SL; O.Reg R1; O.Reg R3 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (7)`` () = + "fbd0ced5" + ++ SMLSLDX ** [ O.Reg IP; O.Reg LR; O.Reg R0; O.Reg R5 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (8)`` () = + "fb58f019" + ++ SMMULR ** [ O.Reg R0; O.Reg R8; O.Reg SB ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (9)`` () = + "fb1bf837" + ++ SMULTT ** [ O.Reg R8; O.Reg FP; O.Reg R7 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Multiply Parse test (10)`` () = + "fb83a904" + ++ SMULL ** [ O.Reg SL; O.Reg SB; O.Reg R3; O.Reg R4 ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.4 Saturating instructions + [] + member __.``[Thumb] Saturating Parse test (1)`` () = + "f3280c05" + ++ SSAT16 ** [ O.Reg IP; O.Imm 6L; O.Reg R8 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Saturating Parse test (2)`` () = + "f3a31791" + ++ USAT ** [ O.Reg R7; O.Imm 17L; O.Reg R3; O.Shift (SRTypeASR, 6u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.5 Saturating addition and subtraction instructions + [] + member __.``[Thumb] Saturating addition and subtraction Parse test (1)`` () = + "fa86fc9e" + ++ QDADD ** [ O.Reg IP; O.Reg LR; O.Reg R6 ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.6 Packing and unpacking instructions + [] + member __.``[Thumb] Packing and unpacking Parse test (1)`` () = + "eacc404a" + ++ PKHBT ** [ O.Reg R0; O.Reg IP; O.Reg SL; O.Shift (SRTypeLSL, 17u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Packing and unpacking Parse test (2)`` () = + "fa00f4b6" + ++ SXTAH ** [ O.Reg R4; O.Reg R0; O.Reg R6; O.Shift (SRTypeROR, 24u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Packing and unpacking Parse test (3)`` () = + "fa2ff996" + ++ SXTB16 ** [ O.Reg SB; O.Reg R6; O.Shift (SRTypeROR, 8u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Packing and unpacking Parse test (4)`` () = + "b287" + ++ UXTH ** [ O.Reg R7; O.Reg R0 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Packing and unpacking Parse test (5)`` () = + "fa1ff28c" + ++ UXTH ** [ O.Reg R2; O.Reg IP ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + /// A4.4.7 Parallel addition and subtraction instructions + [] + member __.``[Thumb] Parallel addition and subtraction Parse test (1)`` () = + // Signed + "fa9cfb00" + ++ SADD16 ** [ O.Reg FP; O.Reg IP; O.Reg R0 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Parallel addition and subtraction Parse test (2)`` () = + // Saturating + "fae8fe19" + ++ QSAX ** [ O.Reg LR; O.Reg R8; O.Reg SB ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Parallel addition and subtraction Parse test (3)`` () = + // Signed halving + "fac0fc27" + ++ SHSUB8 ** [ O.Reg IP; O.Reg R0; O.Reg R7 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Parallel addition and subtraction Parse test (4)`` () = + // Unsigned + "faa0f146" + ++ UASX ** [ O.Reg R1; O.Reg R0; O.Reg R6 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Parallel addition and subtraction Parse test (5)`` () = + // Unsigned saturating + "fa8ef953" + ++ UQADD8 ** [ O.Reg SB; O.Reg LR; O.Reg R3 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Parallel addition and subtraction Parse test (6)`` () = + // Unsigned halving + "faa0f86a" + ++ UHASX ** [ O.Reg R8; O.Reg R0; O.Reg SL ] + ||> testNoWbackNoQNoSimd Condition.AL + + //// A4.4.8 Divide instructions + [] + member __.``[Thumb] Divide Parse test (1)`` () = + "fbb0fcfe" + ++ UDIV ** [ O.Reg IP; O.Reg R0; O.Reg LR ] + ||> testNoWbackNoQNoSimd Condition.AL + + /// A4.4.9 Miscellaneous data-processing instructions + [] + member __.``[Thumb] Miscellaneous data-processing Parse test (1)`` () = + "f36f1c12" + ++ BFC ** [ O.Reg IP; O.Imm 4L; O.Imm 15L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous data-processing Parse test (2)`` () = + "f3612ad1" + ++ BFI ** [ O.Reg SL; O.Reg R1; O.Imm 11L; O.Imm 7L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous data-processing Parse test (3)`` () = + "fa94fca4" + ++ RBIT ** [ O.Reg IP; O.Reg R4 ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous data-processing Parse test (4)`` () = + "f34e0918" + ++ SBFX ** [ O.Reg SB; O.Reg LR; O.Imm 0L; O.Imm 25L ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.5 Status register access instructions +[] +type StatusOprRegAccessClass () = + [] + member __.``[Thumb] Status register access Parse test (1)`` () = + "f3ef8500" + ++ MRS ** [ O.Reg R5; O.Reg APSR ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Status register access Parse test (2)`` () = + "f3ff8c00" + ++ MRS ** [ O.Reg IP; O.Reg SPSR ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Status register access Parse test (3)`` () = + "f38b8400" + ++ MSR ** [ O.SpecReg (CPSR, PSRs); O.Reg FP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Status register access Parse test (4)`` () = + "f38c8500" + ++ MSR ** [ O.SpecReg (CPSR, PSRsc); O.Reg IP ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Status register access Parse test (5)`` () = + "f3af8764" + ++ CPSID ** [ O.Iflag IF; O.Imm 4L ] + ||> testNoWbackNoQNoSimd Condition.UN (* W *) + + [] + member __.``[Thumb] Status register access Parse test (6)`` () = + "b665" + ++ CPSIE ** [ O.Iflag AF ] + ||> testNoWbackNoQNoSimd Condition.UN + + /// A4.5.1 Banked register access instructions + [] + member __.``[Thumb] Banked register access Parse test (1)`` () = + "f3e68020" + ++ MRS ** [ O.Reg R0; O.Reg LRusr ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Banked register access Parse test (2)`` () = + "f3918430" + ++ MSR ** [ O.Reg SPSRabt; O.Reg R1 ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.6 Load/store instructions +[] +type LoadStoreClass () = + [] + member __.``[Thumb] Load/store (Lord) Parse test (1)`` () = + "990f" + ++ LDR ** [ O.Reg R1; O.MemOffsetImm (SP, Some Plus, Some 60L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Lord) Parse test (2)`` () = + "4c37" + ++ LDR ** [ O.Reg R4; O.MemLabel 220L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Lord) Parse test (3)`` () = + "f8df0087" + ++ LDR ** [ O.Reg R0; O.MemLabel 135L ] + ||> testNoSimd Condition.AL false (Some W) + + [] + member __.``[Thumb] Load/store (Lord) Parse test (4)`` () = + "f859c038" + ++ LDR ** [ O.Reg IP; O.MemOffsetReg (SB, Some Plus, R8, SRTypeLSL, 3u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Lord) Parse test (5)`` () = + "f8512f33" + ++ LDR ** [ O.Reg R2; O.MemPreIdxImm (R1, Some Plus, Some 51L) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Load/store (Lord) Parse test (6)`` () = + "f8dec080" + ++ LDR ** [ O.Reg IP; O.MemOffsetImm (LR, Some Plus, Some 128L) ] + ||> testNoSimd Condition.AL false (Some W) + + [] + member __.``[Thumb] Load/store (Lord) Parse test (7)`` () = + "f839bc82" + ++ LDRH ** [ O.Reg FP; O.MemOffsetImm (SB, Some Minus, Some 130L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Lord) Parse test (8)`` () = + "f93f624b" + ++ LDRSH ** [ O.Reg R6; O.MemLabel -587L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Lord) Parse test (9)`` () = + "f9b3b00b" + ++ LDRSH ** [ O.Reg FP; O.MemOffsetImm (R3, Some Plus, Some 11L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Lord) Parse test (10)`` () = + "79a6" + ++ LDRB ** [ O.Reg R6; O.MemOffsetImm (R4, Some Plus, Some 6L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Lord) Parse test (11)`` () = + "f812a036" + ++ LDRB ** [ O.Reg SL; O.MemOffsetReg (R2, Some Plus, R6, SRTypeLSL, 3u) ] + ||> testNoQNoSimd Condition.AL false (* W *) + + [] + member __.``[Thumb] Load/store (Lord) Parse test (12)`` () = + "f814890c" + ++ LDRB ** [ O.Reg R8; O.MemPostIdxImm (R4, Some Minus, Some 12L) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Load/store (Lord) Parse test (13)`` () = + "f89f30f0" + ++ LDRB ** [ O.Reg R3; O.MemLabel 240L ] + ||> testNoWbackNoQNoSimd Condition.AL (* W *) + + [] + member __.``[Thumb] Load/store (Lord) Parse test (14)`` () = + "f9981c32" + ++ LDRSB ** [ O.Reg R1; O.MemOffsetImm (R8, Some Plus, Some 3122L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Lord) Parse test (15)`` () = + "f91e9020" + ++ LDRSB ** [ O.Reg SB; O.MemOffsetReg (LR, Some Plus, R0, SRTypeLSL, 2u) ] + ||> testNoQNoSimd Condition.AL false (* W *) + + [] + member __.``[Thumb] Load/store (Lord) Parse test (16)`` () = + "e95fc642" + ++ LDRD ** [ O.Reg IP; O.Reg R6; O.MemLabel -264L ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Store) Parse test (1)`` () = + "6637" + ++ STR ** [ O.Reg R7; O.MemOffsetImm (R6, Some Plus, Some 96L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Store) Parse test (2)`` () = + "8457" + ++ STRH ** [ O.Reg R7; O.MemOffsetImm (R2, Some Plus, Some 34L) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Store) Parse test (3)`` () = + "549c" + ++ STRB ** [ O.Reg R4; O.MemOffsetReg (R3, Some Plus, R2) ] + ||> testNoQNoSimd Condition.AL false + + [] + member __.``[Thumb] Load/store (Store) Parse test (4)`` () = + "f809e982" + ++ STRB ** [ O.Reg LR; O.MemPostIdxImm (SB, Some Minus, Some 130L) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Load/store (Store) Parse test (5)`` () = + "f886c80c" + ++ STRB ** [ O.Reg IP; O.MemOffsetImm (R6, Some Plus, Some 2060L) ] + ||> testNoSimd Condition.AL false (Some W) + + [] + member __.``[Thumb] Load/store (Store) Parse test (6)`` () = + "f80a002c" + ++ STRB ** [ O.Reg R0; O.MemOffsetReg (SL, Some Plus, IP, SRTypeLSL, 2u) ] + ||> testNoQNoSimd Condition.AL false (* W *) + + [] + member __.``[Thumb] Load/store (Store) Parse test (7)`` () = + "e96a393c" + ++ STRD ** [ O.Reg R3; O.Reg SB; + O.MemPreIdxImm (SL, Some Minus, Some 240L) ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Load/store (Load unprivileged) Parse test (1)`` () = + "f8501e04" + ++ LDRT ** [ O.Reg R1; O.MemOffsetImm (R0, None, Some 4L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Load unprivileged) Parse test (2)`` () = + "f834ce01" + ++ LDRHT ** [ O.Reg IP; O.MemOffsetImm (R4, None, Some 1L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Load unprivileged) Parse test (3)`` () = + "f91c9e09" + ++ LDRSBT ** [ O.Reg SB; O.MemOffsetImm (IP, None, Some 9L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Store unprivileged) Parse test (1)`` () = + "f827be53" + ++ STRHT ** [ O.Reg FP; O.MemOffsetImm (R7, None, Some 83L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Load-Exclusive) Parse test (1)`` () = + "e859bf0e" + ++ LDREX ** [ O.Reg FP; O.MemOffsetImm (SB, None, Some 56L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Load-Exclusive) Parse test (2)`` () = + "e8d90f4f" + ++ LDREXB ** [ O.Reg R0; O.MemOffsetImm (SB, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Load-Exclusive) Parse test (3)`` () = + "e8deac7f" + ++ LDREXD ** [ O.Reg SL; O.Reg IP; O.MemOffsetImm (LR, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Store-Exclusive) Parse test (1)`` () = + "e841ea0c" + ++ STREX ** [ O.Reg SL; O.Reg LR; O.MemOffsetImm (R1, None, Some 48L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Store-Exclusive) Parse test (2)`` () = + "e8c8af56" + ++ STREXH ** [ O.Reg R6; O.Reg SL; O.MemOffsetImm (R8, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store (Store-Exclusive) Parse test (3)`` () = + "e8c0cb74" + ++ STREXD ** [ O.Reg R4; O.Reg IP; O.Reg FP; + O.MemOffsetImm (R0, None, None) ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A4.7 Load/store multiple instructions +[] +type LoadStoreMultipleClass () = + [] + member __.``[Thumb] Load/store multiple Parse test (1)`` () = + "cbc1" + ++ LDM ** [ O.Reg R3; O.RegList [ R0; R6; R7 ] ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Load/store multiple Parse test (2)`` () = + "e8985184" + ++ LDM ** [ O.Reg R8; O.RegList [ R2; R7; R8; IP; LR ] ] + ||> testNoSimd Condition.AL false (Some W) + + [] + member __.``[Thumb] Load/store multiple Parse test (3)`` () = + "e8bd8611" + ++ POP ** [ O.RegList [ R0; R4; SB; SL; PC ] ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Load/store multiple Parse test (4)`` () = + "f85d3b04" + ++ POP ** [ O.RegList [ R3 ] ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Load/store multiple Parse test (5)`` () = + "b533" + ++ PUSH ** [ O.RegList [ R0; R1; R4; R5; LR ] ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Load/store multiple Parse test (6)`` () = + "e92d0184" + ++ PUSH ** [ O.RegList [ R2; R7; R8 ] ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Load/store multiple Parse test (7)`` () = + "f84d1d04" + ++ PUSH ** [ O.RegList [ R1 ] ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Load/store multiple Parse test (8)`` () = + "c5a3" + ++ STM ** [ O.Reg R5; O.RegList [ R0; R1; R5; R7 ] ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Load/store multiple Parse test (9)`` () = + "e8825990" + ++ STM ** [ O.Reg R2; O.RegList [ R4; R7; R8; FP; IP; LR ] ] + ||> testNoSimd Condition.AL false (Some W) + +/// A4.8 Miscellaneous instructions +[] +type MiscellaneousClass () = + [] + member __.``[Thumb] Miscellaneous Parse test (1)`` () = + "f3af80fb" + ++ DBG ** [ O.Imm 11L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (2)`` () = + "f3bf8f57" + ++ DMB ** [ O.Option BarrierOption.NSH ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (3)`` () = + "bf6c" + ++ ITE ** [ O.Cond Condition.VS ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Miscellaneous Parse test (4)`` () = + "f3af8000" + ++ NOP ** [ ] + ||> testNoWbackNoSimd Condition.AL (Some W) + + [] + member __.``[Thumb] Miscellaneous Parse test (5)`` () = + "f81cf01b" + ++ PLD ** [ O.MemOffsetReg (IP, None, FP, SRTypeLSL, 1u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (6)`` () = + "f810fc20" + ++ PLD ** [ O.MemOffsetImm (R0, Some Minus, Some 32L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (7)`` () = + "f81ff08e" + ++ PLD ** [ O.MemLabel -142L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (8)`` () = + "f89ff00f" + ++ PLD ** [ O.MemLabel 15L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (9)`` () = + "f837f01b" + ++ PLDW ** [ O.MemOffsetReg (R7, None, FP, SRTypeLSL, 1u) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (10)`` () = + "f832fc31" + ++ PLDW ** [ O.MemOffsetImm (R2, Some Minus, Some 49L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (11)`` () = + "f8bcf0c3" + ++ PLDW ** [ O.MemOffsetImm (IP, Some Plus, Some 195L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (12)`` () = + "f99af003" + ++ PLI ** [ O.MemOffsetImm (SL, Some Plus, Some 3L) ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Miscellaneous Parse test (13)`` () = + "b658" + ++ SETEND ** [ O.Endian Endian.Big ] + ||> testNoWbackNoQNoSimd Condition.UN + +/// A4.9 Exception-generating and exception-handling instructions +[] +type ExcepGenAndExcepHandClass () = + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (1)`` () = + "be30" + ++ BKPT ** [ O.Imm 48L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (2)`` () = + "f7f88000" + ++ SMC ** [ O.Imm 8L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (3)`` () = + "e9bac000" + ++ RFEIA ** [ O.Reg SL ] + ||> testNoQNoSimd Condition.AL true + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (4)`` () = + "f3de8f08" + ++ SUBS ** [ O.Reg PC; O.Reg LR; O.Imm 8L ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (5)`` () = + "f7e1800c" + ++ HVC ** [ O.Imm 4108L ] + ||> testNoWbackNoQNoSimd Condition.UN + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (6)`` () = + "f3de8f00" + ++ ERET ** [ ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (7)`` () = + "f3de8f00" + ++ ERET ** [ ] + ||> testNoWbackNoQNoSimd Condition.AL + + [] + member __.``[Thumb] Exception-gen and exception-handling Parse test (8)`` () = + "e82dc013" + ++ SRSDB ** [ O.Reg SP; O.Imm 19L ] + ||> testNoQNoSimd Condition.AL true + +/// A5.4 Media instructions +[] +type MediaClass () = + [] + member __.``[Thumb] Media Parse test (1)`` () = + "de0f" + ++ UDF ** [ O.Imm 15L ] + ||> testNoWbackNoQNoSimd Condition.AL + +/// A6.3.4 Branches and miscellaneous control +[] +type MiscellaneousControlClass () = + [] + member __.``[Thumb] Miscellaneous control Parse test (1)`` () = + "f3bf8f2f" + ++ CLREX ** [ ] + ||> testNoWbackNoQNoSimd Condition.AL diff --git a/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs index 7544e97f..9d4c8f76 100644 --- a/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/AVR.Lifter.Tests.fs @@ -1,4 +1,4 @@ -(* +(* B2R2 - the Next-Generation Reversing Platform Copyright (c) SoftSec Lab. @ KAIST, since 2016 @@ -27,61 +27,69 @@ module B2R2.FrontEnd.Tests.AVRLifter open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 open B2R2.BinIR.LowUIR -open B2R2.FrontEnd.BinLifter.AVR open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.AVR open B2R2.BinIR.LowUIR.AST.InfixOp +open type Register + +[] +module TestHelper = + let isa = ISA.Init Architecture.AVR Endian.Little + + let ctxt = AVRTranslationContext isa -let isa = ISA.Init Architecture.AVR Endian.Little + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) -let struct (ctxt, _) = AVR.Basis.init isa + let inline ( ++ ) (byteStr: string) givenStmts = + ByteArray.ofHexString byteStr, givenStmts -let inline ( !. ) (ctxt: TranslationContext) name = - Register.toRegID name |> ctxt.GetRegVar + let inline ( !. ) name = Register.toRegID name |> ctxt.GetRegVar -let private test bytes len (actStmts : Stmt []) = - let reader = BinReader.binReaderLE - let span = System.ReadOnlySpan bytes - let ins = Parser.parse span reader 0UL - let expStmts = (Lifter.translate ins.Info len ctxt).ToStmts () - Assert.AreEqual (Array.toList expStmts, Array.toList actStmts) + let test (bytes: byte[], givenStmts: Stmt[]) = + let parser = AVRParser () :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) + CollectionAssert.AreEqual (givenStmts, unwrapStmts <| ins.Translate ctxt) [] type AVRUnitTest () = [] member __.``[AVR] Instructions with start and end statements lift Test`` () = - test [| 0x00uy; 0x00uy |] 2u [| AST.ismark 2u; AST.iemark 2u |] + "0000" + ++ [| |] + |> test + + [] + member __.``[AVR] Instructions with Put statements lift Test (1)`` () = + "4c2f" + ++ [| !.R20 := !.R28 |] + |> test + + [] + member __.``[AVR] Instructions with Put statements lift Test (2)`` () = + "5401" + ++ [| !.R10 := !.R8 + !.R11 := !.R9 |] + |> test [] - member __.``[AVR] Instructions with Put statements lift Test`` () = - test [| 0x4cuy; 0x2fuy |] 2u - [| AST.ismark 2u - (!.ctxt R.R20 := !.ctxt R.R28) - AST.iemark 2u |] - test [| 0x54uy; 0x01uy |] 2u - [| AST.ismark 2u - (!.ctxt R.R10 := !.ctxt R.R8) - (!.ctxt R.R11 := !.ctxt R.R9) - AST.iemark 2u |] + member __.``[AVR] Put statements for flag registers lift Test (1)`` () = + "f894" + ++ [| !.IF := AST.b0 |] + |> test [] - member __.``[AVR] Put statements for flag registers lift Test`` () = - test [| 0xf8uy; 0x94uy |] 2u - [| AST.ismark 2u - (!.ctxt R.IF := AST.b0) - AST.iemark 2u |] - test [| 0x11uy; 0x24uy |] 2u - [| AST.ismark 2u - (!.ctxt R.R1 := !.ctxt R.R1 <+> !.ctxt R.R1) - (!.ctxt R.VF := AST.b0) - (!.ctxt R.NF := AST.xthi 1 (!.ctxt R.R1)) - (!.ctxt R.ZF := !. ctxt R.R1 == AST.num0 8) - (!.ctxt R.SF := !.ctxt R.NF <+> !.ctxt R.VF) - AST.iemark 2u |] + member __.``[AVR] Put statements for flag registers lift Test (2)`` () = + "1124" + ++ [| !.R1 := !.R1 <+> !.R1 + !.VF := AST.b0 + !.NF := AST.xthi 1 !.R1 + !.ZF := !.R1 == AST.num0 8 + !.SF := !.NF <+> !.VF |] + |> test [] member __.``[AVR] Load statements lift Test`` () = - test [| 0x6fuy; 0x92uy |] 2u - [| AST.ismark 2u - (AST.loadLE 8 (!.ctxt R.SP) := !.ctxt R.R6) - (!.ctxt R.SP := !.ctxt R.SP .- AST.num1 16) - AST.iemark 2u |] \ No newline at end of file + "6f92" + ++ [| AST.loadLE 8 !.SP := !.R6 + !.SP := !.SP .- AST.num1 16 |] + |> test diff --git a/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs index 84d157d7..a2481426 100644 --- a/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/AVR.Parser.Tests.fs @@ -1,4 +1,4 @@ -(* +(* B2R2 - the Next-Generation Reversing Platform Copyright (c) SoftSec Lab. @ KAIST, since 2016 @@ -22,58 +22,88 @@ SOFTWARE. *) -module B2R2.FrontEnd.Tests.AVRParser +module B2R2.FrontEnd.Tests.AVR open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 open B2R2.FrontEnd.BinLifter.AVR +open type Opcode +open type Register -let private test opcode oprs bytes = - let reader = BinReader.binReaderLE +/// Shortcut for creating operands. +type O = + static member Reg (r) = + OprReg r + + static member Imm (v) = + OprImm v + + static member Addr (v) = + OprAddr v + + static member MemDisp (r, v) = + OprMemory (DispMode (r, v)) + + static member MemPostIdx (r) = + OprMemory (PostIdxMode r) + +let private test (bytes: byte[]) (opcode, oprs) = + let reader = BinReader.Init Endian.Little let span = System.ReadOnlySpan bytes - let ins = Parser.parse span reader 0UL + let ins = ParsingMain.parse span reader 0UL Assert.AreEqual (ins.Info.Opcode, opcode) Assert.AreEqual (ins.Info.Operands, oprs) +let private operandsFromArray oprList = + let oprs = Array.ofList oprList + match oprs.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprs[0] + | 2 -> TwoOperands (oprs[0], oprs[1]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + [] type AVRUnitTest () = [] - member __.``[AVR] No Operand Insturctions Parse Test`` () = - test Opcode.RET - (NoOperand) - [| 0x08uy; 0x95uy |] + member __.``[AVR] No Operand Insturctions Parse Test (1)`` () = + "0895" + ++ RET ** [ ] ||> test + + [] + member __.``[AVR] One Operand Insturctions Parse Test (1)`` () = + "81f1" + ++ BREQ ** [ O.Addr 96 ] ||> test [] - member __.``[AVR] One Operand Insturctions Parse Test`` () = - test Opcode.BREQ - (OneOperand (OprAddr 96)) - [| 0x81uy; 0xf1uy |] - test Opcode.BRGE - (OneOperand (OprAddr 44)) - [| 0xB4uy; 0xf4uy |] + member __.``[AVR] One Operand Insturctions Parse Test (2)`` () = + "b4f4" + ++ BRGE ** [ O.Addr 44 ] ||> test [] - member __.``[AVR] Two Register Operands Insturctions Parse Test`` () = - test Opcode.ADD - (TwoOperands (OprReg R.R12, OprReg R.R25)) - [| 0xC9uy; 0x0Euy |] - test Opcode.MOV - (TwoOperands (OprReg R.R14, OprReg R.R1)) - [| 0xE1uy; 0x2Cuy |] + member __.``[AVR] Two Register Operands Insturctions Parse Test (1)`` () = + "c90e" + ++ ADD ** [ O.Reg R12; O.Reg R25 ] ||> test [] - member __.``[AVR] Memory Operands Insturctions Parse Test`` () = - test Opcode.ST - (TwoOperands (OprMemory (PostIdxMode (R.X)), OprReg R.R1)) - [| 0x1Duy; 0x92uy |] - test Opcode.LDD - (TwoOperands (OprReg R.R6, OprMemory (DispMode ((R.Y, 1))))) - [| 0x69uy; 0x80uy |] + member __.``[AVR] Two Register Operands Insturctions Parse Test (2)`` () = + "e12c" + ++ MOV ** [ O.Reg R14; O.Reg R1 ] ||> test [] - member __.``[AVR] Immediate Operand Insturction Parse Test`` () = - test Opcode.LDI - (TwoOperands (OprReg R.R24, OprImm 0xff)) - [| 0x8Fuy; 0xEFuy |] + member __.``[AVR] Memory Operands Insturctions Parse Test (1)`` () = + "1d92" + ++ ST ** [ O.MemPostIdx X; OprReg R.R1 ] ||> test + [] + member __.``[AVR] Memory Operands Insturctions Parse Test (2)`` () = + "6980" + ++ LDD ** [ O.Reg R6; O.MemDisp (Y, 1) ] ||> test + [] + member __.``[AVR] Immediate Operand Insturction Parse Test (1)`` () = + "8fef" + ++ LDI ** [ O.Reg R24; O.Imm 0xff ] ||> test diff --git a/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj b/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj index 278def8c..15a713f7 100644 --- a/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj +++ b/src/FrontEnd/BinLifter.Tests/B2R2.FrontEnd.BinLifter.Tests.fsproj @@ -1,4 +1,4 @@ - + false @@ -6,20 +6,35 @@ - + + + + + + + + + + + + + + + + - - - + + + - + diff --git a/src/FrontEnd/BinLifter.Tests/EVM.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/EVM.Lifter.Tests.fs new file mode 100644 index 00000000..cbb5241e --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/EVM.Lifter.Tests.fs @@ -0,0 +1,81 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.EVMLifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.EVM +open type Register + +[] +module TestHelper = + let num v rt = BitVector.OfInt32 v rt |> AST.num + + let bigint v = BitVectorBig (v, 256) |> AST.num + + let isa = ISA.Init Architecture.EVM Endian.Little + + let ctxt = EVMTranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + let inline ( ++ ) byteString givenStmts = + ByteArray.ofHexString byteString, givenStmts + + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) + + let test (bytes: byte[], givenStmts) = + let parser = EVMParser (isa) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) + CollectionAssert.AreEqual (givenStmts, unwrapStmts <| ins.Translate ctxt) + +[] +type PUSHClass () = + [] + member __.``[EVM] PUSH8 lift test`` () = + "670011223344556677" + ++ [| !.SP := !.SP .+ num 32 256 + AST.store Endian.Big !.SP (bigint 4822678189205111I) + !.GAS := !.GAS .+ num 3 64 |] + |> test + + [] + member __.``[EVM] PUSH9 lift test`` () = + "68001122334455667788" + ++ [| !.SP := !.SP .+ num 32 256 + AST.store Endian.Big !.SP (bigint 1234605616436508552I) + !.GAS := !.GAS .+ num 3 64 |] + |> test + + [] + member __.``[EVM] PUSH10 lift test`` () = + "6900112233445566778899" + ++ [| !.SP := !.SP .+ num 32 256 + AST.store Endian.Big !.SP (bigint 316059037807746189465I) + !.GAS := !.GAS .+ num 3 64 |] + |> test diff --git a/src/FrontEnd/BinLifter.Tests/EVM.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/EVM.Parser.Tests.fs new file mode 100644 index 00000000..3b713dc8 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/EVM.Parser.Tests.fs @@ -0,0 +1,46 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.EVM + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter.EVM +open type BitVector + +let private test (bytes: byte[]) opcode = + let span = System.ReadOnlySpan bytes + let ins = ParsingMain.parse span 0UL WordSize.Bit64 0UL + let opcode' = ins.Info.Opcode + Assert.AreEqual (opcode', opcode) + +let private ( ++ ) byteString op = (ByteArray.ofHexString byteString, op) + +/// 60s & 70s: Push Operations +[] +type PUSHClass () = + [] + member __.``[EVM] PUSH10 Parse Test (1)`` () = + "6900112233445566778899" + ++ (PUSH10 <| (OfBInt 316059037807746189465I 80)) ||> test diff --git a/src/FrontEnd/BinLifter.Tests/Intel.Disassembler.Tests.fs b/src/FrontEnd/BinLifter.Tests/Intel.Disassembler.Tests.fs new file mode 100644 index 00000000..578da770 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/Intel.Disassembler.Tests.fs @@ -0,0 +1,112 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.Disassembler + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel +open B2R2.FrontEnd.BinLifter.Intel.Disasm +open type Opcode + +let private test wordSize (bytes: byte[]) (instruction: string[]) = + let parser = IntelParser (wordSize) :> IInstructionParsable + let actualInstruction (syntax: DisasmSyntax) = + setDisassemblyFlavor syntax + parser.Parse (bytes, 0UL) :?> IntelInstruction + |> fun instruction -> (instruction.Disasm ()).ToLowerInvariant () + Assert.AreEqual(instruction[0], actualInstruction DefaultSyntax, "Intel") + Assert.AreEqual(instruction[1], actualInstruction ATTSyntax, "AT&T") + +let private testX86 (bytes: byte[], instruction) = + test WordSize.Bit32 bytes instruction + +let private testX64 (bytes: byte[], instruction) = + test WordSize.Bit64 bytes instruction + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +[] +type GeneralPurposeClass () = + [] + member __.``X86 ADD instruction test (1)`` () = + "0500000100" ++ [| "add eax, 0x10000"; "add $0x10000, %eax" |] + |> testX86 + + [] + member __.``X86 ADD instruction test (2)`` () = + "83000a" ++ [| "add dword ptr [eax], 0xa"; "addl $0xa, (%eax)" |] + |> testX86 + + [] + // gcc isn't contain '+' + member __.``X86 ADD instruction test (3)`` () = + "8340100a" + ++ [| "add dword ptr [eax+0x10], 0xa"; "addl $0xa, +0x10(%eax)" |] + |> testX86 + + [] + member __.``X86 ADD instruction test (4)`` () = + "8304580a" + ++ [| "add dword ptr [eax+ebx*2], 0xa"; "addl $0xa, (%eax, %ebx, 2)" |] + |> testX86 + + [] + // gcc isn't contain '+' + member __.``X86 ADD instruction test (5)`` () = + "838458000100000a" + ++ [| "add dword ptr [eax+ebx*2+0x100], 0xa" + "addl $0xa, +0x100(%eax, %ebx, 2)" |] + |> testX86 + + [] + member __.``X64 ADD instruction test (6)`` () = + "480500000100" ++ [| "add rax, 0x10000"; "add $0x10000, %rax" |] + |> testX64 + + [] + member __.``X64 ADD instruction test (7)`` () = + "4883000a" ++ [| "add qword ptr [rax], 0xa"; "addq $0xa, (%rax)" |] + |> testX64 + + [] + member __.``X64 ADD instruction test (8)`` () = + "678340100a" + ++ [| "add dword ptr [eax+0x10], 0xa"; "addl $0xa, +0x10(%eax)" |] + |> testX64 + + [] + member __.``X64 ADD instruction test (9)`` () = + "678304580a" + ++ [| "add dword ptr [eax+ebx*2], 0xa"; "addl $0xa, (%eax, %ebx, 2)" |] + |> testX64 + + [] + // gcc isn't contain '+' + member __.``X64 ADD instruction test (10)`` () = + "67838458000100000a" + ++ [| "add dword ptr [eax+ebx*2+0x100], 0xa" + "addl $0xa, +0x100(%eax, %ebx, 2)" |] + |> testX64 diff --git a/src/FrontEnd/BinLifter.Tests/Intel.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/Intel.Lifter.Tests.fs new file mode 100644 index 00000000..fdb4a862 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/Intel.Lifter.Tests.fs @@ -0,0 +1,138 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.IntelLifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel +open type Register + +[] +module TestHelper = + let num v rt = BitVector.OfUInt32 v rt |> AST.num + + let t1 id = AST.tmpvar 1 id + + let t32 id = AST.tmpvar 32 id + + let t64 id = AST.tmpvar 64 id + + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) + + let inline ( ++ ) byteStr givenStmts = + ByteArray.ofHexString byteStr, Array.ofList givenStmts + + let inline ( ** ) stmts eflagsStmts = List.append stmts eflagsStmts + + let test ctxt wordSize (givenStmts: Stmt[]) (bytes: byte[]) = + let parser = IntelParser (wordSize) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) :?> IntelInternalInstruction + CollectionAssert.AreEqual (givenStmts, unwrapStmts <| ins.Translate ctxt) + + let testX86 ctxt (bytes: byte[], givenStmts) = + test ctxt WordSize.Bit32 givenStmts bytes + + let testX64 ctxt (bytes: byte[], givenStmts) = + test ctxt WordSize.Bit64 givenStmts bytes + + let eflagsOnAdd srcE dstE addVal operator = + let ( !. ) = operator + let tmpvarId = + match dstE with + | { E = TempVar (_, id) } -> id + | _ -> failwithf "Expr should be tmpvar" + [ t1 (tmpvarId + 1) := AST.xthi 1 <| srcE + t1 (tmpvarId + 2) := AST.xthi 1 <| dstE + !.CF := dstE .< srcE + !.OF := (t1 (tmpvarId + 1) == AST.num0 1) + .& (t1 (tmpvarId + 1) <+> t1 (tmpvarId + 2)) + !.AF := (((dstE <+> srcE) <+> num addVal 32) .& num 0x10u 32) + == num 0x10u 32 + !.SF := t1 (tmpvarId + 2) + !.ZF := dstE == AST.num0 32 + t32 (tmpvarId + 3) := dstE <+> (dstE >> num 0x4u 32) + t32 (tmpvarId + 4) := t32 (tmpvarId + 3) + <+> (t32 (tmpvarId + 3) >> num 0x2u 32) + !.PF := AST.not <| AST.xtlo 1 (t32 (tmpvarId + 4) + <+> (t32 (tmpvarId + 4) >> AST.num1 32)) ] + +#if !EMULATION +[] +type IntelX86UnitTest () = + let isa = ISA.Init Architecture.IntelX86 Endian.Little + + let ctxt = IntelTranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + [] + member __.``[X86] ADD instruction lift Test (1)`` () = + "0500000100" + ++ [ t32 1 := !.EAX + t32 2 := t32 1 .+ num 0x10000u 32 + !.EAX := t32 2 ] + ** eflagsOnAdd (t32 1) (t32 2) (0x10000u) (!.) + |> testX86 ctxt + + [] + member __.``[X86] ADD instruction lift Test (2)`` () = + "8340100a" + ++ [ t32 1 := !.EAX .+ num 0x10u 32 + t32 2 := AST.loadLE 32 <| t32 1 + t32 3 := t32 2 .+ num 0xau 32 + AST.loadLE 32 <| t32 1 := t32 3 ] + ** eflagsOnAdd (t32 2) (t32 3) (0xau) (!.) + |> testX86 ctxt + +[] +type IntelX64UnitTest () = + let isa = ISA.Init Architecture.IntelX64 Endian.Little + + let ctxt = IntelTranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + [] + member __.``[X64] ADD instruction lift Test (1)`` () = + "0500000100" + ++ [ t32 1 := AST.xtlo 32 !.RAX + t32 2 := t32 1 .+ num 0x10000u 32 + !.RAX := AST.zext 64 <| t32 2 ] + ** eflagsOnAdd (t32 1) (t32 2) (0x10000u) (!.) + |> testX64 ctxt + + [] + member __.``[X64] ADD instruction lift Test (2)`` () = + "8340100a" + ++ [ t64 1 := !.RAX .+ num 0x10ul 64 + t32 2 := AST.loadLE 32 <| t64 1 + t32 3 := t32 2 .+ num 0xau 32 + AST.loadLE 32 <| t64 1 := t32 3 ] + ** eflagsOnAdd (t32 2) (t32 3) (0xau) (!.) + |> testX64 ctxt +#endif diff --git a/src/FrontEnd/BinLifter.Tests/Intel.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/Intel.Parser.Tests.fs new file mode 100644 index 00000000..19a23e5d --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/Intel.Parser.Tests.fs @@ -0,0 +1,1903 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.Intel + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.Intel +open type Opcode + +/// Shortcut for creating operands. +type O = + static member Reg (r) = + OprReg r + + static member Mem (bReg, rt) = + OprMem (Some bReg, None, None, rt) + + static member Mem (bReg, disp: Disp, rt) = + OprMem (Some bReg, None, Some disp, rt) + + static member Mem (bReg, idx, scale, rt) = + OprMem (Some bReg, Some (idx, scale), None, rt) + + static member Mem (bReg, idx, scale, disp, rt) = + OprMem (Some bReg, Some (idx, scale), Some disp, rt) + + static member Mem (disp: Disp, rt) = + OprMem (None, None, Some disp, rt) + + static member Imm (v, rt) = + OprImm (v, rt) + + static member Addr (selector, addr, rt) = + OprDirAddr (Absolute (selector, addr, rt)) + +let private test prefs segment wordSize opcode oprs (bytes: byte[]) = + let parser = IntelParser (wordSize) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) :?> IntelInternalInstruction + Assert.AreEqual (ins.Prefixes, prefs) + Assert.AreEqual (Helper.getSegment ins.Prefixes, segment) + Assert.AreEqual (ins.Opcode, opcode) + Assert.AreEqual (ins.Operands, oprs) + Assert.AreEqual (ins.Length, uint32 bytes.Length) + +let private testX86NoPrefixNoSeg (bytes: byte[]) (opcode, operands) = + test Prefix.PrxNone None WordSize.Bit32 opcode operands bytes + +let private testX86Prefix pref (bytes: byte[]) (opcode, operands) = + test pref None WordSize.Bit32 opcode operands bytes + +let private testX86 pref seg (bytes: byte[]) (opcode, operands) = + test pref (Some seg) WordSize.Bit32 opcode operands bytes + +let private testX64NoPrefixNoSeg (bytes: byte[]) (opcode, operands) = + test Prefix.PrxNone None WordSize.Bit64 opcode operands bytes + +let private operandsFromArray oprList = + let oprArray = Array.ofList oprList + match oprArray.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprArray[0] + | 2 -> TwoOperands (oprArray[0], oprArray[1]) + | 3 -> ThreeOperands (oprArray[0], oprArray[1], oprArray[2]) + | 4 -> FourOperands (oprArray[0], oprArray[1], oprArray[2], oprArray[3]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +/// 5.1 GENERAL-PURPOSE INSTRUCTIONS +[] +type GeneralPurposeClass () = + [] + member __.``5.1.1 Data Transfer Instructions (1)`` () = + "c70518bb210002000000" + ++ MOV ** [ O.Mem (2210584L, 32); O.Imm (2L, 32) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.1 Data Transfer Instructions (2)`` () = + "6811223344" + ++ PUSH ** [ O.Imm (0x44332211L, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.1.1 Data Transfer Instructions (3)`` () = + "0fbe7fff" + ++ MOVSX ** [ O.Reg R.EDI; O.Mem (R.EDI, -1L, 8) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.1 Data Transfer Instructions (4)`` () = + "4863c8" + ++ MOVSXD ** [ O.Reg R.RCX; O.Reg R.EAX ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.1.2 Binary Arithmetic Instructions (1)`` () = + "4803c8" + ++ ADD ** [ O.Reg R.RCX; O.Reg R.RAX ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.1.2 Binary Arithmetic Instructions (2)`` () = + "6bfa0a" + ++ IMUL ** [ O.Reg R.EDI; O.Reg R.EDX; O.Imm (10L, 8) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.2 Binary Arithmetic Instructions (3)`` () = + "f720" + ++ MUL ** [ O.Mem (R.EAX, 32) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.2 Binary Arithmetic Instructions (4)`` () = + "f7f1" + ++ DIV ** [ O.Reg R.ECX ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.3 Decimal Arithmetic Instructions (1)`` () = + "37" + ++ AAA ** [] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.3 Decimal Arithmetic Instructions (2)`` () = + "3F" + ++ AAS ** [] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.4 Logical Instructions (1)`` () = + "212414" + ++ AND ** [ O.Mem (R.ESP, R.EDX, Scale.X1, 32); O.Reg R.ESP ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.4 Logical Instructions (2)`` () = + "212542424242" + ++ AND ** [ O.Mem (1111638594L, 32); O.Reg R.ESP ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.5 Shift and Rotate Instructions (1)`` () = + "c1000a" + ++ ROL ** [ O.Mem (R.EAX, 32); O.Imm (10L, 8) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.5 Shift and Rotate Instructions (2)`` () = + "c0000a" + ++ ROL ** [ O.Mem (R.EAX, 8); O.Imm (10L, 8) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.6 Bit and Byte Instructions (1)`` () = + "f6000a" + ++ TEST ** [ O.Mem (R.EAX, 8); O.Imm (10L, 8) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.7 Control Transfer Instructions (1)`` () = + "ffe4" + ++ JMPNear ** [ O.Reg R.ESP ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.7 Control Transfer Instructions (2)`` () = + "ea123456789000" + ++ JMPFar ** [ O.Addr (0x90s, 0x78563412UL, 32) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.7 Control Transfer Instructions (3)`` () = + "65ff1510000000" + ++ CALLNear ** [ O.Mem (16L, 32) ] + ||> testX86 (Prefix.PrxGS) R.GS + + [] + member __.``5.1.7 Control Transfer Instructions (4)`` () = + "9a987654321000" + ++ CALLFar ** [ O.Addr (0x10s, 0x32547698UL, 32) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.7 Control Transfer Instructions (5)`` () = + "cd01" + ++ INT ** [ O.Imm (1L, 8) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.9 I/O Instructions (1)`` () = + "ed" + ++ IN ** [ O.Reg R.EAX; O.Reg R.DX ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.9 I/O Instructions (2)`` () = + "ee" + ++ OUT ** [ O.Reg R.DX; O.Reg R.AL ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.9 I/O Instructions (3)`` () = + "66ef" + ++ OUT ** [ O.Reg R.DX; O.Reg R.AX ] + ||> testX86Prefix Prefix.PrxOPSIZE + + [] + member __.``5.1.9 I/O Instructions (4)`` () = + "ef" + ++ OUT ** [ O.Reg R.DX; O.Reg R.EAX ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.12 Segment Register Instructions (1)`` () = + "c40f" + ++ LES ** [ O.Reg R.ECX; O.Mem (R.EDI, 48) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.1.12 Segment Register Instructions (2)`` () = + "c511" + ++ LDS ** [ O.Reg R.EDX; O.Mem (R.ECX, 48) ] + ||> testX86NoPrefixNoSeg + +/// 5.2 X87 FPU INSTRUCTIONS +[] +type X87FPUClass () = + [] + member __.``5.2.1 x87 FPU Data Transfer Instructions (1)`` () = + "df84ca01020304" + ++ FILD ** [ O.Mem (R.EDX, R.ECX, Scale.X8, 67305985L, 16) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.2.1 x87 FPU Data Transfer Instructions (2)`` () = + "df20" + ++ FBLD ** [ O.Mem (R.EAX, 80) ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.2.3 x87 FPU Comparison Instructions (1)`` () = + "dff1" + ++ FCOMIP ** [ O.Reg R.ST0; O.Reg R.ST1 ] + ||> testX86NoPrefixNoSeg + + [] + member __.``5.2.3 x87 FPU Comparison Instructions (2)`` () = + "dfe9" + ++ FUCOMIP ** [ O.Reg R.ST0; O.Reg R.ST1 ] + ||> testX86NoPrefixNoSeg + +/// 5.4 MMX INSTRUCTIONS +[] +type MMXClass () = + [] + member __.``5.4.1 MMX Conversion Instructions (1)`` () = + "c4e1f9d69001020304;" + ++ VMOVQ ** [ O.Mem (R.RAX, 67305985L, 64); O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.4.1 MMX Conversion Instructions (2)`` () = + "c4e1f9d6d0" + ++ VMOVQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.4.4 MMX Comparison Instructions (1)`` () = + "0f7501" + ++ PCMPEQW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.4.4 MMX Comparison Instructions (2)`` () = + "0f75c1" + ++ PCMPEQW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.4.4 MMX Comparison Instructions (3)`` () = + "660f7501" + ++ PCMPEQW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.4.4 MMX Comparison Instructions (4)`` () = + "660f75c1" + ++ PCMPEQW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + +/// 5.5 SSE INSTRUCTIONS +[] +type SSEClass () = + [] + member __.``5.5.1.6 SSE Conversion Instructions (1)`` () = + "c4e1fa2d9001020304;" + ++ VCVTSS2SI ** [ O.Reg R.RDX; O.Mem (R.RAX, 67305985L, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.5.1.6 SSE Conversion Instructions (2)`` () = + "c4e17b2d9001020304;" + ++ VCVTSD2SI ** [ O.Reg R.EDX; O.Mem (R.RAX, 67305985L, 64) ] + ||> testX64NoPrefixNoSeg + +/// 5.6 SSE2 INSTRUCTIONS +[] +type SSE2Class () = + [] + member __.``Intel SSE 128-Bits SIMD Interger Instructions (1)`` () = + "62f1fd486f4c2401" + ++ VMOVDQA64 ** [ O.Reg R.ZMM1; O.Mem (R.RSP, 64L, 512) ] + ||> testX64NoPrefixNoSeg + +/// 5.8 SUPPLEMENTAL STREAMING SIMD EXTENSIONS 3 (SSSE3) INSTRUCTIONS +[] +type SSSE3Class () = + [] + member __.``5.8.1 Horizontal Addition/Subtraction (1)`` () = + "0f380101" + ++ PHADDW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (2)`` () = + "0f3801c1" + ++ PHADDW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (3)`` () = + "660f380101" + ++ PHADDW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (4)`` () = + "660f3801c1" + ++ PHADDW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (5)`` () = + "0f380301" + ++ PHADDSW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (6)`` () = + "0f3803c1" + ++ PHADDSW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (7)`` () = + "660f380301" + ++ PHADDSW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (8)`` () = + "660f3803c1" + ++ PHADDSW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (9)`` () = + "0f380201" + ++ PHADDD ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (10)`` () = + "0f3802c1" + ++ PHADDD ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (11)`` () = + "660f380201" + ++ PHADDD ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (12)`` () = + "660f3802c1" + ++ PHADDD ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (13)`` () = + "0f380501" + ++ PHSUBW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (14)`` () = + "0f3805c1" + ++ PHSUBW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (15)`` () = + "660f380501" + ++ PHSUBW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (16)`` () = + "660f3805c1" + ++ PHSUBW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (17)`` () = + "0f380701" + ++ PHSUBSW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (18)`` () = + "0f3807c1" + ++ PHSUBSW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (19)`` () = + "660f380701" + ++ PHSUBSW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (20)`` () = + "660f3807c1" + ++ PHSUBSW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (21)`` () = + "0f380601" + ++ PHSUBD ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (22)`` () = + "0f3806c1" + ++ PHSUBD ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (23)`` () = + "660f380601" + ++ PHSUBD ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.1 Horizontal Addition/Subtraction (24)`` () = + "660f3806c1" + ++ PHSUBD ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (1)`` () = + "0f381c01" + ++ PABSB ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (2)`` () = + "0f381cc1" + ++ PABSB ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (3)`` () = + "660f381c01" + ++ PABSB ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (4)`` () = + "660f381cc1" + ++ PABSB ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (5)`` () = + "0f381e01" + ++ PABSD ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (6)`` () = + "0f381ec1" + ++ PABSD ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (7)`` () = + "660f381e01" + ++ PABSD ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (8)`` () = + "660f381ec1" + ++ PABSD ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (9)`` () = + "0f381d01" + ++ PABSW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (10)`` () = + "0f381dc1" + ++ PABSW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (11)`` () = + "660f381d01" + ++ PABSW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.2. Packed Absolute Values (12)`` () = + "660f381dc1" + ++ PABSW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.4 Packed Multiply High with Round and Scale (1)`` () = + "0f380b01" + ++ PMULHRSW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.4 Packed Multiply High with Round and Scale (2)`` () = + "0f380bc1" + ++ PMULHRSW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.4 Packed Multiply High with Round and Scale (3)`` () = + "660f380b01" + ++ PMULHRSW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.4 Packed Multiply High with Round and Scale (4)`` () = + "660f380bc1" + ++ PMULHRSW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (1)`` () = + "0f380801" + ++ PSIGNB ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (2)`` () = + "0f3808c1" + ++ PSIGNB ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (3)`` () = + "660f380801" + ++ PSIGNB ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (4)`` () = + "660f3808c1" + ++ PSIGNB ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (5)`` () = + "0f380901" + ++ PSIGNW ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (6)`` () = + "0f3809c1" + ++ PSIGNW ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (7)`` () = + "660f380901" + ++ PSIGNW ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (8)`` () = + "660f3809c1" + ++ PSIGNW ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (9)`` () = + "0f380a01" + ++ PSIGND ** [ O.Reg R.MM0; O.Mem (R.RCX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (10)`` () = + "0f380ac1" + ++ PSIGND ** [ O.Reg R.MM0; O.Reg R.MM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (11)`` () = + "660f380a01" + ++ PSIGND ** [ O.Reg R.XMM0; O.Mem (R.RCX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.6 Packed Sign (12)`` () = + "660f380ac1" + ++ PSIGND ** [ O.Reg R.XMM0; O.Reg R.XMM1 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.8.7 Packed Align Right (1)`` () = + "660f3a0fd101" + ++ PALIGNR ** [ O.Reg R.XMM2; O.Reg R.XMM1; O.Imm (1L, 8) ] + ||> testX64NoPrefixNoSeg + +/// 5.10 SSE4.1 INSTRUCTIONS +[] +type SSSE41Class () = + [] + member __.``5.10.1 Dword Multiply Instructions (1)`` () = + "660f384002" + ++ PMULLD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.1 Dword Multiply Instructions (2)`` () = + "660f3840c2" + ++ PMULLD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.1 Dword Multiply Instructions (3)`` () = + "660f382802" + ++ PMULDQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.1 Dword Multiply Instructions (4)`` () = + "660f3828c2" + ++ PMULDQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (1)`` () = + "660f383a02" + ++ PMINUW ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (2)`` () = + "660f383ac2" + ++ PMINUW ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (3)`` () = + "660f383902" + ++ PMINSD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (4)`` () = + "660f3839c2" + ++ PMINSD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (5)`` () = + "660f383e02" + ++ PMAXUW ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (6)`` () = + "660f383ec2" + ++ PMAXUW ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (7)`` () = + "660f383f02" + ++ PMAXUD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (8)`` () = + "660f383fc2" + ++ PMAXUD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (9)`` () = + "660f383c02" + ++ PMAXSB ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (10)`` () = + "660f383cc2" + ++ PMAXSB ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (11)`` () = + "660f383d02" + ++ PMAXSD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.5 Packed Integer MIN/MAX Instructions (12)`` () = + "660f383dc2" + ++ PMAXSD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (1)`` () = + "660f382102" + ++ PMOVSXBD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (2)`` () = + "660f3821c2" + ++ PMOVSXBD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (3)`` () = + "660f382202" + ++ PMOVSXBQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 16) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (4)`` () = + "660f3822c2" + ++ PMOVSXBQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (5)`` () = + "660f382002" + ++ PMOVSXBW ** [ O.Reg R.XMM0; O.Mem (R.RDX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (6)`` () = + "660f3820c2" + ++ PMOVSXBW ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (7)`` () = + "660f382502" + ++ PMOVSXDQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (8)`` () = + "660f3825c2" + ++ PMOVSXDQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (9)`` () = + "660f382302" + ++ PMOVSXWD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (10)`` () = + "660f3823c2" + ++ PMOVSXWD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (11)`` () = + "660f382402" + ++ PMOVSXWQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (12)`` () = + "660f3824c2" + ++ PMOVSXWQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (13)`` () = + "660f383102" + ++ PMOVZXBD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (14)`` () = + "660f3831c2" + ++ PMOVZXBD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (15)`` () = + "660f383202" + ++ PMOVZXBQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 16) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (16)`` () = + "660f3832c2" + ++ PMOVZXBQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (17)`` () = + "660f383002" + ++ PMOVZXBW ** [ O.Reg R.XMM0; O.Mem (R.RDX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (18)`` () = + "660f3830c2" + ++ PMOVZXBW ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (19)`` () = + "660f383502" + ++ PMOVZXDQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (20)`` () = + "660f3835c2" + ++ PMOVZXDQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (21)`` () = + "660f383302" + ++ PMOVZXWD ** [ O.Reg R.XMM0; O.Mem (R.RDX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (22)`` () = + "660f3833c2" + ++ PMOVZXWD ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (23)`` () = + "660f383402" + ++ PMOVZXWQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.8 Packed Integer Format Conversions (24)`` () = + "660f3834c2" + ++ PMOVZXWQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.10 Horizontal Search (1)`` () = + "660f384102" + ++ PHMINPOSUW ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.10 Horizontal Search (2)`` () = + "660f3841c2" + ++ PHMINPOSUW ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.13 Dword Packing With Unsigned Saturation (1)`` () = + "660f382b02" + ++ PACKUSDW ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.10.13 Dword Packing With Unsigned Saturation (2)`` () = + "660f382bc2" + ++ PACKUSDW ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + +/// 5.11 SSE4.2 INSTRUCTION SET +[] +type SSSE42Class () = + [] + member __.``5.11.2 Packed Comparison SIMD integer Instruction (1)`` () = + "660f383702" + ++ PCMPGTQ ** [ O.Reg R.XMM0; O.Mem (R.RDX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``5.11.2 Packed Comparison SIMD integer Instruction (2)`` () = + "660f3837c2" + ++ PCMPGTQ ** [ O.Reg R.XMM0; O.Reg R.XMM2 ] + ||> testX64NoPrefixNoSeg + +/// 5.22 INTEL MEMORY PROTECTION EXTENSIONS +[] +type IntelMemoryProtectionClass () = + [] + member __.``Intel Memory Protection Extension Instruction (1)`` () = + "660f1b842400020000" + ++ BNDMOV ** [ O.Mem (R.RSP, 512L, 128); O.Reg R.BND0 ] + ||> testX64NoPrefixNoSeg + +/// INTEL ADVANCED VECTOR EXTENSIONS +[] +type AVXClass () = + [] + member __.``AVX (1)`` () = + "c4e1297503" + ++ VPCMPEQW ** [ O.Reg R.XMM0; O.Reg R.XMM10; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (2)`` () = + "c4e12975c3" + ++ VPCMPEQW ** [ O.Reg R.XMM0; O.Reg R.XMM10; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (3)`` () = + "c4e12d7503" + ++ VPCMPEQW ** [ O.Reg R.YMM0; O.Reg R.YMM10; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (4)`` () = + "c4e12d75c3" + ++ VPCMPEQW ** [ O.Reg R.YMM0; O.Reg R.YMM10; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (5)`` () = + "c4e2611c03" + ++ VPABSB ** [ O.Reg R.XMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (6)`` () = + "c4e2611cc3" + ++ VPABSB ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (7)`` () = + "c4e2651c03" + ++ VPABSB ** [ O.Reg R.YMM0; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (8)`` () = + "c4e2651cc3" + ++ VPABSB ** [ O.Reg R.YMM0; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (9)`` () = + "c4e2611e03" + ++ VPABSD ** [ O.Reg R.XMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (10)`` () = + "c4e2611ec3" + ++ VPABSD ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (11)`` () = + "c4e2651e03" + ++ VPABSD ** [ O.Reg R.YMM0; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (12)`` () = + "c4e2651ec3" + ++ VPABSD ** [ O.Reg R.YMM0; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (13)`` () = + "c4e2611d03" + ++ VPABSW ** [ O.Reg R.XMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (14)`` () = + "c4e2611dc3" + ++ VPABSW ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (15)`` () = + "c4e2651d03" + ++ VPABSW ** [ O.Reg R.YMM0; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (16)`` () = + "c4e2651dc3" + ++ VPABSW ** [ O.Reg R.YMM0; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (17)`` () = + "c4e2610203" + ++ VPHADDD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (18)`` () = + "c4e26102c3" + ++ VPHADDD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (19)`` () = + "c4e2650203" + ++ VPHADDD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (20)`` () = + "c4e26502c3" + ++ VPHADDD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (21)`` () = + "c4e2610303" + ++ VPHADDSW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (22)`` () = + "c4e26103c3" + ++ VPHADDSW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (23)`` () = + "c4e2650303" + ++ VPHADDSW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (24)`` () = + "c4e26503c3" + ++ VPHADDSW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (25)`` () = + "c4e2610103" + ++ VPHADDW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (26)`` () = + "c4e26101c3" + ++ VPHADDW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (27)`` () = + "c4e2650103" + ++ VPHADDW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (28)`` () = + "c4e26501c3" + ++ VPHADDW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (29)`` () = + "c4e2610603" + ++ VPHSUBD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (30)`` () = + "c4e26106c3" + ++ VPHSUBD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (31)`` () = + "c4e2650603" + ++ VPHSUBD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (32)`` () = + "c4e26506c3" + ++ VPHSUBD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (33)`` () = + "c4e2610703" + ++ VPHSUBSW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (34)`` () = + "c4e26107c3" + ++ VPHSUBSW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (35)`` () = + "c4e2650703" + ++ VPHSUBSW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (36)`` () = + "c4e26507c3" + ++ VPHSUBSW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (37)`` () = + "c4e2610503" + ++ VPHSUBW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (38)`` () = + "c4e26105c3" + ++ VPHSUBW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (39)`` () = + "c4e2650503" + ++ VPHSUBW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (40)`` () = + "c4e26505c3" + ++ VPHSUBW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (41)`` () = + "c4e2610b03" + ++ VPMULHRSW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (42)`` () = + "c4e2610bc3" + ++ VPMULHRSW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (43)`` () = + "c4e2650b03" + ++ VPMULHRSW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (44)`` () = + "c4e2650bc3" + ++ VPMULHRSW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (45)`` () = + "c4e2610803" + ++ VPSIGNB ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (46)`` () = + "c4e26108c3" + ++ VPSIGNB ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (47)`` () = + "c4e2650803" + ++ VPSIGNB ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (48)`` () = + "c4e26508c3" + ++ VPSIGNB ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (49)`` () = + "c4e2610a03" + ++ VPSIGND ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (50)`` () = + "c4e2610ac3" + ++ VPSIGND ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (51)`` () = + "c4e2650a03" + ++ VPSIGND ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (52)`` () = + "c4e2650ac3" + ++ VPSIGND ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (53)`` () = + "c4e2610903" + ++ VPSIGNW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (54)`` () = + "c4e26109c3" + ++ VPSIGNW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (55)`` () = + "c4e2650903" + ++ VPSIGNW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (56)`` () = + "c4e26509c3" + ++ VPSIGNW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (57)`` () = + "c4e2612b03" + ++ VPACKUSDW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (58)`` () = + "c4e2612bc3" + ++ VPACKUSDW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (59)`` () = + "c4e2652b03" + ++ VPACKUSDW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (60)`` () = + "c4e2652bc3" + ++ VPACKUSDW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (61)`` () = + "c4e2613703" + ++ VPCMPGTQ ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (62)`` () = + "c4e26137c3" + ++ VPCMPGTQ ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (63)`` () = + "c4e2653703" + ++ VPCMPGTQ ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (64)`` () = + "c4e26537c3" + ++ VPCMPGTQ ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (65)`` () = + "c4e2614103" + ++ VPHMINPOSUW ** [ O.Reg R.XMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (66)`` () = + "c4e26141c3" + ++ VPHMINPOSUW ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (67)`` () = + "c4e2613c03" + ++ VPMAXSB ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (68)`` () = + "c4e2613cc3" + ++ VPMAXSB ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (69)`` () = + "c4e2653c03" + ++ VPMAXSB ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (70)`` () = + "c4e2653cc3" + ++ VPMAXSB ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (71)`` () = + "c4e2613d03" + ++ VPMAXSD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (72)`` () = + "c4e2613dc3" + ++ VPMAXSD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (73)`` () = + "c4e2653d03" + ++ VPMAXSD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (74)`` () = + "c4e2653dc3" + ++ VPMAXSD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (75)`` () = + "c4e2613f03" + ++ VPMAXUD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (76)`` () = + "c4e2613fc3" + ++ VPMAXUD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (77)`` () = + "c4e2653f03" + ++ VPMAXUD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (78)`` () = + "c4e2653fc3" + ++ VPMAXUD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (79)`` () = + "c4e2613e03" + ++ VPMAXUW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (80)`` () = + "c4e2613ec3" + ++ VPMAXUW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (81)`` () = + "c4e2653e03" + ++ VPMAXUW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (82)`` () = + "c4e2653ec3" + ++ VPMAXUW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (83)`` () = + "c4e2613803" + ++ VPMINSB ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (84)`` () = + "c4e26138c3" + ++ VPMINSB ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (85)`` () = + "c4e2653803" + ++ VPMINSB ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (86)`` () = + "c4e26538c3" + ++ VPMINSB ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (87)`` () = + "c4e2613903" + ++ VPMINSD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (88)`` () = + "c4e26139c3" + ++ VPMINSD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (89)`` () = + "c4e2653903" + ++ VPMINSD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (90)`` () = + "c4e26539c3" + ++ VPMINSD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (91)`` () = + "c4e2613a03" + ++ VPMINUW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (92)`` () = + "c4e2613ac3" + ++ VPMINUW ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (93)`` () = + "c4e2653a03" + ++ VPMINUW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (94)`` () = + "c4e2653ac3" + ++ VPMINUW ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (95)`` () = + "c4e2612103" + ++ VPMOVSXBD ** [ O.Reg R.XMM0; O.Mem (R.RBX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (96)`` () = + "c4e26121c3" + ++ VPMOVSXBD ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (97)`` () = + "c4e2652103" + ++ VPMOVSXBD ** [ O.Reg R.YMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (98)`` () = + "c4e26521c3" + ++ VPMOVSXBD ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (99)`` () = + "c4e2612203" + ++ VPMOVSXBQ ** [ O.Reg R.XMM0; O.Mem (R.RBX, 16) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (100)`` () = + "c4e26122c3" + ++ VPMOVSXBQ ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (101)`` () = + "c4e2652203" + ++ VPMOVSXBQ ** [ O.Reg R.YMM0; O.Mem (R.RBX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (102)`` () = + "c4e26522c3" + ++ VPMOVSXBQ ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (103)`` () = + "c4e2612003" + ++ VPMOVSXBW ** [ O.Reg R.XMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (104)`` () = + "c4e26120c3" + ++ VPMOVSXBW ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (105)`` () = + "c4e2652003" + ++ VPMOVSXBW ** [ O.Reg R.YMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (106)`` () = + "c4e26520c3" + ++ VPMOVSXBW ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (107)`` () = + "c4e2612503" + ++ VPMOVSXDQ ** [ O.Reg R.XMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (108)`` () = + "c4e26125c3" + ++ VPMOVSXDQ ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (109)`` () = + "c4e2652503" + ++ VPMOVSXDQ ** [ O.Reg R.YMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (110)`` () = + "c4e26525c3" + ++ VPMOVSXDQ ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (111)`` () = + "c4e2612303" + ++ VPMOVSXWD ** [ O.Reg R.XMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (112)`` () = + "c4e26123c3" + ++ VPMOVSXWD ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (113)`` () = + "c4e2652303" + ++ VPMOVSXWD ** [ O.Reg R.YMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (114)`` () = + "c4e26523c3" + ++ VPMOVSXWD ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (115)`` () = + "c4e2612403" + ++ VPMOVSXWQ ** [ O.Reg R.XMM0; O.Mem (R.RBX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (116)`` () = + "c4e26124c3" + ++ VPMOVSXWQ ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (117)`` () = + "c4e2652403" + ++ VPMOVSXWQ ** [ O.Reg R.YMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (118)`` () = + "c4e26524c3" + ++ VPMOVSXWQ ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (119)`` () = + "c4e2613103" + ++ VPMOVZXBD ** [ O.Reg R.XMM0; O.Mem (R.RBX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (120)`` () = + "c4e26131c3" + ++ VPMOVZXBD ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (121)`` () = + "c4e2653103" + ++ VPMOVZXBD ** [ O.Reg R.YMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (122)`` () = + "c4e26531c3" + ++ VPMOVZXBD ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (123)`` () = + "c4e2613203" + ++ VPMOVZXBQ ** [ O.Reg R.XMM0; O.Mem (R.RBX, 16) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (124)`` () = + "c4e26132c3" + ++ VPMOVZXBQ ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (125)`` () = + "c4e2653203" + ++ VPMOVZXBQ ** [ O.Reg R.YMM0; O.Mem (R.RBX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (126)`` () = + "c4e26532c3" + ++ VPMOVZXBQ ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (127)`` () = + "c4e2613003" + ++ VPMOVZXBW ** [ O.Reg R.XMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (128)`` () = + "c4e26130c3" + ++ VPMOVZXBW ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (129)`` () = + "c4e2653003" + ++ VPMOVZXBW ** [ O.Reg R.YMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (130)`` () = + "c4e26530c3" + ++ VPMOVZXBW ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (131)`` () = + "c4e2613503" + ++ VPMOVZXDQ ** [ O.Reg R.XMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (132)`` () = + "c4e26135c3" + ++ VPMOVZXDQ ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (133)`` () = + "c4e2653503" + ++ VPMOVZXDQ ** [ O.Reg R.YMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (134)`` () = + "c4e26535c3" + ++ VPMOVZXDQ ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (135)`` () = + "c4e2613303" + ++ VPMOVZXWD ** [ O.Reg R.XMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (136)`` () = + "c4e26133c3" + ++ VPMOVZXWD ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (137)`` () = + "c4e2653303" + ++ VPMOVZXWD ** [ O.Reg R.YMM0; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (138)`` () = + "c4e26533c3" + ++ VPMOVZXWD ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (139)`` () = + "c4e2613403" + ++ VPMOVZXWQ ** [ O.Reg R.XMM0; O.Mem (R.RBX, 32) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (140)`` () = + "c4e26134c3" + ++ VPMOVZXWQ ** [ O.Reg R.XMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (141)`` () = + "c4e2653403" + ++ VPMOVZXWQ ** [ O.Reg R.YMM0; O.Mem (R.RBX, 64) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (142)`` () = + "c4e26534c3" + ++ VPMOVZXWQ ** [ O.Reg R.YMM0; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (143)`` () = + "c4e2612803" + ++ VPMULDQ ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (144)`` () = + "c4e26128c3" + ++ VPMULDQ ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (145)`` () = + "c4e2652803" + ++ VPMULDQ ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (146)`` () = + "c4e26528c3" + ++ VPMULDQ ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (147)`` () = + "c4e2614003" + ++ VPMULLD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Mem (R.RBX, 128) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (148)`` () = + "c4e26140c3" + ++ VPMULLD ** [ O.Reg R.XMM0; O.Reg R.XMM3; O.Reg R.XMM3 ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (149)`` () = + "c4e2654003" + ++ VPMULLD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Mem (R.RBX, 256) ] + ||> testX64NoPrefixNoSeg + + [] + member __.``AVX (150)`` () = + "c4e26540c3" + ++ VPMULLD ** [ O.Reg R.YMM0; O.Reg R.YMM3; O.Reg R.YMM3 ] + ||> testX64NoPrefixNoSeg + +#if !EMULATION +/// Exception Test +[] +type ExceptionTestClass () = + [] + [)>] + member __.``Size cond ParsingFailure Test (1)`` () = + "37" + ++ AAA ** [] + ||> testX64NoPrefixNoSeg + + [] + [)>] + member __.``Size cond ParsingFailure Test (2)`` () = + "3F" + ++ AAS ** [] + ||> testX64NoPrefixNoSeg + + [] + [)>] + member __.``Size cond ParsingFailure Test (3)`` () = + "ea123456789000" + ++ JMPFar ** [ O.Addr (0x90s, 0x78563412UL, 32) ] + ||> testX64NoPrefixNoSeg + + [] + [)>] + member __.``Size cond ParsingFailure Test (4)`` () = + "9a987654321000" + ++ CALLFar ** [ O.Addr (0x10s, 0x32547698UL, 32) ] + ||> testX64NoPrefixNoSeg + + [] + [)>] + member __.``Size cond ParsingFailure Test (5)`` () = + "c40f" + ++ LES ** [ O.Reg R.ECX; O.Mem (R.EDI, 48) ] + ||> testX64NoPrefixNoSeg + + [] + [)>] + member __.``Size cond ParsingFailure Test (6)`` () = + "c511" + ++ LDS ** [ O.Reg R.EDX; O.Mem (R.ECX, 48) ] + ||> testX64NoPrefixNoSeg +#endif diff --git a/src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs index 17286f99..1fc0e439 100644 --- a/src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/Lifter.Tests.fs @@ -31,24 +31,91 @@ module Lifter = open B2R2.BinIR open B2R2.BinIR.LowUIR + let assertEqualOfStrAndStmt actual stmt = + (actual, Pp.stmtToString stmt) + |> Assert.AreEqual + + let assertEqualOfStrAndExpr actual expr = + (actual, Pp.expToString expr) + |> Assert.AreEqual + + let tmpvarNum0 = AST.tmpvar 32 0 + + let tmpvarNum1 = AST.tmpvar 32 1 + [] type TestClass () = + [] + member __.``PP bitVector from uint32 test`` () = + let e = BitVector.OfUInt32 42ul 32 |> AST.num + assertEqualOfStrAndExpr "0x2a:I32" e + + [] + member __.``PP construct tempVar test (1)`` () = + assertEqualOfStrAndExpr "T_0:I32" tmpvarNum0 + + [] + member __.``PP construct tempVar test (2)`` () = + assertEqualOfStrAndExpr "T_1:I32" tmpvarNum1 + + [] + member __.``PP binary operator test (1)`` () = + let e = AST.binop BinOpType.ADD tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndExpr "(T_0:I32 + T_1:I32)" e + + [] + member __.``PP binary operator test (2)`` () = + let e = AST.binop BinOpType.AND tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndExpr "(T_0:I32 & T_1:I32)" e + + [] + member __.``PP binary operator test (3)`` () = + let e = AST.binop BinOpType.DIV tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndExpr "(T_0:I32 / T_1:I32)" e + + [] + member __.``PP unary operator test (1)`` () = + assertEqualOfStrAndExpr "(- T_1:I32)" (AST.unop UnOpType.NEG tmpvarNum1) + + [] + member __.``PP unary operator test (2)`` () = + let binop = AST.binop BinOpType.ADD tmpvarNum0 tmpvarNum1 + let e = AST.unop UnOpType.NOT binop + assertEqualOfStrAndExpr "(~ (T_0:I32 + T_1:I32))" e + + [] + member __.``PP construct load test (1)`` () = + let e = AST.load Endian.Little 32 tmpvarNum0 + assertEqualOfStrAndExpr "[T_0:I32]:I32" e + + [] + member __.``PP construct load test (2)`` () = + let e = AST.load Endian.Big 64 tmpvarNum0 + assertEqualOfStrAndExpr "[T_0:I32]:I64" e + + [] + member __.``PP construct ite test`` () = + let e = AST.ite (AST.tmpvar 1 2) tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndExpr "((T_2:I1) ? (T_0:I32) : (T_1:I32))" e + + [] + member __.``PP relative operator test`` () = + let e = AST.relop RelOpType.EQ tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndExpr "(T_0:I32 = T_1:I32)" e + + [] + member __.``PP conditional jump test`` () = + let e = AST.cjmp tmpvarNum0 tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndStmt "if T_0:I32 then jmp T_0:I32 else jmp T_1:I32" e + + [] + member __.``PP interConditional jump test`` () = + let e = AST.intercjmp tmpvarNum0 tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndStmt "if T_0:I32 then ijmp T_0:I32 else ijmp T_1:I32" e [] - member __.``PP Test`` () = - let e = BitVector.ofUInt32 42ul 32 |> AST.num - Assert.AreEqual (Pp.expToString e, "0x2a:I32") - let e0 = AST.tmpvar 32 0 - Assert.AreEqual (Pp.expToString e0, "T_0:I32") - let e1 = AST.tmpvar 32 1 - Assert.AreEqual (Pp.expToString e1, "T_1:I32") - let e = AST.unop UnOpType.NEG e1 - Assert.AreEqual (Pp.expToString e, "(- T_1:I32)") - let e = AST.unop UnOpType.NOT (AST.binop BinOpType.ADD e0 e1) - Assert.AreEqual (Pp.expToString e, "(~ (T_0:I32 + T_1:I32))") - let e = AST.load Endian.Little 32 e0 - Assert.AreEqual (Pp.expToString e, "[T_0:I32]:I32") - let e = AST.ite (AST.tmpvar 1 2) e0 e1 - Assert.AreEqual (Pp.expToString e, "((T_2:I1) ? (T_0:I32) : (T_1:I32))") + member __.``PP assignment statement test`` () = + let e = AST.assign tmpvarNum0 tmpvarNum1 + assertEqualOfStrAndStmt "T_0:I32 := T_1:I32" e // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter.Tests/MIPS.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/MIPS.Lifter.Tests.fs new file mode 100644 index 00000000..bae77838 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/MIPS.Lifter.Tests.fs @@ -0,0 +1,104 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.MIPS64Lifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.MIPS +open type Register + +[] +module TestHelper = + let checkOverflowOnAdd e1 e2 r = + let e1High = AST.extract e1 1 31 + let e2High = AST.extract e2 1 31 + let rHigh = AST.extract r 1 31 + (e1High == e2High) .& (e1High <+> rHigh) + + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) + + let inline ( ++ ) (byteStr: string) (givenStmts: Stmt[]) = + ByteArray.ofHexString byteStr, givenStmts + + let test isa ctxt (bytes: byte[], givenStmts) = + let parser = MIPSParser (isa) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) + CollectionAssert.AreEqual (givenStmts, unwrapStmts <| ins.Translate ctxt) + +[] +type MIPS64UnitTest () = + let isa = ISA.Init Architecture.MIPS64 Endian.Big + + let ctxt = MIPSTranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + [] + member __.``[MIPS64] ADD lift test`` () = + let ir = IRBuilder (241) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let signExtLo64 = AST.sext 64 <| AST.xtlo 32 (!.R1 .+ !.R2) + let cond = checkOverflowOnAdd !.R1 !.R2 signExtLo64 + "00220820" + ++ [| AST.cjmp cond (AST.name lblL0) (AST.name lblL1) + AST.lmark lblL0 + AST.sideEffect (Exception "int overflow") + AST.jmp (AST.name lblEnd) + AST.lmark lblL1 + !.R1 := AST.sext 64 <| AST.xtlo 32 (!.R1 .+ !.R2) + AST.lmark lblEnd |] + |> test isa ctxt + +[] +type MIPS32UnitTest () = + let isa = ISA.Init Architecture.MIPS32 Endian.Big + + let ctxt = MIPSTranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + [] + member __.``[MIPS32] ADD lift test`` () = + let ir = IRBuilder (241) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = checkOverflowOnAdd !.R1 !.R2 (!.R1 .+ !.R2) + "00220820" + ++ [| AST.cjmp cond (AST.name lblL0) (AST.name lblL1) + AST.lmark lblL0 + AST.sideEffect (Exception "int overflow") + AST.jmp (AST.name lblEnd) + AST.lmark lblL1 + !.R1 := !.R1 .+ !.R2 + AST.lmark lblEnd |] + |> test isa ctxt diff --git a/src/FrontEnd/BinLifter.Tests/MIPS32.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/MIPS32.Parser.Tests.fs new file mode 100644 index 00000000..293f5ad6 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/MIPS32.Parser.Tests.fs @@ -0,0 +1,512 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.MIPS32 + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter.MIPS +open type Opcode +open type Register + +type O = + static member Reg (r) = + OpReg r + + static member Imm (v) = + OpImm v + + static member Mem (r, o: int64, rt) = + OpMem (r, Imm o, rt) + + static member Mem (r, o: Register, rt) = + OpMem (r, Reg o, rt) + + static member Addr (t) = + OpAddr t + + static member Shift (s) = + OpShiftAmount s + +let private test arch endian opcode cond fmt oprs (bytes: byte[]) = + let reader = BinReader.Init endian + let span = System.ReadOnlySpan bytes + let ins = ParsingMain.parse span reader arch WordSize.Bit32 0UL + let opcode' = ins.Info.Opcode + let cond' = ins.Info.Condition + let fmt' = ins.Info.Fmt + let oprs' = ins.Info.Operands + Assert.AreEqual (opcode', opcode) + Assert.AreEqual (cond', cond) + Assert.AreEqual (fmt', fmt) + Assert.AreEqual (oprs', oprs) + +let private test32R2 cond fmt (bs: byte[]) (opcode, operands) = + test Architecture.MIPS32 Endian.Big opcode (Some cond) (Some fmt) operands bs + +let private test32R2NoCond fmt (bytes: byte[]) (opcode, operands) = + test Architecture.MIPS32 Endian.Big opcode None (Some fmt) operands bytes + +let private test32R2NoCondNofmt (bytes: byte[]) (opcode, operands) = + test Architecture.MIPS32 Endian.Big opcode None None operands bytes + +let private operandsFromArray oprList = + let oprArray = Array.ofList oprList + match oprArray.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprArray[0] + | 2 -> TwoOperands (oprArray[0], oprArray[1]) + | 3 -> ThreeOperands (oprArray[0], oprArray[1], oprArray[2]) + | 4 -> FourOperands (oprArray[0], oprArray[1], oprArray[2], oprArray[3]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +/// Arithmetic Operations +[] +type ArithmeticClass () = + [] + member __.``[MIPS32] Arithmetic Operations Parse Test (1)`` () = + "279c85bc" + ++ ADDIU ** [ O.Reg R28; O.Reg R28; O.Imm 0xffffffffffff85bcUL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Arithmetic Operations Parse Test (2)`` () = + "70e21020" + ++ CLZ ** [ O.Reg R2; O.Reg R7 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Arithmetic Operations Parse Test (3)`` () = + "3c1c0004" + ++ LUI ** [ O.Reg R28; O.Imm 4UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Arithmetic Operations Parse Test (4)`` () = + "7c0a5420" + ++ SEB ** [ O.Reg R10; O.Reg R10 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Arithmetic Operations Parse Test (5)`` () = + "02131023" + ++ SUBU ** [ O.Reg R2; O.Reg R16; O.Reg R19 ] + ||> test32R2NoCondNofmt + +/// Shift And Rotate Operations +[] +type ShiftAndRotateClass () = + [] + member __.``[MIPS32] Shift And Rotate Operations Parse Test (1)`` () = + "002410c2" + ++ ROTR ** [ O.Reg R2; O.Reg R4; O.Shift 3UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Shift And Rotate Operations Parse Test (2)`` () = + "00021080" + ++ SLL ** [ O.Reg R2; O.Reg R2; O.Shift 2UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Shift And Rotate Operations Parse Test (3)`` () = + "00052883" + ++ SRA ** [ O.Reg R5; O.Reg R5; O.Shift 2UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Shift And Rotate Operations Parse Test (4)`` () = + "000517c2" + ++ SRL ** [ O.Reg R2; O.Reg R5; O.Shift 31UL ] + ||> test32R2NoCondNofmt + +/// Logical And Bit-Field Operations +[] +type LogicalAndBitFieldClass () = + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (1)`` () = + "02621024" + ++ AND ** [ O.Reg R2; O.Reg R19; O.Reg R2 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (2)`` () = + "30420001" + ++ ANDI ** [ O.Reg R2; O.Reg R2; O.Imm 1UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (3)`` () = + "7c420180" + ++ EXT ** [ O.Reg R2; O.Reg R2; O.Imm 6UL; O.Imm 1UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (4)`` () = + "7cc33184" + ++ INS ** [ O.Reg R3; O.Reg R6; O.Imm 6UL; O.Imm 1UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (5)`` () = + "00063027" + ++ NOR ** [ O.Reg R6; O.Reg R0; O.Reg R6 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (6)`` () = + "00609825" + ++ OR ** [ O.Reg R19; O.Reg R3; O.Reg R0 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (7)`` () = + "3673ffff" + ++ ORI ** [ O.Reg R19; O.Reg R19; O.Imm 65535UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (8)`` () = + "00461026" + ++ XOR ** [ O.Reg R2; O.Reg R2; O.Reg R6 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Logical And Bit-Field operations Parse Test (9)`` () = + "3a620006" + ++ XORI ** [ O.Reg R2; O.Reg R19; O.Imm 6UL ] + ||> test32R2NoCondNofmt + +/// Condition Testing And Conditional Move Operations +[] +type CondTestAndCondMoveClass () = + [] + member __.``[MIPS32] Condition Testing And .. Operations Parse Test (1)`` () = + "0082180b" + ++ MOVN ** [ O.Reg R3; O.Reg R4; O.Reg R2 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Condition Testing And .. Operations Parse Test (2)`` () = + "0005100a" + ++ MOVZ ** [ O.Reg R2; O.Reg R0; O.Reg R5 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Condition Testing And .. Operations Parse Test (3)`` () = + "0270102a" + ++ SLT ** [ O.Reg R2; O.Reg R19; O.Reg R16 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Condition Testing And .. Operations Parse Test (4)`` () = + "28570002" + ++ SLTI ** [ O.Reg R23; O.Reg R2; O.Imm 2UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Condition Testing And .. Operations Parse Test (5)`` () = + "2c430113" + ++ SLTIU ** [ O.Reg R3; O.Reg R2; O.Imm 275UL ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Condition Testing And .. Operations Parse Test (6)`` () = + "0002102b" + ++ SLTU ** [ O.Reg R2; O.Reg R0; O.Reg R2 ] + ||> test32R2NoCondNofmt + +/// Multiply and Divide operations +[] +type MultiplyAndDivideClass () = + [] + member __.``[MIPS32] Multiply and Divide operations Parse Test (1)`` () = + "0062001b" + ++ DIVU ** [ O.Reg R3; O.Reg R2 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Multiply and Divide operations Parse Test (2)`` () = + "70881802" + ++ MUL ** [ O.Reg R3; O.Reg R4; O.Reg R8 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Multiply and Divide operations Parse Test (3)`` () = + "02e50019" + ++ MULTU ** [ O.Reg R23; O.Reg R5 ] + ||> test32R2NoCondNofmt + +/// Accumulator Access operations +[] +type AccumulatorAccessClass () = + [] + member __.``[MIPS32] Accumulator Access operations Parse Test (1)`` () = + "00001010" + ++ MFHI ** [ O.Reg R2 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Accumulator Access operations Parse Test (2)`` () = + "00001812" + ++ MFLO ** [ O.Reg R3 ] + ||> test32R2NoCondNofmt + +/// Jumps And Branches Operations +[] +type JumpAndBranchesClass () = + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (1)`` () = + "14400400" + ++ BNE ** [ O.Reg R2; O.Reg R0; O.Addr (Relative 4100L) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (2)`` () = + "1ae00456" + ++ BLEZ ** [ O.Reg R23; O.Addr (Relative 4444L) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (3)`` () = + "1c40fff3" + ++ BGTZ ** [ O.Reg R2; O.Addr (Relative -48L) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (4)`` () = + "03e00008" + ++ JR ** [ O.Reg R31 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (5)`` () = + "0320f809" + ++ JALR ** [ O.Reg R25 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (6)`` () = + "04113e1d" + ++ BAL ** [ O.Addr (Relative 63608L) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (7)`` () = + "04400069" + ++ BLTZ ** [ O.Reg R2; O.Addr (Relative 424L) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Jump And Branches operations Parse Test (8)`` () = + "06c1015e" + ++ BGEZ ** [ O.Reg R22; O.Addr (Relative 1404L) ] + ||> test32R2NoCondNofmt + +/// Load And Store operations +[] +type LoadAndStoreClass () = + [] + member __.``[MIPS32] Load And Store operations Parse Test (1)`` () = + "80420000" + ++ LB ** [ O.Reg R2; O.Mem (R.R2, 0L, 8) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (2)`` () = + "92624418" + ++ LBU ** [ O.Reg R2; O.Mem (R.R19, 17432L, 8) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (3)`` () = + "97a200aa" + ++ LHU ** [ O.Reg R2; O.Mem (R.R29, 170L, 16) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (4)`` () = + "8f8282c4" + ++ LW ** [ O.Reg R2; O.Mem (R.R28, -032060L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (5)`` () = + "a2c443dc" + ++ SB ** [ O.Reg R4; O.Mem (R.R22, 17372L, 8) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (6)`` () = + "a7a200b8" + ++ SH ** [ O.Reg R2; O.Mem (R.R29, 184L, 16) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (7)`` () = + "afbc0010" + ++ SW ** [ O.Reg R28; O.Mem (R.R29, 16L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (8)`` () = + "a8440000" + ++ SWL ** [ O.Reg R4; O.Mem (R.R2, 0L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Load And Store operations Parse Test (9)`` () = + "b8440003" + ++ SWR ** [ O.Reg R4; O.Mem (R.R2, 3L, 32) ] + ||> test32R2NoCondNofmt + +/// Floating Point operations +[] +type FloatingPointClass () = + [] + member __.``[MIPS32] Floating Point operations Parse Test (1)`` () = + "46022080" + ++ ADD ** [ O.Reg F2; O.Reg F4; O.Reg F2 ] + ||> test32R2NoCond Fmt.S + + [] + member __.``[MIPS32] Floating Point operations Parse Test (2)`` () = + "46220000" + ++ ADD ** [ O.Reg F0; O.Reg F0; O.Reg F2 ] + ||> test32R2NoCond Fmt.D + + [] + member __.``[MIPS32] Floating Point operations Parse Test (3)`` () = + "46206301" + ++ SUB ** [ O.Reg F12; O.Reg F12; O.Reg F0 ] + ||> test32R2NoCond Fmt.D + + [] + member __.``[MIPS32] Floating Point operations Parse Test (4)`` () = + "46220003" + ++ DIV ** [ O.Reg F0; O.Reg F0; O.Reg F2 ] + ||> test32R2NoCond Fmt.D + + [] + member __.``[MIPS32] Floating Point operations Parse Test (5)`` () = + "46020003" + ++ DIV ** [ O.Reg F0; O.Reg F0; O.Reg F2 ] + ||> test32R2NoCond Fmt.S + + [] + member __.``[MIPS32] Floating Point operations Parse Test (6)`` () = + "46200506" + ++ MOV ** [ O.Reg F20; O.Reg F0 ] + ||> test32R2NoCond Fmt.D + + [] + member __.``[MIPS32] Floating Point operations Parse Test (7)`` () = + "44140000" + ++ MFC1 ** [ O.Reg R20; O.Reg F0 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Floating Point operations Parse Test (8)`` () = + "44803000" + ++ MTC1 ** [ O.Reg R0; O.Reg F6 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Floating Point operations Parse Test (9)`` () = + "d4440a48" + ++ LDC1 ** [ O.Reg F4; O.Mem (R.R2, 2632L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Floating Point operations Parse Test (10)`` () = + "c4600008" + ++ LWC1 ** [ O.Reg F0; O.Mem (R.R3, 8L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Floating Point operations Parse Test (11)`` () = + "f7a00010" + ++ SDC1 ** [ O.Reg F0; O.Mem (R.R29, 16L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Floating Point operations Parse Test (12)`` () = + "e4800004" + ++ SWC1 ** [ O.Reg F0; O.Mem (R.R4, 4L, 32) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] Floating Point operations Parse Test (13)`` () = + "4600103c" + ++ C ** [ O.Reg F2; O.Reg F0 ] + ||> test32R2 Condition.LT Fmt.S + + [] + member __.``[MIPS32] Floating Point operations Parse Test (14)`` () = + "46800021" + ++ CVTD ** [ O.Reg F0; O.Reg F0 ] + ||> test32R2NoCond Fmt.W + + [] + member __.``[MIPS32] Floating Point operations Parse Test (15)`` () = + "46200020" + ++ CVTS ** [ O.Reg F0; O.Reg F0 ] + ||> test32R2NoCond Fmt.D + + [] + member __.``[MIPS32] Floating Point operations Parse Test (16)`` () = + "4620000d" + ++ TRUNCW ** [ O.Reg F0; O.Reg F0 ] + ||> test32R2NoCond Fmt.D + + [] + member __.``[MIPS32] Floating Point operations Parse Test (17)`` () = + "4600000d" + ++ TRUNCW ** [ O.Reg F0; O.Reg F0 ] + ||> test32R2NoCond Fmt.S + +/// ETC Operations +[] +type ETCClass () = + [] + member __.``[MIPS32] ETC Operations Parse Test (1)`` () = + "004001f4" + ++ TEQ ** [ O.Reg R2; O.Reg R0 ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] ETC Operations Parse Test (2)`` () = + "45190004" + ++ BC1T ** [ O.Imm 6UL; O.Addr (Relative 20L) ] + ||> test32R2NoCondNofmt + + [] + member __.``[MIPS32] ETC Operations Parse Test (3)`` () = + "4500001a" + ++ BC1F ** [ O.Addr (Relative 108L) ] + ||> test32R2NoCondNofmt diff --git a/src/FrontEnd/BinLifter.Tests/MIPS64.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/MIPS64.Parser.Tests.fs new file mode 100644 index 00000000..615967e4 --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/MIPS64.Parser.Tests.fs @@ -0,0 +1,205 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.MIPS64 + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter.MIPS +open type Opcode +open type Register + +type O = + static member Reg (r) = + OpReg r + + static member Imm (v) = + OpImm v + + static member Mem (r, o: int64, rt) = + OpMem (r, Imm o, rt) + + static member Mem (r, o: Register, rt) = + OpMem (r, Reg o, rt) + + static member Addr (t) = + OpAddr t + + static member Shift (s) = + OpShiftAmount s + +let private test arch endian opcode oprs (bytes: byte[]) = + let reader = BinReader.Init endian + let span = System.ReadOnlySpan bytes + let ins = ParsingMain.parse span reader arch WordSize.Bit64 0UL + let opcode' = ins.Info.Opcode + let oprs' = ins.Info.Operands + Assert.AreEqual (opcode', opcode) + Assert.AreEqual (oprs', oprs) + +let private test64R2 (bytes: byte[]) (opcode, operands) = + test Architecture.MIPS64 Endian.Big opcode operands bytes + +let private operandsFromArray oprList = + let oprArray = Array.ofList oprList + match oprArray.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprArray[0] + | 2 -> TwoOperands (oprArray[0], oprArray[1]) + | 3 -> ThreeOperands (oprArray[0], oprArray[1], oprArray[2]) + | 4 -> FourOperands (oprArray[0], oprArray[1], oprArray[2], oprArray[3]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +/// Arithmetic operations +[] +type ArithmeticClass () = + [] + member __.``[MIPS64] Arithmetic operations Parse Test (1)`` () = + "02bd782d" + ++ DADDU ** [ O.Reg R15; O.Reg R21; O.Reg R29 ] + ||> test64R2 + + [] + member __.``[MIPS64] Arithmetic operations Parse Test (2)`` () = + "64cdccd5" + ++ DADDIU ** [ O.Reg R13; O.Reg R6; O.Imm 0xffffffffffffccd5UL ] + ||> test64R2 + + [] + member __.``[MIPS64] Arithmetic operations Parse Test (3)`` () = + "0229d02f" + ++ DSUBU ** [ O.Reg R26; O.Reg R17; O.Reg R9 ] + ||> test64R2 + +/// Shift And Rotate operations +[] +type ShiftAndRotateClass () = + [] + member __.``[MIPS64] Shift And Rotate operations Parse Test (1)`` () = + "002df6ba" + ++ DROTR ** [ O.Reg R30; O.Reg R13; O.Shift 0x1aUL ] + ||> test64R2 + + [] + member __.``[MIPS64] Shift And Rotate operations Parse Test (2)`` () = + "000eeef8" + ++ DSLL ** [ O.Reg R29; O.Reg R14; O.Shift 0x1bUL ] + ||> test64R2 + + [] + member __.``[MIPS64] Shift And Rotate operations Parse Test (3)`` () = + "0011e57c" + ++ DSLL32 ** [ O.Reg R28; O.Reg R17; O.Shift 0x15UL ] + ||> test64R2 + + [] + member __.``[MIPS64] Shift And Rotate operations Parse Test (4)`` () = + "02baf014" + ++ DSLLV ** [ O.Reg R30; O.Reg R26; O.Reg R21 ] + ||> test64R2 + + [] + member __.``[MIPS64] Shift And Rotate operations Parse Test (5)`` () = + "000ef7fb" + ++ DSRA ** [ O.Reg R30; O.Reg R14; O.Shift 0x1fUL ] + ||> test64R2 + + [] + member __.``[MIPS64] Shift And Rotate operations Parse Test (6)`` () = + "000fd1ff" + ++ DSRA32 ** [ O.Reg R26; O.Reg R15; O.Shift 0x7UL ] + ||> test64R2 + +/// Logical and Bit-Field Operations +[] +type LogicalAndBitFieldClass () = + [] + member __.``[MIPS64] Logical and Bit-Field operations Parse Test (1)`` () = + "7d5d6883" + ++ DEXT ** [ O.Reg R29; O.Reg R10; O.Imm 0x2UL; O.Imm 0xeUL ] + ||> test64R2 + + [] + member __.``[MIPS64] Logical and Bit-Field operations Parse Test (2)`` () = + "7df5ca47" + ++ DINS ** [ O.Reg R21; O.Reg R15; O.Imm 0x9UL; O.Imm 0x11UL ] + ||> test64R2 + +/// Multiply and Divide operations +[] +type MultiplyAndDivideClass () = + [] + member __.``[MIPS64] Multiply and Divide operations Parse Test (1)`` () = + "03c3001f" + ++ DDIVU ** [ O.Reg R30; O.Reg R3 ] + ||> test64R2 + + [] + member __.``[MIPS64] Multiply and Divide operations Parse Test (2)`` () = + "030e001c" + ++ DMULT ** [ O.Reg R24; O.Reg R14 ] + ||> test64R2 + + [] + member __.``[MIPS64] Multiply and Divide operations Parse Test (3)`` () = + "0232001d" + ++ DMULTU ** [ O.Reg R17; O.Reg R18 ] + ||> test64R2 + +/// Load and Store operations +[] +type LoadAndStoreClass () = + [] + member __.``[MIPS64] Load and Store operations Parse Test (1)`` () = + "df5d2afd" + ++ LD ** [ O.Reg R29; O.Mem (R26, 0x2afdL, 64) ] + ||> test64R2 + + [] + member __.``[MIPS64] Load and Store operations Parse Test (2)`` () = + "9f11ad01" + ++ LWU ** [ O.Reg R17; O.Mem (R24, -0x52ffL, 32) ] + ||> test64R2 + + [] + member __.``[MIPS64] Load and Store operations Parse Test (3)`` () = + "fe25380a" + ++ SD ** [ O.Reg R5; O.Mem (R.R17, 0x380aL, 64) ] + ||> test64R2 + + [] + member __.``[MIPS64] Load and Store operations Parse Test (4)`` () = + "b34c3f02" + ++ SDL ** [ O.Reg R12; O.Mem (R26, 0x3f02L, 64) ] + ||> test64R2 + + [] + member __.``[MIPS64] Load and Store operations Parse Test (5)`` () = + "b4cb8715" + ++ SDR ** [ O.Reg R11; O.Mem (R6, -0x78ebL, 64) ] + ||> test64R2 diff --git a/src/FrontEnd/BinLifter.Tests/Optimizer.Tests.fs b/src/FrontEnd/BinLifter.Tests/Optimizer.Tests.fs new file mode 100644 index 00000000..4ce21fde --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/Optimizer.Tests.fs @@ -0,0 +1,133 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.Optimizer + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp + +[] +module TestHelper = + let num v = BitVector.OfUInt32 v 32 |> AST.num + + let t32 id = AST.tmpvar 32 id + + let ismark = AST.ismark 1u + + let iemark = AST.iemark 1u + + let varA = AST.var 32 (RegisterID.create 0) "A" + + let varB = AST.var 32 (RegisterID.create 1) "B" + + let varC = AST.var 32 (RegisterID.create 2) "C" + + let wrapStmts stmts = [| ismark; yield! stmts; iemark |] + + let test optimizeFn (expectedStmts, givenStmts) = + let optimizedStmts = optimizeFn <| wrapStmts givenStmts + CollectionAssert.AreEqual (wrapStmts expectedStmts, optimizedStmts) + +[] +type ConstantFoldingTest () = + [] + member __.``[ConstantFolding] Binary operator replacement test`` () = + ([ varA := num 30u + varB := num 3u + varC := num 12u ], + [ varA := num 30u + varB := num 9u .- (varA ./ num 5u) + varC := varB .* num 4u ]) + |> test ConstantFolding.optimize + + [] + member __.``[ConstantFolding] ite replacement test`` () = + ([ varC := num 12u + varC := num 2u ], + [ varC := num 12u + varC := AST.ite (varC .> num 10u) (varC .- num 10u) varC ]) + |> test ConstantFolding.optimize + + [] + member __.``[ConstantFolding] Tempvar replacement test`` () = + ([ t32 1 := num 6u + varA := varA .- num 4u + AST.loadLE 32 varA := varB + AST.loadLE 32 varA := varB + varA := varA .- num 0x6u ], + [ t32 1 := num 6u + varA := varA .- num 4u + AST.loadLE 32 varA := varB + AST.loadLE 32 varA := varB + varA := varA .- t32 1 ]) + |> test ConstantFolding.optimize + + [] + member __.``[ConstantFolding] Condition jump replacement test`` () = + let ir = IRBuilder 42 + let lblTarget = !%ir "Target" + let lblImpossible = !%ir "Impossible" + let lblEnd = !%ir "End" + ([ varA := num 1u + AST.jmp (AST.name lblTarget) + AST.lmark lblImpossible + varB := num 0u + AST.lmark lblTarget + varB := num 1u + AST.lmark lblEnd ], + [ varA := num 1u + AST.cjmp (varA == varA) (AST.name lblTarget) (AST.name lblImpossible) + AST.lmark lblImpossible + varB := num 0u + AST.lmark lblTarget + varB := num 1u + AST.lmark lblEnd ]) + |> test ConstantFolding.optimize + +[] +type DeadCodeEliminationTest () = + [] + member __.``[DeadCodeElimination] Dead code removal test (1)`` () = + ([ t32 1 := num 1u + t32 2 := num 2u + varA := t32 1 .+ t32 2 ], + [ t32 1 := num 1u + t32 2 := num 2u + t32 3 := num 3u + varA := t32 1 .+ t32 2 ]) + |> test DeadCodeElimination.optimize + + [] + member __.``[DeadCodeElimination] Dead code removal test (2)`` () = + ([ varB := num 3u + varA := t32 1 .+ t32 2 ], + [ varB := num 1u + varB := num 2u + varB := num 3u + varA := t32 1 .+ t32 2 ]) + |> test DeadCodeElimination.optimize diff --git a/src/FrontEnd/BinLifter.Tests/Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/Parser.Tests.fs deleted file mode 100644 index e365adc8..00000000 --- a/src/FrontEnd/BinLifter.Tests/Parser.Tests.fs +++ /dev/null @@ -1,6614 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*) - -namespace B2R2.FrontEnd.Tests - -open Microsoft.VisualStudio.TestTools.UnitTesting -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface - -module Intel = - open B2R2.FrontEnd.BinLifter.Intel - - let private test prefs segment wordSize opcode oprs length (bytes: byte[]) = - let parser = IntelParser (wordSize) - let ins = parser.Parse (bytes, 0UL) :?> IntelInternalInstruction - Assert.AreEqual (ins.Prefixes, prefs) - Assert.AreEqual (Helper.getSegment ins.Prefixes, segment) - Assert.AreEqual (ins.Opcode, opcode) - Assert.AreEqual (ins.Operands, oprs) - Assert.AreEqual (ins.Length, length) - - let private test32 = test Prefix.PrxNone None WordSize.Bit32 - let private test32WithPrx prefix = test prefix None WordSize.Bit32 - let private test64 = test Prefix.PrxNone None WordSize.Bit64 - - /// 5.1 GENERAL-PURPOSE INSTRUCTIONS - [] - type GeneralPurposeClass () = - /// 5.1.1 Data Transfer Instruction - [] - member __.``Intel Data Transfer Parse Test`` () = - test32 Opcode.MOV - (TwoOperands (OprMem (None, None, Some 2210584L, 32), - OprImm (2L, 32)) ) 10ul - [| 0xc7uy; 0x05uy; 0x18uy; 0xbbuy; 0x21uy; - 0x00uy; 0x02uy; 0x00uy; 0x00uy; 0x00uy |] - - test64 Opcode.PUSH (OneOperand (OprImm (0x44332211L, 32))) 5ul - [| 0x68uy; 0x11uy; 0x22uy; 0x33uy; 0x44uy |] - - test32 Opcode.MOVSX - (TwoOperands (OprReg R.EDI, - OprMem (Some R.EDI, None, Some -1L, 8))) 4ul - [| 0x0fuy; 0xbeuy; 0x7fuy; 0xffuy |] - - test64 Opcode.MOVSXD (TwoOperands (OprReg R.RCX, OprReg R.EAX)) 3ul - [| 0x48uy; 0x63uy; 0xc8uy |] - - /// 5.1.2 Binary Arithmetic Instructions - [] - member __.``Intel Binary Arithmetic Parse Test`` () = - test64 Opcode.ADD (TwoOperands (OprReg R.RCX, OprReg R.RAX)) 3ul - [| 0x48uy; 0x03uy; 0xc8uy |] - - test32 Opcode.IMUL - (ThreeOperands (OprReg R.EDI, OprReg R.EDX, OprImm (10L, 8))) - 3ul - [| 0x6buy; 0xfauy; 0x0auy |] - - test32 Opcode.MUL - (OneOperand (OprMem (Some R.EAX, None, None, 32))) 2ul - [| 0xf7uy; 0x20uy |] - - test32 Opcode.DIV (OneOperand (OprReg R.ECX)) 2ul [| 0xf7uy; 0xf1uy |] - - /// 5.1.3 Decimal Arithmetic Instructions - [] - member __.``Decimal Arithmetic Parse Test`` () = - test32 Opcode.AAA NoOperand 1ul [| 0x37uy |] - - test32 Opcode.AAS NoOperand 1ul [| 0x3Fuy |] - - /// 5.1.4 Logical Instructions - [] - member __.``Intel Logical Parse Test`` () = - test32 Opcode.AND - (TwoOperands (OprMem (Some R.ESP, - Some (R.EDX, Scale.X1), None, 32), - OprReg R.ESP)) - 3ul [| 0x21uy; 0x24uy; 0x14uy |] - - test32 Opcode.AND - (TwoOperands (OprMem (None, None, Some 1111638594L, 32), - OprReg R.ESP)) - 6ul [| 0x21uy; 0x25uy; 0x42uy; 0x42uy; 0x42uy; 0x42uy |] - - /// 5.1.5 Shift and Rotate Instructions - [] - member __.``Intel Shift And Rotate Parse Test`` () = - test32 Opcode.ROL - (TwoOperands (OprMem (Some R.EAX, None, None, 32), - OprImm (10L, 8))) 3ul - [| 0xc1uy; 0x00uy; 0x0auy |] - - test32 Opcode.ROL - (TwoOperands (OprMem (Some R.EAX, None, None, 8), - OprImm (10L, 8))) 3ul - [| 0xc0uy; 0x00uy; 0x0auy |] - - /// 5.1.6 Bit and Byte Instructions - [] - member __.``Intel Bit And Byte Parse Test`` () = - test32 Opcode.TEST - (TwoOperands (OprMem (Some R.EAX, None, None, 8), - OprImm (10L, 8))) 3ul - [| 0xf6uy; 0x00uy; 0x0auy |] - - /// 5.1.7 Control Transfer Instructions - [] - member __.``Intel Control Transfer Parse Test`` () = - test32 Opcode.JMPNear (OneOperand (OprReg R.ESP)) 2ul [| 0xffuy; 0xe4uy |] - - test32 Opcode.JMPFar - (OneOperand (OprDirAddr (Absolute (0x90s, 0x78563412UL, 32)))) - 7ul - [| 0xeauy; 0x12uy; 0x34uy; 0x56uy; 0x78uy; 0x90uy; 0x00uy |] - - test Prefix.PrxGS (Some R.GS) WordSize.Bit32 - Opcode.CALLNear - (OneOperand (OprMem (None, None, Some 16L, 32))) 7ul - [| 0x65uy; 0xffuy; 0x15uy; 0x10uy; 0x00uy; 0x00uy; 0x00uy |] - - test32 Opcode.CALLFar - (OneOperand (OprDirAddr (Absolute (0x10s, 0x32547698UL, 32)))) - 7ul - [| 0x9auy; 0x98uy; 0x76uy; 0x54uy; 0x32uy; 0x10uy; 0x00uy |] - - test32 Opcode.INT (OneOperand (OprImm (1L, 8))) - 2ul [| 0xcduy; 0x01uy |] - - /// 5.1.9 I/O Instructions - [] - member __.``I/O Instructions Parse Test`` () = - test32 Opcode.IN (TwoOperands (OprReg R.EAX, OprReg R.DX)) 1ul - [| 0xEDuy |] - - test32 Opcode.OUT (TwoOperands (OprReg R.DX, OprReg R.AL)) 1ul - [| 0xEEuy |] - - test32WithPrx Prefix.PrxOPSIZE - Opcode.OUT (TwoOperands (OprReg R.DX, OprReg R.AX)) 2ul - [| 0x66uy; 0xEFuy |] - - test32 Opcode.OUT (TwoOperands (OprReg R.DX, OprReg R.EAX)) 1ul - [| 0xEFuy |] - - /// 5.1.12 Segment Register Instructions - [] - member __.``Segment Register Parse Test`` () = - test32 Opcode.LES - (TwoOperands (OprReg R.ECX, - OprMem (Some R.EDI, None, None, 48))) 2ul - [| 0xc4uy; 0x0fuy |] - - test32 Opcode.LDS - (TwoOperands (OprReg R.EDX, - OprMem (Some R.ECX, None, None, 48))) 2ul - [| 0xc5uy; 0x11uy |] - - /// 5.2 X87 FPU INSTRUCTIONS - [] - type X87FPUClass () = - /// 5.2.1 x87 FPU Data Transfer Instructions - [] - member __.``Intel FPU Data Transfer Parse Test`` () = - test32 Opcode.FILD (OneOperand (OprMem (Some R.EDX, - Some (R.ECX, Scale.X8), - Some 67305985L, 16))) - 7ul [| 0xdfuy; 0x84uy; 0xcauy; 0x01uy; 0x02uy; 0x03uy; 0x04uy |] - - test32 Opcode.FBLD - (OneOperand (OprMem (Some R.EAX, None, None, 80))) 2ul - [| 0xdfuy; 0x20uy |] - - /// 5.2.3 x87 FPU Comparison Instructions - [] - member __.``Intel FPU Comparision Parse Test`` () = - test32 Opcode.FCOMIP (TwoOperands (OprReg R.ST0, OprReg R.ST1)) 2ul - [| 0xdfuy; 0xf1uy |] - - test32 Opcode.FUCOMIP (TwoOperands (OprReg R.ST0, OprReg R.ST1)) 2ul - [| 0xdfuy; 0xe9uy |] - - /// 5.4 MMX INSTRUCTIONS - [] - type MMXClass () = - /// 5.4.1 MMX Conversion Instructions - [] - member __.``Intel MMX Conversion Parse Test`` () = - test64 Opcode.VMOVQ - (TwoOperands - (OprMem (Some R.RAX, None, Some 67305985L, 64), - OprReg (R.XMM2))) 9ul - [| 0xc4uy; 0xe1uy; 0xf9uy; 0xd6uy; 0x90uy; - 0x01uy; 0x02uy; 0x03uy; 0x04uy |] - - test64 Opcode.VMOVQ (TwoOperands (OprReg (R.XMM0), OprReg (R.XMM2))) 5ul - [|0xc4uy; 0xe1uy; 0xf9uy; 0xd6uy; 0xd0uy|] - - /// 5.4.4 MMX Comparison Instructions - [] - member __.``Intel MMX Comparison Parse Test`` () = - test64 Opcode.PCMPEQW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 3u - [| 0x0Fuy; 0x75uy; 0x01uy |] - - test64 Opcode.PCMPEQW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 3u - [| 0x0Fuy; 0x75uy; 0xc1uy |] - - test64 Opcode.PCMPEQW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 4u - [| 0x66uy; 0x0Fuy; 0x75uy; 0x01uy |] - - test64 Opcode.PCMPEQW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 4u - [| 0x66uy; 0x0Fuy; 0x75uy; 0xc1uy |] - - /// 5.5 SSE INSTRUCTIONS - [] - type SSEClass () = - /// 5.5.1 SSE SIMD Single-Precision Floating-Point Instructions - /// 5.5.1.6 SSE Conversion Instructions - [] - member __.``Intel SSE Conversion Parse Test`` () = - test64 Opcode.VCVTSS2SI - (TwoOperands - (OprReg R.RDX, - OprMem (Some R.RAX, None, Some 67305985L, 32))) 9ul - [| 0xc4uy; 0xe1uy; 0xfauy; 0x2duy; 0x90uy; - 0x01uy; 0x02uy; 0x03uy; 0x04uy |] - - test64 Opcode.VCVTSD2SI - (TwoOperands - (OprReg R.EDX, - OprMem (Some R.RAX, None, Some 67305985L, 64))) 9ul - [| 0xc4uy; 0xe1uy; 0x7buy; 0x2duy; 0x90uy; - 0x01uy; 0x02uy; 0x03uy; 0x04uy |] - - /// 5.6 SSE2 INSTRUCTIONS - [] - type SSE2Class () = - /// 5.6.3 SSE2 128-Bits SIMD Integer Instructions - [] - member __.``Intel SSE 128-Bits SIMD Interger Parse Test`` () = - test64 Opcode.VMOVDQA64 - (TwoOperands - (OprReg R.ZMM1, - OprMem (Some R.RSP, None, Some 64L, 512))) 8ul - [| 0x62uy; 0xf1uy; 0xfduy; 0x48uy; - 0x6fuy; 0x4cuy; 0x24uy; 0x01uy |] - - /// 5.8 SUPPLEMENTAL STREAMING SIMD EXTENSIONS 3 (SSSE3) INSTRUCTIONS - [] - type SSSE3Class () = - /// 5.8.1 Horizontal Addition/Subtraction - [] - member __.``Intel Horizontal Addition/Subtraction Parse Test`` () = - test64 Opcode.PHADDW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x01uy; 0x01uy |] - - test64 Opcode.PHADDW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x01uy; 0xc1uy |] - - test64 Opcode.PHADDW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x01uy; 0x01uy |] - - test64 Opcode.PHADDW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x01uy; 0xc1uy |] - - test64 Opcode.PHADDSW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x03uy; 0x01uy |] - - test64 Opcode.PHADDSW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x03uy; 0xc1uy |] - - test64 Opcode.PHADDSW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x03uy; 0x01uy |] - - test64 Opcode.PHADDSW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x03uy; 0xc1uy |] - - test64 Opcode.PHADDD - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x02uy; 0x01uy |] - - test64 Opcode.PHADDD - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x02uy; 0xc1uy |] - - test64 Opcode.PHADDD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x02uy; 0x01uy |] - - test64 Opcode.PHADDD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x02uy; 0xc1uy |] - - test64 Opcode.PHSUBW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x05uy; 0x01uy |] - - test64 Opcode.PHSUBW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x05uy; 0xc1uy |] - - test64 Opcode.PHSUBW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x05uy; 0x01uy |] - - test64 Opcode.PHSUBW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x05uy; 0xc1uy |] - - test64 Opcode.PHSUBSW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x07uy; 0x01uy |] - - test64 Opcode.PHSUBSW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x07uy; 0xc1uy |] - - test64 Opcode.PHSUBSW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x07uy; 0x01uy |] - - test64 Opcode.PHSUBSW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x07uy; 0xc1uy |] - - test64 Opcode.PHSUBD - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x06uy; 0x01uy |] - - test64 Opcode.PHSUBD - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x06uy; 0xc1uy |] - - test64 Opcode.PHSUBD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x06uy; 0x01uy |] - - test64 Opcode.PHSUBD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x06uy; 0xc1uy |] - - /// 5.8.2 Packed Absolute Values - [] - member __.``Intel Packed Absolute Values Parse Test`` () = - test64 Opcode.PABSB - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x1Cuy; 0x01uy |] - - test64 Opcode.PABSB - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x1Cuy; 0xc1uy |] - - test64 Opcode.PABSB - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x1Cuy; 0x01uy |] - - test64 Opcode.PABSB - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x1Cuy; 0xc1uy |] - - test64 Opcode.PABSD - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x1Euy; 0x01uy |] - - test64 Opcode.PABSD - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x1Euy; 0xc1uy |] - - test64 Opcode.PABSD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x1Euy; 0x01uy |] - - test64 Opcode.PABSD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x1Euy; 0xc1uy |] - - test64 Opcode.PABSW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x1Duy; 0x01uy |] - - test64 Opcode.PABSW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x1Duy; 0xc1uy |] - - test64 Opcode.PABSW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x1Duy; 0x01uy |] - - test64 Opcode.PABSW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x1Duy; 0xc1uy |] - - /// 5.8.4 Packed Multiply High with Round and Scale - [] - member __.``Intel Packed Mul High with Round and Scale Parse Test`` () = - test64 Opcode.PMULHRSW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x0Buy; 0x01uy |] - - test64 Opcode.PMULHRSW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x0Buy; 0xc1uy |] - - test64 Opcode.PMULHRSW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x0Buy; 0x01uy |] - - test64 Opcode.PMULHRSW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x0Buy; 0xc1uy |] - - /// 5.8.6 Packed Sign - [] - member __.``Intel Packed Sign Parse Test`` () = - test64 Opcode.PSIGNB - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x08uy; 0x01uy |] - - test64 Opcode.PSIGNB - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x08uy; 0xc1uy |] - - test64 Opcode.PSIGNB - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x08uy; 0x01uy |] - - test64 Opcode.PSIGNB - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x08uy; 0xc1uy |] - - test64 Opcode.PSIGNW - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x09uy; 0x01uy |] - - test64 Opcode.PSIGNW - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x09uy; 0xc1uy |] - - test64 Opcode.PSIGNW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x09uy; 0x01uy |] - - test64 Opcode.PSIGNW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x09uy; 0xc1uy |] - - test64 Opcode.PSIGND - (TwoOperands (OprReg R.MM0, - OprMem (Some R.RCX, None, None, 64))) 4u - [| 0x0Fuy; 0x38uy; 0x0Auy; 0x01uy |] - - test64 Opcode.PSIGND - (TwoOperands (OprReg R.MM0, OprReg R.MM1)) 4u - [| 0x0Fuy; 0x38uy; 0x0Auy; 0xc1uy |] - - test64 Opcode.PSIGND - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RCX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x0Auy; 0x01uy |] - - test64 Opcode.PSIGND - (TwoOperands (OprReg R.XMM0, OprReg R.XMM1)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x0Auy; 0xc1uy |] - - /// 5.8.7 Packed Align Right - [] - member __.``Intel Packed Align Right Parse Test`` () = - test64 Opcode.PALIGNR - (ThreeOperands (OprReg R.XMM2, OprReg R.XMM1, OprImm (1L, 8))) - 6ul - [| 0x66uy; 0x0fuy; 0x3auy; 0x0fuy; 0xd1uy; 0x01uy |] - - /// 5.10 SSE4.1 INSTRUCTIONS - [] - type SSSE41Class () = - /// 5.10.1 Dword Multiply Instructions - [] - member __.``Intel Dword Multiply Parse Test`` () = - test64 Opcode.PMULLD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x40uy; 0x02uy |] - - test64 Opcode.PMULLD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x40uy; 0xc2uy |] - - test64 Opcode.PMULDQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x28uy; 0x02uy |] - - test64 Opcode.PMULDQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x28uy; 0xc2uy |] - - /// 5.10.5 Packed Integer MIN/MAX Instructions - [] - member __.``Intel Packed Integer MIN/MAX Parse Test`` () = - test64 Opcode.PMINUW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Auy; 0x02uy |] - - test64 Opcode.PMINUW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Auy; 0xc2uy |] - - test64 Opcode.PMINSD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x39uy; 0x02uy |] - - test64 Opcode.PMINSD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x39uy; 0xc2uy |] - - test64 Opcode.PMAXUW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Euy; 0x02uy |] - - test64 Opcode.PMAXUW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Euy; 0xc2uy |] - - test64 Opcode.PMAXUD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Fuy; 0x02uy |] - - test64 Opcode.PMAXUD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Fuy; 0xc2uy |] - - test64 Opcode.PMAXSB - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Cuy; 0x02uy |] - - test64 Opcode.PMAXSB - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Cuy; 0xc2uy |] - - test64 Opcode.PMAXSD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Duy; 0x02uy |] - - test64 Opcode.PMAXSD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x3Duy; 0xc2uy |] - - /// 5.10.8 Packed Integer Format Conversions - [] - member __.``Intel Packed Integer Format Conversions Parse Test`` () = - test64 Opcode.PMOVSXBD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 32))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x21uy; 0x02uy |] - - test64 Opcode.PMOVSXBD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x21uy; 0xc2uy |] - - test64 Opcode.PMOVSXBQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 16))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x22uy; 0x02uy |] - - test64 Opcode.PMOVSXBQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x22uy; 0xc2uy |] - - test64 Opcode.PMOVSXBW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 64))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x20uy; 0x02uy |] - - test64 Opcode.PMOVSXBW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x20uy; 0xc2uy |] - - test64 Opcode.PMOVSXDQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 64))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x25uy; 0x02uy |] - - test64 Opcode.PMOVSXDQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x25uy; 0xc2uy |] - - test64 Opcode.PMOVSXWD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 64))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x23uy; 0x02uy |] - - test64 Opcode.PMOVSXWD - (TwoOperands (OprReg R.XMM0, - OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x23uy; 0xc2uy |] - - test64 Opcode.PMOVSXWQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 32))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x24uy; 0x02uy |] - - test64 Opcode.PMOVSXWQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x24uy; 0xc2uy |] - - test64 Opcode.PMOVZXBD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 32))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x31uy; 0x02uy |] - - test64 Opcode.PMOVZXBD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x31uy; 0xc2uy |] - - test64 Opcode.PMOVZXBQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 16))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x32uy; 0x02uy |] - - test64 Opcode.PMOVZXBQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x32uy; 0xc2uy |] - - test64 Opcode.PMOVZXBW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 64))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x30uy; 0x02uy |] - - test64 Opcode.PMOVZXBW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x30uy; 0xc2uy |] - - test64 Opcode.PMOVZXDQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 64))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x35uy; 0x02uy |] - - test64 Opcode.PMOVZXDQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x35uy; 0xc2uy |] - - test64 Opcode.PMOVZXWD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 64))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x33uy; 0x02uy |] - - test64 Opcode.PMOVZXWD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x33uy; 0xc2uy |] - - test64 Opcode.PMOVZXWQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 32))) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x34uy; 0x02uy |] - - test64 Opcode.PMOVZXWQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0fuy; 0x38uy; 0x34uy; 0xc2uy |] - - /// 5.10.10 Horizontal Search - [] - member __.``Intel Horizontal Search Parse Test`` () = - test64 Opcode.PHMINPOSUW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x41uy; 0x02uy |] - - test64 Opcode.PHMINPOSUW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x41uy; 0xc2uy |] - - /// 5.10.13 Dword Packing With Unsigned Saturation - [] - member __.``Intel Dword Packing With Unsigned Saturation Parse Test`` () = - test64 Opcode.PACKUSDW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x2Buy; 0x02uy |] - test64 Opcode.PACKUSDW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x2Buy; 0xc2uy |] - - /// 5.11 SSE4.2 INSTRUCTION SET - [] - type SSSE42Class () = - /// 5.11.2 Packed Comparison SIMD integer Instruction - [] - member __.``Intel Packed Comparison SIMD integer Parse Test`` () = - test64 Opcode.PCMPGTQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RDX, None, None, 128))) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x37uy; 0x02uy |] - - test64 Opcode.PCMPGTQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM2)) 5u - [| 0x66uy; 0x0Fuy; 0x38uy; 0x37uy; 0xc2uy |] - - /// 5.22 INTEL MEMORY PROTECTION EXTENSIONS - [] - type IntelMemoryProtectionClass () = - [] - member __.``Intel Memory Protection Extensions Parse Test`` () = - test64 Opcode.BNDMOV - (TwoOperands (OprMem (Some R.RSP, None, Some 512L, 128), - OprReg R.BND0)) 9ul - [| 0x66uy; 0x0fuy; 0x1buy; 0x84uy; 0x24uy; - 0x00uy; 0x02uy; 0x00uy; 0x00uy |] - - /// INTEL ADVANCED VECTOR EXTENSIONS - [] - type AVXClass () = - [] - member __.``Intel AVX Parse Test`` () = - test64 Opcode.VPCMPEQW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM10, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE1uy; 0x29uy; 0x75uy; 0x03uy |] - - test64 Opcode.VPCMPEQW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM10, - OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE1uy; 0x29uy; 0x75uy; 0xc3uy |] - test64 Opcode.VPCMPEQW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM10, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE1uy; 0x2Duy; 0x75uy; 0x03uy |] - - test64 Opcode.VPCMPEQW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM10, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE1uy; 0x2Duy; 0x75uy; 0xc3uy |] - - test64 Opcode.VPABSB - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x1Cuy; 0x03uy |] - - test64 Opcode.VPABSB - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x1Cuy; 0xc3uy |] - - test64 Opcode.VPABSB - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x1Cuy; 0x03uy |] - - test64 Opcode.VPABSB - (TwoOperands (OprReg R.YMM0, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x1Cuy; 0xc3uy |] - - test64 Opcode.VPABSD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x1Euy; 0x03uy |] - - test64 Opcode.VPABSD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x1Euy; 0xc3uy |] - - test64 Opcode.VPABSD - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x1Euy; 0x03uy |] - - test64 Opcode.VPABSD - (TwoOperands (OprReg R.YMM0, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x1Euy; 0xc3uy |] - - test64 Opcode.VPABSW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x1Duy; 0x03uy |] - - test64 Opcode.VPABSW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x1Duy; 0xc3uy |] - - test64 Opcode.VPABSW - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x1Duy; 0x03uy |] - - test64 Opcode.VPABSW - (TwoOperands (OprReg R.YMM0, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x1Duy; 0xc3uy |] - - test64 Opcode.VPHADDD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x02uy; 0x03uy |] - - test64 Opcode.VPHADDD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x02uy; 0xc3uy |] - - test64 Opcode.VPHADDD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x02uy; 0x03uy |] - - test64 Opcode.VPHADDD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x02uy; 0xc3uy |] - - test64 Opcode.VPHADDSW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x03uy; 0x03uy |] - - test64 Opcode.VPHADDSW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x03uy; 0xc3uy |] - - test64 Opcode.VPHADDSW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x03uy; 0x03uy |] - - test64 Opcode.VPHADDSW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x03uy; 0xc3uy |] - - test64 Opcode.VPHADDW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x01uy; 0x03uy |] - - test64 Opcode.VPHADDW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x01uy; 0xc3uy |] - - test64 Opcode.VPHADDW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x01uy; 0x03uy |] - - test64 Opcode.VPHADDW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x01uy; 0xc3uy |] - - test64 Opcode.VPHSUBD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x06uy; 0x03uy |] - - test64 Opcode.VPHSUBD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x06uy; 0xc3uy |] - - test64 Opcode.VPHSUBD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x06uy; 0x03uy |] - - test64 Opcode.VPHSUBD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x06uy; 0xc3uy |] - - test64 Opcode.VPHSUBSW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x07uy; 0x03uy |] - - test64 Opcode.VPHSUBSW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x07uy; 0xc3uy |] - - test64 Opcode.VPHSUBSW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x07uy; 0x03uy |] - - test64 Opcode.VPHSUBSW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x07uy; 0xc3uy |] - - test64 Opcode.VPHSUBW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x05uy; 0x03uy |] - - test64 Opcode.VPHSUBW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x05uy; 0xc3uy |] - - test64 Opcode.VPHSUBW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x05uy; 0x03uy |] - - test64 Opcode.VPHSUBW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x05uy; 0xc3uy |] - - test64 Opcode.VPMULHRSW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x0Buy; 0x03uy |] - - test64 Opcode.VPMULHRSW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x0Buy; 0xc3uy |] - - test64 Opcode.VPMULHRSW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x0Buy; 0x03uy |] - - test64 Opcode.VPMULHRSW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x0Buy; 0xc3uy |] - - test64 Opcode.VPSIGNB - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x08uy; 0x03uy |] - - test64 Opcode.VPSIGNB - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x08uy; 0xc3uy |] - - test64 Opcode.VPSIGNB - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x08uy; 0x03uy |] - - test64 Opcode.VPSIGNB - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x08uy; 0xc3uy |] - - test64 Opcode.VPSIGND - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x0Auy; 0x03uy |] - - test64 Opcode.VPSIGND - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x0Auy; 0xc3uy |] - - test64 Opcode.VPSIGND - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x0Auy; 0x03uy |] - - test64 Opcode.VPSIGND - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x0Auy; 0xc3uy |] - - test64 Opcode.VPSIGNW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x09uy; 0x03uy |] - - test64 Opcode.VPSIGNW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x09uy; 0xc3uy |] - - test64 Opcode.VPSIGNW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x09uy; 0x03uy |] - - test64 Opcode.VPSIGNW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x09uy; 0xc3uy |] - - test64 Opcode.VPACKUSDW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x2Buy; 0x03uy |] - - test64 Opcode.VPACKUSDW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x2Buy; 0xc3uy |] - - test64 Opcode.VPACKUSDW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x2Buy; 0x03uy |] - - test64 Opcode.VPACKUSDW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x2Buy; 0xc3uy |] - - test64 Opcode.VPCMPGTQ - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x37uy; 0x03uy |] - - test64 Opcode.VPCMPGTQ - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x37uy; 0xc3uy |] - - test64 Opcode.VPCMPGTQ - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x37uy; 0x03uy |] - - test64 Opcode.VPCMPGTQ - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x37uy; 0xc3uy |] - - test64 Opcode.VPHMINPOSUW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x41uy; 0x03uy |] - - test64 Opcode.VPHMINPOSUW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x41uy; 0xc3uy |] - - test64 Opcode.VPMAXSB - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Cuy; 0x03uy |] - - test64 Opcode.VPMAXSB - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Cuy; 0xc3uy |] - - test64 Opcode.VPMAXSB - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Cuy; 0x03uy |] - - test64 Opcode.VPMAXSB - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Cuy; 0xc3uy |] - - test64 Opcode.VPMAXSD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Duy; 0x03uy |] - - test64 Opcode.VPMAXSD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Duy; 0xc3uy |] - - test64 Opcode.VPMAXSD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Duy; 0x03uy |] - - test64 Opcode.VPMAXSD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Duy; 0xc3uy |] - - test64 Opcode.VPMAXUD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Fuy; 0x03uy |] - - test64 Opcode.VPMAXUD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Fuy; 0xc3uy |] - - test64 Opcode.VPMAXUD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Fuy; 0x03uy |] - - test64 Opcode.VPMAXUD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Fuy; 0xc3uy |] - - test64 Opcode.VPMAXUW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Euy; 0x03uy |] - - test64 Opcode.VPMAXUW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Euy; 0xc3uy |] - - test64 Opcode.VPMAXUW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Euy; 0x03uy |] - - test64 Opcode.VPMAXUW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Euy; 0xc3uy |] - - test64 Opcode.VPMINSB - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x38uy; 0x03uy |] - - test64 Opcode.VPMINSB - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x38uy; 0xc3uy |] - - test64 Opcode.VPMINSB - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x38uy; 0x03uy |] - - test64 Opcode.VPMINSB - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x38uy; 0xc3uy |] - - test64 Opcode.VPMINSD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x39uy; 0x03uy |] - - test64 Opcode.VPMINSD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x39uy; 0xc3uy |] - - test64 Opcode.VPMINSD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x39uy; 0x03uy |] - - test64 Opcode.VPMINSD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x39uy; 0xc3uy |] - - test64 Opcode.VPMINUW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Auy; 0x03uy |] - - test64 Opcode.VPMINUW - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x3Auy; 0xc3uy |] - - test64 Opcode.VPMINUW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Auy; 0x03uy |] - - test64 Opcode.VPMINUW - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x3Auy; 0xc3uy |] - - test64 Opcode.VPMOVSXBD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 32))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x21uy; 0x03uy |] - - test64 Opcode.VPMOVSXBD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x21uy; 0xc3uy |] - - test64 Opcode.VPMOVSXBD - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x21uy; 0x03uy |] - - test64 Opcode.VPMOVSXBD - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x21uy; 0xc3uy |] - - test64 Opcode.VPMOVSXBQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 16))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x22uy; 0x03uy |] - - test64 Opcode.VPMOVSXBQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x22uy; 0xc3uy |] - - test64 Opcode.VPMOVSXBQ - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 32))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x22uy; 0x03uy |] - - test64 Opcode.VPMOVSXBQ - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x22uy; 0xc3uy |] - - test64 Opcode.VPMOVSXBW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x20uy; 0x03uy |] - - test64 Opcode.VPMOVSXBW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x20uy; 0xc3uy |] - - test64 Opcode.VPMOVSXBW - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x20uy; 0x03uy |] - - test64 Opcode.VPMOVSXBW - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x20uy; 0xc3uy |] - - test64 Opcode.VPMOVSXDQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x25uy; 0x03uy |] - - test64 Opcode.VPMOVSXDQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x25uy; 0xc3uy |] - - test64 Opcode.VPMOVSXDQ - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x25uy; 0x03uy |] - - test64 Opcode.VPMOVSXDQ - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x25uy; 0xc3uy |] - - test64 Opcode.VPMOVSXWD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x23uy; 0x03uy |] - - test64 Opcode.VPMOVSXWD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x23uy; 0xc3uy |] - - test64 Opcode.VPMOVSXWD - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x23uy; 0x03uy |] - - test64 Opcode.VPMOVSXWD - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x23uy; 0xc3uy |] - - test64 Opcode.VPMOVSXWQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 32))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x24uy; 0x03uy |] - - test64 Opcode.VPMOVSXWQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x24uy; 0xc3uy |] - - test64 Opcode.VPMOVSXWQ - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x24uy; 0x03uy |] - - test64 Opcode.VPMOVSXWQ - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x24uy; 0xc3uy |] - - test64 Opcode.VPMOVZXBD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 32))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x31uy; 0x03uy |] - - test64 Opcode.VPMOVZXBD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x31uy; 0xc3uy |] - - test64 Opcode.VPMOVZXBD - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x31uy; 0x03uy |] - - test64 Opcode.VPMOVZXBD - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x31uy; 0xc3uy |] - - test64 Opcode.VPMOVZXBQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 16))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x32uy; 0x03uy |] - - test64 Opcode.VPMOVZXBQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x32uy; 0xc3uy |] - - test64 Opcode.VPMOVZXBQ - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 32))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x32uy; 0x03uy |] - - test64 Opcode.VPMOVZXBQ - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x32uy; 0xc3uy |] - - test64 Opcode.VPMOVZXBW - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x30uy; 0x03uy |] - - test64 Opcode.VPMOVZXBW - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x30uy; 0xc3uy |] - - test64 Opcode.VPMOVZXBW - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x30uy; 0x03uy |] - - test64 Opcode.VPMOVZXBW - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x30uy; 0xc3uy |] - - test64 Opcode.VPMOVZXDQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x35uy; 0x03uy |] - - test64 Opcode.VPMOVZXDQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x35uy; 0xc3uy |] - - test64 Opcode.VPMOVZXDQ - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x35uy; 0x03uy |] - - test64 Opcode.VPMOVZXDQ - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x35uy; 0xc3uy |] - - test64 Opcode.VPMOVZXWD - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x33uy; 0x03uy |] - - test64 Opcode.VPMOVZXWD - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x33uy; 0xc3uy |] - - test64 Opcode.VPMOVZXWD - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x33uy; 0x03uy |] - - test64 Opcode.VPMOVZXWD - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x33uy; 0xc3uy |] - - test64 Opcode.VPMOVZXWQ - (TwoOperands (OprReg R.XMM0, - OprMem (Some R.RBX, None, None, 32))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x34uy; 0x03uy |] - - test64 Opcode.VPMOVZXWQ - (TwoOperands (OprReg R.XMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x34uy; 0xc3uy |] - - test64 Opcode.VPMOVZXWQ - (TwoOperands (OprReg R.YMM0, - OprMem (Some R.RBX, None, None, 64))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x34uy; 0x03uy |] - - test64 Opcode.VPMOVZXWQ - (TwoOperands (OprReg R.YMM0, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x34uy; 0xc3uy |] - - test64 Opcode.VPMULDQ - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x28uy; 0x03uy |] - - test64 Opcode.VPMULDQ - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x28uy; 0xc3uy |] - - test64 Opcode.VPMULDQ - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x28uy; 0x03uy |] - - test64 Opcode.VPMULDQ - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x28uy; 0xc3uy |] - - test64 Opcode.VPMULLD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, - OprMem (Some R.RBX, None, None, 128))) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x40uy; 0x03uy |] - - test64 Opcode.VPMULLD - (ThreeOperands (OprReg R.XMM0, OprReg R.XMM3, OprReg R.XMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x61uy; 0x40uy; 0xc3uy |] - - test64 Opcode.VPMULLD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, - OprMem (Some R.RBX, None, None, 256))) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x40uy; 0x03uy |] - - test64 Opcode.VPMULLD - (ThreeOperands (OprReg R.YMM0, OprReg R.YMM3, OprReg R.YMM3)) 5u - [| 0xC4uy; 0xE2uy; 0x65uy; 0x40uy; 0xc3uy |] - -#if !EMULATION - /// Exception Test - [] - type ExceptionTestClass () = - [] - [)>] - member __.``Size cond ParsingFailure Test`` () = - test64 Opcode.AAA NoOperand 1ul [| 0x37uy |] - - test64 Opcode.AAS NoOperand 1ul [| 0x3Fuy |] - - test64 Opcode.JMPFar - (OneOperand (OprDirAddr (Absolute (0x90s, 0x78563412UL, 32)))) - 7ul - [| 0xeauy; 0x12uy; 0x34uy; 0x56uy; 0x78uy; 0x90uy; 0x00uy |] - - test64 Opcode.CALLFar - (OneOperand (OprDirAddr (Absolute (0x10s, 0x32547698UL, 32)))) - 7ul - [| 0x9auy; 0x98uy; 0x76uy; 0x54uy; 0x32uy; 0x10uy; 0x00uy |] - - test64 Opcode.LES - (TwoOperands (OprReg R.ECX, - OprMem (Some R.EDI, None, None, 48))) 2ul - [| 0xc4uy; 0x0fuy |] - - test64 Opcode.LDS - (TwoOperands (OprReg R.EDX, - OprMem (Some R.ECX, None, None, 48))) 2ul - [| 0xc5uy; 0x11uy |] - - /// IR Test - [] - type TestClass () = - [] - member __.``Intel IL Test`` () = - let isa = ISA.Init Arch.IntelX86 Endian.Little - let hdl = BinHandle.Init (isa) - Assert.AreEqual (0, hdl.FileInfo.Span.Length) -#endif - -module ARMv7 = - open B2R2.FrontEnd.BinLifter.ARM32 - - let private test arch endian cond op w q simd oprs (bytes: byte[]) = - let mode = ArchOperationMode.ARMMode - let parser = ARM32Parser (ISA.Init arch endian, mode, None) - let ins = parser.Parse (bytes, 0UL) :?> ARM32Instruction - let cond' = ins.Condition - let opcode' = ins.Opcode - let wback' = ins.WriteBack - let q' = ins.Qualifier - let simd' = ins.SIMDTyp - let oprs' = ins.Operands - let w = match w with | Some true -> true | _ -> false // XXX - let q = match q with | Some W -> W | _ -> N // XXX - Assert.AreEqual (cond', cond) - Assert.AreEqual (opcode', op) - Assert.AreEqual (wback', w) - Assert.AreEqual (q', q) - Assert.AreEqual (simd', simd) - Assert.AreEqual (oprs', oprs) - - let private test32 = test Arch.ARMv7 Endian.Big - - /// A4.3 Branch instructions - [] - type BranchClass () = - [] - member __.``[ARMv7] Branch Parse Test`` () = - test32 (Condition.AL) Op.B None None None - (OneOperand (OprMemory (LiteralMode 1020L))) - [| 0xeauy; 0x00uy; 0x00uy; 0xffuy |] - - test32 (Condition.UN) Op.BLX None None None - (OneOperand (OprMemory (LiteralMode 64L))) - [| 0xfauy; 0x00uy; 0x00uy; 0x10uy |] - - test32 (Condition.AL) Op.BX None None None - (OneOperand (OprReg R.R0)) - [| 0xe1uy; 0x2fuy; 0xffuy; 0x10uy |] - - /// A4.4 Data-processing instructions - [] - type DataProcessingClass () = - /// A4.4.1 Standard data-processing instructions - [] - member __.``[ARMv7] Standard data-processing Parse Test`` () = - test32 (Condition.AL) Op.ADD None None None - (FourOperands (OprReg R.R2, OprReg R.R0, OprReg R.LR, - OprRegShift (SRTypeASR, R.R8))) - [| 0xe0uy; 0x80uy; 0x28uy; 0x5euy |] - - test32 (Condition.AL) Op.ADD None None None (* It used to be ADR *) - (ThreeOperands (OprReg R.R0, OprReg R.PC, OprImm 960L)) - [| 0xe2uy; 0x8fuy; 0x0fuy; 0xf0uy |] - - test32 (Condition.AL) Op.AND None None None - (FourOperands (OprReg R.R0, OprReg R.R0, OprReg R.R0, - OprShift (SRTypeLSL, Imm 0u))) - [| 0xe0uy; 0x00uy; 0x00uy; 0x00uy |] - - test32 (Condition.AL) Op.CMP None None None - (ThreeOperands (OprReg R.IP, OprReg R.R2, - OprShift (SRTypeROR, Imm 4u))) - [| 0xe1uy; 0x5cuy; 0x02uy; 0x62uy |] - - test32 (Condition.AL) Op.EORS None None None - (ThreeOperands (OprReg R.R1, OprReg R.R0, OprImm 252L)) - [| 0xe2uy; 0x30uy; 0x10uy; 0xfcuy |] - - test32 (Condition.AL) Op.MOVW None None None - (TwoOperands (OprReg R.SL, OprImm 15L)) - [| 0xe3uy; 0x00uy; 0xa0uy; 0x0fuy |] - - test32 (Condition.AL) Op.MOVS None None None - (TwoOperands (OprReg R.R8, OprReg R.IP)) - [| 0xe1uy; 0xb0uy; 0x80uy; 0x0cuy |] - - test32 (Condition.AL) Op.MVN None None None - (ThreeOperands (OprReg R.R0, OprReg R.SB, - OprRegShift (SRTypeLSL, R.R8))) - [| 0xe1uy; 0xe0uy; 0x08uy; 0x19uy |] - - test32 (Condition.AL) Op.TEQ None None None - (ThreeOperands (OprReg R.SL, OprReg R.R6, - OprRegShift (SRTypeLSL, R.IP))) - [| 0xe1uy; 0x3auy; 0x0cuy; 0x16uy |] - - test32 (Condition.AL) Op.TST None None None - (TwoOperands (OprReg R.R3, OprImm 4L)) - [| 0xe3uy; 0x13uy; 0x00uy; 0x04uy |] - - /// A4.4.2 Shift instructions - [] - member __.``[ARMv7] Shift Parse Test`` () = - test32 (Condition.AL) Op.LSLS None None None - (ThreeOperands (OprReg R.R0, OprReg R.R3, OprReg R.R1)) - [| 0xe1uy; 0xb0uy; 0x01uy; 0x13uy |] - - test32 (Condition.AL) Op.ROR None None None - (ThreeOperands (OprReg R.R0, OprReg R.R5, OprImm 28L)) - [| 0xe1uy; 0xa0uy; 0x0euy; 0x65uy |] - - /// A4.4.3 Multiply instructions - [] - member __.``[ARMv7] Multiply Parse Test`` () = - test32 (Condition.AL) Op.MULS None None None - (ThreeOperands (OprReg R.R0, OprReg R.SB, OprReg R.IP)) - [| 0xe0uy; 0x10uy; 0x0cuy; 0x99uy |] - - test32 (Condition.AL) Op.SMLABT None None None - (FourOperands (OprReg R.R0, OprReg R.R5, OprReg R.SL, - OprReg R.IP)) - [| 0xe1uy; 0x00uy; 0xcauy; 0xc5uy |] - - test32 (Condition.AL) Op.SMLALTT None None None - (FourOperands (OprReg R.R1, OprReg R.R0, OprReg R.R8, - OprReg R.R2)) - [| 0xe1uy; 0x40uy; 0x12uy; 0xe8uy |] - - test32 (Condition.AL) Op.SMUAD None None None - (ThreeOperands (OprReg R.R0, OprReg R.R2, OprReg R.R1)) - [| 0xe7uy; 0x00uy; 0xf1uy; 0x12uy |] - - test32 (Condition.AL) Op.SMULBB None None None - (ThreeOperands (OprReg R.R0, OprReg R.IP, OprReg R.LR)) - [| 0xe1uy; 0x60uy; 0x0euy; 0x8cuy |] - - /// A4.4.4 Saturating instructions - [] - member __.``[ARMv7] Saturating Parse Test`` () = - test32 (Condition.AL) Op.SSAT None None None - (FourOperands (OprReg R.R0, OprImm 29L, OprReg R.R2, - OprShift (SRTypeASR, Imm 7u))) - [| 0xe6uy; 0xbcuy; 0x03uy; 0xd2uy |] - - /// A4.4.5 Saturating addition and subtraction instructions - [] - member __.``[ARMv7] Saturating addition and subtraction Parse Test`` () = - test32 (Condition.AL) Op.QADD None None None - (ThreeOperands (OprReg R.R1, OprReg R.R2, OprReg R.R0)) - [| 0xe1uy; 0x00uy; 0x10uy; 0x52uy |] - - /// A4.4.6 Packing and unpacking instructions - [] - member __.``[ARMv7] Packing and unpacking Parse Test`` () = - test32 (Condition.AL) Op.PKHTB None None None - (FourOperands (OprReg R.R1, OprReg R.R0, OprReg R.R8, - OprShift (SRTypeASR, Imm 21u))) - [| 0xe6uy; 0x80uy; 0x1auy; 0xd8uy |] - - test32 (Condition.AL) Op.SXTAB None None None - (FourOperands (OprReg R.R1, OprReg R.R0, OprReg R.R0, - OprShift (SRTypeROR, Imm 24u))) - [| 0xe6uy; 0xa0uy; 0x1cuy; 0x70uy |] - - test32 (Condition.AL) Op.SXTH None None None - (ThreeOperands (OprReg R.R0, OprReg R.R3, - OprShift (SRTypeROR, Imm 0u))) - [| 0xe6uy; 0xbfuy; 0x00uy; 0x73uy |] - - /// A4.4.7 Parallel addition and subtraction instructions - [] - member __.``[ARMv7] Parallel addition and subtraction Parse Test`` () = - test32 (Condition.AL) Op.SASX None None None - (ThreeOperands (OprReg R.R1, OprReg R.R0, OprReg R.R7)) - [| 0xe6uy; 0x10uy; 0x1fuy; 0x37uy |] - - - /// A4.4.9 Miscellaneous data-processing instructions - [] - member __.``[ARMv7] Miscellaneous data-processing Parse Test`` () = - test32 (Condition.AL) Op.BFC None None None - (ThreeOperands (OprReg R.R0, OprImm 3L, OprImm 29L)) - [| 0xe7uy; 0xdfuy; 0x01uy; 0x9fuy |] - - test32 (Condition.AL) Op.BFI None None None - (FourOperands (OprReg R.R0, OprReg R.R0, OprImm 5L, - OprImm 6L)) - [| 0xe7uy; 0xcauy; 0x02uy; 0x90uy |] - - test32 (Condition.AL) Op.CLZ None None None - (TwoOperands (OprReg R.R0, OprReg R.R1)) - [| 0xe1uy; 0x6fuy; 0x0fuy; 0x11uy |] - - test32 (Condition.AL) Op.SBFX None None None - (FourOperands (OprReg R.R0, OprReg R.R2, OprImm 28L, - OprImm 3L)) - [| 0xe7uy; 0xa2uy; 0x0euy; 0x52uy |] - - /// A4.5 Status register access instructions - [] - type StatusOprRegAccessClass () = - [] - member __.``[ARMv7] Status register access Parse Test`` () = - test32 (Condition.AL) Op.MSR None None None - (TwoOperands (OprSpecReg (R.CPSR, Some PSRfs), OprImm 240L)) - [| 0xe3uy; 0x2cuy; 0xf0uy; 0xf0uy |] - - test32 (Condition.AL) Op.MSR None None None - (TwoOperands (OprSpecReg (R.CPSR, Some PSRfs), OprReg R.R2)) - [| 0xe1uy; 0x2cuy; 0xf0uy; 0x02uy |] - - test32 (Condition.UN) Op.CPSIE None None None - (TwoOperands (OprIflag AF, OprImm 2L)) - [| 0xf1uy; 0x0auy; 0x01uy; 0x42uy |] - - /// A4.6 Load/store instructions - [] - type LoadStoreClass () = - [] - member __.``[ARMv7] Load/store (Lord) Parse Test`` () = - test32 (Condition.AL) Op.LDR None None None - (TwoOperands (OprReg R.R0, - OprMemory (LiteralMode 15L))) - [| 0xe5uy; 0x9fuy; 0x00uy; 0x0fuy |] - - test32 (Condition.AL) Op.LDRH (Some true) None None - (TwoOperands (OprReg R.R1, - OprMemory (PostIdxMode - (RegOffset (R.R0, Some Plus, - R.IP, None))))) - [| 0xe0uy; 0x90uy; 0x10uy; 0xbcuy |] - - test32 (Condition.AL) Op.LDRB (Some false) None None - (TwoOperands (OprReg R.R1, - OprMemory (OffsetMode - (RegOffset (R.R0, Some Minus, R.R2, - Some (SRTypeASR, Imm 1u)))))) - [| 0xe7uy; 0x50uy; 0x10uy; 0xc2uy |] - - test32 (Condition.AL) Op.LDRSB (Some true) None None - (TwoOperands (OprReg R.R1, - OprMemory (PreIdxMode - (ImmOffset (R.R0, Some Minus, Some 195L))))) - [| 0xe1uy; 0x70uy; 0x1cuy; 0xd3uy |] - - [] - member __.``[ARMv7] Load/store (Store) Parse Test`` () = - test32 (Condition.AL) Op.STR (Some false) None None - (TwoOperands (OprReg R.R1, - OprMemory (OffsetMode - (ImmOffset (R.R0, Some Minus, Some 243L))))) - [| 0xe5uy; 0x00uy; 0x10uy; 0xf3uy |] - - test32 (Condition.AL) Op.STRB (Some true) None None - (TwoOperands (OprReg R.R1, - OprMemory (PostIdxMode - (RegOffset (R.R0, Some Minus, R.IP, - Some (SRTypeLSR,Imm 4u)))))) - [| 0xe6uy; 0x40uy; 0x12uy; 0x2cuy |] - - test32 (Condition.AL) Op.STRD (Some true) None None - (ThreeOperands (OprReg R.IP, OprReg R.SP, - OprMemory (PreIdxMode - (RegOffset (R.R0, Some Plus, - R.R8, None))))) - [| 0xe1uy; 0xa0uy; 0xc0uy; 0xf8uy |] - - [] - member __.``[ARMv7] Load/store (Load unprivileged) Parse Test`` () = - test32 (Condition.AL) Op.LDRSHT None None None - (TwoOperands (OprReg R.LR, - OprMemory (PostIdxMode - (ImmOffset (R.R0, Some Minus, Some 14L))))) - [| 0xe0uy; 0x70uy; 0xe0uy; 0xfeuy |] - - [] - member __.``[ARMv7] Load/store (Store unprivileged) Parse Test`` () = - test32 (Condition.AL) Op.STRT None None None - (TwoOperands (OprReg R.R1, - OprMemory (PostIdxMode - (ImmOffset (R.R0, Some Plus, Some 15L))))) - [| 0xe4uy; 0xa0uy; 0x10uy; 0x0fuy |] - - test32 (Condition.AL) Op.STRHT None None None - (TwoOperands (OprReg R.R1, - OprMemory (PostIdxMode - (RegOffset (R.R0, Some Minus, - R.R4, None))))) - [| 0xe0uy; 0x20uy; 0x10uy; 0xb4uy |] - - [] - member __.``[ARMv7] Load/store (Load-Exclusive) Parse Test`` () = - test32 (Condition.AL) Op.LDREX None None None - (TwoOperands (OprReg R.LR, - OprMemory (OffsetMode (ImmOffset (R.R0, None, None))))) - [| 0xe1uy; 0x90uy; 0xefuy; 0x9fuy |] - - [] - member __.``[ARMv7] Load/store (Store-Exclusive) Parse Test`` () = - test32 (Condition.AL) Op.STREXD None None None - (FourOperands (OprReg R.R1, OprReg R.R2, OprReg R.R3, - OprMemory (OffsetMode (ImmOffset (R.R0, None, None))))) - [| 0xe1uy; 0xa0uy; 0x1fuy; 0x92uy |] - - /// A4.7 Load/store multiple instructions - [] - type LoadStoreMultipleClass () = - [] - member __.``[ARMv7] Load/store multiple Parse Test`` () = - test32 (Condition.AL) Op.LDMDA (Some false) None None - (TwoOperands (OprReg R.R0, - OprRegList [ R.R2; R.R3; R.R8; R.SB; R.SL; R.FP ])) - [| 0xe8uy; 0x10uy; 0x0fuy; 0x0cuy |] - - test32 (Condition.AL) Op.LDMDA (Some true) None None - (TwoOperands (OprReg R.R0, - OprRegList [ R.R2; R.R3; R.R8; R.SB; R.SL; R.FP ])) - [| 0xe8uy; 0x30uy; 0x0fuy; 0x0cuy |] - - test32 (Condition.AL) Op.POP None None None - (OneOperand (OprRegList [ R.R0; R.R1; R.R2; R.R3 ])) - [| 0xe8uy; 0xbduy; 0x00uy; 0x0fuy |] - - (* test32 (Condition.AL) Op.STR (Some true) None None - (TwoOperands (OprReg R.R0, - OprMemory (PreIdxMode (ImmOffset (R.SP, Some Minus, Some 4L))))) - [| 0xe5uy; 0x2duy; 0x00uy; 0x04uy |] *) - - test32 (Condition.AL) Op.PUSH (Some true) None None - (OneOperand (OprRegList [ R.R0 ])) - [| 0xe5uy; 0x2duy; 0x00uy; 0x04uy |] - - test32 (Condition.AL) Op.STMIA None None None - (TwoOperands (OprReg R.SB, OprRegList [ R.SP; R.LR; R.PC ])) - [| 0xe8uy; 0xc9uy; 0xe0uy; 0x00uy |] - - /// A4.8 Miscellaneous instructions - [] - type MiscellaneousClass () = - [] - member __.``[ARMv7] Miscellaneous Parse Test`` () = - test32 (Condition.UN) Op.CLREX None None None (NoOperand) - [| 0xf5uy; 0x7fuy; 0xf0uy; 0x1fuy |] - - test32 (Condition.UN) Op.DMB None None None - (OneOperand (OprOption BarrierOption.SY)) - [| 0xf5uy; 0x7fuy; 0xf0uy; 0x5fuy |] - - test32 (Condition.AL) Op.NOP None None None NoOperand - [| 0xe3uy; 0x20uy; 0xf0uy; 0x00uy |] - - test32 (Condition.UN) Op.PLD None None None - (OneOperand (OprMemory (LiteralMode -3840L))) - [| 0xf5uy; 0x5fuy; 0xffuy; 0x00uy |] - - test32 (Condition.UN) Op.PLDW None None None - (OneOperand (OprMemory (OffsetMode - (RegOffset (R.R0, Some Plus, R.R0, - Some (SRTypeASR, Imm 3u)))))) - [| 0xf7uy; 0x90uy; 0xf1uy; 0xc0uy |] - - test32 (Condition.UN) Op.PLI None None None - (OneOperand (OprMemory (LiteralMode -240L))) - [| 0xf4uy; 0x50uy; 0xf0uy; 0xf0uy |] - - test32 (Condition.UN) Op.SETEND None None None - (OneOperand (OprEndian Endian.Big)) - [| 0xf1uy; 0x01uy; 0x02uy; 0x00uy |] - - /// Only ARMv7 - test32 (Condition.AL) Op.SWP None None None - (ThreeOperands (OprReg R.IP, OprReg R.LR, - OprMemory (OffsetMode - (ImmOffset (R.R0, None, None))))) - [| 0xe1uy; 0x00uy; 0xc0uy; 0x9euy |] - - /// A4.9 Exception-generating and exception-handling instructions - [] - type ExcepGenAndExcepHandlClass () = - [] - member __.``[ARMv7] Exception-gen and exception-handling Parse Test`` () = - test32 Condition.UN Op.BKPT None None None - (OneOperand (OprImm 3852L)) - [| 0xe1uy; 0x20uy; 0xf0uy; 0x7cuy |] - - test32 (Condition.AL) Op.SMC None None None - (OneOperand (OprImm 15L)) - [| 0xe1uy; 0x60uy; 0x00uy; 0x7fuy |] - - test32 (Condition.UN) Op.RFEIB (Some true) None None - (OneOperand (OprReg R.IP)) - [| 0xf9uy; 0xbcuy; 0x0auy; 0x00uy |] - - test32 (Condition.UN) Op.SRSDB (Some true) None None - (TwoOperands (OprReg R.SP, OprImm 4L)) - [| 0xf9uy; 0x6duy; 0x05uy; 0x04uy |] - - /// A4.10 Co-processor instructions - [] - type CoprocessorClass () = - [] - member __.``[ARMv7] Co-processor Parse Test`` () = - /// Only ARMv7 - test32 (Condition.AL) Op.CDP None None None - (SixOperands (OprReg R.P3, OprImm 0L, OprReg R.C2, - OprReg R.C1, OprReg R.C8, OprImm 7L)) - [| 0xeeuy; 0x01uy; 0x23uy; 0xe8uy |] - - test32 (Condition.AL) Op.MCRR None None None - (FiveOperands (OprReg R.P15, OprImm 14L, OprReg R.R1, - OprReg R.R0, OprReg R.C3)) - [| 0xecuy; 0x40uy; 0x1fuy; 0xe3uy |] - - test32 (Condition.AL) Op.MRC None None None - (SixOperands (OprReg R.P14, OprImm 4L, OprReg R.SB, - OprReg R.C14, OprReg R.C2, OprImm 1L)) - [| 0xeeuy; 0x9euy; 0x9euy; 0x32uy |] - - test32 (Condition.AL) Op.LDC (Some false) None None - (ThreeOperands (OprReg R.P14, OprReg R.C5, - OprMemory (LiteralMode 192L))) - [| 0xeduy; 0x9fuy; 0x5euy; 0x30uy |] - - test32 (Condition.AL) Op.LDC None None None - (ThreeOperands (OprReg R.P14, OprReg R.C5, - OprMemory (UnIdxMode (R.R0, 128L)))) - [| 0xecuy; 0x90uy; 0x5euy; 0x80uy |] - - /// A4.11 Advanced SIMD and Floating-point load/store instructions - [] - type AdvSIMDAndFPLoadStoreClass () = - /// A4.11.1 Element and structure load/store instructions - [] - member __.``[ARMv7] Element and structure load/store Parse Test`` () = - test32 (Condition.UN) Op.VLD4 (Some true) None - (Some (OneDT SIMDTyp16)) - (TwoOperands - (OprSIMD (FourRegs (Scalar (R.D18, None), Scalar (R.D20, None), - Scalar (R.D22, None), Scalar (R.D24, None))), - OprMemory (PostIdxMode - (AlignOffset (R.R0, Some 64L, - Some R.R0))))) - [| 0xf4uy; 0xe0uy; 0x2fuy; 0x70uy |] - - test32 (Condition.UN) Op.VST1 (Some true) None - (Some (OneDT SIMDTyp32)) - (TwoOperands (OprSIMD (ThreeRegs (Vector R.D12, Vector R.D13, - Vector R.D14)), - OprMemory (PostIdxMode - (AlignOffset (R.R2, Some 64L, - Some R.R0))))) - [| 0xf4uy; 0x02uy; 0xc6uy; 0x90uy |] - - test32 (Condition.UN) Op.VST3 (Some true) None - (Some (OneDT SIMDTyp32)) - (TwoOperands - (OprSIMD (ThreeRegs (Scalar (R.D14, Some 1uy), - Scalar (R.D16, Some 1uy), - Scalar (R.D18, Some 1uy))), - OprMemory (PostIdxMode (RegOffset (R.LR, None, R.R3, None))))) - [| 0xf4uy; 0x8euy; 0xeauy; 0xc3uy |] - - /// A4.12 Advanced SIMD and Floating-point register transfer instructions - [] - type AdvSIMDAndFPRegTransClass () = - [] - member __.``[ARMv7] Advanced SIMD and FP register transfer Parse Test`` () = - test32 (Condition.AL) Op.VDUP None None (Some (OneDT SIMDTyp16)) - (TwoOperands (OprSIMD (SFReg (Vector R.D18)), OprReg R.LR)) - [| 0xeeuy; 0x82uy; 0xebuy; 0xb0uy |] - - test32 (Condition.AL) Op.VMOV None None (Some (OneDT SIMDTyp8)) - (TwoOperands (OprSIMD (SFReg (Scalar (R.D18, Some 1uy))), - OprReg R.IP)) - [| 0xeeuy; 0x42uy; 0xcbuy; 0xb0uy |] - - test32 (Condition.AL) Op.VMOV None None (Some (OneDT SIMDTypS16)) - (TwoOperands (OprReg R.R8, - OprSIMD (SFReg (Scalar (R.D16, Some 0uy))))) - [| 0xeeuy; 0x10uy; 0x8buy; 0xb0uy |] - - /// A4.13 Advanced SIMD data-processing instructions - [] - type AdvSIMDDataProcessingClass () = - /// A4.13.1 Advanced SIMD parallel addition and subtraction - [] - member __.``[ARMv7] Advanced SIMD parallel add and sub Parse Test`` () = - test32 (Condition.UN) Op.VADDW None None - (Some (OneDT SIMDTypS8)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q14)), - OprSIMD (SFReg (Vector R.Q8)), - OprSIMD (SFReg (Vector R.D10)))) - [| 0xf2uy; 0xc0uy; 0xc1uy; 0x8auy |] - - test32 (Condition.UN) Op.VHSUB None None - (Some (OneDT SIMDTypU32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D1)), - OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.D28)))) - [| 0xf3uy; 0x20uy; 0x12uy; 0x2cuy |] - - test32 (Condition.UN) Op.VPADDL None None - (Some (OneDT SIMDTypU8)) - (TwoOperands (OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.D14)))) - [| 0xf3uy; 0xb0uy; 0x02uy; 0x8euy |] - - test32 (Condition.UN) Op.VSUBHN None None - (Some (OneDT SIMDTypI32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D12)), - OprSIMD (SFReg (Vector R.Q8)), - OprSIMD (SFReg (Vector R.Q1)))) - [| 0xf2uy; 0x90uy; 0xc6uy; 0x82uy |] - - /// A4.13.2 Bitwise Advanced SIMD data-processing instructions - [] - member __.``[ARMv7] Bitwise Advanced SIMD data-processing Parse Test`` () = - test32 (Condition.UN) Op.VAND None None None - (ThreeOperands (OprSIMD (SFReg (Vector R.Q14)), - OprSIMD (SFReg (Vector R.Q9)), - OprSIMD (SFReg (Vector R.Q12)))) - [| 0xf2uy; 0x42uy; 0xc1uy; 0xf8uy |] - - test32 (Condition.UN) Op.VBIC None None - (Some (OneDT SIMDTypI32)) - (TwoOperands (OprSIMD (SFReg (Vector R.Q15)), OprImm 0x9B0000L)) - [| 0xf3uy; 0xc1uy; 0xe5uy; 0x7buy |] - - test32 (Condition.AL) Op.VMOV None None None - (TwoOperands (OprReg R.IP, OprSIMD (SFReg (Vector R.S4)))) - [| 0xeeuy; 0x12uy; 0xcauy; 0x10uy |] - - /// A4.13.3 Advanced SIMD comparison instructions - [] - member __.``[ARMv7] Advanced SIMD comparison Parse Test`` () = - test32 (Condition.UN) Op.VCEQ None None - (Some (OneDT SIMDTypF32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q12)), - OprSIMD (SFReg (Vector R.Q6)), - OprSIMD (SFReg (Vector R.Q0)))) - [| 0xf2uy; 0x4cuy; 0x8euy; 0x40uy |] - - /// A4.13.4 Advanced SIMD shift instructions - [] - member __.``[ARMv7] Advanced SIMD shift Parse Test`` () = - test32 (Condition.UN) Op.VQRSHRN None None - (Some (OneDT SIMDTypU64)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.Q0)), OprImm 32L)) - [| 0xf3uy; 0xa0uy; 0x09uy; 0x50uy |] - - test32 (Condition.UN) Op.VQSHRUN None None - (Some (OneDT SIMDTypS64)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.Q8)), OprImm 8L)) - [| 0xf3uy; 0xb8uy; 0x08uy; 0x30uy |] - - test32 (Condition.UN) Op.VSHL None None - (Some (OneDT SIMDTypI64)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q1)), - OprSIMD (SFReg (Vector R.Q4)), OprImm 56L)) - [| 0xf2uy; 0xb8uy; 0x25uy; 0xd8uy |] - - test32 (Condition.UN) Op.VSHRN None None - (Some (OneDT SIMDTypI64)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.Q9)), OprImm 32L)) - [| 0xf2uy; 0xa0uy; 0x08uy; 0x32uy |] - - test32 (Condition.UN) Op.VSRA None None - (Some (OneDT SIMDTypU64)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q8)), - OprSIMD (SFReg (Vector R.Q8)), OprImm 24L)) - [| 0xf3uy; 0xe8uy; 0x01uy; 0xf0uy |] - - test32 (Condition.UN) Op.VSRI None None - (Some (OneDT SIMDTyp32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D9)), - OprSIMD (SFReg (Vector R.D26)), OprImm 7L)) - [| 0xf3uy; 0xb9uy; 0x94uy; 0x3auy |] - - /// A4.13.5 Advanced SIMD multiply instructions - [] - member __.``[ARMv7] Advanced SIMD multiply Parse Test`` () = - test32 (Condition.UN) Op.VMLSL None None - (Some (OneDT SIMDTypU32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q1)), - OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.D24)))) - [| 0xf3uy; 0xa0uy; 0x2auy; 0x28uy |] - - test32 (Condition.AL) Op.VMUL None None (Some (OneDT SIMDTypF32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.S4)), - OprSIMD (SFReg (Vector R.S1)), - OprSIMD (SFReg (Vector R.S17)))) - [| 0xeeuy; 0x20uy; 0x2auy; 0xa8uy |] - - test32 (Condition.UN) Op.VMULL None None - (Some (OneDT SIMDTypS8)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q12)), - OprSIMD (SFReg (Vector R.D18)), - OprSIMD (SFReg (Vector R.D16)))) - [| 0xf2uy; 0xc2uy; 0x8cuy; 0xa0uy |] - - test32 (Condition.UN) Op.VMULL None None - (Some (OneDT SIMDTypU32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q10)), - OprSIMD (SFReg (Vector R.D2)), - OprSIMD (SFReg (Scalar (R.D10, Some 0uy))))) - [| 0xf3uy; 0xe2uy; 0x4auy; 0x4auy |] - - test32 (Condition.UN) Op.VQDMULH None None - (Some (OneDT SIMDTypS16)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q9)), - OprSIMD (SFReg (Vector R.Q8)), - OprSIMD (SFReg (Scalar (R.D0, Some 3uy))))) - [| 0xf3uy; 0xd0uy; 0x2cuy; 0xe8uy |] - - /// A4.13.6 Miscellaneous Advanced SIMD data-processing instructions - [] - member __.``[ARMv7] Misc Advanced SIMD data-processing Parse Test`` () = - test32 (Condition.UN) Op.VCVT None None - (Some (TwoDT (SIMDTypU32, SIMDTypF32))) - (ThreeOperands (OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.D16)), OprImm 22L)) - [| 0xf3uy; 0xaauy; 0x0fuy; 0x30uy |] - - test32 (Condition.AL) Op.VCVT None None - (Some (TwoDT (SIMDTypU16, SIMDTypF64))) - (ThreeOperands (OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.D0)), OprImm 11L)) - [| 0xeeuy; 0xbfuy; 0x0buy; 0x62uy |] - - test32 (Condition.UN) Op.VCNT None None - (Some (OneDT SIMDTyp8)) - (TwoOperands (OprSIMD (SFReg (Vector R.Q13)), - OprSIMD (SFReg (Vector R.Q15)))) - [| 0xf3uy; 0xf0uy; 0xa5uy; 0x6euy |] - - test32 (Condition.UN) Op.VEXT None None - (Some (OneDT SIMDTyp8)) - (FourOperands (OprSIMD (SFReg (Vector R.Q0)), - OprSIMD (SFReg (Vector R.Q8)), - OprSIMD (SFReg (Vector R.Q7)), OprImm 3L)) - [| 0xf2uy; 0xb0uy; 0x03uy; 0xceuy |] - - test32 (Condition.AL) Op.VNEG None None (Some (OneDT SIMDTypF64)) - (TwoOperands (OprSIMD (SFReg (Vector R.D16)), - OprSIMD (SFReg (Vector R.D18)))) - [| 0xeeuy; 0xf1uy; 0x0buy; 0x62uy |] - - test32 (Condition.UN) Op.VPMAX None None - (Some (OneDT SIMDTypF32)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D25)), - OprSIMD (SFReg (Vector R.D0)), - OprSIMD (SFReg (Vector R.D15)))) - [| 0xf3uy; 0x40uy; 0x9fuy; 0x0fuy |] - - test32 (Condition.UN) Op.VREV32 None None - (Some (OneDT SIMDTyp16)) - (TwoOperands (OprSIMD (SFReg (Vector R.Q0)), - OprSIMD (SFReg (Vector R.Q1)))) - [| 0xf3uy; 0xb4uy; 0x00uy; 0xc2uy |] - - test32 (Condition.UN) Op.VTBX None None - (Some (OneDT SIMDTyp8)) - (ThreeOperands (OprSIMD (SFReg (Vector R.D5)), - OprSIMD (FourRegs (Vector R.D3, Vector R.D4, - Vector R.D5, Vector R.D6)), - OprSIMD (SFReg (Vector R.D3)))) - [| 0xf3uy; 0xb3uy; 0x5buy; 0x43uy |] - - /// A4.14 Floating-point data-processing instructions - [] - type FPDataProcessingClass () = - [] - member __.``[ARMv7] Floating-point data-processing Parse Test`` () = - test32 (Condition.AL) Op.VCMPE None None (Some (OneDT SIMDTypF64)) - (TwoOperands (OprSIMD (SFReg (Vector R.D0)), OprImm 0L)) - [| 0xeeuy; 0xb5uy; 0x0buy; 0xc0uy |] - - test32 (Condition.AL) Op.VCVT None None - (Some (TwoDT (SIMDTypF32, SIMDTypU32))) - (TwoOperands (OprSIMD (SFReg (Vector R.S4)), - OprSIMD (SFReg (Vector R.S17)))) - [| 0xeeuy; 0xb8uy; 0x2auy; 0x68uy |] - - test32 (Condition.AL) Op.VCVTB None None - (Some (TwoDT (SIMDTypF16, SIMDTypF32))) - (TwoOperands (OprSIMD (SFReg (Vector R.S0)), - OprSIMD (SFReg (Vector R.S6)))) - [| 0xeeuy; 0xb3uy; 0x0auy; 0x43uy |] - - test32 (Condition.AL) Op.VMOV None None (Some (OneDT SIMDTypF32)) - (TwoOperands (OprSIMD (SFReg (Vector R.S6)), OprImm 1091567616L)) - [| 0xeeuy; 0xb2uy; 0x3auy; 0x02uy |] - - test32 (Condition.UN) Op.VMLS None None - (Some (OneDT SIMDTypI16)) - (ThreeOperands (OprSIMD (SFReg (Vector R.Q14)), - OprSIMD (SFReg (Vector R.Q1)), - OprSIMD (SFReg (Scalar (R.D0, Some 2uy))))) - [| 0xf3uy; 0xd2uy; 0xc4uy; 0x60uy |] - -module ARM64 = - open B2R2.FrontEnd.BinLifter.ARM64 - open B2R2.FrontEnd.BinLifter.ARM64.OperandHelper - - let private test endian opcode oprs bytes = - let reader = - if endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - let span = System.ReadOnlySpan bytes - let ins = Parser.parse span reader 0UL - let opcode' = ins.Info.Opcode - let oprs' = ins.Info.Operands - Assert.AreEqual (opcode', opcode) - Assert.AreEqual (oprs', oprs) - - let private test64 = test Endian.Big - - /// C4.2 Data processing - immediate - [] - type DataProcessingImmClass () = - /// C4.2.1 Add/subtract (immediate) - [] - member __.``[AArch64] Add/subtract (immedate) Parse Test`` () = - test64 Opcode.ADD (FourOperands (OprRegister R.W26, - OprRegister R.W5, - Immediate 0x371L, - Shift (SRTypeLSL, Imm 12L))) - [| 0x11uy; 0x4duy; 0xc4uy; 0xbauy |] - - /// C4.2.2 Bit Field - [] - member __.``[AArch64] Bitfield Parse Test`` () = - test64 Opcode.SBFX (FourOperands (OprRegister R.W1, - OprRegister R.W0, - Immediate 0x1L, - Immediate 0x1L)) - [| 0x13uy; 0x01uy; 0x04uy; 0x01uy |] - - /// C4.2.3 Extract - [] - member __.``[AArch64] Extract Parse Test`` () = - test64 Opcode.EXTR (FourOperands (OprRegister R.X2, - OprRegister R.X1, - OprRegister R.X0, - LSB 0x1uy)) - [| 0x93uy; 0xc0uy; 0x04uy; 0x22uy |] - - /// C4.2.4 Logical (immediate) - [] - member __.``[AArch64] Logical (immedate) Parse Test`` () = - test64 Opcode.AND (ThreeOperands (OprRegister R.W1, - OprRegister R.W0, - Immediate 0x80000001L)) - [| 0x12uy; 0x01uy; 0x04uy; 0x01uy |] - - test64 Opcode.AND (ThreeOperands (OprRegister R.W1, - OprRegister R.W0, - Immediate 0xE0000001L)) - [| 0x12uy; 0x03uy; 0x0cuy; 0x01uy |] - - test64 Opcode.AND (ThreeOperands (OprRegister R.W1, - OprRegister R.W0, - Immediate 0x3L)) - [| 0x12uy; 0x20uy; 0x04uy; 0x01uy |] - - test64 Opcode.AND (ThreeOperands (OprRegister R.W1, - OprRegister R.W1, - Immediate 0xffffffdfL)) - [| 0x12uy; 0x1auy; 0x78uy; 0x21uy |] - - test64 Opcode.AND (ThreeOperands (OprRegister R.X1, - OprRegister R.X0, - Immediate 0x300000003L)) - [| 0x92uy; 0x20uy; 0x04uy; 0x01uy |] - - /// C4.2.5 Move wide (immediate) - [] - member __.``[AArch64] Move wide (immediate) Parse Test`` () = - test64 Opcode.MOVN (ThreeOperands (OprRegister R.X21, Immediate 0x0L, - Shift (SRTypeLSL, Imm 0x10L))) - [| 0x92uy; 0xa0uy; 0x00uy; 0x15uy |] - - test64 Opcode.MOV (TwoOperands (OprRegister R.XZR, - Immediate 0XE002FFFFFFFFFFFFL)) - [| 0x92uy; 0xe3uy; 0xffuy; 0xbfuy |] (* Alias of MOVN *) - - test64 Opcode.MOV (TwoOperands (OprRegister R.W26, Immediate 0x7FFFFFFFL)) - [| 0x12uy; 0xb0uy; 0x00uy; 0x1auy |] (* Alias of MOVN *) - - /// C4.2.6 PC-rel. addressing - [] - member __.``[AArch64] PC-rel. addressing Parse Test`` () = - test64 Opcode.ADR (TwoOperands (OprRegister R.X7, memLabel 0xffe0fL)) - [| 0x70uy; 0x7fuy; 0xf0uy; 0x67uy |] - - /// C4.3 Branches, exception generating and system instructions - [] - type BranchesAndExcepGenAndSystemClass () = - /// C4.3.1 Compare & branch (immediate) - [] - member __.``[AArch64] Compare & branch Parse Test`` () = - test64 Opcode.CBZ (TwoOperands (OprRegister R.X3, memLabel 0x8204L)) - [| 0xb4uy; 0x04uy; 0x10uy; 0x23uy |] - - /// C4.3.2 Conditional branch (immediate) - [] - member __.``[AArch64] Conditional branch (immediate) Parse Test`` () = - test64 Opcode.BNE (OneOperand (memLabel 0x4L)) - [| 0x54uy; 0x00uy; 0x00uy; 0x21uy |] - - /// C4.3.3 Exception generation - [] - member __.``[AArch64] Exception generation Parse Test`` () = - test64 Opcode.SVC (OneOperand (Immediate 0x3L)) - [| 0xd4uy; 0x00uy; 0x00uy; 0x61uy |] - - /// C4.3.4 System - [] - member __.``[AArch64] System Parse Test`` () = - test64 Opcode.MSR (TwoOperands (Pstate SPSEL, Immediate 0x2L)) - [| 0xd5uy; 0x00uy; 0x42uy; 0xbfuy |] - - test64 Opcode.MSR (TwoOperands (Pstate DAIFSET, Immediate 0x2L)) - [| 0xd5uy; 0x03uy; 0x42uy; 0xdfuy |] - - test64 Opcode.HINT (OneOperand (Immediate 0x6L)) - [| 0xd5uy; 0x03uy; 0x20uy; 0xdfuy |] - - test64 Opcode.SEVL NoOperand - [| 0xd5uy; 0x03uy; 0x20uy; 0xbfuy |] - - test64 Opcode.DC (TwoOperands (SysOpr (DCOpr ZVA), OprRegister R.X3)) - [| 0xd5uy; 0x0buy; 0x74uy; 0x23uy |] - - test64 Opcode.SYSL (FiveOperands (OprRegister R.X24, - Immediate 0L, OprRegister R.C15, - OprRegister R.C4, Immediate 6L)) - [| 0xd5uy; 0x28uy; 0xf4uy; 0xd8uy |] - - test64 Opcode.MSR (TwoOperands (OprRegister (R.HPFAREL2), - OprRegister R.X0)) - [| 0xd5uy; 0x1cuy; 0x60uy; 0x80uy |] - - test64 Opcode.MSR (TwoOperands (OprRegister (R.ACTLREL1), - OprRegister R.X0)) - [| 0xd5uy; 0x18uy; 0x10uy; 0x20uy |] - - test64 Opcode.MRS (TwoOperands (OprRegister R.X0, - OprRegister (R.ACTLREL1))) - [| 0xd5uy; 0x38uy; 0x10uy; 0x20uy |] - - /// C4.3.5 Test & branch (immediate) - [] - member __.``[AArch64] Test & branch (immediate) Parse Test`` () = - test64 Opcode.TBZ (ThreeOperands (OprRegister R.X3, - Immediate 0x21L, memLabel 0x8L)) - [| 0xb6uy; 0x08uy; 0x00uy; 0x43uy |] - - /// C4.3.6 Unconditional branch (immediate) - [] - member __.``[AArch64] Unconditional branch (immediate) Parse Test`` () = - test64 Opcode.B (OneOperand (memLabel 0x20a824L)) - [| 0x14uy; 0x08uy; 0x2auy; 0x09uy |] - - /// C4.3.7 Unconditional branch (register) - [] - member __.``[AArch64] Unconditional branch (register) Parse Test`` () = - test64 Opcode.BR (OneOperand (OprRegister R.XZR)) - [| 0xd6uy; 0x1fuy; 0x03uy; 0xe0uy |] - - /// C4.4 Loads and stores - [] - type LoadAndStoreClass () = - /// C4.4.1 Advanced SIMD load/store multiple structures - [] - member __.``[AArch64] Adv SIMD ld/st multiple structures Parse Test`` () = - test64 Opcode.ST4 (TwoOperands (SIMDOpr (FourRegs (SIMDVecReg (R.V5, EightB), - SIMDVecReg (R.V6, EightB), - SIMDVecReg (R.V7, EightB), - SIMDVecReg (R.V8, EightB))), - memBaseImm (R.X14, None))) - [| 0x0cuy; 0x00uy; 0x01uy; 0xc5uy |] - - test64 Opcode.ST2 (TwoOperands (SIMDOpr (TwoRegs (SIMDVecReg (R.V24, EightB), - SIMDVecReg (R.V25, EightB))), - memBaseImm (R.X15, None))) - [| 0x0cuy; 0x00uy; 0x81uy; 0xf8uy |] - - test64 Opcode.LD1 (TwoOperands (SIMDOpr (FourRegs (SIMDVecReg (R.V29, OneD), - SIMDVecReg (R.V30, OneD), - SIMDVecReg (R.V31, OneD), - SIMDVecReg (R.V0, OneD))), - memBaseImm (R.X25, None))) - [| 0x0cuy; 0x40uy; 0x2fuy; 0x3duy |] - - /// C4.4.2 Advanced SIMD load/store multiple structures (post-indexed) - [] - member __.``[AArch64] Adv SIMD ld/st mul struct (post-idx) Parse Test`` () = - test64 Opcode.ST4 (TwoOperands (SIMDOpr (FourRegs (SIMDVecReg (R.V1, FourH), - SIMDVecReg (R.V2, FourH), - SIMDVecReg (R.V3, FourH), - SIMDVecReg (R.V4, FourH))), - memPostIdxReg (R.X1, R.X0, None))) - [| 0x0cuy; 0x80uy; 0x04uy; 0x21uy |] - - test64 Opcode.ST4 (TwoOperands (SIMDOpr (FourRegs (SIMDVecReg (R.V25, FourH), - SIMDVecReg (R.V26, FourH), - SIMDVecReg (R.V27, FourH), - SIMDVecReg (R.V28, FourH))), - memPostIdxReg (R.X9, R.X21, None))) - [| 0x0cuy; 0x95uy; 0x05uy; 0x39uy |] - - test64 Opcode.ST4 (TwoOperands (SIMDOpr (FourRegs (SIMDVecReg (R.V4, EightH), - SIMDVecReg (R.V5, EightH), - SIMDVecReg (R.V6, EightH), - SIMDVecReg (R.V7, EightH))), - memPostIdxImm (R.X20, Some 0x40L))) - [| 0x4cuy; 0x9fuy; 0x06uy; 0x84uy |] - - test64 Opcode.LD3 (TwoOperands (SIMDOpr (ThreeRegs (SIMDVecReg (R.V30, EightH), - SIMDVecReg (R.V31, EightH), - SIMDVecReg (R.V0, EightH))), - memPostIdxReg (R.X21, R.X10, None))) - [| 0x4cuy; 0xcauy; 0x46uy; 0xbeuy |] - - test64 Opcode.LD4 (TwoOperands (SIMDOpr (FourRegs (SIMDVecReg (R.V4, EightH), - SIMDVecReg (R.V5, EightH), - SIMDVecReg (R.V6, EightH), - SIMDVecReg (R.V7, EightH))), - memPostIdxImm (R.X20, Some 0x40L))) - [| 0x4cuy; 0xdfuy; 0x06uy; 0x84uy |] - - /// C4.4.3 Advanced SIMD load/store single structure - [] - member __.``[AArch64] Adv SIMD load/store single structure Parse Test`` () = - test64 Opcode.ST1 (TwoOperands (SIMDOpr (OneReg (sVRegIdx R.V30 VecB 5uy)), - memBaseImm (R.X3, None))) - [| 0x0duy; 0x00uy; 0x14uy; 0x7euy |] - - test64 Opcode.ST3 (TwoOperands (SIMDOpr (ThreeRegs (sVRegIdx R.V3 VecB 1uy, - sVRegIdx R.V4 VecB 1uy, - sVRegIdx R.V5 VecB 1uy)), - memBaseImm (R.X14, None))) - [| 0x0duy; 0x00uy; 0x25uy; 0xc3uy |] - - test64 Opcode.ST4 (TwoOperands (SIMDOpr (FourRegs (sVRegIdx R.V29 VecS 3uy, - sVRegIdx R.V30 VecS 3uy, - sVRegIdx R.V31 VecS 3uy, - sVRegIdx R.V0 VecS 3uy)), - memBaseImm (R.X21, None))) - [| 0x4duy; 0x20uy; 0xb2uy; 0xbduy |] - - test64 Opcode.LD2 (TwoOperands (SIMDOpr (TwoRegs (sVRegIdx R.V10 VecB 0xfuy, - sVRegIdx R.V11 VecB 0xfuy)), - memBaseImm (R.X10, None))) - [| 0x4duy; 0x60uy; 0x1duy; 0x4auy |] - - test64 Opcode.LD3R (TwoOperands (SIMDOpr (ThreeRegs (SIMDVecReg (R.V21, EightH), - SIMDVecReg (R.V22, EightH), - SIMDVecReg (R.V23, - EightH))), - memBaseImm (R.X21, None))) - [| 0x4duy; 0x40uy; 0xe6uy; 0xb5uy |] - - /// C4.4.4 Advanced SIMD load/store single structure (post-indexed) - [] - member __.``[AArch64] Adv SIMD ld/st sgl struct (post-idx) Parse Test`` () = - test64 Opcode.ST1 (TwoOperands (SIMDOpr (OneReg (sVRegIdx R.V30 VecB 1uy)), - memPostIdxReg (R.X21, R.X10, None))) - [| 0x0duy; 0x8auy; 0x06uy; 0xbeuy |] - - test64 Opcode.ST1 (TwoOperands (SIMDOpr (OneReg (sVRegIdx R.V30 VecH 7uy)), - memPostIdxImm (R.X11, Some 0x2L))) - [| 0x4duy; 0x9fuy; 0x59uy; 0x7euy |] - - test64 Opcode.ST2 (TwoOperands (SIMDOpr (TwoRegs (sVRegIdx R.V29 VecS 2uy, - sVRegIdx R.V30 VecS 2uy)), - memPostIdxReg (R.X13, R.X21, None))) - [| 0x4duy; 0xb5uy; 0x81uy; 0xbduy |] - - test64 Opcode.LD1 (TwoOperands (SIMDOpr (OneReg (sVRegIdx R.V30 VecB 1uy)), - memPostIdxReg (R.X21, R.X10, None))) - [| 0x0duy; 0xcauy; 0x06uy; 0xbeuy |] - - test64 Opcode.LD4 (TwoOperands (SIMDOpr (FourRegs (sVRegIdx R.V29 VecB 0xeuy, - sVRegIdx R.V30 VecB 0xeuy, - sVRegIdx R.V31 VecB 0xeuy, - sVRegIdx R.V0 VecB 0xeuy)), - memPostIdxImm (R.X15, Some 0x4L))) - [| 0x4duy; 0xffuy; 0x39uy; 0xfduy |] - - /// C4.4.5 Load register (literal) - [] - member __.``[AArch64] Load register (literal) Parse Test`` () = - test64 Opcode.LDR (TwoOperands (OprRegister R.X9, memLabel 0xa6388L)) - [| 0x58uy; 0x53uy; 0x1cuy; 0x49uy |] - - test64 Opcode.LDRSW (TwoOperands (OprRegister R.X30, - memLabel 0xfffffffffff00000L)) - [| 0x98uy; 0x80uy; 0x00uy; 0x1euy |] - - test64 Opcode.PRFM (TwoOperands (PrfOp PLIL2STRM, memLabel 0x1004L)) - [| 0xd8uy; 0x00uy; 0x80uy; 0x2buy |] - - /// C4.4.6 Load/store exclusive - [] - member __.``[AArch64] Load/store exclusive Parse Test`` () = - test64 Opcode.STXRB (ThreeOperands (OprRegister R.W20, OprRegister R.W21, - memBaseImm (R.X5, None))) - [| 0x08uy; 0x14uy; 0x7cuy; 0xb5uy |] - - test64 Opcode.STXP (FourOperands (OprRegister R.W11, - OprRegister R.W2, - OprRegister R.W1, - memBaseImm (R.X6, None))) - [| 0x88uy; 0x2buy; 0x04uy; 0xc2uy |] - - test64 Opcode.LDXRB (TwoOperands (OprRegister R.W26, - memBaseImm (R.X11, None))) - [| 0x08uy; 0x5fuy; 0x7duy; 0x7auy |] - - /// C4.4.7 Load/store no-allocate pair (offset) - [] - member __.``[AArch64] Load/store no-allocate pair (offset) Parse Test`` () = - test64 Opcode.STNP (ThreeOperands (OprRegister R.W3, OprRegister R.W10, - memBaseImm (R.X21, Some 0x60L))) - [| 0x28uy; 0x0cuy; 0x2auy; 0xa3uy |] - - test64 Opcode.STNP (ThreeOperands (scalReg R.Q21, scalReg R.Q1, - memBaseImm (R.X13, Some 0x2a0L))) - [| 0xacuy; 0x15uy; 0x05uy; 0xb5uy |] - - /// C4.4.8 Load/store register (immediate post-indexed) - [] - member __.``[AArch64] Load/store register (imm post-idx) Parse Test`` () = - test64 Opcode.STRB (TwoOperands (OprRegister R.W3, - memPostIdxImm (R.X1, Some 0xffffffffffffff0aL))) - [| 0x38uy; 0x10uy; 0xa4uy; 0x23uy |] - - test64 Opcode.LDRSB (TwoOperands (OprRegister R.W18, - memPostIdxImm (R.X5, Some 0xeaL))) - [| 0x38uy; 0xceuy; 0xa4uy; 0xb2uy |] - - test64 Opcode.STR (TwoOperands (scalReg R.H2, memPostIdxImm (R.X1, Some 0xcaL))) - [| 0x7cuy; 0x0cuy; 0xa4uy; 0x22uy |] - - test64 Opcode.STRH (TwoOperands (OprRegister R.W21, - memPostIdxImm (R.X7, Some 0xffffffffffffff00L))) - [| 0x78uy; 0x10uy; 0x04uy; 0xf5uy |] - - test64 Opcode.LDRSW (TwoOperands (OprRegister R.X21, - memPostIdxImm (R.X10, Some 0x3L))) - [| 0xb8uy; 0x80uy; 0x35uy; 0x55uy |] - - /// C4.4.9 Load/store register (immediate pre-indexed) - [] - member __.``[AArch64] Load/store register (imm pre-idx) Parse Test`` () = - test64 Opcode.STRB (TwoOperands (OprRegister R.W17, - memPreIdxImm (R.X5, Some 0xfL))) - [| 0x38uy; 0x00uy; 0xfcuy; 0xb1uy |] - - test64 Opcode.STR (TwoOperands (scalReg R.H10, memPreIdxImm (R.X3, Some 0xfL))) - [| 0x7cuy; 0x00uy; 0xfcuy; 0x6auy |] - - /// C4.4.10 Load/store register (register offset) - [] - member __.``[AArch64] Load/store register (reg offset) Parse Test`` () = - test64 Opcode.STRB (TwoOperands (OprRegister R.W7, - memBaseReg (R.X3, R.W1, - Some (ExtRegOffset (ExtUXTW, - None))))) - [| 0x38uy; 0x21uy; 0x48uy; 0x67uy |] - - test64 Opcode.STRB (TwoOperands (OprRegister R.W7, - memBaseReg (R.X3, R.W3, - Some (ExtRegOffset (ExtUXTW, - Some 0x0L))))) - [| 0x38uy; 0x23uy; 0x58uy; 0x67uy |] - - test64 Opcode.STRB (TwoOperands (OprRegister R.W12, - memBaseReg (R.X1, R.X0, - Some (ShiftOffset (SRTypeLSL, - Imm 0x0L))))) - [| 0x38uy; 0x20uy; 0x78uy; 0x2cuy |] - - test64 Opcode.LDRH (TwoOperands (OprRegister R.WZR, - memBaseReg (R.X21, R.W7, - Some (ExtRegOffset (ExtSXTW, - None))))) - [| 0x78uy; 0x67uy; 0xcauy; 0xbfuy |] - - test64 Opcode.LDRSH (TwoOperands (OprRegister R.W17, - memBaseReg (R.X3, R.X3, - Some (ShiftOffset (SRTypeLSL, - Imm 0x1L))))) - [| 0x78uy; 0xe3uy; 0x78uy; 0x71uy |] - - test64 Opcode.PRFM (TwoOperands (Immediate 0x7L, - memBaseReg (R.X3, R.W3, - Some (ExtRegOffset (ExtUXTW, - Some 0x3L))))) - [| 0xf8uy; 0xa3uy; 0x58uy; 0x67uy |] - - test64 Opcode.PRFM (TwoOperands (PrfOp PLIL3KEEP, - memBaseReg (R.X3, R.W3, - Some (ExtRegOffset (ExtUXTW, - Some 0x3L))))) - [| 0xf8uy; 0xa3uy; 0x58uy; 0x6cuy |] - - /// C4.4.11 Load/store register (unprivileged) - [] - member __.``[AArch64] Load/store register (unprivileged) Parse Test`` () = - test64 Opcode.STTRB (TwoOperands (OprRegister R.W14, - memBaseImm (R.X7, Some 0x19L))) - [| 0x38uy; 0x01uy; 0x98uy; 0xeeuy |] - - test64 Opcode.STTRH (TwoOperands (OprRegister R.W26, - memBaseImm (R.X5, Some 0xffffffffffffff18L))) - [| 0x78uy; 0x11uy; 0x88uy; 0xbauy |] - - test64 Opcode.LDTRSW (TwoOperands (OprRegister R.X10, - memBaseImm (R.X3, Some 0x1fL))) - [| 0xb8uy; 0x81uy; 0xf8uy; 0x6auy |] - - /// C4.4.12 Load/store register (unscaled immediate) - [] - member __.``[AArch64] Load/store register (unscaled imm) Parse Test`` () = - test64 Opcode.STURB (TwoOperands (OprRegister R.W24, - memBaseImm (R.X7, Some 0x6aL))) - [| 0x38uy; 0x06uy; 0xa0uy; 0xf8uy |] - - test64 Opcode.LDUR (TwoOperands (scalReg R.Q3, memBaseImm (R.X20, Some 0xe0L))) - [| 0x3cuy; 0xceuy; 0x02uy; 0x83uy |] - - test64 Opcode.PRFUM (TwoOperands (Immediate 0x1cL, - memBaseImm (R.X3, Some 0x1fL))) - [| 0xf8uy; 0x81uy; 0xf0uy; 0x7cuy |] - - /// C4.4.13 Load/store register (unsigned immediate) - [] - member __.``[AArch64] Load/store register (unsigned imm) Parse Test`` () = - test64 Opcode.STRB (TwoOperands (OprRegister R.WZR, - memBaseImm (R.SP, Some 0x555L))) - [| 0x39uy; 0x15uy; 0x57uy; 0xffuy |] - - test64 Opcode.STR (TwoOperands (scalReg R.S31, memBaseImm (R.SP, Some 0x1ffcL))) - [| 0xbduy; 0x1fuy; 0xffuy; 0xffuy |] - - test64 Opcode.PRFM (TwoOperands (PrfOp PSTL2KEEP, memBaseImm (R.X15, - Some 0x7c00L))) - [| 0xf9uy; 0xbeuy; 0x01uy; 0xf2uy |] - - /// C4.4.14 Load/store register pair (offset) - [] - member __.``[AArch64] Load/store register pair (offset) Parse Test`` () = - test64 Opcode.LDP (ThreeOperands (OprRegister R.W25, - OprRegister R.W18, - memBaseImm (R.X29, - Some 0xffffffffffffff0cL))) - [| 0x29uy; 0x61uy; 0xcbuy; 0xb9uy |] - - /// C4.4.15 Load/store register pair (post-indexed) - [] - member __.``[AArch64] Load/store register pair (post-idx) Parse Test`` () = - test64 Opcode.STP (ThreeOperands (OprRegister R.X11, OprRegister R.X21, - memPostIdxImm (R.SP, Some 0x1f8L))) - [| 0xa8uy; 0x9fuy; 0xd7uy; 0xebuy |] - - test64 Opcode.LDPSW (ThreeOperands (OprRegister R.XZR, OprRegister R.X23, - memPostIdxImm (R.X30, Some 0x7cL))) - [| 0x68uy; 0xcfuy; 0xdfuy; 0xdfuy |] - - /// C4.4.16 Load/store register pair (pre-indexed) - [] - member __.``[AArch64] Load/store register pair (pre-idx) Parse Test`` () = - test64 Opcode.STP (ThreeOperands (OprRegister R.XZR, OprRegister R.XZR, - memPreIdxImm (R.SP, Some 0x1f8L))) - [| 0xa9uy; 0x9fuy; 0xffuy; 0xffuy |] - - /// C4.5 Data processing - register - [] - type DataPorcessingRegClass () = - /// C4.5.1 Add/subtract (extended register) - [] - member __.``[AArch64] Add/subtract (extended register) Parse Test`` () = - test64 Opcode.ADD (FourOperands (OprRegister R.WSP, - OprRegister R.WSP, - OprRegister R.WZR, - ExtReg None)) - [| 0x0buy; 0x3fuy; 0x43uy; 0xffuy |] - - test64 Opcode.ADD (FourOperands (OprRegister R.WSP, - OprRegister R.WSP, - OprRegister R.WZR, - ExtReg (Some (ShiftOffset (SRTypeLSL, - Imm 2L))))) - [| 0x0buy; 0x3fuy; 0x4buy; 0xffuy |] - - test64 Opcode.ADD (FourOperands (OprRegister R.SP, - OprRegister R.X10, - OprRegister R.W10, - ExtReg (Some (ExtRegOffset (ExtUXTW, - Some 2L))))) - [| 0x8buy; 0x2auy; 0x49uy; 0x5fuy |] - - test64 Opcode.CMN (ThreeOperands (OprRegister R.SP, - OprRegister R.X14, - ExtReg (Some (ShiftOffset (SRTypeLSL, - Imm 1L))))) - [| 0xabuy; 0x2euy; 0x67uy; 0xffuy |] - - /// C4.5.2 Add/subtract (shifted register) - [] - member __.``[AArch64] Add/subtract (shifted register) Parse Test`` () = - test64 Opcode.ADD (FourOperands (OprRegister R.W27, - OprRegister R.W28, - OprRegister R.W14, - Shift (SRTypeASR, Imm 23L))) - [| 0x0buy; 0x8euy; 0x5fuy; 0x9buy |] - - test64 Opcode.SUBS (FourOperands (OprRegister R.W11, - OprRegister R.W29, - OprRegister R.W14, - Shift (SRTypeLSR, Imm 7L))) - [| 0x6buy; 0x4euy; 0x1fuy; 0xabuy |] - - test64 Opcode.ADDS (FourOperands (OprRegister R.X18, - OprRegister R.X29, - OprRegister R.X14, - Shift (SRTypeASR, Imm 7L))) - [| 0xabuy; 0x8euy; 0x1fuy; 0xb2uy |] - - /// C4.5.3 Add/subtract (with carry) - [] - member __.``[AArch64] Add/subtract (with carry) Parse Test`` () = - test64 Opcode.ADCS (ThreeOperands (OprRegister R.XZR, - OprRegister R.X21, - OprRegister R.X10)) - [| 0xbauy; 0x0auy; 0x02uy; 0xbfuy |] - - test64 Opcode.NGC (TwoOperands (OprRegister R.W30, OprRegister R.W11)) - [| 0x5auy; 0x0buy; 0x03uy; 0xfeuy |] - - /// C4.5.4 Conditional compare (immediate) - [] - member __.``[AArch64] Conditional compare (immediate) Parse Test`` () = - test64 Opcode.CCMN (FourOperands (OprRegister R.X3, - Immediate 0x15L, - NZCV 8uy, - Cond GT)) - [| 0xbauy; 0x55uy; 0xc8uy; 0x68uy |] - - /// C4.5.5 Conditional compare (register) - [] - member __.``[AArch64] Conditional compare (register) Parse Test`` () = - test64 Opcode.CCMN (FourOperands (OprRegister R.X15, - OprRegister R.X28, - NZCV 0xfuy, - Cond PL)) - [| 0xbauy; 0x5cuy; 0x51uy; 0xefuy |] - - /// C4.5.6 Conditional select - [] - member __.``[AArch64] Conditional select Parse Test`` () = - test64 Opcode.CSEL (FourOperands (OprRegister R.X28, - OprRegister R.X23, - OprRegister R.X6, - Cond LS)) - [| 0x9auy; 0x86uy; 0x92uy; 0xfcuy |] - - test64 Opcode.CSINC (FourOperands (OprRegister R.W21, - OprRegister R.W0, - OprRegister R.W16, - Cond CS)) // HS - [| 0x1auy; 0x90uy; 0x24uy; 0x15uy |] - - test64 Opcode.CINC (ThreeOperands (OprRegister R.W21, - OprRegister R.W16, Cond CC))// LO - [| 0x1auy; 0x90uy; 0x26uy; 0x15uy |] - - test64 Opcode.CSET (TwoOperands (OprRegister R.W7, Cond LE)) - [| 0x1auy; 0x9fuy; 0xc7uy; 0xe7uy |] - - test64 Opcode.CINV (ThreeOperands (OprRegister R.X10, - OprRegister R.X7, Cond LE)) - [| 0xdauy; 0x87uy; 0xc0uy; 0xeauy |] - - test64 Opcode.CSETM (TwoOperands (OprRegister R.X10, Cond LE)) - [| 0xdauy; 0x9fuy; 0xc3uy; 0xeauy |] - - test64 Opcode.CSINV (FourOperands (OprRegister R.X10, - OprRegister R.X27, - OprRegister R.XZR, Cond GT)) - [| 0xdauy; 0x9fuy; 0xc3uy; 0x6auy |] - - test64 Opcode.CSNEG (FourOperands (OprRegister R.W30, - OprRegister R.W21, - OprRegister R.W10, Cond AL)) - [| 0x5auy; 0x8auy; 0xe6uy; 0xbeuy |] - - test64 Opcode.CNEG (ThreeOperands (OprRegister R.W30, - OprRegister R.W21, Cond LE)) - [| 0x5auy; 0x95uy; 0xc6uy; 0xbeuy |] - - /// C4.5.7 Data-processing (1 source) - [] - member __.``[AArch64] Data-processing (1 source) Parse Test`` () = - test64 Opcode.RBIT (TwoOperands (OprRegister R.W28, OprRegister R.W11)) - [| 0x5auy; 0xc0uy; 0x01uy; 0x7cuy |] - - test64 Opcode.CLS (TwoOperands (OprRegister R.XZR, OprRegister R.X11)) - [| 0xdauy; 0xc0uy; 0x15uy; 0x7fuy |] - - test64 Opcode.REV32 (TwoOperands (OprRegister R.X30, OprRegister R.X15)) - [| 0xdauy; 0xc0uy; 0x09uy; 0xfeuy |] - - /// C4.5.8 Data-processing (2 source) - [] - member __.``[AArch64] Data-processing (2 source) Parse Test`` () = - test64 Opcode.UDIV (ThreeOperands (OprRegister R.W30, OprRegister R.W23, - OprRegister R.W9)) - [| 0x1auy; 0xc9uy; 0x0auy; 0xfeuy |] - - test64 Opcode.CRC32CX (ThreeOperands (OprRegister R.W29, OprRegister R.W3, - OprRegister R.X26)) - [| 0x9auy; 0xdauy; 0x5cuy; 0x7duy |] - - /// C4.5.9 Data-processing (3 source) - [] - member __.``[AArch64] Data-processing (3 source) Parse Test`` () = - test64 Opcode.MADD (FourOperands (OprRegister R.X7, - OprRegister R.X28, - OprRegister R.X10, - OprRegister R.X11)) - [| 0x9buy; 0x0auy; 0x2fuy; 0x87uy |] - - test64 Opcode.MUL (ThreeOperands (OprRegister R.X7, - OprRegister R.X28, - OprRegister R.X10)) - [| 0x9buy; 0x0auy; 0x7fuy; 0x87uy |] (* Alias of MADD *) - - test64 Opcode.MSUB (FourOperands (OprRegister R.X7, - OprRegister R.X28, - OprRegister R.X10, - OprRegister R.X11)) - [| 0x9buy; 0x0auy; 0xafuy; 0x87uy |] - - test64 Opcode.SMADDL (FourOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10, - OprRegister R.X11)) - [| 0x9buy; 0x2auy; 0x2fuy; 0x87uy |] - - test64 Opcode.SMSUBL (FourOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10, - OprRegister R.X11)) - [| 0x9buy; 0x2auy; 0xafuy; 0x87uy |] - - test64 Opcode.SMULH (ThreeOperands (OprRegister R.X7, - OprRegister R.X28, - OprRegister R.X10)) - [| 0x9buy; 0x4auy; 0x2fuy; 0x87uy |] - - test64 Opcode.UMADDL (FourOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10, - OprRegister R.X11)) - [| 0x9buy; 0xaauy; 0x2fuy; 0x87uy |] - - test64 Opcode.UMSUBL (FourOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10, - OprRegister R.X11)) - [| 0x9buy; 0xaauy; 0xafuy; 0x87uy |] - - test64 Opcode.UMULH (ThreeOperands (OprRegister R.X7, - OprRegister R.X28, - OprRegister R.X10)) - [| 0x9buy; 0xcauy; 0x2fuy; 0x87uy |] - - test64 Opcode.MNEG (ThreeOperands (OprRegister R.X7, - OprRegister R.X28, - OprRegister R.X10)) - [| 0x9buy; 0x0auy; 0xffuy; 0x87uy |] (* Alias of MSUB *) - - test64 Opcode.SMULL (ThreeOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10)) - [| 0x9buy; 0x2auy; 0x7fuy; 0x87uy |] (* Alias of SMADDL *) - - test64 Opcode.SMNEGL (ThreeOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10)) - [| 0x9buy; 0x2auy; 0xffuy; 0x87uy |] (* Alias of SMSUBL *) - - test64 Opcode.UMULL (ThreeOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10)) - [| 0x9buy; 0xaauy; 0x7fuy; 0x87uy |] (* Alias of UMADDL *) - - test64 Opcode.UMNEGL (ThreeOperands (OprRegister R.X7, - OprRegister R.W28, - OprRegister R.W10)) - [| 0x9buy; 0xaauy; 0xffuy; 0x87uy |] (* Alias of UMSUBL *) - - /// C4.5.10 Logical (shifted register) - [] - member __.``[AArch64] Logical (shifted register) Parse Test`` () = - test64 Opcode.AND (FourOperands (OprRegister R.X5, - OprRegister R.X10, - OprRegister R.X24, - Shift (SRTypeLSR, Imm 14L))) - [| 0x8auy; 0x58uy; 0x39uy; 0x45uy |] - - test64 Opcode.ORN (FourOperands (OprRegister R.W26, - OprRegister R.W29, - OprRegister R.W22, - Shift (SRTypeROR, Imm 7L))) - [| 0x2auy; 0xf6uy; 0x1fuy; 0xbauy |] - - test64 Opcode.MVN (ThreeOperands (OprRegister R.W26, - OprRegister R.W22, - Shift (SRTypeROR, Imm 0x7L))) - [| 0x2auy; 0xf6uy; 0x1fuy; 0xfauy |] - - /// C4.6 Data processing - SIMD and floating point - [] - type DataProcessingSIMDAndFPClass () = - /// C4.6.1 Advanced SIMD across lanes - [] - member __.``[AArch64] Advanced SIMD across lanes Parse Test`` () = - test64 Opcode.SADDLV (TwoOperands (scalReg R.D2, - SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))))) - [| 0x4euy; 0xb0uy; 0x3auy; 0xc2uy |] - - test64 Opcode.SMAXV (TwoOperands (scalReg R.B18, - SIMDOpr (SFReg (SIMDVecReg (R.V6, EightB))))) - [| 0x0euy; 0x30uy; 0xa8uy; 0xd2uy |] - - test64 Opcode.SMINV (TwoOperands (scalReg R.H10, - SIMDOpr (SFReg (SIMDVecReg (R.V16, FourH))))) - [| 0x0euy; 0x71uy; 0xaauy; 0x0auy |] - - test64 Opcode.ADDV (TwoOperands (scalReg R.H26, - SIMDOpr (SFReg (SIMDVecReg (R.V4, EightH))))) - [| 0x4euy; 0x71uy; 0xb8uy; 0x9auy |] - - test64 Opcode.UADDLV (TwoOperands (scalReg R.D17, - SIMDOpr (SFReg (SIMDVecReg (R.V9, FourS))))) - [| 0x6euy; 0xb0uy; 0x39uy; 0x31uy |] - - test64 Opcode.UMAXV (TwoOperands (scalReg R.H8, - SIMDOpr (SFReg (SIMDVecReg (R.V28, FourH))))) - [| 0x2euy; 0x70uy; 0xabuy; 0x88uy |] - - test64 Opcode.UMINV (TwoOperands (scalReg R.S10, - SIMDOpr (SFReg (SIMDVecReg (R.V23, FourS))))) - [| 0x6euy; 0xb1uy; 0xaauy; 0xeauy |] - - test64 Opcode.FMAXNMV (TwoOperands (scalReg R.S11, - SIMDOpr (SFReg (SIMDVecReg (R.V18, FourS))))) - [| 0x6euy; 0x30uy; 0xcauy; 0x4buy |] - - test64 Opcode.FMAXV (TwoOperands (scalReg R.S8, - SIMDOpr (SFReg (SIMDVecReg (R.V10, FourS))))) - [| 0x6euy; 0x30uy; 0xf9uy; 0x48uy |] - - test64 Opcode.FMINNMV (TwoOperands (scalReg R.S12, - SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))))) - [| 0x6euy; 0xb0uy; 0xcauy; 0xccuy |] - - test64 Opcode.FMINV (TwoOperands (scalReg R.S2, - SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))))) - [| 0x6euy; 0xb0uy; 0xfauy; 0xc2uy |] - - /// C4.6.2 Advanced SIMD copy - [] - member __.``[AArch64] Advanced SIMD copy Parse Test`` () = - test64 Opcode.DUP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoD))), - SIMDOpr (SFReg (sVRegIdx R.V4 VecD 1uy)))) - [| 0x4euy; 0x18uy; 0x04uy; 0x86uy |] - - test64 Opcode.DUP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoD))), - OprRegister R.X3)) - [| 0x4euy; 0x08uy; 0x0cuy; 0x61uy |] - - test64 Opcode.DUP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, FourH))), - OprRegister R.WZR)) // Online HEX To ARM Conv error - [| 0x0euy; 0x1euy; 0x0fuy; 0xfcuy |] - - test64 Opcode.DUP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, FourH))), - OprRegister R.WZR)) - [| 0x0euy; 0x02uy; 0x0fuy; 0xfcuy |] - - test64 Opcode.SMOV (TwoOperands (OprRegister R.W26, - SIMDOpr (SFReg (sVRegIdx R.V7 VecH 0uy)))) - [| 0x0euy; 0x02uy; 0x2cuy; 0xfauy |] - - test64 Opcode.UMOV (TwoOperands (OprRegister R.W3, - SIMDOpr (SFReg (sVRegIdx R.V14 VecB 0uy)))) - [| 0x0euy; 0x01uy; 0x3duy; 0xc3uy |] - - test64 Opcode.MOV (TwoOperands (OprRegister R.W3, - SIMDOpr (SFReg (sVRegIdx R.V14 VecS 0uy)))) - [| 0x0euy; 0x04uy; 0x3duy; 0xc3uy |] - - test64 Opcode.MOV (TwoOperands (OprRegister R.X3, - SIMDOpr (SFReg (sVRegIdx R.V14 VecD 0uy)))) - [| 0x4euy; 0x08uy; 0x3duy; 0xc3uy |] - - test64 Opcode.INS (TwoOperands (SIMDOpr (SFReg (sVRegIdx R.V9 VecS 0uy)), - OprRegister R.W1)) - [| 0x4euy; 0x04uy; 0x1cuy; 0x29uy |] - - test64 Opcode.INS (TwoOperands (SIMDOpr (SFReg (sVRegIdx R.V5 VecH 0uy)), - SIMDOpr (SFReg (sVRegIdx R.V6 VecH 7uy)))) - [| 0x6euy; 0x02uy; 0x74uy; 0xc5uy |] - - /// C4.6.3 Advanced SIMD extract - [] - member __.``[AArch64] Advanced SIMD extract Parse Test`` () = - test64 Opcode.EXT (FourOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V12, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, SixteenB))), - Immediate 9L)) - [| 0x6euy; 0x06uy; 0x49uy; 0x83uy |] - - test64 Opcode.EXT (FourOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, EightB))), - Immediate 7L)) - [| 0x2euy; 0x07uy; 0x38uy; 0xfcuy |] - - /// C4.6.4 Advanced SIMD modified immediate - [] - member __.``[AArch64] Advanced SIMD modified immediate Parse Test`` () = - test64 Opcode.MOVI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - Immediate 0xAAL, - Shift (SRTypeLSL, Imm 24L))) - [| 0x4fuy; 0x05uy; 0x65uy; 0x59uy |] - - test64 Opcode.MOVI (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - Immediate 0xAAL)) - [| 0x4fuy; 0x05uy; 0x05uy; 0x59uy |] - - test64 Opcode.ORR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - Immediate 0x46L, - Shift (SRTypeLSL, Imm 8L))) - [| 0x4fuy; 0x02uy; 0x34uy; 0xc5uy |] - - test64 Opcode.MOVI (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, SixteenB))), - Immediate 0x2EL)) - [| 0x4fuy; 0x01uy; 0xe5uy; 0xd9uy |] - - test64 Opcode.ORR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourH))), - Immediate 0xC7L, - Shift (SRTypeLSL, Imm 8L))) - [| 0x0fuy; 0x06uy; 0xb4uy; 0xe5uy |] - - test64 Opcode.MOVI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, EightH))), - Immediate 0x9AL, - Shift (SRTypeLSL, Imm 8L))) - [| 0x4fuy; 0x04uy; 0xa7uy; 0x59uy |] - - test64 Opcode.MOVI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - Immediate 0xB2L, - Shift (SRTypeMSL, Imm 8L))) - [| 0x4fuy; 0x05uy; 0xc6uy; 0x55uy |] - - test64 Opcode.FMOV (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - FPImmediate -11.5)) - [| 0x4fuy; 0x05uy; 0xf4uy; 0xe5uy |] - - test64 Opcode.MVNI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - Immediate 0xE6L, - Shift (SRTypeLSL, Imm 8L))) - [| 0x6fuy; 0x07uy; 0x24uy; 0xd5uy |] - - test64 Opcode.BIC (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))), - Immediate 0xB5L, - Shift (SRTypeLSL, Imm 8L))) - [| 0x2fuy; 0x05uy; 0x36uy; 0xa7uy |] - - test64 Opcode.MVNI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - Immediate 0xE6L, - Shift (SRTypeLSL, Imm 8L))) - [| 0x6fuy; 0x07uy; 0xa4uy; 0xd5uy |] - - test64 Opcode.BIC (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V7, FourH))), - Immediate 0xB5L)) - [| 0x2fuy; 0x05uy; 0x96uy; 0xa7uy |] - - test64 Opcode.MVNI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - Immediate 0xE6L, - Shift (SRTypeMSL, Imm 8L))) - [| 0x6fuy; 0x07uy; 0xc4uy; 0xd5uy |] - - test64 Opcode.MOVI (TwoOperands (scalReg R.D27, Immediate 0xFF00FFFFFF00FF00L)) - [| 0x2fuy; 0x05uy; 0xe7uy; 0x5buy |] - - test64 Opcode.MOVI (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V23, TwoD))), - Immediate 0xFF00FFFFFF00FF00L)) - [| 0x6fuy; 0x05uy; 0xe7uy; 0x57uy |] - - test64 Opcode.FMOV (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - FPImmediate -11.5)) - [| 0x6fuy; 0x05uy; 0xf4uy; 0xe5uy |] - - /// C4.6.5 Advanced SIMD permute - [] - member __.``[AArch64] Advanced SIMD permute Parse Test`` () = - test64 Opcode.UZP1 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V12, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, EightH))))) - [| 0x4euy; 0x4euy; 0x19uy; 0x83uy |] - - test64 Opcode.TRN1 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))))) - [| 0x0euy; 0x87uy; 0x28uy; 0xfeuy |] - - test64 Opcode.ZIP1 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, - SixteenB))))) - [| 0x4euy; 0x03uy; 0x38uy; 0x3cuy |] - - test64 Opcode.ZIP1 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V1, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, EightB))))) - [| 0x0euy; 0x07uy; 0x38uy; 0xc1uy |] - - test64 Opcode.UZP2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoD))))) - [| 0x4euy; 0xc1uy; 0x58uy; 0xc6uy |] - - test64 Opcode.TRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))))) - [| 0x0euy; 0x87uy; 0x68uy; 0xc3uy |] - - test64 Opcode.ZIP2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, - SixteenB))))) - [| 0x4euy; 0x01uy; 0x78uy; 0x85uy |] - - /// C4.6.6 Advanced SIMD scalar copy - [] - member __.``[AArch64] Advanced SIMD scalar copy Parse Test`` () = - test64 Opcode.MOV (TwoOperands (scalReg R.D10, - SIMDOpr (SFReg (sVRegIdx R.V10 VecD 0uy)))) - [| 0x5euy; 0x08uy; 0x05uy; 0x4auy |] - - test64 Opcode.MOV (TwoOperands (scalReg R.B1, - SIMDOpr (SFReg (sVRegIdx R.V10 VecB 3uy)))) - [| 0x5euy; 0x07uy; 0x05uy; 0x41uy |] - - /// C4.6.7 Advanced SIMD scalar pairwise - [] - member __.``[AArch64] Advanced SIMD scalar pairwise Parse Test`` () = - test64 Opcode.ADDP (TwoOperands (scalReg R.D7, - SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))))) - [| 0x5euy; 0xf1uy; 0xb8uy; 0x67uy |] - test64 Opcode.FMAXNMP (TwoOperands (scalReg R.D15, - SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoD))))) - [| 0x7euy; 0x70uy; 0xc9uy; 0xcfuy |] - test64 Opcode.FADDP (TwoOperands (scalReg R.S31, - SIMDOpr (SFReg (SIMDVecReg (R.V15, TwoS))))) - [| 0x7euy; 0x30uy; 0xd9uy; 0xffuy |] - test64 Opcode.FMAXP (TwoOperands (scalReg R.D18, - SIMDOpr (SFReg (SIMDVecReg (R.V17, TwoD))))) - [| 0x7euy; 0x70uy; 0xfauy; 0x32uy |] - test64 Opcode.FMINNMP (TwoOperands (scalReg R.S1, - SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoS))))) - [| 0x7euy; 0xb0uy; 0xc9uy; 0xc1uy |] - test64 Opcode.FMINP (TwoOperands (scalReg R.D7, - SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoD))))) - [| 0x7euy; 0xf0uy; 0xf8uy; 0x27uy |] - - /// C4.6.8 Advanced SIMD scalar shift by immediate - [] - member __.``[AArch64] Advanced SIMD scalar shift by imm Parse Test`` () = - test64 Opcode.SSHR (ThreeOperands (scalReg R.D1, scalReg R.D10, Immediate 0x3eL)) - [| 0x5fuy; 0x42uy; 0x05uy; 0x41uy |] - - test64 Opcode.SSRA (ThreeOperands (scalReg R.D28, scalReg R.D3, Immediate 0x1cL)) - [| 0x5fuy; 0x64uy; 0x14uy; 0x7cuy |] - - test64 Opcode.SRSHR (ThreeOperands (scalReg R.D1, scalReg R.D7, Immediate 0x27L)) - [| 0x5fuy; 0x59uy; 0x24uy; 0xe1uy |] - - test64 Opcode.SRSRA (ThreeOperands (scalReg R.D3, scalReg R.D6, Immediate 1L)) - [| 0x5fuy; 0x7fuy; 0x34uy; 0xc3uy |] - - test64 Opcode.SHL (ThreeOperands (scalReg R.D13, scalReg R.D7, Immediate 2L)) - [| 0x5fuy; 0x42uy; 0x54uy; 0xeduy |] - - test64 Opcode.SQSHL (ThreeOperands (scalReg R.S25, scalReg R.S16, Immediate 4L)) - [| 0x5fuy; 0x24uy; 0x76uy; 0x19uy |] - - test64 Opcode.SQSHL (ThreeOperands (scalReg R.D25, scalReg R.D16, - Immediate 0x24L)) - [| 0x5fuy; 0x64uy; 0x76uy; 0x19uy |] - - test64 Opcode.SQSHRN (ThreeOperands (scalReg R.S7, scalReg R.D12, - Immediate 0x17L)) - [| 0x5fuy; 0x29uy; 0x95uy; 0x87uy |] - - test64 Opcode.SQRSHRN (ThreeOperands (scalReg R.H25, scalReg R.S7, Immediate 1L)) - [| 0x5fuy; 0x1fuy; 0x9cuy; 0xf9uy |] - - test64 Opcode.SCVTF (ThreeOperands (scalReg R.D1, scalReg R.D6, Fbits 0x1fuy)) - [| 0x5fuy; 0x61uy; 0xe4uy; 0xc1uy |] - - test64 Opcode.FCVTZS (ThreeOperands (scalReg R.D11, scalReg R.D8, Fbits 0x25uy)) - [| 0x5fuy; 0x5buy; 0xfduy; 0x0buy |] - - test64 Opcode.USHR (ThreeOperands (scalReg R.D7, scalReg R.D14, Immediate 0x17L)) - [| 0x7fuy; 0x69uy; 0x05uy; 0xc7uy |] - - test64 Opcode.USRA (ThreeOperands (scalReg R.D17, scalReg R.D1, Immediate 0x36L)) - [| 0x7fuy; 0x4auy; 0x14uy; 0x31uy |] - - test64 Opcode.URSHR (ThreeOperands (scalReg R.D9, scalReg R.D2, Immediate 0x20L)) - [| 0x7fuy; 0x60uy; 0x24uy; 0x49uy |] - - test64 Opcode.URSRA (ThreeOperands (scalReg R.D9, scalReg R.D6, Immediate 0x3cL)) - [| 0x7fuy; 0x44uy; 0x34uy; 0xc9uy |] - - test64 Opcode.SRI (ThreeOperands (scalReg R.D3, scalReg R.D14, Immediate 0x1fL)) - [| 0x7fuy; 0x61uy; 0x45uy; 0xc3uy |] - - test64 Opcode.SLI (ThreeOperands (scalReg R.D3, scalReg R.D6, Immediate 0xeL)) - [| 0x7fuy; 0x4euy; 0x54uy; 0xc3uy |] - - test64 Opcode.SQSHLU (ThreeOperands (scalReg R.S7, scalReg R.S20, - Immediate 0xbL)) - [| 0x7fuy; 0x2buy; 0x66uy; 0x87uy |] - - test64 Opcode.UQSHL (ThreeOperands (scalReg R.B24, scalReg R.B7, Immediate 3L)) - [| 0x7fuy; 0x0buy; 0x74uy; 0xf8uy |] - - test64 Opcode.SQSHRUN (ThreeOperands (scalReg R.S13, scalReg R.D12, - Immediate 0x11L)) - [| 0x7fuy; 0x2fuy; 0x85uy; 0x8duy |] - - test64 Opcode.SQRSHRUN (ThreeOperands (scalReg R.S16, scalReg R.D1, - Immediate 6L)) - [| 0x7fuy; 0x3auy; 0x8cuy; 0x30uy |] - - test64 Opcode.UQSHRN (ThreeOperands (scalReg R.H13, scalReg R.S6, - Immediate 0xbL)) - [| 0x7fuy; 0x15uy; 0x94uy; 0xcduy |] - - test64 Opcode.UQRSHRN (ThreeOperands (scalReg R.B6, scalReg R.H2, Immediate 4L)) - [| 0x7fuy; 0x0cuy; 0x9cuy; 0x46uy |] - - test64 Opcode.UCVTF (ThreeOperands (scalReg R.S1, scalReg R.S6, Fbits 0x1cuy)) - [| 0x7fuy; 0x24uy; 0xe4uy; 0xc1uy |] - - test64 Opcode.FCVTZU (ThreeOperands (scalReg R.D3, scalReg R.D4, Fbits 0x2fuy)) - [| 0x7fuy; 0x51uy; 0xfcuy; 0x83uy |] - - /// C4.6.9 Advanced SIMD scalar three different - [] - member __.``[AArch64] Advanced SIMD scalar three different Parse Test`` () = - test64 Opcode.SQDMLAL (ThreeOperands (scalReg R.D2, scalReg R.S30, scalReg R.S6)) - [| 0x5euy; 0xa6uy; 0x93uy; 0xc2uy |] - test64 Opcode.SQDMLSL (ThreeOperands (scalReg R.S6, scalReg R.H0, scalReg R.H1)) - [| 0x5euy; 0x61uy; 0xb0uy; 0x06uy |] - test64 Opcode.SQDMULL (ThreeOperands (scalReg R.D2, scalReg R.S18, scalReg R.S2)) - [| 0x5euy; 0xa2uy; 0xd2uy; 0x42uy |] - - /// C4.6.10 Advanced SIMD scalar three same - [] - member __.``[AArch64] Advanced SIMD scalar three same Parse Test`` () = - test64 Opcode.SQADD (ThreeOperands (scalReg R.B28, scalReg R.B15, scalReg R.B1)) - [| 0x5euy; 0x21uy; 0x0duy; 0xfcuy |] - - test64 Opcode.SQSUB (ThreeOperands (scalReg R.H5, scalReg R.H30, scalReg R.H3)) - [| 0x5euy; 0x63uy; 0x2fuy; 0xc5uy |] - - test64 Opcode.CMGT (ThreeOperands (scalReg R.D5, scalReg R.D6, scalReg R.D1)) - [| 0x5euy; 0xe1uy; 0x34uy; 0xc5uy |] - - test64 Opcode.CMGE (ThreeOperands (scalReg R.D10, scalReg R.D6, scalReg R.D7)) - [| 0x5euy; 0xe7uy; 0x3cuy; 0xcauy |] - - test64 Opcode.SSHL (ThreeOperands (scalReg R.D30, scalReg R.D0, scalReg R.D31)) - [| 0x5euy; 0xffuy; 0x44uy; 0x1euy |] - - test64 Opcode.SQSHL (ThreeOperands (scalReg R.B14, scalReg R.B24, scalReg R.B9)) - [| 0x5euy; 0x29uy; 0x4fuy; 0x0euy |] - - test64 Opcode.SRSHL (ThreeOperands (scalReg R.D17, scalReg R.D28, scalReg R.D30)) - [| 0x5euy; 0xfeuy; 0x57uy; 0x91uy |] - - test64 Opcode.SQRSHL (ThreeOperands (scalReg R.H14, scalReg R.H17, - scalReg R.H14)) - [| 0x5euy; 0x6euy; 0x5euy; 0x2euy |] - - test64 Opcode.ADD (ThreeOperands (scalReg R.D24, scalReg R.D3, scalReg R.D24)) - [| 0x5euy; 0xf8uy; 0x84uy; 0x78uy |] - - test64 Opcode.CMTST (ThreeOperands (scalReg R.D10, scalReg R.D12, scalReg R.D28)) - [| 0x5euy; 0xfcuy; 0x8duy; 0x8auy |] - - test64 Opcode.SQDMULH (ThreeOperands (scalReg R.S16, scalReg R.S7, scalReg R.S1)) - [| 0x5euy; 0xa1uy; 0xb4uy; 0xf0uy |] - - test64 Opcode.FMULX (ThreeOperands (scalReg R.D12, scalReg R.D24, scalReg R.D1)) - [| 0x5euy; 0x61uy; 0xdfuy; 0x0cuy |] - - test64 Opcode.FCMEQ (ThreeOperands (scalReg R.S1, scalReg R.S6, scalReg R.S24)) - [| 0x5euy; 0x38uy; 0xe4uy; 0xc1uy |] - - test64 Opcode.FRECPS (ThreeOperands (scalReg R.D4, scalReg R.D2, scalReg R.D1)) - [| 0x5euy; 0x61uy; 0xfcuy; 0x44uy |] - - test64 Opcode.FRSQRTS (ThreeOperands (scalReg R.D24, scalReg R.D16, - scalReg R.D1)) - [| 0x5euy; 0xe1uy; 0xfeuy; 0x18uy |] - - test64 Opcode.UQADD (ThreeOperands (scalReg R.H18, scalReg R.H8, scalReg R.H1)) - [| 0x7euy; 0x61uy; 0x0duy; 0x12uy |] - - test64 Opcode.UQSUB (ThreeOperands (scalReg R.B1, scalReg R.B12, scalReg R.B12)) - [| 0x7euy; 0x2cuy; 0x2duy; 0x81uy |] - - test64 Opcode.CMHI (ThreeOperands (scalReg R.D30, scalReg R.D5, scalReg R.D1)) - [| 0x7euy; 0xe1uy; 0x34uy; 0xbeuy |] - - test64 Opcode.CMHS (ThreeOperands (scalReg R.D18, scalReg R.D24, scalReg R.D3)) - [| 0x7euy; 0xe3uy; 0x3fuy; 0x12uy |] - - test64 Opcode.USHL (ThreeOperands (scalReg R.D1, scalReg R.D10, scalReg R.D3)) - [| 0x7euy; 0xe3uy; 0x45uy; 0x41uy |] - - test64 Opcode.UQSHL (ThreeOperands (scalReg R.B17, scalReg R.B16, scalReg R.B7)) - [| 0x7euy; 0x27uy; 0x4euy; 0x11uy |] - - test64 Opcode.URSHL (ThreeOperands (scalReg R.D3, scalReg R.D24, scalReg R.D1)) - [| 0x7euy; 0xe1uy; 0x57uy; 0x03uy |] - - test64 Opcode.UQRSHL (ThreeOperands (scalReg R.H24, scalReg R.H17, scalReg R.H7)) - [| 0x7euy; 0x67uy; 0x5euy; 0x38uy |] - - test64 Opcode.SUB (ThreeOperands (scalReg R.D31, scalReg R.D6, scalReg R.D10)) - [| 0x7euy; 0xeauy; 0x84uy; 0xdfuy |] - - test64 Opcode.CMEQ (ThreeOperands (scalReg R.D4, scalReg R.D17, scalReg R.D0)) - [| 0x7euy; 0xe0uy; 0x8euy; 0x24uy |] - - test64 Opcode.SQRDMULH (ThreeOperands (scalReg R.H10, scalReg R.H6, - scalReg R.H1)) - [| 0x7euy; 0x61uy; 0xb4uy; 0xcauy |] - - test64 Opcode.SQRDMULH (ThreeOperands (scalReg R.S1, scalReg R.S8, scalReg R.S7)) - [| 0x7euy; 0xa7uy; 0xb5uy; 0x01uy |] - - test64 Opcode.FCMGE (ThreeOperands (scalReg R.D6, scalReg R.D16, scalReg R.D1)) - [| 0x7euy; 0x61uy; 0xe6uy; 0x06uy |] - - test64 Opcode.FACGE (ThreeOperands (scalReg R.S1, scalReg R.S2, scalReg R.S1)) - [| 0x7euy; 0x21uy; 0xecuy; 0x41uy |] - - test64 Opcode.FABD (ThreeOperands (scalReg R.S6, scalReg R.S17, scalReg R.S1)) - [| 0x7euy; 0xa1uy; 0xd6uy; 0x26uy |] - - test64 Opcode.FCMGT (ThreeOperands (scalReg R.D7, scalReg R.D20, scalReg R.D4)) - [| 0x7euy; 0xe4uy; 0xe6uy; 0x87uy |] - - test64 Opcode.FACGT (ThreeOperands (scalReg R.S19, scalReg R.S3, scalReg R.S5)) - [| 0x7euy; 0xa5uy; 0xecuy; 0x73uy |] - - /// C4.6.11 Advanced SIMD scalar two-scalReg miscellaneous - [] - member __.``[AArch64] Advanced SIMD scalar two-reg misc Parse Test`` () = - test64 Opcode.SUQADD (TwoOperands (scalReg R.S21,scalReg R.S29)) - [| 0x5euy; 0xa0uy; 0x3buy; 0xb5uy |] - - test64 Opcode.SQABS (TwoOperands (scalReg R.H1, scalReg R.H30)) - [| 0x5euy; 0x60uy; 0x7buy; 0xc1uy |] - - test64 Opcode.CMGT (ThreeOperands (scalReg R.D30, scalReg R.D15, Immediate 0L)) - [| 0x5euy; 0xe0uy; 0x89uy; 0xfeuy |] - - test64 Opcode.CMEQ (ThreeOperands (scalReg R.D20, scalReg R.D23, Immediate 0L)) - [| 0x5euy; 0xe0uy; 0x9auy; 0xf4uy |] - - test64 Opcode.CMLT (ThreeOperands (scalReg R.D28, scalReg R.D30, Immediate 0L)) - [| 0x5euy; 0xe0uy; 0xabuy; 0xdcuy |] - - test64 Opcode.ABS (TwoOperands (scalReg R.D17, scalReg R.D24)) - [| 0x5euy; 0xe0uy; 0xbbuy; 0x11uy |] - - test64 Opcode.SQXTN (TwoOperands (scalReg R.H7, scalReg R.S28)) - [| 0x5euy; 0x61uy; 0x4buy; 0x87uy |] - - test64 Opcode.FCVTNS (TwoOperands (scalReg R.D1, scalReg R.D24)) - [| 0x5euy; 0x61uy; 0xabuy; 0x01uy |] - - test64 Opcode.FCVTMS (TwoOperands (scalReg R.S22, scalReg R.S25)) - [| 0x5euy; 0x21uy; 0xbbuy; 0x36uy |] - - test64 Opcode.FCVTAS (TwoOperands (scalReg R.D31, scalReg R.D23)) - [| 0x5euy; 0x61uy; 0xcauy; 0xffuy |] - - test64 Opcode.SCVTF (TwoOperands (scalReg R.S10, scalReg R.S21)) - [| 0x5euy; 0x21uy; 0xdauy; 0xaauy |] - - test64 Opcode.FCMGT (ThreeOperands (scalReg R.S28, scalReg R.S21, - FPImmediate 0.0)) - [| 0x5euy; 0xa0uy; 0xcauy; 0xbcuy |] - - test64 Opcode.FCMEQ (ThreeOperands (scalReg R.D25, scalReg R.D17, - FPImmediate 0.0)) - [| 0x5euy; 0xe0uy; 0xdauy; 0x39uy |] - - test64 Opcode.FCMGT (ThreeOperands (scalReg R.D30, scalReg R.D15, - FPImmediate 0.0)) - [| 0x5euy; 0xe0uy; 0xc9uy; 0xfeuy |] - - test64 Opcode.FCVTPS (TwoOperands (scalReg R.S28, scalReg R.S31)) - [| 0x5euy; 0xa1uy; 0xabuy; 0xfcuy |] - - test64 Opcode.FCVTZS (TwoOperands (scalReg R.D30, scalReg R.D15)) - [| 0x5euy; 0xe1uy; 0xb9uy; 0xfeuy |] - - test64 Opcode.FRECPE (TwoOperands (scalReg R.S22, scalReg R.S23)) - [| 0x5euy; 0xa1uy; 0xdauy; 0xf6uy |] - - test64 Opcode.FRECPX (TwoOperands (scalReg R.D31, scalReg R.D15)) - [| 0x5euy; 0xe1uy; 0xf9uy; 0xffuy |] - - test64 Opcode.USQADD (TwoOperands (scalReg R.S28, scalReg R.S19)) - [| 0x7euy; 0xa0uy; 0x3auy; 0x7cuy |] - - test64 Opcode.SQNEG (TwoOperands (scalReg R.H27, scalReg R.H10)) - [| 0x7euy; 0x60uy; 0x79uy; 0x5buy |] - - test64 Opcode.CMGE (ThreeOperands (scalReg R.D1, scalReg R.D20, Immediate 0L)) - [| 0x7euy; 0xe0uy; 0x8auy; 0x81uy |] - - test64 Opcode.CMLE (ThreeOperands (scalReg R.D24, scalReg R.D17, Immediate 0L)) - [| 0x7euy; 0xe0uy; 0x9auy; 0x38uy |] - - test64 Opcode.NEG (TwoOperands (scalReg R.D31, scalReg R.D11)) - [| 0x7euy; 0xe0uy; 0xb9uy; 0x7fuy |] - - test64 Opcode.SQXTUN (TwoOperands (scalReg R.S17, scalReg R.D16)) - [| 0x7euy; 0xa1uy; 0x2auy; 0x11uy |] - - test64 Opcode.UQXTN (TwoOperands (scalReg R.B1, scalReg R.H20)) - [| 0x7euy; 0x21uy; 0x4auy; 0x81uy |] - - test64 Opcode.FCVTXN (TwoOperands (scalReg R.S24, scalReg R.D23)) - [| 0x7euy; 0x61uy; 0x6auy; 0xf8uy |] - - test64 Opcode.FCVTNU (TwoOperands (scalReg R.S24, scalReg R.S23)) - [| 0x7euy; 0x21uy; 0xaauy; 0xf8uy |] - - test64 Opcode.FCVTMU (TwoOperands (scalReg R.D7, scalReg R.D0)) - [| 0x7euy; 0x61uy; 0xb8uy; 0x07uy |] - - test64 Opcode.FCVTAU (TwoOperands (scalReg R.S17, scalReg R.S16)) - [| 0x7euy; 0x21uy; 0xcauy; 0x11uy |] - - test64 Opcode.UCVTF (TwoOperands (scalReg R.D4, scalReg R.D2)) - [| 0x7euy; 0x61uy; 0xd8uy; 0x44uy |] - - test64 Opcode.FCMGE (ThreeOperands (scalReg R.S30, scalReg R.S23, - FPImmediate 0.0)) - [| 0x7euy; 0xa0uy; 0xcauy; 0xfeuy |] - - test64 Opcode.FCMLE (ThreeOperands (scalReg R.D8, scalReg R.D6, FPImmediate 0.0)) - [| 0x7euy; 0xe0uy; 0xd8uy; 0xc8uy |] - - test64 Opcode.FCVTPU (TwoOperands (scalReg R.S1, scalReg R.S17)) - [| 0x7euy; 0xa1uy; 0xaauy; 0x21uy |] - - test64 Opcode.FCVTZU (TwoOperands (scalReg R.D3, scalReg R.D1)) - [| 0x7euy; 0xe1uy; 0xb8uy; 0x23uy |] - - test64 Opcode.FRSQRTE (TwoOperands (scalReg R.S21, scalReg R.S17)) - [| 0x7euy; 0xa1uy; 0xdauy; 0x35uy |] - - test64 Opcode.FRSQRTE (TwoOperands (scalReg R.D29, scalReg R.D21)) - [| 0x7euy; 0xe1uy; 0xdauy; 0xbduy |] - - /// C4.6.12 Advanced SIMD scalar x indexed element - [] - member __.``[AArch64] Advanced SIMD scalar x indexed elem Parse Test`` () = - test64 Opcode.SQDMLAL (ThreeOperands (scalReg R.D1, scalReg R.S17, - SIMDOpr (SFReg (sVRegIdx R.V8 VecS 2uy)))) - [| 0x5fuy; 0x88uy; 0x3auy; 0x21uy |] - - test64 Opcode.SQDMLSL (ThreeOperands (scalReg R.S26, scalReg R.H24, - SIMDOpr (SFReg (sVRegIdx R.V6 VecH 7uy)))) - [| 0x5fuy; 0x76uy; 0x7buy; 0x1auy |] - - test64 Opcode.SQDMULL (ThreeOperands (scalReg R.D7, scalReg R.S19, - SIMDOpr (SFReg (sVRegIdx R.V12 VecS 3uy)))) - [| 0x5fuy; 0xacuy; 0xbauy; 0x67uy |] - - test64 Opcode.SQDMULH (ThreeOperands (scalReg R.H3, scalReg R.H16, - SIMDOpr (SFReg (sVRegIdx R.V14 VecH 3uy)))) - [| 0x5fuy; 0x7euy; 0xc2uy; 0x03uy |] - - test64 Opcode.SQDMULH (ThreeOperands (scalReg R.S27, scalReg R.S27, - SIMDOpr (SFReg (sVRegIdx R.V31 VecS 3uy)))) - [| 0x5fuy; 0xbfuy; 0xcbuy; 0x7buy |] - - test64 Opcode.SQRDMULH (ThreeOperands (scalReg R.H28, scalReg R.H19, - SIMDOpr (SFReg (sVRegIdx R.V15 VecH 7uy)))) - [| 0x5fuy; 0x7fuy; 0xdauy; 0x7cuy |] - - test64 Opcode.FMLA (ThreeOperands (scalReg R.D3, scalReg R.D6, - SIMDOpr (SFReg (sVRegIdx R.V19 VecD 1uy)))) - [| 0x5fuy; 0xd3uy; 0x18uy; 0xc3uy |] - - test64 Opcode.FMLS (ThreeOperands (scalReg R.S2, scalReg R.S1, - SIMDOpr (SFReg (sVRegIdx R.V16 VecS 3uy)))) - [| 0x5fuy; 0xb0uy; 0x58uy; 0x22uy |] - - test64 Opcode.FMUL (ThreeOperands (scalReg R.D30, scalReg R.D3, - SIMDOpr (SFReg (sVRegIdx R.V17 VecD 1uy)))) - [| 0x5fuy; 0xd1uy; 0x98uy; 0x7euy |] - - test64 Opcode.FMULX (ThreeOperands (scalReg R.S25, scalReg R.S6, - SIMDOpr (SFReg (sVRegIdx R.V30 VecS 1uy)))) - [| 0x7fuy; 0xbeuy; 0x90uy; 0xd9uy |] - - /// C4.6.13 Advanced SIMD shift by immediate - [] - member __.``[AArch64] Advanced SIMD shift by immediate Parse Test`` () = - test64 Opcode.SSHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 3L)) - [| 0x4fuy; 0x0duy; 0x05uy; 0xc5uy |] - - test64 Opcode.SSHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, EightH))), - Immediate 0xBL)) - [| 0x4fuy; 0x15uy; 0x05uy; 0xc5uy |] - - test64 Opcode.SSHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, FourS))), - Immediate 0xBL)) - [| 0x4fuy; 0x35uy; 0x05uy; 0xc5uy |] - - test64 Opcode.SSHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoD))), - Immediate 0x2EL)) - [| 0x4fuy; 0x52uy; 0x05uy; 0xc5uy |] - - test64 Opcode.SSRA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 3L)) - [| 0x4fuy; 0x0duy; 0x15uy; 0xc5uy |] - - test64 Opcode.SRSHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, EightH))), - Immediate 0xBL)) - [| 0x4fuy; 0x15uy; 0x25uy; 0xc5uy |] - - test64 Opcode.SRSRA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, FourS))), - Immediate 0xBL)) - [| 0x4fuy; 0x35uy; 0x35uy; 0xc5uy |] - - test64 Opcode.SHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, SixteenB))), - Immediate 5L)) - [| 0x4fuy; 0x0duy; 0x55uy; 0xc5uy |] - - test64 Opcode.SQSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 5L)) - [| 0x4fuy; 0x0duy; 0x75uy; 0xc5uy |] - - test64 Opcode.SHRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoD))), - Immediate 0x12L)) - [| 0x4fuy; 0x2euy; 0x85uy; 0xc5uy |] - - test64 Opcode.RSHRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - EightH))), - Immediate 3L)) - [| 0x4fuy; 0x0duy; 0x8duy; 0xc5uy |] - - test64 Opcode.SQSHRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - EightH))), - Immediate 3L)) - [| 0x4fuy; 0x0duy; 0x95uy; 0xc5uy |] - - test64 Opcode.SQRSHRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - EightH))), - Immediate 3L)) - [| 0x4fuy; 0x0duy; 0x9duy; 0xc5uy |] - - test64 Opcode.SSHLL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 5L)) - [| 0x4fuy; 0x0duy; 0xa5uy; 0xc5uy |] - - test64 Opcode.SCVTF (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V13, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V10, TwoD))), - Fbits 0x31uy)) - [| 0x4fuy; 0x4fuy; 0xe5uy; 0x4duy |] - - test64 Opcode.FCVTZS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V13, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V10, TwoD))), - Fbits 0x31uy)) - [| 0x4fuy; 0x4fuy; 0xfduy; 0x4duy |] - - test64 Opcode.USHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 3L)) - [| 0x6fuy; 0x0duy; 0x05uy; 0xc5uy |] - - test64 Opcode.USRA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 3L)) - [| 0x6fuy; 0x0duy; 0x15uy; 0xc5uy |] - - test64 Opcode.URSHR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 3L)) - [| 0x6fuy; 0x0duy; 0x25uy; 0xc5uy |] - - test64 Opcode.URSRA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 3L)) - [| 0x6fuy; 0x0duy; 0x35uy; 0xc5uy |] - - test64 Opcode.SRI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, SixteenB))), - Immediate 3L)) - [| 0x6fuy; 0x0duy; 0x45uy; 0xc5uy |] - - test64 Opcode.SLI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, SixteenB))), - Immediate 5L)) - [| 0x6fuy; 0x0duy; 0x55uy; 0xc5uy |] - - test64 Opcode.SQSHLU (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 5L)) - [| 0x6fuy; 0x0duy; 0x65uy; 0xc5uy |] - - test64 Opcode.UQSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - SixteenB))), - Immediate 5L)) - [| 0x6fuy; 0x0duy; 0x75uy; 0xc5uy |] - - test64 Opcode.SQSHRUN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - TwoD))), - Immediate 0x17L)) - [| 0x6fuy; 0x29uy; 0x85uy; 0xc5uy |] - - test64 Opcode.SQRSHRUN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - FourS))), - Immediate 5L)) - [| 0x6fuy; 0x1buy; 0x8duy; 0xc5uy |] - - test64 Opcode.UQSHRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoD))), - Immediate 0x1AL)) - [| 0x6fuy; 0x26uy; 0x95uy; 0xc5uy |] - - test64 Opcode.UQRSHRN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - FourS))), - Immediate 1L)) - [| 0x6fuy; 0x1fuy; 0x9duy; 0xc5uy |] - - test64 Opcode.USHLL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoS))), - Immediate 0xDL)) - [| 0x2fuy; 0x2duy; 0xa4uy; 0xbbuy |] - - test64 Opcode.UCVTF (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, FourS))), - Fbits 7uy)) - [| 0x6fuy; 0x39uy; 0xe5uy; 0xc5uy |] - - test64 Opcode.FCVTZU (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, FourS))), - Fbits 0x1Auy)) - [| 0x6fuy; 0x26uy; 0xfduy; 0xc5uy |] - - /// C4.6.14 Advanced SIMD table lookup - [] - member __.``[AArch64] Advanced SIMD table lookup Parse Test`` () = - test64 Opcode.TBL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V1, SixteenB))), - SIMDOpr (TwoRegs (SIMDVecReg (R.V6, SixteenB), - SIMDVecReg (R.V7, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, SixteenB))))) - [| 0x4euy; 0x03uy; 0x20uy; 0xc1uy |] - - test64 Opcode.TBL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V9, EightB))), - SIMDOpr (ThreeRegs (SIMDVecReg (R.V22, - SixteenB), - SIMDVecReg (R.V23, - SixteenB), - SIMDVecReg (R.V24, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, EightB))))) - [| 0x0euy; 0x03uy; 0x42uy; 0xc9uy |] - - test64 Opcode.TBL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (FourRegs (SIMDVecReg (R.V31, - SixteenB), - SIMDVecReg (R.V0, SixteenB), - SIMDVecReg (R.V1, SixteenB), - SIMDVecReg (R.V2, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, SixteenB))))) - [| 0x4euy; 0x03uy; 0x63uy; 0xe5uy |] - - test64 Opcode.TBL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V17, EightB))), - SIMDOpr (OneReg (SIMDVecReg (R.V27, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, EightB))))) - [| 0x0euy; 0x03uy; 0x03uy; 0x71uy |] - - test64 Opcode.TBX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, EightB))), - SIMDOpr (TwoRegs (SIMDVecReg (R.V7, SixteenB), - SIMDVecReg (R.V8, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V25, EightB))))) - [| 0x0euy; 0x19uy; 0x30uy; 0xfcuy |] - - test64 Opcode.TBX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, SixteenB))), - SIMDOpr (ThreeRegs (SIMDVecReg (R.V7, - SixteenB), - SIMDVecReg (R.V8, - SixteenB), - SIMDVecReg (R.V9, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V25, - SixteenB))))) - [| 0x4euy; 0x19uy; 0x50uy; 0xfcuy |] - - test64 Opcode.TBX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, EightB))), - SIMDOpr (FourRegs (SIMDVecReg (R.V7, SixteenB), - SIMDVecReg (R.V8, SixteenB), - SIMDVecReg (R.V9, SixteenB), - SIMDVecReg (R.V10, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V25, EightB))))) - [| 0x0euy; 0x19uy; 0x70uy; 0xfcuy |] - - test64 Opcode.TBX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, SixteenB))), - SIMDOpr (OneReg (SIMDVecReg (R.V7, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V25, - SixteenB))))) - [| 0x4euy; 0x19uy; 0x10uy; 0xfcuy |] - - /// C4.6.15 Advanced SIMD three different - [] - member __.``[AArch64] Advanced SIMD three different Parse Test`` () = - test64 Opcode.SADDL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, FourH))), - SIMDOpr (SFReg (SIMDVecReg (R.V11, FourH))))) - [| 0x0euy; 0x6buy; 0x03uy; 0x9auy |] - - test64 Opcode.SADDL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x03uy; 0x25uy |] - - test64 Opcode.SADDW (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, EightB))))) - [| 0x0euy; 0x27uy; 0x12uy; 0xbauy |] - - test64 Opcode.SADDW2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, EightH))))) - [| 0x4euy; 0x63uy; 0x10uy; 0x79uy |] - - test64 Opcode.SSUBL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, - EightH))))) - [| 0x4euy; 0x63uy; 0x20uy; 0x79uy |] - - test64 Opcode.SSUBW2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, - EightH))))) - [| 0x4euy; 0x63uy; 0x30uy; 0x79uy |] - - test64 Opcode.ADDHN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))))) - [| 0x4euy; 0x63uy; 0x40uy; 0x79uy |] - - test64 Opcode.SABAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, - EightH))))) - [| 0x4euy; 0x63uy; 0x50uy; 0x79uy |] - - test64 Opcode.SUBHN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))))) - [| 0x4euy; 0x63uy; 0x60uy; 0x79uy |] - - test64 Opcode.SABDL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, - EightH))))) - [| 0x4euy; 0x63uy; 0x70uy; 0x79uy |] - - test64 Opcode.SMLAL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V24, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoS))))) - [| 0x0euy; 0xa6uy; 0x82uy; 0x58uy |] - - test64 Opcode.SQDMLAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, - TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V23, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, - FourS))))) - [| 0x4euy; 0xa6uy; 0x92uy; 0xfauy |] - - test64 Opcode.SMLSL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V12, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V17, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, - EightH))))) - [| 0x4euy; 0x66uy; 0xa2uy; 0x2cuy |] - - test64 Opcode.SQDMLSL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V22, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - FourS))))) - [| 0x4euy; 0xa5uy; 0xb2uy; 0xc3uy |] - - test64 Opcode.SMULL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V11, FourH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourH))))) - [| 0x0euy; 0x65uy; 0xc1uy; 0x7cuy |] - - test64 Opcode.SQDMULL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V8, TwoS))))) - [| 0x0euy; 0xa8uy; 0xd0uy; 0x79uy |] - - test64 Opcode.PMULL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, OneQ))), - SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))))) - [| 0x4euy; 0xe3uy; 0xe2uy; 0x45uy |] - - test64 Opcode.UADDL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V11, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V19, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - EightB))))) - [| 0x2euy; 0x2euy; 0x02uy; 0x6buy |] - - test64 Opcode.UADDW2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - FourS))))) - [| 0x6euy; 0xaeuy; 0x12uy; 0x52uy |] - - test64 Opcode.USUBL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoS))))) - [| 0x2euy; 0xa1uy; 0x22uy; 0xbduy |] - - test64 Opcode.USUBW2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - SixteenB))))) - [| 0x6euy; 0x27uy; 0x33uy; 0x9buy |] - - test64 Opcode.RADDHN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - EightH))))) - [| 0x6euy; 0x27uy; 0x43uy; 0x9buy |] - - test64 Opcode.UABAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - SixteenB))))) - [| 0x6euy; 0x27uy; 0x53uy; 0x9buy |] - - test64 Opcode.RSUBHN2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - EightH))))) - [| 0x6euy; 0x27uy; 0x63uy; 0x9buy |] - - test64 Opcode.UABDL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - SixteenB))))) - [| 0x6euy; 0x27uy; 0x73uy; 0x9buy |] - - test64 Opcode.UMLAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - SixteenB))))) - [| 0x6euy; 0x27uy; 0x83uy; 0x9buy |] - - test64 Opcode.UMLSL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - SixteenB))))) - [| 0x6euy; 0x27uy; 0xa3uy; 0x9buy |] - - test64 Opcode.UMULL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V28, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, - SixteenB))))) - [| 0x6euy; 0x27uy; 0xc3uy; 0x9buy |] - - /// C4.6.16 Advanced SIMD three same - [] - member __.``[AArch64] Advanced SIMD three same Parse Test`` () = - test64 Opcode.SHADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x4euy; 0x25uy; 0x04uy; 0xb5uy |] - - test64 Opcode.SQADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0x0cuy; 0xb5uy |] - - test64 Opcode.SRHADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x14uy; 0xb5uy |] - - test64 Opcode.SHSUB (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x4euy; 0x25uy; 0x24uy; 0xb5uy |] - - test64 Opcode.SQSUB (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0x2cuy; 0xb5uy |] - - test64 Opcode.CMGT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x34uy; 0xb5uy |] - - test64 Opcode.CMGE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x4euy; 0x25uy; 0x3cuy; 0xb5uy |] - - test64 Opcode.SSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0x44uy; 0xb5uy |] - - test64 Opcode.SQSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x4cuy; 0xb5uy |] - - test64 Opcode.SRSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x4euy; 0x25uy; 0x54uy; 0xb5uy |] - - test64 Opcode.SQRSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))))) - [| 0x4euy; 0x65uy; 0x5cuy; 0xb5uy |] - - test64 Opcode.SMAX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x64uy; 0xb5uy |] - - test64 Opcode.SMIN (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x4euy; 0x25uy; 0x6cuy; 0xb5uy |] - - test64 Opcode.SABD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0x74uy; 0xb5uy |] - - test64 Opcode.SABA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x7cuy; 0xb5uy |] - - test64 Opcode.ADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0x25uy; 0x84uy; 0xb5uy |] - - test64 Opcode.CMTST (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0x8cuy; 0xb5uy |] - - test64 Opcode.MLA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0x94uy; 0xb5uy |] - - test64 Opcode.MUL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0x25uy; 0x9cuy; 0xb5uy |] - - test64 Opcode.SMAXP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0xa4uy; 0xb5uy |] - - test64 Opcode.SMINP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0xacuy; 0xb5uy |] - - test64 Opcode.SQDMULH (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - FourS))))) - [| 0x4euy; 0xa5uy; 0xb4uy; 0xb5uy |] - - test64 Opcode.ADDP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x4euy; 0x65uy; 0xbcuy; 0xb5uy |] - - test64 Opcode.FMAXNM (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0x25uy; 0xc6uy; 0xb5uy |] - - test64 Opcode.FMLA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V13, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x4euy; 0x65uy; 0xcduy; 0xb5uy |] - - test64 Opcode.FADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0x25uy; 0xd4uy; 0xb5uy |] - - test64 Opcode.FMULX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V17, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x4euy; 0x65uy; 0xdcuy; 0xb1uy |] - - test64 Opcode.FCMEQ (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V2, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0x25uy; 0xe4uy; 0x55uy |] - - test64 Opcode.FMAX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V13, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x4euy; 0x65uy; 0xf5uy; 0xb5uy |] - - test64 Opcode.FRECPS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V13, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0x25uy; 0xfduy; 0xb5uy |] - - test64 Opcode.AND (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V17, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0x25uy; 0x1cuy; 0xb1uy |] - - test64 Opcode.BIC (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0x65uy; 0x1euy; 0xb9uy |] - - test64 Opcode.FMINNM (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0xc4uy; 0x3duy |] - - test64 Opcode.FMLS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V20, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V29, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x4euy; 0xe5uy; 0xcfuy; 0xb4uy |] - - test64 Opcode.FSUB (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0xa5uy; 0xd4uy; 0xb5uy |] - - test64 Opcode.FMIN (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x4euy; 0xe5uy; 0xf4uy; 0x25uy |] - - test64 Opcode.FRSQRTS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - FourS))))) - [| 0x4euy; 0xa5uy; 0xfcuy; 0xbduy |] - - test64 Opcode.MOV (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0xa5uy; 0x1cuy; 0xb5uy |] - - test64 Opcode.ORN (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V9, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V13, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0xe5uy; 0x1duy; 0xa9uy |] - - test64 Opcode.UHADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x6euy; 0x25uy; 0x04uy; 0xb5uy |] - - test64 Opcode.UQADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x6euy; 0x65uy; 0x0cuy; 0xb5uy |] - - test64 Opcode.URHADD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0x14uy; 0xb5uy |] - - test64 Opcode.UHSUB (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x6euy; 0x25uy; 0x24uy; 0xb5uy |] - - test64 Opcode.UQSUB (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x6euy; 0x65uy; 0x2cuy; 0xb5uy |] - - test64 Opcode.CMHI (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0x34uy; 0xb5uy |] - - test64 Opcode.CMHS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x6euy; 0x25uy; 0x3cuy; 0xb5uy |] - - test64 Opcode.USHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x6euy; 0x65uy; 0x44uy; 0xb5uy |] - - test64 Opcode.UQSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0x4cuy; 0xb5uy |] - - test64 Opcode.URSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x6euy; 0x25uy; 0x54uy; 0xb5uy |] - - test64 Opcode.UQRSHL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))))) - [| 0x6euy; 0x65uy; 0x5cuy; 0xb5uy |] - - test64 Opcode.UMAX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0x64uy; 0xb5uy |] - - test64 Opcode.UMIN (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x6euy; 0x25uy; 0x6cuy; 0xb5uy |] - - test64 Opcode.UABD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x6euy; 0x65uy; 0x74uy; 0xb5uy |] - - test64 Opcode.UABA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0x7cuy; 0xb5uy |] - - test64 Opcode.SUB (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x6euy; 0x25uy; 0x84uy; 0xb5uy |] - - test64 Opcode.CMEQ (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x6euy; 0x65uy; 0x8cuy; 0xb5uy |] - - test64 Opcode.MLS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0x94uy; 0xb5uy |] - - test64 Opcode.PMUL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - SixteenB))))) - [| 0x6euy; 0x25uy; 0x9cuy; 0xb5uy |] - - test64 Opcode.UMAXP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, EightH))))) - [| 0x6euy; 0x65uy; 0xa4uy; 0xb5uy |] - - test64 Opcode.UMINP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0xacuy; 0xb5uy |] - - test64 Opcode.SQRDMULH (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - EightH))))) - [| 0x6euy; 0x65uy; 0xb4uy; 0xb5uy |] - - test64 Opcode.FMAXNMP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - FourS))))) - [| 0x6euy; 0x25uy; 0xc4uy; 0xb5uy |] - - test64 Opcode.FADDP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x6euy; 0x65uy; 0xd4uy; 0xb5uy |] - - test64 Opcode.FMUL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0x25uy; 0xdcuy; 0xb5uy |] - - test64 Opcode.FCMGE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x6euy; 0x65uy; 0xe4uy; 0xb5uy |] - - test64 Opcode.FACGE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0x25uy; 0xecuy; 0xb5uy |] - - test64 Opcode.FMAXP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x6euy; 0x65uy; 0xf4uy; 0xb5uy |] - - test64 Opcode.FDIV (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0x25uy; 0xfcuy; 0xb5uy |] - - test64 Opcode.EOR (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x6euy; 0x25uy; 0x1cuy; 0xb5uy |] - - test64 Opcode.BSL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x6euy; 0x65uy; 0x1cuy; 0xb5uy |] - - test64 Opcode.FMINNMP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, - FourS))))) - [| 0x6euy; 0xa5uy; 0xc4uy; 0xb5uy |] - - test64 Opcode.FABD (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x6euy; 0xe5uy; 0xd4uy; 0xb5uy |] - - test64 Opcode.FCMGT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0xe4uy; 0xb5uy |] - - test64 Opcode.FACGT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x6euy; 0xe5uy; 0xecuy; 0xb5uy |] - - test64 Opcode.FMINP (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa5uy; 0xf4uy; 0xb5uy |] - - test64 Opcode.BIT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x6euy; 0xa5uy; 0x1cuy; 0xb5uy |] - - test64 Opcode.BIF (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x6euy; 0xe5uy; 0x1cuy; 0xb5uy |] - - /// C4.6.17 Advanced SIMD two-register miscellaneous - [] - member __.``[AArch64] Advanced SIMD two-reg miscellaneous Parse Test`` () = - test64 Opcode.REV64 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V12, EightH))))) - [| 0x4euy; 0x60uy; 0x09uy; 0x83uy |] - - test64 Opcode.REV16 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V18, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))))) - [| 0x4euy; 0x20uy; 0x18uy; 0xb2uy |] - - test64 Opcode.SADDLP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V12, EightH))))) - [| 0x4euy; 0x60uy; 0x29uy; 0x83uy |] - - test64 Opcode.SUQADD (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V19, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V17, EightH))))) - [| 0x4euy; 0x60uy; 0x3auy; 0x33uy |] - - test64 Opcode.CLS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))))) - [| 0x4euy; 0xa0uy; 0x48uy; 0x7cuy |] - - test64 Opcode.SADDLP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V13, OneD))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoS))))) - [| 0x0euy; 0xa0uy; 0x28uy; 0xcduy |] - - test64 Opcode.SQABS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoD))))) - [| 0x4euy; 0xe0uy; 0x7auy; 0x46uy |] - - test64 Opcode.CMGT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V7, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, SixteenB))), - Immediate 0L)) - [| 0x4euy; 0x20uy; 0x88uy; 0x67uy |] - - test64 Opcode.CMEQ (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, FourH))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourH))), - Immediate 0L)) - [| 0x0euy; 0x60uy; 0x98uy; 0x79uy |] - - test64 Opcode.CMLT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V1, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V2, FourS))), - Immediate 0L)) - [| 0x4euy; 0xa0uy; 0xa8uy; 0x41uy |] - - test64 Opcode.ABS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V27, SixteenB))))) - [| 0x4euy; 0x20uy; 0xbbuy; 0x7duy |] - - test64 Opcode.XTN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x0euy; 0xa1uy; 0x28uy; 0xb9uy |] - - test64 Opcode.XTN2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V24, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoD))))) - [| 0x4euy; 0xa1uy; 0x28uy; 0xf8uy |] - - test64 Opcode.SQXTN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, EightH))))) - [| 0x0euy; 0x21uy; 0x48uy; 0xc3uy |] - - - test64 Opcode.SQXTN2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V10, EightH))))) - [| 0x4euy; 0x21uy; 0x49uy; 0x45uy |] - - test64 Opcode.FCVTN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, TwoD))))) - [| 0x0euy; 0x61uy; 0x68uy; 0x85uy |] - - test64 Opcode.FCVTN2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V24, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, FourS))))) - [| 0x4euy; 0x21uy; 0x68uy; 0xf8uy |] - - test64 Opcode.FCVTL (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V19, FourH))))) - [| 0x0euy; 0x21uy; 0x7auy; 0x7cuy |] - - test64 Opcode.FCVTL2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, FourS))))) - [| 0x4euy; 0x61uy; 0x7buy; 0x43uy |] - - test64 Opcode.FRINTN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V24, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x4euy; 0x61uy; 0x88uy; 0xb8uy |] - - test64 Opcode.FRINTM (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoS))))) - [| 0x0euy; 0x21uy; 0x98uy; 0x65uy |] - - test64 Opcode.FCVTNS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V13, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))))) - [| 0x4euy; 0x21uy; 0xa8uy; 0x6duy |] - - test64 Opcode.FCVTMS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoS))))) - [| 0x0euy; 0x21uy; 0xb8uy; 0x7euy |] - - test64 Opcode.FCVTAS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V22, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))))) - [| 0x4euy; 0x61uy; 0xc8uy; 0x76uy |] - - test64 Opcode.SCVTF (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V18, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, FourS))))) - [| 0x4euy; 0x21uy; 0xd8uy; 0x92uy |] - - test64 Opcode.FCMGT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - FPImmediate 0.0)) - [| 0x4euy; 0xa0uy; 0xc8uy; 0xbduy |] - - test64 Opcode.FCMEQ (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoS))), - FPImmediate 0.0)) - [| 0x0euy; 0xa0uy; 0xd8uy; 0x3euy |] - - test64 Opcode.FCMLT (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V25, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V9, TwoD))), - FPImmediate 0.0)) - [| 0x4euy; 0xe0uy; 0xe9uy; 0x39uy |] - - test64 Opcode.FABS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V14, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, FourS))))) - [| 0x4euy; 0xa0uy; 0xf8uy; 0x8euy |] - - test64 Opcode.FRINTP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V22, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, TwoS))))) - [| 0x0euy; 0xa1uy; 0x88uy; 0x96uy |] - - test64 Opcode.FRINTZ (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V9, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V2, TwoD))))) - [| 0x4euy; 0xe1uy; 0x98uy; 0x49uy |] - - test64 Opcode.FCVTPS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))))) - [| 0x4euy; 0xa1uy; 0xaauy; 0xc3uy |] - - test64 Opcode.FCVTZS (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V19, TwoS))))) - [| 0x0euy; 0xa1uy; 0xbauy; 0x7auy |] - - test64 Opcode.URECPE (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoS))))) - [| 0x0euy; 0xa1uy; 0xc8uy; 0xc7uy |] - - test64 Opcode.FRECPE (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, TwoD))))) - [| 0x4euy; 0xe1uy; 0xd8uy; 0x83uy |] - - test64 Opcode.REV32 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, EightH))))) - [| 0x6euy; 0x60uy; 0x08uy; 0x3euy |] - - test64 Opcode.UADDLP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, FourS))))) - [| 0x6euy; 0xa0uy; 0x28uy; 0xfcuy |] - - test64 Opcode.USQADD (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V3, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, TwoD))))) - [| 0x6euy; 0xe0uy; 0x38uy; 0x83uy |] - - test64 Opcode.CLZ (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V9, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, FourS))))) - [| 0x6euy; 0xa0uy; 0x48uy; 0xc9uy |] - - test64 Opcode.UADALP (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, EightH))))) - [| 0x6euy; 0x60uy; 0x68uy; 0x3euy |] - - test64 Opcode.SQNEG (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V15, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))))) - [| 0x2euy; 0xa0uy; 0x78uy; 0xefuy |] - - test64 Opcode.CMGE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V20, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V3, SixteenB))), - Immediate 0L)) - [| 0x6euy; 0x20uy; 0x88uy; 0x74uy |] - - test64 Opcode.CMLE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, EightB))), - Immediate 0L)) - [| 0x2euy; 0x20uy; 0x98uy; 0xfduy |] - - test64 Opcode.NEG (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V10, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, EightH))))) - [| 0x6euy; 0x60uy; 0xb8uy; 0xcauy |] - - test64 Opcode.SQXTN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, TwoD))))) - [| 0x0euy; 0xa1uy; 0x48uy; 0x87uy |] - - test64 Opcode.SQXTN2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V20, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x4euy; 0x61uy; 0x48uy; 0xb4uy |] - - test64 Opcode.SHLL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V19, TwoS))), - Shift (SRTypeLSL, Imm 32L))) - [| 0x2euy; 0xa1uy; 0x3auy; 0x75uy |] - - test64 Opcode.SHLL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V19, EightH))), - Shift (SRTypeLSL, Imm 16L))) - [| 0x6euy; 0x61uy; 0x3auy; 0x7duy |] - - test64 Opcode.UQXTN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V9, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, TwoD))))) - [| 0x2euy; 0xa1uy; 0x48uy; 0xe9uy |] - - test64 Opcode.UQXTN2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V2, EightH))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, FourS))))) - [| 0x6euy; 0x61uy; 0x48uy; 0xc2uy |] - - test64 Opcode.FCVTXN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V10, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoD))))) - [| 0x2euy; 0x61uy; 0x68uy; 0xcauy |] - - test64 Opcode.FCVTXN2 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoD))))) - [| 0x6euy; 0x61uy; 0x69uy; 0xc5uy |] - - test64 Opcode.FRINTA (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0x21uy; 0x88uy; 0xbauy |] - - test64 Opcode.FRINTX (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V28, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoD))))) - [| 0x6euy; 0x61uy; 0x98uy; 0xbcuy |] - - test64 Opcode.FCVTNU (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, TwoS))))) - [| 0x2euy; 0x21uy; 0xa8uy; 0xc5uy |] - - test64 Opcode.FCVTMU (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V6, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))))) - [| 0x6euy; 0x21uy; 0xbauy; 0xc6uy |] - - test64 Opcode.FCVTAU (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V27, TwoS))))) - [| 0x2euy; 0x21uy; 0xcbuy; 0x65uy |] - - test64 Opcode.UCVTF (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, FourS))))) - [| 0x6euy; 0x21uy; 0xd8uy; 0x96uy |] - - test64 Opcode.MVN (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V9, SixteenB))))) - [| 0x6euy; 0x20uy; 0x59uy; 0x3auy |] - - test64 Opcode.RBIT (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V18, EightB))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, EightB))))) - [| 0x2euy; 0x60uy; 0x58uy; 0xf2uy |] - - test64 Opcode.FCMGE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V23, FourS))), - FPImmediate 0.0)) - [| 0x6euy; 0xa0uy; 0xcauy; 0xe5uy |] - - test64 Opcode.FCMLE (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V14, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoS))), - FPImmediate 0.0)) - [| 0x2euy; 0xa0uy; 0xdauy; 0x4euy |] - - test64 Opcode.FNEG (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V19, TwoD))))) - [| 0x6euy; 0xe0uy; 0xfauy; 0x75uy |] - - test64 Opcode.FRINTI (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, TwoS))))) - [| 0x2euy; 0xa1uy; 0x9auy; 0xbeuy |] - - test64 Opcode.FCVTPU (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V9, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, TwoD))))) - [| 0x6euy; 0xe1uy; 0xa8uy; 0x89uy |] - - test64 Opcode.FCVTZU (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V15, TwoS))))) - [| 0x2euy; 0xa1uy; 0xb9uy; 0xfeuy |] - - test64 Opcode.URSQRTE (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V29, FourS))))) - [| 0x6euy; 0xa1uy; 0xcbuy; 0xa5uy |] - - test64 Opcode.FRSQRTE (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V18, TwoS))), - SIMDOpr (SFReg (SIMDVecReg (R.V25, TwoS))))) - [| 0x2euy; 0xa1uy; 0xdbuy; 0x32uy |] - - test64 Opcode.FSQRT (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V6, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))))) - [| 0x6euy; 0xa1uy; 0xf8uy; 0xa6uy |] - - /// C4.6.18 Advanced SIMD vector x indexed element - [] - member __.``[AArch64] Advanced SIMD vector x indexed elem Parse Test`` () = - test64 Opcode.SMLAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, EightH))), - SIMDOpr (SFReg (sVRegIdx R.V2 VecH 6uy)))) - [| 0x4fuy; 0x62uy; 0x28uy; 0xdauy |] - - test64 Opcode.SQDMLAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V2, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, - FourS))), - SIMDOpr (SFReg (sVRegIdx R.V17 VecS - 3uy)))) - [| 0x4fuy; 0xb1uy; 0x3buy; 0x42uy |] - - test64 Opcode.SMLSL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V10, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V14, - EightH))), - SIMDOpr (SFReg (sVRegIdx R.V9 VecH 3uy)))) - [| 0x4fuy; 0x79uy; 0x61uy; 0xcauy |] - - test64 Opcode.SQDMLSL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V15, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V1, TwoS))), - SIMDOpr (SFReg (sVRegIdx R.V18 VecS 0uy)))) - [| 0x0fuy; 0x92uy; 0x70uy; 0x2fuy |] - - test64 Opcode.MUL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V2, FourH))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, FourH))), - SIMDOpr (SFReg (sVRegIdx R.V3 VecH 3uy)))) - [| 0x0fuy; 0x73uy; 0x83uy; 0x42uy |] - - test64 Opcode.SMULL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, FourH))), - SIMDOpr (SFReg (sVRegIdx R.V12 VecH 6uy)))) - [| 0x0fuy; 0x6cuy; 0xa8uy; 0xc5uy |] - - test64 Opcode.SQDMULL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V2, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, - FourS))), - SIMDOpr (SFReg (sVRegIdx R.V29 VecS - 3uy)))) - [| 0x4fuy; 0xbduy; 0xbbuy; 0x42uy |] - - test64 Opcode.SQDMULH (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V29, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, - FourS))), - SIMDOpr (SFReg (sVRegIdx R.V29 VecS 2uy)))) - [| 0x4fuy; 0x9duy; 0xcbuy; 0x5duy |] - - test64 Opcode.SQRDMULH (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V26, - FourH))), - SIMDOpr (SFReg (SIMDVecReg (R.V30, - FourH))), - SIMDOpr (SFReg (sVRegIdx R.V13 VecH - 1uy)))) - [| 0x0fuy; 0x5duy; 0xd3uy; 0xdauy |] - - test64 Opcode.FMLA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, FourS))), - SIMDOpr (SFReg (sVRegIdx R.V3 VecS 3uy)))) - [| 0x4fuy; 0xa3uy; 0x1buy; 0x5buy |] - - test64 Opcode.FMLS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, TwoD))), - SIMDOpr (SFReg (sVRegIdx R.V19 VecD 0uy)))) - [| 0x4fuy; 0xd3uy; 0x53uy; 0x5buy |] - - test64 Opcode.FMUL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V27, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, FourS))), - SIMDOpr (SFReg (sVRegIdx R.V3 VecS 2uy)))) - [| 0x4fuy; 0x83uy; 0x9buy; 0x5buy |] - - test64 Opcode.MLA (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (sVRegIdx R.V13 VecS 3uy)))) - [| 0x6fuy; 0xaduy; 0x08uy; 0xbeuy |] - - test64 Opcode.UMLAL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V26, - EightH))), - SIMDOpr (SFReg (sVRegIdx R.V15 VecH 7uy)))) - [| 0x6fuy; 0x7fuy; 0x2buy; 0x56uy |] - - test64 Opcode.MLS (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V10, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V4, FourS))), - SIMDOpr (SFReg (sVRegIdx R.V23 VecS 2uy)))) - [| 0x6fuy; 0x97uy; 0x48uy; 0x8auy |] - - test64 Opcode.UMLSL (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V30, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V6, FourH))), - SIMDOpr (SFReg (sVRegIdx R.V14 VecH 2uy)))) - [| 0x2fuy; 0x6euy; 0x60uy; 0xdeuy |] - - test64 Opcode.UMULL2 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V10, TwoD))), - SIMDOpr (SFReg (SIMDVecReg (R.V7, FourS))), - SIMDOpr (SFReg (sVRegIdx R.V31 VecS 3uy)))) - [| 0x6fuy; 0xbfuy; 0xa8uy; 0xeauy |] - - test64 Opcode.FMULX (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V5, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V22, FourS))), - SIMDOpr (SFReg (sVRegIdx R.V13 VecS 1uy)))) - [| 0x6fuy; 0xaduy; 0x92uy; 0xc5uy |] - - /// C4.6.19 Cryptographic AES - [] - member __.``[AArch64] Cryptographic AES Parse Test`` () = - test64 Opcode.AESE (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))))) - [| 0x4euy; 0x28uy; 0x4auy; 0xb5uy |] - - test64 Opcode.AESD (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))))) - [| 0x4euy; 0x28uy; 0x5auy; 0xb5uy |] - - test64 Opcode.AESMC (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))))) - [| 0x4euy; 0x28uy; 0x6auy; 0xb5uy |] - - test64 Opcode.AESIMC (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, - SixteenB))))) - [| 0x4euy; 0x28uy; 0x7auy; 0xb5uy |] - - /// C4.6.20 Cryptographic three-register SHA - [] - member __.``[AArch64] Cryptographic three-register SHA Parse Test`` () = - test64 Opcode.SHA1C (ThreeOperands (scalReg R.Q24, scalReg R.S27, - SIMDOpr (SFReg (SIMDVecReg (R.V25, FourS))))) - [| 0x5euy; 0x19uy; 0x03uy; 0x78uy |] - - test64 Opcode.SHA1P (ThreeOperands (scalReg R.Q31, scalReg R.S31, - SIMDOpr (SFReg (SIMDVecReg (R.V19, FourS))))) - [| 0x5euy; 0x13uy; 0x13uy; 0xffuy |] - - test64 Opcode.SHA1M (ThreeOperands (scalReg R.Q28, scalReg R.S21, - SIMDOpr (SFReg (SIMDVecReg (R.V14, FourS))))) - [| 0x5euy; 0x0euy; 0x22uy; 0xbcuy |] - - test64 Opcode.SHA1SU0 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V7, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V16, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V23, - FourS))))) - [| 0x5euy; 0x17uy; 0x32uy; 0x07uy |] - - test64 Opcode.SHA256H (ThreeOperands (scalReg R.Q30, scalReg R.Q30, - SIMDOpr (SFReg (SIMDVecReg (R.V17, - FourS))))) - [| 0x5euy; 0x11uy; 0x43uy; 0xdeuy |] - - test64 Opcode.SHA256H2 (ThreeOperands (scalReg R.Q30, scalReg R.Q24, - SIMDOpr (SFReg (SIMDVecReg (R.V25, - FourS))))) - [| 0x5euy; 0x19uy; 0x53uy; 0x1euy |] - - test64 Opcode.SHA1SU0 (ThreeOperands (SIMDOpr (SFReg (SIMDVecReg (R.V31, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V21, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V23, - FourS))))) - [| 0x5euy; 0x17uy; 0x32uy; 0xbfuy |] - - /// C4.6.21 Cryptographic two-register SHA - [] - member __.``[AArch64] Cryptographic two-register SHA Parse Test`` () = - test64 Opcode.SHA1H (TwoOperands (scalReg R.S31, scalReg R.S10)) - [| 0x5euy; 0x28uy; 0x09uy; 0x5fuy |] - - test64 Opcode.SHA1SU1 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V23, FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V30, FourS))))) - [| 0x5euy; 0x28uy; 0x1buy; 0xd7uy |] - - test64 Opcode.SHA256SU0 (TwoOperands (SIMDOpr (SFReg (SIMDVecReg (R.V21, - FourS))), - SIMDOpr (SFReg (SIMDVecReg (R.V10, - FourS))))) - [| 0x5euy; 0x28uy; 0x29uy; 0x55uy |] - - /// C4.6.22 Floating-point compare - [] - member __.``[AArch64] Floating-point compare Parse Test`` () = - test64 Opcode.FCMP (TwoOperands (scalReg R.S7, scalReg R.S21)) - [| 0x1euy; 0x35uy; 0x20uy; 0xe0uy |] - - test64 Opcode.FCMP (TwoOperands (scalReg R.S28, FPImmediate 0.0)) - [| 0x1euy; 0x31uy; 0x23uy; 0x88uy |] - - test64 Opcode.FCMPE (TwoOperands (scalReg R.S22, scalReg R.S11)) - [| 0x1euy; 0x2buy; 0x22uy; 0xd0uy |] - - test64 Opcode.FCMPE (TwoOperands (scalReg R.S17, FPImmediate 0.0)) - [| 0x1euy; 0x39uy; 0x22uy; 0x38uy |] - - test64 Opcode.FCMP (TwoOperands (scalReg R.D6, scalReg R.D2)) - [| 0x1euy; 0x62uy; 0x20uy; 0xc0uy |] - - test64 Opcode.FCMP (TwoOperands (scalReg R.D14, FPImmediate 0.0)) - [| 0x1euy; 0x79uy; 0x21uy; 0xc8uy |] - - test64 Opcode.FCMPE (TwoOperands (scalReg R.D11, scalReg R.D20)) - [| 0x1euy; 0x74uy; 0x21uy; 0x70uy |] - - test64 Opcode.FCMPE (TwoOperands (scalReg R.D29, FPImmediate 0.0)) - [| 0x1euy; 0x63uy; 0x23uy; 0xb8uy |] - - /// C4.6.23 Floating-point conditional compare - [] - member __.``[AArch64] Floating-point conditional compare Parse Test`` () = - test64 Opcode.FCCMP (FourOperands (scalReg R.S26, scalReg R.S13, NZCV 0xDuy, - Cond CS)) // HS - [| 0x1euy; 0x2duy; 0x27uy; 0x4duy |] - - test64 Opcode.FCCMPE (FourOperands (scalReg R.S26, scalReg R.S10, NZCV 6uy, - Cond AL)) - [| 0x1euy; 0x2auy; 0xe7uy; 0x56uy |] - - test64 Opcode.FCCMP (FourOperands (scalReg R.D18, scalReg R.D9, NZCV 9uy, - Cond CC)) - [| 0x1euy; 0x69uy; 0x36uy; 0x49uy |] // LO - - test64 Opcode.FCCMPE (FourOperands (scalReg R.D26, scalReg R.D14, NZCV 2uy, - Cond AL)) - [| 0x1euy; 0x6euy; 0xe7uy; 0x52uy |] - - /// C4.6.24 Floating-point conditional select - [] - member __.``[AArch64] Floating-point conditional select Parse Test`` () = - test64 Opcode.FCSEL (FourOperands (scalReg R.S27, scalReg R.S2, scalReg R.S9, - Cond CS)) // HS - [| 0x1euy; 0x29uy; 0x2cuy; 0x5buy |] - - test64 Opcode.FCSEL (FourOperands (scalReg R.D19, scalReg R.D10, scalReg R.D28, - Cond AL)) - [| 0x1euy; 0x7cuy; 0xeduy; 0x53uy |] - - /// C4.6.25 Floating-point data-processing (1 source) - [] - member __.``[AArch64] FP data-processing (1 source) Parse Test`` () = - test64 Opcode.FMOV (TwoOperands (scalReg R.S26, scalReg R.S17)) - [| 0x1euy; 0x20uy; 0x42uy; 0x3auy |] - - test64 Opcode.FABS (TwoOperands (scalReg R.S10, scalReg R.S7)) - [| 0x1euy; 0x20uy; 0xc0uy; 0xeauy |] - - test64 Opcode.FNEG (TwoOperands (scalReg R.S14, scalReg R.S8)) - [| 0x1euy; 0x21uy; 0x41uy; 0x0euy |] - - test64 Opcode.FSQRT (TwoOperands (scalReg R.S24, scalReg R.S11)) - [| 0x1euy; 0x21uy; 0xc1uy; 0x78uy |] - - test64 Opcode.FCVT (TwoOperands (scalReg R.D10, scalReg R.S22)) - [| 0x1euy; 0x22uy; 0xc2uy; 0xcauy |] - - test64 Opcode.FCVT (TwoOperands (scalReg R.H16, scalReg R.S15)) - [| 0x1euy; 0x23uy; 0xc1uy; 0xf0uy |] - - test64 Opcode.FRINTN (TwoOperands (scalReg R.S1, scalReg R.S19)) - [| 0x1euy; 0x24uy; 0x42uy; 0x61uy |] - - test64 Opcode.FRINTP (TwoOperands (scalReg R.S28, scalReg R.S10)) - [| 0x1euy; 0x24uy; 0xc1uy; 0x5cuy |] - - test64 Opcode.FRINTM (TwoOperands (scalReg R.S24, scalReg R.S14)) - [| 0x1euy; 0x25uy; 0x41uy; 0xd8uy |] - - test64 Opcode.FRINTZ (TwoOperands (scalReg R.S14, scalReg R.S6)) - [| 0x1euy; 0x25uy; 0xc0uy; 0xceuy |] - - test64 Opcode.FRINTA (TwoOperands (scalReg R.S12, scalReg R.S10)) - [| 0x1euy; 0x26uy; 0x41uy; 0x4cuy |] - - test64 Opcode.FRINTX (TwoOperands (scalReg R.S24, scalReg R.S11)) - [| 0x1euy; 0x27uy; 0x41uy; 0x78uy |] - - test64 Opcode.FRINTI (TwoOperands (scalReg R.S2, scalReg R.S15)) - [| 0x1euy; 0x27uy; 0xc1uy; 0xe2uy |] - - test64 Opcode.FMOV (TwoOperands (scalReg R.D20, scalReg R.D17)) - [| 0x1euy; 0x60uy; 0x42uy; 0x34uy |] - - test64 Opcode.FABS (TwoOperands (scalReg R.D2, scalReg R.D17)) - [| 0x1euy; 0x60uy; 0xc2uy; 0x22uy |] - - test64 Opcode.FNEG (TwoOperands (scalReg R.D2, scalReg R.D21)) - [| 0x1euy; 0x61uy; 0x42uy; 0xa2uy |] - - test64 Opcode.FSQRT (TwoOperands (scalReg R.D6, scalReg R.D13)) - [| 0x1euy; 0x61uy; 0xc1uy; 0xa6uy |] - - test64 Opcode.FCVT (TwoOperands (scalReg R.S13, scalReg R.D14)) - [| 0x1euy; 0x62uy; 0x41uy; 0xcduy |] - - test64 Opcode.FCVT (TwoOperands (scalReg R.H10, scalReg R.D21)) - [| 0x1euy; 0x63uy; 0xc2uy; 0xaauy |] - - test64 Opcode.FRINTN (TwoOperands (scalReg R.D3, scalReg R.D15)) - [| 0x1euy; 0x64uy; 0x41uy; 0xe3uy |] - - test64 Opcode.FRINTP (TwoOperands (scalReg R.D18, scalReg R.D21)) - [| 0x1euy; 0x64uy; 0xc2uy; 0xb2uy |] - - test64 Opcode.FRINTM (TwoOperands (scalReg R.D20, scalReg R.D27)) - [| 0x1euy; 0x65uy; 0x43uy; 0x74uy |] - - test64 Opcode.FRINTZ (TwoOperands (scalReg R.D2, scalReg R.D23)) - [| 0x1euy; 0x65uy; 0xc2uy; 0xe2uy |] - - test64 Opcode.FRINTA (TwoOperands (scalReg R.D17, scalReg R.D26)) - [| 0x1euy; 0x66uy; 0x43uy; 0x51uy |] - - test64 Opcode.FRINTX (TwoOperands (scalReg R.D24, scalReg R.D21)) - [| 0x1euy; 0x67uy; 0x42uy; 0xb8uy |] - - test64 Opcode.FRINTI (TwoOperands (scalReg R.D21, scalReg R.D27)) - [| 0x1euy; 0x67uy; 0xc3uy; 0x75uy |] - - test64 Opcode.FCVT (TwoOperands (scalReg R.S20, scalReg R.H14)) - [| 0x1euy; 0xe2uy; 0x41uy; 0xd4uy |] - - test64 Opcode.FCVT (TwoOperands (scalReg R.D8, scalReg R.H28)) - [| 0x1euy; 0xe2uy; 0xc3uy; 0x88uy |] - - /// C4.6.26 Floating-point data-processing (2 source) - [] - member __.``[AArch64] FP data-processing (2 source) Parse Test`` () = - test64 Opcode.FMUL (ThreeOperands (scalReg R.S2, scalReg R.S1, scalReg R.S1)) - [| 0x1euy; 0x21uy; 0x08uy; 0x22uy |] - - test64 Opcode.FDIV (ThreeOperands (scalReg R.S8, scalReg R.S20, scalReg R.S2)) - [| 0x1euy; 0x22uy; 0x1auy; 0x88uy |] - - test64 Opcode.FADD (ThreeOperands (scalReg R.S14, scalReg R.S5, scalReg R.S2)) - [| 0x1euy; 0x22uy; 0x28uy; 0xaeuy |] - - test64 Opcode.FSUB (ThreeOperands (scalReg R.S22, scalReg R.S10, scalReg R.S3)) - [| 0x1euy; 0x23uy; 0x39uy; 0x56uy |] - - test64 Opcode.FMAX (ThreeOperands (scalReg R.S20, scalReg R.S23, scalReg R.S4)) - [| 0x1euy; 0x24uy; 0x4auy; 0xf4uy |] - - test64 Opcode.FMIN (ThreeOperands (scalReg R.S21, scalReg R.S8, scalReg R.S5)) - [| 0x1euy; 0x25uy; 0x59uy; 0x15uy |] - - test64 Opcode.FMAXNM (ThreeOperands (scalReg R.S18, scalReg R.S9, scalReg R.S6)) - [| 0x1euy; 0x26uy; 0x69uy; 0x32uy |] - - test64 Opcode.FMINNM (ThreeOperands (scalReg R.S26, scalReg R.S5, scalReg R.S7)) - [| 0x1euy; 0x27uy; 0x78uy; 0xbauy |] - - test64 Opcode.FNMUL (ThreeOperands (scalReg R.S26, scalReg R.S21, scalReg R.S8)) - [| 0x1euy; 0x28uy; 0x8auy; 0xbauy |] - - test64 Opcode.FMUL (ThreeOperands (scalReg R.D27, scalReg R.D21, scalReg R.D9)) - [| 0x1euy; 0x69uy; 0x0auy; 0xbbuy |] - - test64 Opcode.FDIV (ThreeOperands (scalReg R.D2, scalReg R.D5, scalReg R.D10)) - [| 0x1euy; 0x6auy; 0x18uy; 0xa2uy |] - - test64 Opcode.FADD (ThreeOperands (scalReg R.D26, scalReg R.D21, scalReg R.D11)) - [| 0x1euy; 0x6buy; 0x2auy; 0xbauy |] - - test64 Opcode.FSUB (ThreeOperands (scalReg R.D30, scalReg R.D13, scalReg R.D12)) - [| 0x1euy; 0x6cuy; 0x39uy; 0xbeuy |] - - test64 Opcode.FMAX (ThreeOperands (scalReg R.D26, scalReg R.D5, scalReg R.D13)) - [| 0x1euy; 0x6duy; 0x48uy; 0xbauy |] - - test64 Opcode.FMIN (ThreeOperands (scalReg R.D27, scalReg R.D21, scalReg R.D14)) - [| 0x1euy; 0x6euy; 0x5auy; 0xbbuy |] - - test64 Opcode.FMAXNM (ThreeOperands (scalReg R.D2, scalReg R.D23, scalReg R.D18)) - [| 0x1euy; 0x72uy; 0x6auy; 0xe2uy |] - - test64 Opcode.FMINNM (ThreeOperands (scalReg R.D2, scalReg R.D4, scalReg R.D31)) - [| 0x1euy; 0x7fuy; 0x78uy; 0x82uy |] - - test64 Opcode.FNMUL (ThreeOperands (scalReg R.D20, scalReg R.D30, scalReg R.D0)) - [| 0x1euy; 0x60uy; 0x8buy; 0xd4uy |] - - /// C4.6.27 Floating-point data-processing (3 source) - [] - member __.``[AArch64] FP data-processing (3 source) Parse Test`` () = - test64 Opcode.FMADD (FourOperands (scalReg R.S25, scalReg R.S26, scalReg R.S31, - scalReg R.S1)) - [| 0x1fuy; 0x1fuy; 0x07uy; 0x59uy |] - - test64 Opcode.FMSUB (FourOperands (scalReg R.S4, scalReg R.S26, scalReg R.S30, - scalReg R.S2)) - [| 0x1fuy; 0x1euy; 0x8buy; 0x44uy |] - - test64 Opcode.FNMADD (FourOperands (scalReg R.S22, scalReg R.S8, scalReg R.S28, - scalReg R.S4)) - [| 0x1fuy; 0x3cuy; 0x11uy; 0x16uy |] - - test64 Opcode.FNMSUB (FourOperands (scalReg R.S21, scalReg R.S14, scalReg R.S24, - scalReg R.S8)) - [| 0x1fuy; 0x38uy; 0xa1uy; 0xd5uy |] - - test64 Opcode.FMADD (FourOperands (scalReg R.D25, scalReg R.D10, scalReg R.D16, - scalReg R.D16)) - [| 0x1fuy; 0x50uy; 0x41uy; 0x59uy |] - - test64 Opcode.FMSUB (FourOperands (scalReg R.D29, scalReg R.D14, scalReg R.D8, - scalReg R.D24)) - [| 0x1fuy; 0x48uy; 0xe1uy; 0xdduy |] - - test64 Opcode.FNMADD (FourOperands (scalReg R.D17, scalReg R.D11, scalReg R.D4, - scalReg R.D28)) - [| 0x1fuy; 0x64uy; 0x71uy; 0x71uy |] - - test64 Opcode.FNMSUB (FourOperands (scalReg R.D17, scalReg R.D3, scalReg R.D2, - scalReg R.D30)) - [| 0x1fuy; 0x62uy; 0xf8uy; 0x71uy |] - - /// C4.6.28 Floating-point immediate - [] - member __.``[AArch64] Floating-point immediate Parse Test`` () = - test64 Opcode.FMOV (TwoOperands (scalReg R.S21, FPImmediate 2.0)) - [| 0x1euy; 0x20uy; 0x10uy; 0x15uy |] - - test64 Opcode.FMOV (TwoOperands (scalReg R.D25, FPImmediate 10.5)) - [| 0x1euy; 0x64uy; 0xb0uy; 0x19uy |] - - /// C4.6.29 Conversion between floating-point and fixed-point - [] - member __.``[AArch64] Conversion between FP and fixed-pt Parse Test`` () = - test64 Opcode.SCVTF (ThreeOperands (scalReg R.S28, - OprRegister R.W5, Fbits 0x16uy)) - [| 0x1euy; 0x02uy; 0xa8uy; 0xbcuy |] - - test64 Opcode.UCVTF (ThreeOperands (scalReg R.S5, - OprRegister R.W5, Fbits 2uy)) - [| 0x1euy; 0x03uy; 0xf8uy; 0xa5uy |] - - test64 Opcode.FCVTZS (ThreeOperands (OprRegister R.W17, - scalReg R.S4, Fbits 1uy)) - [| 0x1euy; 0x18uy; 0xfcuy; 0x91uy |] - - test64 Opcode.FCVTZU (ThreeOperands (OprRegister R.W5, - scalReg R.S14, Fbits 0x1Fuy)) - [| 0x1euy; 0x19uy; 0x85uy; 0xc5uy |] - - test64 Opcode.SCVTF (ThreeOperands (scalReg R.D5, - OprRegister R.W14, Fbits 0xFuy)) - [| 0x1euy; 0x42uy; 0xc5uy; 0xc5uy |] - - test64 Opcode.UCVTF (ThreeOperands (scalReg R.D5, - OprRegister R.W14, Fbits 0x17uy)) - [| 0x1euy; 0x43uy; 0xa5uy; 0xc5uy |] - - test64 Opcode.FCVTZS (ThreeOperands (OprRegister R.W5, - scalReg R.D14, Fbits 0x1Buy)) - [| 0x1euy; 0x58uy; 0x95uy; 0xc5uy |] - - test64 Opcode.FCVTZU (ThreeOperands (OprRegister R.W5, - scalReg R.D26, Fbits 0x16uy)) - [| 0x1euy; 0x59uy; 0xabuy; 0x45uy |] - - test64 Opcode.SCVTF (ThreeOperands (scalReg R.S17, - OprRegister R.X6, Fbits 0xFuy)) - [| 0x9euy; 0x02uy; 0xc4uy; 0xd1uy |] - - test64 Opcode.UCVTF (ThreeOperands (scalReg R.S5, - OprRegister R.X13, Fbits 0x13uy)) - [| 0x9euy; 0x03uy; 0xb5uy; 0xa5uy |] - - test64 Opcode.FCVTZS (ThreeOperands (OprRegister R.X13, - scalReg R.S6, Fbits 4uy)) - [| 0x9euy; 0x18uy; 0xf0uy; 0xcduy |] - - test64 Opcode.FCVTZU (ThreeOperands (OprRegister R.X13, - scalReg R.S14, - Fbits 0x1Buy)) - [| 0x9euy; 0x19uy; 0x95uy; 0xcduy |] - - test64 Opcode.SCVTF (ThreeOperands (scalReg R.D5, - OprRegister R.X28, Fbits 0x1Euy)) - [| 0x9euy; 0x42uy; 0x8buy; 0x85uy |] - - test64 Opcode.UCVTF (ThreeOperands (scalReg R.D5, - OprRegister R.X14, Fbits 0xFuy)) - [| 0x9euy; 0x43uy; 0xc5uy; 0xc5uy |] - - test64 Opcode.FCVTZS (ThreeOperands (OprRegister R.X17, - scalReg R.D22, Fbits 7uy)) - [| 0x9euy; 0x58uy; 0xe6uy; 0xd1uy |] - - test64 Opcode.FCVTZU (ThreeOperands (OprRegister R.X18, - scalReg R.D14, Fbits 0xCuy)) - [| 0x9euy; 0x59uy; 0xd1uy; 0xd2uy |] - - /// C4.6.30 Conversion between floating-point and integer - [] - member __.``[AArch64] Conversion between FP and integer Parse Test`` () = - test64 Opcode.FCVTNS (TwoOperands (OprRegister R.W20, scalReg R.S10)) - [| 0x1euy; 0x20uy; 0x01uy; 0x54uy |] - - test64 Opcode.FCVTNS (TwoOperands (OprRegister R.W10, scalReg R.D26)) - [| 0x1euy; 0x60uy; 0x03uy; 0x4auy |] - - test64 Opcode.FCVTNS (TwoOperands (OprRegister R.X2, scalReg R.S11 )) - [| 0x9euy; 0x20uy; 0x01uy; 0x62uy |] - - test64 Opcode.FCVTNS (TwoOperands (OprRegister R.X23, scalReg R.D18)) - [| 0x9euy; 0x60uy; 0x02uy; 0x57uy |] - - test64 Opcode.FCVTNU (TwoOperands (OprRegister R.W24, scalReg R.S5 )) - [| 0x1euy; 0x21uy; 0x00uy; 0xb8uy |] - - test64 Opcode.FCVTNU (TwoOperands (OprRegister R.W18, scalReg R.D21)) - [| 0x1euy; 0x61uy; 0x02uy; 0xb2uy |] - - test64 Opcode.FCVTNU (TwoOperands (OprRegister R.X27, scalReg R.S5 )) - [| 0x9euy; 0x21uy; 0x00uy; 0xbbuy |] - - test64 Opcode.FCVTNU (TwoOperands (OprRegister R.X28, scalReg R.D13)) - [| 0x9euy; 0x61uy; 0x01uy; 0xbcuy |] - - test64 Opcode.SCVTF (TwoOperands (scalReg R.S26, OprRegister R.W5)) - [| 0x1euy; 0x22uy; 0x00uy; 0xbauy |] - - test64 Opcode.SCVTF (TwoOperands (scalReg R.D8, OprRegister R.W15)) - [| 0x1euy; 0x62uy; 0x01uy; 0xe8uy |] - - test64 Opcode.SCVTF (TwoOperands (scalReg R.S2, OprRegister R.X14)) - [| 0x9euy; 0x22uy; 0x01uy; 0xc2uy |] - - test64 Opcode.SCVTF (TwoOperands (scalReg R.D29, OprRegister R.X14)) - [| 0x9euy; 0x62uy; 0x01uy; 0xdduy |] - - test64 Opcode.UCVTF (TwoOperands (scalReg R.S29, OprRegister R.W21)) - [| 0x1euy; 0x23uy; 0x02uy; 0xbduy |] - - test64 Opcode.UCVTF (TwoOperands (scalReg R.D7, OprRegister R.W14)) - [| 0x1euy; 0x63uy; 0x01uy; 0xc7uy |] - - test64 Opcode.UCVTF (TwoOperands (scalReg R.S30, OprRegister R.X14)) - [| 0x9euy; 0x23uy; 0x01uy; 0xdeuy |] - - test64 Opcode.UCVTF (TwoOperands (scalReg R.D25, OprRegister R.X21)) - [| 0x9euy; 0x63uy; 0x02uy; 0xb9uy |] - - test64 Opcode.FCVTAS (TwoOperands (OprRegister R.W10, scalReg R.S12)) - [| 0x1euy; 0x24uy; 0x01uy; 0x8auy |] - - test64 Opcode.FCVTAS (TwoOperands (OprRegister R.W25, scalReg R.D20)) - [| 0x1euy; 0x64uy; 0x02uy; 0x99uy |] - - test64 Opcode.FCVTAS (TwoOperands (OprRegister R.X21, scalReg R.S18)) - [| 0x9euy; 0x24uy; 0x02uy; 0x55uy |] - - test64 Opcode.FCVTAS (TwoOperands (OprRegister R.X24, scalReg R.D25)) - [| 0x9euy; 0x64uy; 0x03uy; 0x38uy |] - - test64 Opcode.FCVTAU (TwoOperands (OprRegister R.W29, scalReg R.S26)) - [| 0x1euy; 0x25uy; 0x03uy; 0x5duy |] - - test64 Opcode.FCVTAU (TwoOperands (OprRegister R.W5, scalReg R.D26)) - [| 0x1euy; 0x65uy; 0x03uy; 0x45uy |] - - test64 Opcode.FCVTAU (TwoOperands (OprRegister R.X17, scalReg R.S24)) - [| 0x9euy; 0x25uy; 0x03uy; 0x11uy |] - - test64 Opcode.FCVTAU (TwoOperands (OprRegister R.X20, scalReg R.D27)) - [| 0x9euy; 0x65uy; 0x03uy; 0x74uy |] - - test64 Opcode.FMOV (TwoOperands (OprRegister R.W14, scalReg R.S25)) - [| 0x1euy; 0x26uy; 0x03uy; 0x2euy |] - - test64 Opcode.FMOV (TwoOperands (scalReg R.S3, OprRegister R.W14)) - [| 0x1euy; 0x27uy; 0x01uy; 0xc3uy |] - - test64 Opcode.FMOV (TwoOperands (OprRegister R.X11, scalReg R.D21)) - [| 0x9euy; 0x66uy; 0x02uy; 0xabuy |] - - test64 Opcode.FMOV (TwoOperands (scalReg R.D3, OprRegister R.X15)) - [| 0x9euy; 0x67uy; 0x01uy; 0xe3uy |] - - test64 Opcode.FMOV (TwoOperands (OprRegister R.X29, - SIMDOpr (SFReg (sVRegIdx R.V16 VecD 1uy)))) - [| 0x9euy; 0xaeuy; 0x02uy; 0x1duy |] - - test64 Opcode.FMOV (TwoOperands (SIMDOpr (SFReg (sVRegIdx R.V24 VecD 1uy)), - OprRegister R.X23)) - [| 0x9euy; 0xafuy; 0x02uy; 0xf8uy |] - - test64 Opcode.FCVTPS (TwoOperands (OprRegister R.W14, scalReg R.S6)) - [| 0x1euy; 0x28uy; 0x00uy; 0xceuy |] - - test64 Opcode.FCVTPS (TwoOperands (OprRegister R.W6, scalReg R.D3)) - [| 0x1euy; 0x68uy; 0x00uy; 0x66uy |] - - test64 Opcode.FCVTPS (TwoOperands (OprRegister R.X3, scalReg R.S17)) - [| 0x9euy; 0x28uy; 0x02uy; 0x23uy |] - - test64 Opcode.FCVTPS (TwoOperands (OprRegister R.X26, scalReg R.D27)) - [| 0x9euy; 0x68uy; 0x03uy; 0x7auy |] - - test64 Opcode.FCVTPU (TwoOperands (OprRegister R.W28, scalReg R.S16)) - [| 0x1euy; 0x29uy; 0x02uy; 0x1cuy |] - - test64 Opcode.FCVTPU (TwoOperands (OprRegister R.W19, scalReg R.D9)) - [| 0x1euy; 0x69uy; 0x01uy; 0x33uy |] - - test64 Opcode.FCVTPU (TwoOperands (OprRegister R.X9, scalReg R.S3)) - [| 0x9euy; 0x29uy; 0x00uy; 0x69uy |] - - test64 Opcode.FCVTPU (TwoOperands (OprRegister R.X21, scalReg R.D19)) - [| 0x9euy; 0x69uy; 0x02uy; 0x75uy |] - - test64 Opcode.FCVTMS (TwoOperands (OprRegister R.W29, scalReg R.S14)) - [| 0x1euy; 0x30uy; 0x01uy; 0xdduy |] - - test64 Opcode.FCVTMS (TwoOperands (OprRegister R.W2, scalReg R.D27)) - [| 0x1euy; 0x70uy; 0x03uy; 0x62uy |] - - test64 Opcode.FCVTMS (TwoOperands (OprRegister R.X25, scalReg R.S3)) - [| 0x9euy; 0x30uy; 0x00uy; 0x79uy |] - - test64 Opcode.FCVTMS (TwoOperands (OprRegister R.X6, scalReg R.D4)) - [| 0x9euy; 0x70uy; 0x00uy; 0x86uy |] - - test64 Opcode.FCVTMU (TwoOperands (OprRegister R.W5, scalReg R.S12)) - [| 0x1euy; 0x31uy; 0x01uy; 0x85uy |] - - test64 Opcode.FCVTMU (TwoOperands (OprRegister R.W29, scalReg R.D19)) - [| 0x1euy; 0x71uy; 0x02uy; 0x7duy |] - - test64 Opcode.FCVTMU (TwoOperands (OprRegister R.XZR, scalReg R.S31)) - [| 0x9euy; 0x31uy; 0x03uy; 0xffuy |] - - test64 Opcode.FCVTMU (TwoOperands (OprRegister R.X0, scalReg R.D0)) - [| 0x9euy; 0x71uy; 0x00uy; 0x00uy |] - - test64 Opcode.FCVTZS (TwoOperands (OprRegister R.W3, scalReg R.S26)) - [| 0x1euy; 0x38uy; 0x03uy; 0x43uy |] - - test64 Opcode.FCVTZS (TwoOperands (OprRegister R.W13, scalReg R.D6)) - [| 0x1euy; 0x78uy; 0x00uy; 0xcduy |] - - test64 Opcode.FCVTZS (TwoOperands (OprRegister R.X25, scalReg R.S19)) - [| 0x9euy; 0x38uy; 0x02uy; 0x79uy |] - - test64 Opcode.FCVTZS (TwoOperands (OprRegister R.X6, scalReg R.D10)) - [| 0x9euy; 0x78uy; 0x01uy; 0x46uy |] - - test64 Opcode.FCVTZU (TwoOperands (OprRegister R.W1, scalReg R.S19)) - [| 0x1euy; 0x39uy; 0x02uy; 0x61uy |] - - test64 Opcode.FCVTZU (TwoOperands (OprRegister R.W27, scalReg R.D25)) - [| 0x1euy; 0x79uy; 0x03uy; 0x3buy |] - - test64 Opcode.FCVTZU (TwoOperands (OprRegister R.X19, scalReg R.S2)) - [| 0x9euy; 0x39uy; 0x00uy; 0x53uy |] - - test64 Opcode.FCVTZU (TwoOperands (OprRegister R.X2, scalReg R.D19)) - [| 0x9euy; 0x79uy; 0x02uy; 0x62uy |] - -module ARMThumb = - open B2R2.FrontEnd.BinLifter.ARM32 - - let private test arch e c op w q (s: SIMDDataTypes option) oprs (b: byte[]) = - let mode = ArchOperationMode.ThumbMode - let parser = ARM32Parser (ISA.Init arch e, mode, None) - let ins = parser.Parse (b, 0UL) :?> ARM32Instruction - let cond' = ins.Condition - let opcode' = ins.Opcode - let wback' = ins.WriteBack - let q' = ins.Qualifier - let simd' = ins.SIMDTyp - let oprs' = ins.Operands - let w = match w with | Some true -> true | _ -> false // XXX - Assert.AreEqual (cond', c) - Assert.AreEqual (opcode', op) - Assert.AreEqual (wback', w) - Assert.AreEqual (q', q) - Assert.AreEqual (simd', s) - Assert.AreEqual (oprs', oprs) - - let private testThumb = test Arch.ARMv7 Endian.Big - - /// A4.3 Branch instructions - [] - type BranchClass () = - [] - member __.``[Thumb] Branch Parse Test`` () = - testThumb (Condition.HI) Op.B None N None - (OneOperand (OprMemory (LiteralMode 76L))) - [| 0xd8uy; 0x26uy |] - - testThumb (Condition.AL) Op.B None N None - (OneOperand (OprMemory (LiteralMode 776L))) - [| 0xe1uy; 0x84uy |] - - testThumb (Condition.LS) Op.B None W None - (OneOperand (OprMemory (LiteralMode 4294652108L))) - [| 0xf6uy; 0x73uy; 0x88uy; 0x66uy |] - - testThumb (Condition.AL) Op.B None W None - (OneOperand (OprMemory (LiteralMode 12780328L))) - [| 0xf0uy; 0x30uy; 0x91uy; 0x94uy |] - - testThumb Condition.UN Op.CBNZ None N None - (TwoOperands (OprReg R.R2, OprMemory (LiteralMode 6L))) - [| 0xb9uy; 0x1auy |] - - testThumb (Condition.AL) Op.BLX None N None - (OneOperand (OprReg R.SB)) - [| 0x47uy; 0xc8uy |] - - testThumb (Condition.AL) Op.BLX None N None - (OneOperand (OprMemory (LiteralMode 4286800648L))) - [| 0xf4uy; 0x36uy; 0xe1uy; 0x84uy |] - - testThumb (Condition.AL) Op.BX None N None - (OneOperand (OprReg R.R3)) - [| 0x47uy; 0x18uy |] - - testThumb (Condition.AL) Op.BXJ None N None - (OneOperand (OprReg R.R5)) - [| 0xf3uy; 0xc5uy; 0x8fuy; 0x00uy |] - - testThumb (Condition.AL) Op.TBH None N None - (OneOperand (OprMemory (OffsetMode - (RegOffset (R.LR, None, R.R7, - Some (SRTypeLSL, Imm 1u)))))) - [| 0xe8uy; 0xdeuy; 0xf0uy; 0x17uy |] - - /// A4.4 Data-processing instructions - [] - type DataProcessingClass () = - /// A4.4.1 Standard data-processing instructions - [] - member __.``[Thumb] Standard data-processing Parse Test`` () = - testThumb (Condition.AL) Op.ADCS None N None - (ThreeOperands (OprReg R.R3, OprReg R.R2, OprImm 159383552L)) - [| 0xf1uy; 0x52uy; 0x63uy; 0x18uy |] - - testThumb (Condition.AL) Op.ADD None N None - (ThreeOperands (OprReg R.IP, OprReg R.SP, OprReg R.IP)) - [| 0x44uy; 0xecuy |] - - testThumb (Condition.AL) Op.ADD None N None - (ThreeOperands (OprReg R.SP, OprReg R.SP, OprReg R.SL)) - [| 0x44uy; 0xd5uy |] - - testThumb (Condition.AL) Op.ADD None N None - (TwoOperands (OprReg R.FP, OprReg R.R1)) - [| 0x44uy; 0x8buy |] - - testThumb (Condition.AL) Op.ADD None N None - (ThreeOperands (OprReg R.SP, OprReg R.SP, OprImm 408L)) - [| 0xb0uy; 0x66uy |] - - testThumb (Condition.AL) Op.ADD None N None - (ThreeOperands (OprReg R.R4, OprReg R.SP, OprImm 160L)) - [| 0xacuy; 0x28uy |] - - testThumb (Condition.AL) Op.ADD None N None - (ThreeOperands (OprReg R.LR, OprReg R.R4, OprImm 1L)) - [| 0xf1uy; 0x04uy; 0x0euy; 0x01uy |] - - testThumb Condition.UN Op.ADDS None N None - (ThreeOperands (OprReg R.R4, OprReg R.R1, OprReg R.R0)) - [| 0x18uy; 0x0cuy |] - - testThumb Condition.UN Op.ADDS None N None - (ThreeOperands (OprReg R.R7, OprReg R.R6, OprImm 1L)) - [| 0x1cuy; 0x77uy |] - - testThumb (Condition.AL) Op.ADDW None N None - (ThreeOperands (OprReg R.R0, OprReg R.FP, OprImm 1L)) - [| 0xf2uy; 0x0buy; 0x00uy; 0x01uy |] - - testThumb (Condition.AL) Op.ADR None W None - (TwoOperands (OprReg R.R0, OprMemory (LiteralMode 1L))) - [| 0xf2uy; 0x0fuy; 0x00uy; 0x01uy |] - - testThumb (Condition.AL) Op.ADR None N None - (TwoOperands (OprReg R.R2, - OprMemory (LiteralMode 60L))) - [| 0xa2uy; 0x0fuy |] - - testThumb Condition.UN Op.ANDS None N None - (ThreeOperands (OprReg R.R6, OprReg R.R6, OprReg R.R7)) - [| 0x40uy; 0x3euy |] - - testThumb (Condition.AL) Op.BICS None N None - (FourOperands (OprReg R.R6, OprReg R.IP, OprReg R.R5, - OprShift (SRTypeLSL, Imm 28u))) - [| 0xeauy; 0x3cuy; 0x76uy; 0x05uy |] - - testThumb (Condition.AL) Op.CMP None N None - (TwoOperands (OprReg R.R5, OprImm 243L)) - [| 0x2duy; 0xf3uy |] - - testThumb (Condition.AL) Op.CMP None N None - (TwoOperands (OprReg R.R8, OprReg R.SB)) - [| 0x45uy; 0xc8uy |] - - testThumb (Condition.AL) Op.CMP None N None - (TwoOperands (OprReg R.R4, OprReg R.R8)) - [| 0x45uy; 0x44uy |] - - testThumb (Condition.AL) Op.MOV None N None - (TwoOperands (OprReg R.R7, OprImm 524296L)) - [| 0xf0uy; 0x4fuy; 0x17uy; 0x08uy |] - - testThumb Condition.UN Op.MOVS None N None - (ThreeOperands (OprReg R.R6, OprReg R.R1, - OprShift (SRTypeLSL, Imm 0u))) - [| 0x00uy; 0x0euy |] - - testThumb (Condition.AL) Op.MOVW None N None - (TwoOperands (OprReg R.FP, OprImm 10242L)) - [| 0xf6uy; 0x42uy; 0x0buy; 0x02uy |] - - testThumb (Condition.AL) Op.MVN None N None - (ThreeOperands (OprReg R.R4, OprReg R.LR, - OprShift (SRTypeLSR, Imm 30u))) - [| 0xeauy; 0x6fuy; 0xf4uy; 0x9euy |] - - testThumb (Condition.AL) Op.RSBS None N None - (ThreeOperands (OprReg R.R3, OprReg R.SB, OprImm 8912896L)) - [| 0xf5uy; 0xd9uy; 0x03uy; 0x08uy |] - - testThumb Condition.UN Op.RSBS None N None - (ThreeOperands (OprReg R.R3, OprReg R.R1, OprImm 0L)) - [| 0x42uy; 0x4buy |] - - testThumb (Condition.AL) Op.TEQ None N None - (TwoOperands (OprReg R.R1, OprImm 17408L)) - [| 0xf4uy; 0x91uy; 0x4fuy; 0x88uy |] - - testThumb (Condition.AL) Op.TST None N None - (ThreeOperands (OprReg R.R2, OprReg R.FP, - OprShift (SRTypeASR, Imm 21u))) - [| 0xeauy; 0x12uy; 0x5fuy; 0x6buy |] - - /// A4.4.2 Shift instructions - [] - member __.``[Thumb] Shift Parse Test`` () = - testThumb (Condition.AL) Op.ASRS None W None - (ThreeOperands (OprReg R.FP, OprReg R.SL, OprReg R.R7)) - [| 0xfauy; 0x5auy; 0xfbuy; 0x07uy |] - - testThumb (Condition.AL) Op.LSLS None N None - (ThreeOperands (OprReg R.R1, OprReg R.R6, OprImm 16L)) - [| 0x04uy; 0x31uy |] - - testThumb (Condition.AL) Op.LSRS None N None - (ThreeOperands (OprReg R.R2, OprReg R.R1, OprImm 32L)) - [| 0x08uy; 0x0auy |] - - testThumb (Condition.AL) Op.LSRS None W None - (ThreeOperands (OprReg R.IP, OprReg R.SL, OprImm 3L)) - [| 0xeauy; 0x5fuy; 0x0cuy; 0xdauy |] - - testThumb (Condition.AL) Op.RRXS None N None - (TwoOperands (OprReg R.R0, OprReg R.SB)) - [| 0xeauy; 0x5fuy; 0x00uy; 0x39uy |] - - /// A4.4.3 Multiply instructions - member __.``[Thumb] Multiply Parse Test`` () = - testThumb (Condition.AL) Op.MLA None N None - (FourOperands (OprReg R.SB, OprReg R.R0, OprReg R.R1, - OprReg R.IP)) - [| 0xfbuy; 0x00uy; 0xc9uy; 0x01uy |] - - testThumb (Condition.AL) Op.MUL None N None - (ThreeOperands (OprReg R.IP, OprReg R.R3, OprReg R.FP)) - [| 0xfbuy; 0x03uy; 0xfcuy; 0x0buy |] - - testThumb Condition.UN Op.MULS None N None - (ThreeOperands (OprReg R.R6, OprReg R.R4, OprReg R.R6)) - [| 0x43uy; 0x66uy |] - - testThumb (Condition.AL) Op.SMLADX None N None - (FourOperands (OprReg R.IP, OprReg R.SL, OprReg R.R4, - OprReg R.R5)) - [| 0xfbuy; 0x2auy; 0x5cuy; 0x14uy |] - - testThumb (Condition.AL) Op.SMLATB None N None - (FourOperands (OprReg R.IP, OprReg R.LR, OprReg R.R1, - OprReg R.R5)) - [| 0xfbuy; 0x1euy; 0x5cuy; 0x21uy |] - - testThumb (Condition.AL) Op.SMLALTB None N None - (FourOperands (OprReg R.R8, OprReg R.SL, OprReg R.R1, - OprReg R.R3)) - [| 0xfbuy; 0xc1uy; 0x8auy; 0xa3uy |] - - testThumb (Condition.AL) Op.SMLSLDX None N None - (FourOperands (OprReg R.IP, OprReg R.LR, OprReg R.R0, - OprReg R.R5)) - [| 0xfbuy; 0xd0uy; 0xceuy; 0xd5uy |] - - testThumb (Condition.AL) Op.SMMULR None N None - (ThreeOperands (OprReg R.R0, OprReg R.R8, OprReg R.SB)) - [| 0xfbuy; 0x58uy; 0xf0uy; 0x19uy |] - - testThumb (Condition.AL) Op.SMULTT None N None - (ThreeOperands (OprReg R.R8, OprReg R.FP, OprReg R.R7)) - [| 0xfbuy; 0x1buy; 0xf8uy; 0x37uy |] - - testThumb (Condition.AL) Op.SMULL None N None - (FourOperands (OprReg R.SL, OprReg R.SB, OprReg R.R3, - OprReg R.R4)) - [| 0xfbuy; 0x83uy; 0xa9uy; 0x04uy |] - - /// A4.4.4 Saturating instructions - [] - member __.``[Thumb] Saturating Parse Test`` () = - testThumb (Condition.AL) Op.SSAT16 None N None - (ThreeOperands (OprReg R.IP, OprImm 6L, OprReg R.R8)) - [| 0xf3uy; 0x28uy; 0x0cuy; 0x05uy |] - - testThumb (Condition.AL) Op.USAT None N None - (FourOperands (OprReg R.R7, OprImm 17L, OprReg R.R3, - OprShift (SRTypeASR, Imm 6u))) - [| 0xf3uy; 0xa3uy; 0x17uy; 0x91uy |] - - /// A4.4.5 Saturating addition and subtraction instructions - [] - member __.``[Thumb] Saturating addition and subtraction Parse Test`` () = - testThumb (Condition.AL) Op.QDADD None N None - (ThreeOperands (OprReg R.IP, OprReg R.LR, OprReg R.R6)) - [| 0xfauy; 0x86uy; 0xfcuy; 0x9euy |] - - /// A4.4.6 Packing and unpacking instructions - [] - member __.``[Thumb] Packing and unpacking Parse Test`` () = - testThumb (Condition.AL) Op.PKHBT None N None - (FourOperands (OprReg R.R0, OprReg R.IP, OprReg R.SL, - OprShift (SRTypeLSL, Imm 17u))) - [| 0xeauy; 0xccuy; 0x40uy; 0x4auy |] - - testThumb (Condition.AL) Op.SXTAH None N None - (FourOperands (OprReg R.R4, OprReg R.R0, OprReg R.R6, - OprShift (SRTypeROR, Imm 24u))) - [| 0xfauy; 0x00uy; 0xf4uy; 0xb6uy |] - - testThumb (Condition.AL) Op.SXTB16 None N None - (ThreeOperands (OprReg R.SB, OprReg R.R6, - OprShift (SRTypeROR, Imm 8u))) - [| 0xfauy; 0x2fuy; 0xf9uy; 0x96uy |] - - testThumb (Condition.AL) Op.UXTH None N None - (TwoOperands (OprReg R.R7, OprReg R.R0)) - [| 0xb2uy; 0x87uy |] - - testThumb (Condition.AL) Op.UXTH None W None - (TwoOperands (OprReg R.R2, OprReg R.IP)) - [| 0xfauy; 0x1fuy; 0xf2uy; 0x8cuy |] - - /// A4.4.7 Parallel addition and subtraction instructions - [] - member __.``[Thumb] Parallel addition and subtraction Parse Test`` () = - // Signed - testThumb (Condition.AL) Op.SADD16 None N None - (ThreeOperands (OprReg R.FP, OprReg R.IP, OprReg R.R0)) - [| 0xfauy; 0x9cuy; 0xfbuy; 0x00uy |] - - // Saturating - testThumb (Condition.AL) Op.QSAX None N None - (ThreeOperands (OprReg R.LR, OprReg R.R8, OprReg R.SB)) - [| 0xfauy; 0xe8uy; 0xfeuy; 0x19uy |] - - // Signed halving - testThumb (Condition.AL) Op.SHSUB8 None N None - (ThreeOperands (OprReg R.IP, OprReg R.R0, OprReg R.R7)) - [| 0xfauy; 0xc0uy; 0xfcuy; 0x27uy |] - - // Unsigned - testThumb (Condition.AL) Op.UASX None N None - (ThreeOperands (OprReg R.R1, OprReg R.R0, OprReg R.R6)) - [| 0xfauy; 0xa0uy; 0xf1uy; 0x46uy |] - - // Unsigned saturating - testThumb (Condition.AL) Op.UQADD8 None N None - (ThreeOperands (OprReg R.SB, OprReg R.LR, OprReg R.R3)) - [| 0xfauy; 0x8euy; 0xf9uy; 0x53uy |] - - // Unsigned halving - testThumb (Condition.AL) Op.UHASX None N None - (ThreeOperands (OprReg R.R8, OprReg R.R0, OprReg R.SL)) - [| 0xfauy; 0xa0uy; 0xf8uy; 0x6auy |] - - //// A4.4.8 Divide instructions - [] - member __.``[Thumb] Divide Parse Test`` () = - testThumb (Condition.AL) Op.UDIV None N None - (ThreeOperands (OprReg R.IP, OprReg R.R0, OprReg R.LR)) - [| 0xfbuy; 0xb0uy; 0xfcuy; 0xfeuy |] - - /// A4.4.9 Miscellaneous data-processing instructions - [] - member __.``[Thumb] Miscellaneous data-processing Parse Test`` () = - testThumb (Condition.AL) Op.BFC None N None - (ThreeOperands (OprReg R.IP, OprImm 4L, OprImm 15L)) - [| 0xf3uy; 0x6fuy; 0x1cuy; 0x12uy |] - - testThumb (Condition.AL) Op.BFI None N None - (FourOperands (OprReg R.SL, OprReg R.R1, OprImm 11L, - OprImm 7L)) - [| 0xf3uy; 0x61uy; 0x2auy; 0xd1uy |] - - testThumb (Condition.AL) Op.RBIT None N None - (TwoOperands (OprReg R.IP, OprReg R.R4)) - [| 0xfauy; 0x94uy; 0xfcuy; 0xa4uy |] - - testThumb (Condition.AL) Op.SBFX None N None - (FourOperands (OprReg R.SB, OprReg R.LR, OprImm 0L, - OprImm 25L)) - [| 0xf3uy; 0x4euy; 0x09uy; 0x18uy |] - - /// A4.5 Status register access instructions - [] - type StatusOprRegAccessClass () = - [] - member __.``[Thumb] Status register access Parse Test`` () = - testThumb (Condition.AL) Op.MRS None N None - (TwoOperands (OprReg R.R5, OprReg R.APSR)) - [| 0xf3uy; 0xefuy; 0x85uy; 0x00uy |] - - testThumb (Condition.AL) Op.MRS None N None - (TwoOperands (OprReg R.IP, OprReg R.SPSR)) - [| 0xf3uy; 0xffuy; 0x8cuy; 0x00uy |] - - testThumb (Condition.AL) Op.MSR None N None - (TwoOperands (OprSpecReg (R.CPSR, Some PSRs),OprReg R.FP)) - [| 0xf3uy; 0x8buy; 0x84uy; 0x00uy |] - - testThumb (Condition.AL) Op.MSR None N None - (TwoOperands (OprSpecReg (R.CPSR, Some PSRsc), OprReg R.IP)) - [| 0xf3uy; 0x8cuy; 0x85uy; 0x00uy |] - - testThumb Condition.UN Op.CPSID None N (* W *) None - (TwoOperands (OprIflag IF, OprImm 4L)) - [| 0xf3uy; 0xafuy; 0x87uy; 0x64uy |] - - testThumb Condition.UN Op.CPSIE None N None - (OneOperand (OprIflag AF)) - [| 0xb6uy; 0x65uy |] - - /// A4.5.1 Banked register access instructions - [] - member __.``[Thumb] Banked register access Parse Test`` () = - testThumb (Condition.AL) Op.MRS None N None - (TwoOperands (OprReg R.R0, OprReg R.LRusr)) - [| 0xf3uy; 0xe6uy; 0x80uy; 0x20uy |] - - testThumb (Condition.AL) Op.MSR None N None - (TwoOperands (OprReg R.SPSRabt, OprReg R.R1)) - [| 0xf3uy; 0x91uy; 0x84uy; 0x30uy |] - - /// A4.6 Load/store instructions - [] - type LoadStoreClass () = - [] - member __.``[Thumb] Load/store (Lord) Parse Test`` () = - testThumb (Condition.AL) Op.LDR (Some false) N None - (TwoOperands (OprReg R.R1, OprMemory - (OffsetMode (ImmOffset (R.SP, Some Plus, Some 60L))))) - [| 0x99uy; 0x0fuy |] - - testThumb (Condition.AL) Op.LDR None N None - (TwoOperands (OprReg R.R4, OprMemory (LiteralMode 220L))) - [| 0x4cuy; 0x37uy |] - - testThumb (Condition.AL) Op.LDR (Some false) W None - (TwoOperands (OprReg R.R0, - OprMemory (LiteralMode 135L))) - [| 0xf8uy; 0xdfuy; 0x00uy; 0x87uy |] - - testThumb (Condition.AL) Op.LDR None N None - (TwoOperands (OprReg R.IP, - OprMemory (OffsetMode - (RegOffset (R.SB, Some Plus, R.R8, - Some (SRTypeLSL, - Imm 3u)))))) - [| 0xf8uy; 0x59uy; 0xc0uy; 0x38uy |] - - testThumb (Condition.AL) Op.LDR (Some true) N None - (TwoOperands (OprReg R.R2, - OprMemory (PreIdxMode - (ImmOffset (R.R1, Some Plus, Some 51L))))) - [| 0xf8uy; 0x51uy; 0x2fuy; 0x33uy |] - - testThumb (Condition.AL) Op.LDR (Some false) W None - (TwoOperands (OprReg R.IP, - OprMemory (OffsetMode - (ImmOffset (R.LR, Some Plus, Some 128L))))) - [| 0xf8uy; 0xdeuy; 0xc0uy; 0x80uy |] - - testThumb (Condition.AL) Op.LDRH (Some false) N None - (TwoOperands (OprReg R.FP, - OprMemory (OffsetMode - (ImmOffset (R.SB, Some Minus, - Some 130L))))) - [| 0xf8uy; 0x39uy; 0xbcuy; 0x82uy |] - - testThumb (Condition.AL) Op.LDRSH None N None - (TwoOperands (OprReg R.R6, - OprMemory (LiteralMode -587L))) - [| 0xf9uy; 0x3fuy; 0x62uy; 0x4buy |] - - testThumb (Condition.AL) Op.LDRSH (Some false) N None - (TwoOperands (OprReg R.FP, - OprMemory (OffsetMode - (ImmOffset (R.R3, Some Plus, Some 11L))))) - [| 0xf9uy; 0xb3uy; 0xb0uy; 0x0buy |] - - testThumb (Condition.AL) Op.LDRB (Some false) N None - (TwoOperands (OprReg R.R6, - OprMemory (OffsetMode - (ImmOffset (R.R4, Some Plus, Some 6L))))) - [| 0x79uy; 0xa6uy |] - - testThumb (Condition.AL) Op.LDRB (Some false) N (* W *) None - (TwoOperands (OprReg R.SL, - OprMemory (OffsetMode - (RegOffset (R.R2, Some Plus, R.R6, - Some (SRTypeLSL, Imm 3u)))))) - [| 0xf8uy; 0x12uy; 0xa0uy; 0x36uy |] - - testThumb (Condition.AL) Op.LDRB (Some true) N None - (TwoOperands (OprReg R.R8, - OprMemory (PostIdxMode - (ImmOffset (R.R4, Some Minus, - Some 12L))))) - [| 0xf8uy; 0x14uy; 0x89uy; 0x0cuy |] - - testThumb (Condition.AL) Op.LDRB None N (* W *) None - (TwoOperands (OprReg R.R3, OprMemory (LiteralMode 240L))) - [| 0xf8uy; 0x9fuy; 0x30uy; 0xf0uy |] - - testThumb (Condition.AL) Op.LDRSB (Some false) N None - (TwoOperands (OprReg R.R1, - OprMemory (OffsetMode - (ImmOffset (R.R8, Some Plus, - Some 3122L))))) - [| 0xf9uy; 0x98uy; 0x1cuy; 0x32uy |] - - testThumb (Condition.AL) Op.LDRSB (Some false) N (* W *) None - (TwoOperands (OprReg R.SB, - OprMemory (OffsetMode - (RegOffset (R.LR, Some Plus, R.R0, - Some (SRTypeLSL, - Imm 2u)))))) - [| 0xf9uy; 0x1euy; 0x90uy; 0x20uy |] - - testThumb (Condition.AL) Op.LDRD (Some false) N None - (ThreeOperands (OprReg R.IP, OprReg R.R6, - OprMemory (LiteralMode -264L))) - [| 0xe9uy; 0x5fuy; 0xc6uy; 0x42uy |] - - [] - member __.``[Thumb] Load/store (Store) Parse Test`` () = - testThumb (Condition.AL) Op.STR (Some false) N None - (TwoOperands (OprReg R.R7, - OprMemory (OffsetMode - (ImmOffset (R.R6, Some Plus, Some 96L))))) - [| 0x66uy; 0x37uy |] - - testThumb (Condition.AL) Op.STRH (Some false) N None - (TwoOperands (OprReg R.R7, - OprMemory (OffsetMode - (ImmOffset (R.R2, Some Plus, Some 34L))))) - [| 0x84uy; 0x57uy |] - - testThumb (Condition.AL) Op.STRB (Some false) N None - (TwoOperands (OprReg R.R4, - OprMemory - (OffsetMode - (RegOffset (R.R3, Some Plus, R.R2, None))))) - [| 0x54uy; 0x9cuy |] - - testThumb (Condition.AL) Op.STRB (Some true) N None - (TwoOperands (OprReg R.LR, - OprMemory (PostIdxMode - (ImmOffset - (R.SB, Some Minus, Some 130L))))) - [| 0xf8uy; 0x09uy; 0xe9uy; 0x82uy |] - - testThumb (Condition.AL) Op.STRB (Some false) W None - (TwoOperands (OprReg R.IP, - OprMemory (OffsetMode - (ImmOffset (R.R6, Some Plus, - Some 2060L))))) - [| 0xf8uy; 0x86uy; 0xc8uy; 0x0cuy |] - - testThumb (Condition.AL) Op.STRB (Some false) N (* W *) None - (TwoOperands (OprReg R.R0, - OprMemory (OffsetMode - (RegOffset (R.SL, Some Plus, R.IP, - Some (SRTypeLSL, - Imm 2u)))))) - [| 0xf8uy; 0x0auy; 0x00uy; 0x2cuy |] - - testThumb (Condition.AL) Op.STRD (Some true) N None - (ThreeOperands (OprReg R.R3, OprReg R.SB, - OprMemory (PreIdxMode - (ImmOffset (R.SL, Some Minus, - Some 240L))))) - [| 0xe9uy; 0x6auy; 0x39uy; 0x3cuy |] - - [] - member __.``[Thumb] Load/store (Load unprivileged) Parse Test`` () = - testThumb (Condition.AL) Op.LDRT None N None - (TwoOperands (OprReg R.R1, - OprMemory (OffsetMode - (ImmOffset (R.R0, None, Some 4L))))) - [| 0xf8uy; 0x50uy; 0x1euy; 0x04uy |] - - testThumb (Condition.AL) Op.LDRHT None N None - (TwoOperands (OprReg R.IP, - OprMemory (OffsetMode - (ImmOffset (R.R4, None, Some 1L))))) - [| 0xf8uy; 0x34uy; 0xceuy; 0x01uy |] - - testThumb (Condition.AL) Op.LDRSBT None N None - (TwoOperands (OprReg R.SB, - OprMemory (OffsetMode - (ImmOffset (R.IP, None, Some 9L))))) - [| 0xf9uy; 0x1cuy; 0x9euy; 0x09uy |] - - [] - member __.``[Thumb] Load/store (Store unprivileged) Parse Test`` () = - testThumb (Condition.AL) Op.STRHT None N None - (TwoOperands (OprReg R.FP, - OprMemory (OffsetMode (ImmOffset (R.R7, None, - Some 83L))))) - [| 0xf8uy; 0x27uy; 0xbeuy; 0x53uy |] - - [] - member __.``[Thumb] Load/store (Load-Exclusive) Parse Test`` () = - testThumb (Condition.AL) Op.LDREX None N None - (TwoOperands (OprReg R.FP, - OprMemory (OffsetMode - (ImmOffset (R.SB, None, Some 56L))))) - [| 0xe8uy; 0x59uy; 0xbfuy; 0x0euy |] - - testThumb (Condition.AL) Op.LDREXB None N None - (TwoOperands (OprReg R.R0, - OprMemory (OffsetMode - (ImmOffset (R.SB, None, None))))) - [| 0xe8uy; 0xd9uy; 0x0fuy; 0x4fuy |] - - testThumb (Condition.AL) Op.LDREXD None N None - (ThreeOperands (OprReg R.SL, OprReg R.IP, - OprMemory (OffsetMode - (ImmOffset (R.LR, None, None))))) - [| 0xe8uy; 0xdeuy; 0xacuy; 0x7fuy |] - - [] - member __.``[Thumb] Load/store (Store-Exclusive) Parse Test`` () = - testThumb (Condition.AL) Op.STREX None N None - (ThreeOperands (OprReg R.SL, OprReg R.LR, - OprMemory (OffsetMode - (ImmOffset (R.R1, None, Some 48L))))) - [| 0xe8uy; 0x41uy; 0xeauy; 0x0cuy |] - - testThumb (Condition.AL) Op.STREXH None N None - (ThreeOperands (OprReg R.R6, OprReg R.SL, - OprMemory (OffsetMode - (ImmOffset (R.R8, None, None))))) - [| 0xe8uy; 0xc8uy; 0xafuy; 0x56uy |] - - testThumb (Condition.AL) Op.STREXD None N None - (FourOperands (OprReg R.R4, OprReg R.IP, OprReg R.FP, - OprMemory (OffsetMode - (ImmOffset (R.R0, None, None))))) - [| 0xe8uy; 0xc0uy; 0xcbuy; 0x74uy |] - - /// A4.7 Load/store multiple instructions - [] - type LoadStoreMultipleClass () = - [] - member __.``[Thumb] Load/store multiple Parse Test`` () = - testThumb (Condition.AL) Op.LDM (Some true) N None - (TwoOperands (OprReg R.R3, OprRegList [R.R0; R.R6; R.R7])) - [| 0xcbuy; 0xc1uy |] - - testThumb (Condition.AL) Op.LDM (Some false) W None - (TwoOperands (OprReg R.R8, - OprRegList [R.R2; R.R7; R.R8; R.IP; R.LR])) - [| 0xe8uy; 0x98uy; 0x51uy; 0x84uy |] - - testThumb (Condition.AL) Op.POP None W None - (OneOperand (OprRegList [R.R0; R.R4; R.SB; R.SL; R.PC])) - [| 0xe8uy; 0xbduy; 0x86uy; 0x11uy |] - - testThumb (Condition.AL) Op.POP None W None - (OneOperand (OprRegList [ R.R3 ])) - [| 0xf8uy; 0x5duy; 0x3buy; 0x04uy |] - - testThumb (Condition.AL) Op.PUSH None N None - (OneOperand (OprRegList [R.R0; R.R1; R.R4; R.R5; R.LR])) - [| 0xb5uy; 0x33uy |] - - testThumb (Condition.AL) Op.PUSH None W None - (OneOperand (OprRegList [R.R2; R.R7; R.R8])) - [| 0xe9uy; 0x2duy; 0x01uy; 0x84uy |] - - testThumb (Condition.AL) Op.PUSH None W None - (OneOperand (OprRegList [ R.R1 ])) - [| 0xf8uy; 0x4duy; 0x1duy; 0x04uy |] - - testThumb (Condition.AL) Op.STM (Some true) N None - (TwoOperands (OprReg R.R5, - OprRegList [R.R0; R.R1; R.R5; R.R7])) - [| 0xc5uy; 0xa3uy |] - - testThumb (Condition.AL) Op.STM (Some false) W None - (TwoOperands (OprReg R.R2, - OprRegList [R.R4; R.R7; R.R8; R.FP; R.IP; R.LR])) - [| 0xe8uy; 0x82uy; 0x59uy; 0x90uy |] - - /// A4.8 Miscellaneous instructions - [] - type MiscellaneousClass () = - [] - member __.``[Thumb] Miscellaneous Parse Test`` () = - testThumb (Condition.AL) Op.DBG None N None - (OneOperand (OprImm 11L)) - [| 0xf3uy; 0xafuy; 0x80uy; 0xfbuy |] - - testThumb (Condition.AL) Op.DMB None N None - (OneOperand (OprOption BarrierOption.NSH)) - [| 0xf3uy; 0xbfuy; 0x8fuy; 0x57uy |] - - testThumb Condition.UN Op.ITE None N None - (OneOperand (OprCond Condition.VS)) - [| 0xbfuy; 0x6cuy |] - - testThumb (Condition.AL) Op.NOP None W None - NoOperand - [| 0xf3uy; 0xafuy; 0x80uy; 0x00uy |] - - testThumb (Condition.AL) Op.PLD None N None - (OneOperand (OprMemory (OffsetMode - (RegOffset (R.IP, None, R.FP, - Some (SRTypeLSL, Imm 1u)))))) - [| 0xf8uy; 0x1cuy; 0xf0uy; 0x1buy |] - - testThumb (Condition.AL) Op.PLD None N None - (OneOperand (OprMemory (OffsetMode - (ImmOffset (R.R0, Some Minus, Some 32L))))) - [| 0xf8uy; 0x10uy; 0xfcuy; 0x20uy |] - - testThumb (Condition.AL) Op.PLD None N None - (OneOperand (OprMemory (LiteralMode -142L))) - [| 0xf8uy; 0x1fuy; 0xf0uy; 0x8euy |] - - testThumb (Condition.AL) Op.PLD None N None - (OneOperand (OprMemory (LiteralMode 15L))) - [| 0xf8uy; 0x9fuy; 0xf0uy; 0x0fuy |] - - testThumb (Condition.AL) Op.PLDW None N None - (OneOperand (OprMemory (OffsetMode - (RegOffset (R.R7, None, R.FP, - Some (SRTypeLSL, Imm 1u)))))) - [| 0xf8uy; 0x37uy; 0xf0uy; 0x1buy |] - - testThumb (Condition.AL) Op.PLDW None N None - (OneOperand (OprMemory (OffsetMode - (ImmOffset (R.R2, Some Minus, Some 49L))))) - [| 0xf8uy; 0x32uy; 0xfcuy; 0x31uy |] - - testThumb (Condition.AL) Op.PLDW None N None - (OneOperand (OprMemory (OffsetMode - (ImmOffset (R.IP, Some Plus, Some 195L))))) - [| 0xf8uy; 0xbcuy; 0xf0uy; 0xc3uy |] - - testThumb (Condition.AL) Op.PLI None N None - (OneOperand (OprMemory (OffsetMode - (ImmOffset (R.SL, Some Plus, Some 3L))))) - [| 0xf9uy; 0x9auy; 0xf0uy; 0x03uy |] - - testThumb Condition.UN Op.SETEND None N None - (OneOperand (OprEndian Endian.Big)) - [| 0xb6uy; 0x58uy |] - - /// A4.9 Exception-generating and exception-handling instructions - [] - type ExcepGenAndExcepHandClass () = - [] - member __.``[Thumb] Exception-gen and exception-handling Parse Test`` () = - testThumb Condition.UN Op.BKPT None N None - (OneOperand (OprImm 48L)) - [| 0xbeuy; 0x30uy |] - - testThumb (Condition.AL) Op.SMC None N None - (OneOperand (OprImm 8L)) - [| 0xf7uy; 0xf8uy; 0x80uy; 0x00uy |] - - testThumb (Condition.AL) Op.RFEIA (Some true) N None - (OneOperand (OprReg R.SL)) - [| 0xe9uy; 0xbauy; 0xc0uy; 0x00uy |] - - testThumb (Condition.AL) Op.SUBS None N None - (ThreeOperands (OprReg R.PC, OprReg R.LR, OprImm 8L)) - [| 0xf3uy; 0xdeuy; 0x8fuy; 0x08uy |] - - testThumb Condition.UN Op.HVC None N None - (OneOperand (OprImm 4108L)) - [| 0xf7uy; 0xe1uy; 0x80uy; 0x0cuy |] - - testThumb (Condition.AL) Op.ERET None N None - NoOperand - [| 0xf3uy; 0xdeuy; 0x8fuy; 0x00uy |] - - testThumb (Condition.AL) Op.ERET None N None - NoOperand - [| 0xf3uy; 0xdeuy; 0x8fuy; 0x00uy |] - - testThumb (Condition.AL) Op.SRSDB (Some true) N None - (TwoOperands ((OprReg R.SP), OprImm 19L)) - [| 0xe8uy; 0x2duy; 0xc0uy; 0x13uy |] - - /// A5.4 Media instructions - [] - type MediaClass () = - [] - member __.``[Thumb] Media Parse Test`` () = - testThumb (Condition.AL) Op.UDF None N None - (OneOperand (OprImm 15L)) - [| 0xdeuy; 0x0fuy |] - - /// A6.3.4 Branches and miscellaneous control - [] - type MiscellaneousControlClass () = - [] - member __.``[Thumb] Miscellaneous control Parse Test`` () = - testThumb (Condition.AL) Op.CLREX None N None - NoOperand - [| 0xf3uy; 0xbfuy; 0x8fuy; 0x2fuy |] - -module MIPS64 = - open B2R2.FrontEnd.BinLifter.MIPS - - let private test arch endian opcode oprs bytes = - let reader = - if endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - let span = System.ReadOnlySpan bytes - let ins = Parser.parse span reader arch WordSize.Bit64 0UL - let opcode' = ins.Info.Opcode - let oprs' = ins.Info.Operands - Assert.AreEqual (opcode', opcode) - Assert.AreEqual (oprs', oprs) - - let private test64R2 = test Arch.MIPS64R2 Endian.Big - - /// Arithmetic operations - [] - type ArithmeticClass () = - [] - member __.``[MIPS64] Arithmetic operations Parse Test`` () = - test64R2 Op.DADDU - (ThreeOperands (OpReg R.R15, OpReg R.R21, OpReg R.R29)) - [| 0x02uy; 0xbduy; 0x78uy; 0x2duy |] - - test64R2 Op.DADDIU - (ThreeOperands (OpReg R.R13, OpReg R.R6, - OpImm 0xffffffffffffccd5UL)) - [| 0x64uy; 0xcduy; 0xccuy; 0xd5uy |] - - test64R2 Op.DSUBU - (ThreeOperands (OpReg R.R26, OpReg R.R17, OpReg R.R9)) - [| 0x02uy; 0x29uy; 0xd0uy; 0x2fuy |] - - /// Shift And Rotate operations - [] - type ShiftAndRotateClass () = - [] - member __.``[MIPS64] Shift And Rotate operations Parse Test`` () = - test64R2 Op.DROTR - (ThreeOperands (OpReg R.R30, OpReg R.R13, - OpShiftAmount 0x1aUL)) - [| 0x00uy; 0x2duy; 0xf6uy; 0xbauy |] - - test64R2 Op.DSLL - (ThreeOperands (OpReg R.R29, OpReg R.R14, - OpShiftAmount 0x1bUL)) - [| 0x00uy; 0x0euy; 0xeeuy; 0xf8uy |] - - test64R2 Op.DSLL32 - (ThreeOperands (OpReg R.R28, OpReg R.R17, - OpShiftAmount 0x15UL)) - [| 0x00uy; 0x11uy; 0xe5uy; 0x7cuy |] - - test64R2 Op.DSLLV - (ThreeOperands (OpReg R.R30, OpReg R.R26, OpReg R.R21)) - [| 0x02uy; 0xbauy; 0xf0uy; 0x14uy |] - - test64R2 Op.DSRA - (ThreeOperands (OpReg R.R30, OpReg R.R14, - OpShiftAmount 0x1fUL)) - [| 0x00uy; 0x0euy; 0xf7uy; 0xfbuy |] - - test64R2 Op.DSRA32 - (ThreeOperands (OpReg R.R26, OpReg R.R15, - OpShiftAmount 0x7UL)) - [| 0x00uy; 0x0fuy; 0xd1uy; 0xffuy |] - - /// Logical and Bit-Field Operations - [] - type LogicalAndBitFieldClass () = - [] - member __.``[MIPS64] Logical and Bit-Field operations Parse Test`` () = - test64R2 Op.DEXT - (FourOperands (OpReg R.R29, OpReg R.R10, - OpImm 0x2UL, OpImm 0xeUL)) - [| 0x7duy; 0x5duy; 0x68uy; 0x83uy |] - - test64R2 Op.DINS - (FourOperands (OpReg R.R21, OpReg R.R15, - OpImm 0x9UL, OpImm 0x11UL)) - [| 0x7duy; 0xf5uy; 0xcauy; 0x47uy |] - - /// Multiply and Divide operations - [] - type MultiplyAndDivideClass () = - [] - member __.``[MIPS64] Multiply and Divide operations Parse Test`` () = - test64R2 Op.DDIVU - (TwoOperands (OpReg R.R30, OpReg R.R3)) - [| 0x03uy; 0xc3uy; 0x00uy; 0x1fuy |] - - test64R2 Op.DMULT - (TwoOperands (OpReg R.R24, OpReg R.R14)) - [| 0x03uy; 0x0euy; 0x00uy; 0x1cuy |] - - test64R2 Op.DMULTU - (TwoOperands (OpReg R.R17, OpReg R.R18)) - [| 0x02uy; 0x32uy; 0x00uy; 0x1duy |] - - /// Load and Store operations - [] - type LoadAndStoreClass () = - [] - member __.``[MIPS64] Load and Store operations Parse Test`` () = - test64R2 Op.LD - (TwoOperands (OpReg R.R29, OpMem (R.R26, Imm 0x2afdL, 64))) - [| 0xdfuy; 0x5duy; 0x2auy; 0xfduy |] - - test64R2 Op.LWU - (TwoOperands (OpReg R.R17, OpMem (R.R24, Imm -0x52ffL, 32))) - [| 0x9fuy; 0x11uy; 0xaduy; 0x01uy |] - - test64R2 Op.SD - (TwoOperands (OpReg R.R5, OpMem (R.R17, Imm 0x380aL, 64))) - [| 0xfeuy; 0x25uy; 0x38uy; 0x0auy |] - - test64R2 Op.SDL - (TwoOperands (OpReg R.R12, OpMem (R.R26, Imm 0x3f02L, 64))) - [| 0xb3uy; 0x4cuy; 0x3fuy; 0x02uy |] - - test64R2 Op.SDR - (TwoOperands (OpReg R.R11, OpMem (R.R6, Imm -0x78ebL, 64))) - [| 0xb4uy; 0xcbuy; 0x87uy; 0x15uy |] - -module MIPS32 = - open B2R2.FrontEnd.BinLifter.MIPS - - let private test arch endian opcode cond fmt oprs bytes = - let reader = - if endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - let span = System.ReadOnlySpan bytes - let ins = Parser.parse span reader arch WordSize.Bit32 0UL - let opcode' = ins.Info.Opcode - let cond' = ins.Info.Condition - let fmt' = ins.Info.Fmt - let oprs' = ins.Info.Operands - Assert.AreEqual (opcode', opcode) - Assert.AreEqual (cond', cond) - Assert.AreEqual (fmt', fmt) - Assert.AreEqual (oprs', oprs) - - let private test32R2 = test Arch.MIPS32R2 Endian.Big - - /// Arithmetic Operations - [] - type ArithmeticClass () = - [] - member __.``[MIPS32] Arithmetic Operations Parse Test`` () = - test32R2 Op.ADDIU None None - (ThreeOperands (OpReg R.R28, OpReg R.R28, - OpImm 0xffffffffffff85bcUL)) - [| 0x27uy; 0x9cuy; 0x85uy; 0xbcuy |] - - test32R2 Op.CLZ None None - (TwoOperands (OpReg R.R2, OpReg R.R7)) - [| 0x70uy; 0xe2uy; 0x10uy; 0x20uy |] - - test32R2 Op.LUI None None - (TwoOperands (OpReg R.R28, OpImm 4UL)) - [| 0x3cuy; 0x1cuy; 0x00uy; 0x04uy |] - - test32R2 Op.SEB None None - (TwoOperands (OpReg R.R10, OpReg R.R10)) - [| 0x7cuy; 0x0auy; 0x54uy; 0x20uy |] - - test32R2 Op.SUBU None None - (ThreeOperands (OpReg R.R2, OpReg R.R16, OpReg R.R19)) - [| 0x02uy; 0x13uy; 0x10uy; 0x23uy |] - -/// Shift And Rotate Operations - [] - type ShiftAndRotateClass () = - [] - member __.``[MIPS32] Shift And Rotate Operations Parse Test`` () = - test32R2 Op.ROTR None None - (ThreeOperands (OpReg R.R2, OpReg R.R4, OpShiftAmount 3UL)) - [| 0x00uy; 0x24uy; 0x10uy; 0xc2uy |] - - test32R2 Op.SLL None None - (ThreeOperands (OpReg R.R2, OpReg R.R2, OpShiftAmount 2UL)) - [| 0x00uy; 0x02uy; 0x10uy; 0x80uy |] - - test32R2 Op.SRA None None - (ThreeOperands (OpReg R.R5, OpReg R.R5, OpShiftAmount 2UL)) - [| 0x00uy; 0x05uy; 0x28uy; 0x83uy |] - - test32R2 Op.SRL None None - (ThreeOperands (OpReg R.R2, OpReg R.R5, OpShiftAmount 31UL)) - [| 0x00uy; 0x05uy; 0x17uy; 0xc2uy |] - -/// Logical And Bit-Field Operations - [] - type LogicalAndBitFieldClass () = - [] - member __.``[MIPS32] Logical And Bit-Field operations Parse Test`` () = - test32R2 Op.AND None None - (ThreeOperands (OpReg R.R2, OpReg R.R19, OpReg R.R2)) - [| 0x02uy; 0x62uy; 0x10uy; 0x24uy |] - - test32R2 Op.ANDI None None - (ThreeOperands (OpReg R.R2, OpReg R.R2, OpImm 1UL)) - [| 0x30uy; 0x42uy; 0x00uy; 0x01uy |] - - test32R2 Op.EXT None None - (FourOperands (OpReg R.R2, OpReg R.R2, OpImm 6UL, - OpImm 1UL)) - [| 0x7cuy; 0x42uy; 0x01uy; 0x80uy |] - - test32R2 Op.INS None None - (FourOperands (OpReg R.R3, OpReg R.R6, OpImm 6UL, - OpImm 1UL)) - [| 0x7cuy; 0xc3uy; 0x31uy; 0x84uy |] - - test32R2 Op.NOR None None - (ThreeOperands (OpReg R.R6, OpReg R.R0, OpReg R.R6)) - [| 0x00uy; 0x06uy; 0x30uy; 0x27uy |] - - test32R2 Op.OR None None - (ThreeOperands (OpReg R.R19, OpReg R.R3, OpReg R.R0)) - [| 0x00uy; 0x60uy; 0x98uy; 0x25uy |] - - test32R2 Op.ORI None None - (ThreeOperands (OpReg R.R19, OpReg R.R19, - OpImm 65535UL)) - [| 0x36uy; 0x73uy; 0xffuy; 0xffuy |] - - test32R2 Op.XOR None None - (ThreeOperands (OpReg R.R2, OpReg R.R2, OpReg R.R6)) - [| 0x00uy; 0x46uy; 0x10uy; 0x26uy |] - - test32R2 Op.XORI None None - (ThreeOperands (OpReg R.R2, OpReg R.R19, OpImm 6UL)) - [| 0x3auy; 0x62uy; 0x00uy; 0x06uy |] - - /// Condition Testing And Conditional Move Operations - [] - type CondTestAndCondMoveClass () = - [] - member __.``[MIPS32] Condition Testing And .. Operations Parse Test`` () = - test32R2 Op.MOVN None None - (ThreeOperands (OpReg R.R3, OpReg R.R4, OpReg R.R2)) - [| 0x00uy; 0x82uy; 0x18uy; 0x0buy |] - - test32R2 Op.MOVZ None None - (ThreeOperands (OpReg R.R2, OpReg R.R0, OpReg R.R5)) - [| 0x00uy; 0x05uy; 0x10uy; 0x0auy |] - - test32R2 Op.SLT None None - (ThreeOperands (OpReg R.R2, OpReg R.R19, OpReg R.R16)) - [| 0x02uy; 0x70uy; 0x10uy; 0x2auy |] - - test32R2 Op.SLTI None None - (ThreeOperands (OpReg R.R23, OpReg R.R2, OpImm 2UL)) - [| 0x28uy; 0x57uy; 0x00uy; 0x02uy |] - - test32R2 Op.SLTIU None None - (ThreeOperands (OpReg R.R3, OpReg R.R2, OpImm 275UL)) - [| 0x2cuy; 0x43uy; 0x01uy; 0x13uy |] - - test32R2 Op.SLTU None None - (ThreeOperands (OpReg R.R2, OpReg R.R0, OpReg R.R2)) - [| 0x00uy; 0x02uy; 0x10uy; 0x2buy |] - - /// Multiply and Divide operations - [] - type MultiplyAndDivideClass () = - [] - member __.``[MIPS32] Multiply and Divide operations Parse Test`` () = - test32R2 Op.DIVU None None - (TwoOperands (OpReg R.R3, OpReg R.R2)) - [| 0x00uy; 0x62uy; 0x00uy; 0x1buy |] - - test32R2 Op.MUL None None - (ThreeOperands (OpReg R.R3, OpReg R.R4, OpReg R.R8)) - [| 0x70uy; 0x88uy; 0x18uy; 0x02uy |] - - test32R2 Op.MULTU None None - (TwoOperands (OpReg R.R23, OpReg R.R5)) - [| 0x02uy; 0xe5uy; 0x00uy; 0x19uy |] - -/// Accumulator Access operations - [] - type AccumulatorAccessClass () = - [] - member __.``[MIPS32] Accumulator Access operations Parse Test`` () = - test32R2 Op.MFHI None None - (OneOperand (OpReg R.R2)) - [| 0x00uy; 0x00uy; 0x10uy; 0x10uy |] - - test32R2 Op.MFLO None None - (OneOperand (OpReg R.R3)) - [| 0x00uy; 0x00uy; 0x18uy; 0x12uy |] - - /// Jumps And Branches Operations - [] - type JumpAndBranchesClass () = - [] - member __.``[MIPS32] Jump And Branches operations Parse Test`` () = - test32R2 Op.BNE None None - (ThreeOperands (OpReg R.R2, OpReg R.R0, - OpAddr (Relative 4100L))) - [| 0x14uy; 0x40uy; 0x04uy; 0x00uy |] - - test32R2 Op.BLEZ None None - (TwoOperands (OpReg R.R23, OpAddr (Relative 4444L))) - [| 0x1auy; 0xe0uy; 0x04uy; 0x56uy |] - - test32R2 Op.BGTZ None None - (TwoOperands (OpReg R.R2, OpAddr (Relative -48L))) - [| 0x1cuy; 0x40uy; 0xffuy; 0xf3uy |] - - test32R2 Op.JR None None - (OneOperand (OpReg R.R31)) - [| 0x03uy; 0xe0uy; 0x00uy; 0x08uy |] - - test32R2 Op.JALR None None - (OneOperand (OpReg R.R25)) - [| 0x03uy; 0x20uy; 0xf8uy; 0x09uy |] - - test32R2 Op.BAL None None - (OneOperand (OpAddr (Relative 63608L))) - [| 0x04uy; 0x11uy; 0x3euy; 0x1duy |] - - test32R2 Op.BLTZ None None - (TwoOperands (OpReg R.R2, OpAddr (Relative 424L))) - [| 0x04uy; 0x40uy; 0x00uy; 0x69uy |] - - test32R2 Op.BGEZ None None - (TwoOperands (OpReg R.R22, OpAddr (Relative 1404L))) - [| 0x06uy; 0xc1uy; 0x01uy; 0x5euy |] - - /// Load And Store operations - [] - type LoadAndStoreClass () = - [] - member __.``[MIPS32] Load And Store operations Parse Test`` () = - test32R2 Op.LB None None - (TwoOperands (OpReg R.R2, OpMem (R.R2, Imm 0L, 8))) - [| 0x80uy; 0x42uy; 0x00uy; 0x00uy |] - - test32R2 Op.LBU None None - (TwoOperands (OpReg R.R2, OpMem (R.R19, Imm 17432L, 8))) - [| 0x92uy; 0x62uy; 0x44uy; 0x18uy |] - - test32R2 Op.LHU None None - (TwoOperands (OpReg R.R2, OpMem (R.R29, Imm 170L, 16))) - [| 0x97uy; 0xa2uy; 0x00uy; 0xaauy |] - - test32R2 Op.LW None None - (TwoOperands (OpReg R.R2, OpMem (R.R28, Imm -032060L, 32))) - [| 0x8fuy; 0x82uy; 0x82uy; 0xc4uy |] - - test32R2 Op.SB None None - (TwoOperands (OpReg R.R4, OpMem (R.R22, Imm 17372L, 8))) - [| 0xa2uy; 0xc4uy; 0x43uy; 0xdcuy |] - - test32R2 Op.SH None None - (TwoOperands (OpReg R.R2, OpMem (R.R29, Imm 184L, 16))) - [| 0xa7uy; 0xa2uy; 0x00uy; 0xb8uy |] - - test32R2 Op.SW None None - (TwoOperands (OpReg R.R28, OpMem (R.R29, Imm 16L, 32))) - [| 0xafuy; 0xbcuy; 0x00uy; 0x10uy |] - - test32R2 Op.SWL None None - (TwoOperands (OpReg R.R4, OpMem (R.R2, Imm 0L, 32))) - [| 0xa8uy; 0x44uy; 0x00uy; 0x00uy |] - - test32R2 Op.SWR None None - (TwoOperands (OpReg R.R4, OpMem (R.R2, Imm 3L, 32))) - [| 0xb8uy; 0x44uy; 0x00uy; 0x03uy |] - - /// Floating Point operations - [] - type FloatingPointClass () = - [] - member __.``[MIPS32] Floating Point operations Parse Test`` () = - test32R2 Op.ADD None (Some Fmt.S) - (ThreeOperands (OpReg R.F2, OpReg R.F4, OpReg R.F2)) - [| 0x46uy; 0x02uy; 0x20uy; 0x80uy |] - - test32R2 Op.ADD None (Some Fmt.D) - (ThreeOperands (OpReg R.F0, OpReg R.F0, OpReg R.F2)) - [| 0x46uy; 0x22uy; 0x00uy; 0x00uy |] - - test32R2 Op.SUB None (Some Fmt.D) - (ThreeOperands (OpReg R.F12, OpReg R.F12, OpReg R.F0)) - [| 0x46uy; 0x20uy; 0x63uy; 0x01uy |] - - test32R2 Op.DIV None (Some Fmt.D) - (ThreeOperands (OpReg R.F0, OpReg R.F0, OpReg R.F2)) - [| 0x46uy; 0x22uy; 0x00uy; 0x03uy |] - - test32R2 Op.DIV None (Some Fmt.S) - (ThreeOperands (OpReg R.F0, OpReg R.F0, OpReg R.F2)) - [| 0x46uy; 0x02uy; 0x00uy; 0x03uy |] - - test32R2 Op.MOV None (Some Fmt.D) - (TwoOperands (OpReg R.F20, OpReg R.F0)) - [| 0x46uy; 0x20uy; 0x05uy; 0x06uy |] - - test32R2 Op.MFC1 None None - (TwoOperands (OpReg R.R20, OpReg R.F0)) - [| 0x44uy; 0x14uy; 0x00uy; 0x00uy |] - - test32R2 Op.MTC1 None None - (TwoOperands (OpReg R.R0, OpReg R.F6)) - [| 0x44uy; 0x80uy; 0x30uy; 0x00uy |] - - test32R2 Op.LDC1 None None - (TwoOperands (OpReg R.F4, OpMem (R.R2, Imm 2632L, 64))) - [| 0xd4uy; 0x44uy; 0x0auy; 0x48uy |] - - test32R2 Op.LWC1 None None - (TwoOperands (OpReg R.F0, OpMem (R.R3, Imm 8L, 32))) - [| 0xc4uy; 0x60uy; 0x00uy; 0x08uy |] - - test32R2 Op.SDC1 None None - (TwoOperands (OpReg R.F0, OpMem (R.R29, Imm 16L, 64))) - [| 0xf7uy; 0xa0uy; 0x00uy; 0x10uy |] - - test32R2 Op.SWC1 None None - (TwoOperands (OpReg R.F0, OpMem (R.R4, Imm 4L, 32))) - [| 0xe4uy; 0x80uy; 0x00uy; 0x04uy |] - - test32R2 Op.C (Some Condition.LT) (Some Fmt.S) - (TwoOperands (OpReg R.F2, OpReg R.F0)) - [| 0x46uy; 0x00uy; 0x10uy; 0x3cuy |] - - test32R2 Op.CVTD None (Some Fmt.W) - (TwoOperands (OpReg R.F0, OpReg R.F0)) - [| 0x46uy; 0x80uy; 0x00uy; 0x21uy |] - - test32R2 Op.CVTS None (Some Fmt.D) - (TwoOperands (OpReg R.F0, OpReg R.F0)) - [| 0x46uy; 0x20uy; 0x00uy; 0x20uy |] - - test32R2 Op.TRUNCW None (Some Fmt.D) - (TwoOperands (OpReg R.F0, OpReg R.F0)) - [| 0x46uy; 0x20uy; 0x00uy; 0x0duy |] - - test32R2 Op.TRUNCW None (Some Fmt.S) - (TwoOperands (OpReg R.F0, OpReg R.F0)) - [| 0x46uy; 0x00uy; 0x00uy; 0x0duy |] - -/// ETC Operations - [] - type ETCClass () = - [] - member __.``[MIPS32] ETC Operations Parse Test`` () = - test32R2 Op.TEQ None None - (TwoOperands (OpReg R.R2, OpReg R.R0)) - [| 0x00uy; 0x40uy; 0x01uy; 0xf4uy |] - - test32R2 Op.BC1T None None - (TwoOperands (OpImm 6UL, OpAddr (Relative 20L))) - [| 0x45uy; 0x19uy; 0x00uy; 0x04uy |] - - test32R2 Op.BC1F None None - (OneOperand (OpAddr (Relative 108L))) - [| 0x45uy; 0x00uy; 0x00uy; 0x1auy |] - -module EVM = - open B2R2.FrontEnd.BinLifter.EVM - - let private test opcode bytes = - let reader = BinReader.binReaderLE - let span = System.ReadOnlySpan bytes - let ins = Parser.parse span reader 0UL WordSize.Bit64 0UL - let opcode' = ins.Info.Opcode - Assert.AreEqual (opcode', opcode) - - /// 60s & 70s: Push Operations - [] - type PUSHClass () = - [] - member __.``[EVM] Push Parse Test`` () = - test (Opcode.PUSH10 <| (BitVector.ofBInt 316059037807746189465I 80)) - [| 0x69uy; 0x00uy; 0x11uy; 0x22uy; 0x33uy; 0x44uy; 0x55uy; 0x66uy; - 0x77uy; 0x88uy; 0x99uy |] - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter.Tests/SPARC.Lifter.Tests.fs b/src/FrontEnd/BinLifter.Tests/SPARC.Lifter.Tests.fs new file mode 100644 index 00000000..e0348e4f --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/SPARC.Lifter.Tests.fs @@ -0,0 +1,85 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.SPARCLifter + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.SPARC +open type Register + +[] +module TestHelper = + let num v = BitVector.OfInt64 v 64 |> AST.num + + let t64 id = AST.tmpvar 64 id + + let isa = ISA.Init Architecture.SPARC Endian.Little + + let ctxt = SPARCTranslationContext isa + + let ( !. ) name = Register.toRegID name |> ctxt.GetRegVar + + let unwrapStmts stmts = Array.sub stmts 1 (Array.length stmts - 2) + + let test (bytes: byte[], givenStmts) = + let parser = SPARCParser (isa) :> IInstructionParsable + let ins = parser.Parse (bytes, 0UL) + CollectionAssert.AreEqual (givenStmts, unwrapStmts <| ins.Translate ctxt) + + let inline ( ++ ) byteString givenStmts = + ByteArray.ofHexString byteString, givenStmts + +[] +type SPARCUnitTest () = + [] + member __.``[SPARC] ADD (three reg operands) lift Test`` () = + "0d80029e" + ++ [| t64 1 := !.O2 .+ !.O5 + !.O7 := t64 1 |] + |> test + + [] + member __.``[SPARC] ADD (two reg op, one imm op) lift Test`` () = + "8ab6029e" + ++ [| t64 1 := !.O2 .+ num 0xfffffffffffff68aL + !.O7 := t64 1 |] + |> test + + [] + member __.``[SPARC] ADD (with carry) lift Test`` () = + "0d80429e" + ++ [| t64 1 := !.O2 .+ !.O5 .+ AST.zext 64 (AST.extract !.CCR 1 0) + !.O7 := t64 1 |] + |> test + + [] + member __.``[SPARC] ADD (with carry and modify icc) lift Test`` () = + "0d80429e" + ++ [| t64 1 := !.O2 .+ !.O5 .+ AST.zext 64 (AST.extract !.CCR 1 0) + !.O7 := t64 1 |] + |> test diff --git a/src/FrontEnd/BinLifter.Tests/SPARC.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/SPARC.Parser.Tests.fs new file mode 100644 index 00000000..38e7601f --- /dev/null +++ b/src/FrontEnd/BinLifter.Tests/SPARC.Parser.Tests.fs @@ -0,0 +1,270 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*) + +module B2R2.FrontEnd.Tests.SPARC + +open Microsoft.VisualStudio.TestTools.UnitTesting +open B2R2 +open B2R2.FrontEnd.BinLifter.SPARC +open type Opcode +open type Register +open type ConditionCode + +/// Shortcut for creating operands. +type O = + static member Reg (r) = + OprReg r + + static member Imm (v) = + OprImm v + + static member Addr (v) = + OprAddr v + + static member CC (cond) = + OprCC cond + +let private test (bytes: byte[]) (opcode, oprs) = + let reader = BinReader.Init Endian.Little + let span = System.ReadOnlySpan bytes + let ins = ParsingMain.parse span reader 0UL + Assert.AreEqual (ins.Info.Opcode, opcode) + Assert.AreEqual (ins.Info.Operands, oprs) + +let private operandsFromArray oprList = + let oprs = Array.ofList oprList + match oprs.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprs[0] + | 2 -> TwoOperands (oprs[0], oprs[1]) + | 3 -> ThreeOperands (oprs[0], oprs[1], oprs[2]) + | 4 -> FourOperands (oprs[0], oprs[1], oprs[2], oprs[3]) + | 5 -> FiveOperands (oprs[0], oprs[1], oprs[2], oprs[3], oprs[4]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + +[] +type SPARCUnitTest () = + [] + member __.``[SPARC] Three Reg Operands ADD Parse Test`` () = + "0d80029e" + ++ ADD ** [ O.Reg O2; O.Reg O5; O.Reg O7 ] ||> test + + [] + member __.``[SPARC] Two Reg Op, One Imm Op ADD Parse Test`` () = + "8ab6029e" + ++ ADD ** [ O.Reg O2; O.Imm -2422; O.Reg O7 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands SUB Parse Test`` () = + "11802692" + ++ SUB ** [ O.Reg I2; O.Reg L1; O.Reg O1 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands SUBcc Parse Test`` () = + "1380a2ba" + ++ SUBcc ** [ O.Reg O2; O.Reg L3; O.Reg I5 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands UMULcc Parse Test`` () = + "0b40d5b2" + ++ UMULcc ** [ O.Reg L5; O.Reg O3; O.Reg I1 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands 64-bit MULX Parse Test`` () = + "05404bb6" + ++ MULX ** [ O.Reg O5; O.Reg G5; O.Reg I3 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands SMUL Parse Test`` () = + "1e8059a6" + ++ SMUL ** [ O.Reg G6; O.Reg I6; O.Reg L3 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands SDIVcc Parse Test`` () = + "0bc0feac" + ++ SDIVcc ** [ O.Reg I3; O.Reg O3; O.Reg L6 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands UDIVX Parse Test`` () = + "13406bb4" + ++ UDIVX ** [ O.Reg O5; O.Reg L3; O.Reg I2 ] ||> test + + [] + member __.``[SPARC] Two Reg Ops, One Imm Op XOR Parse Test`` () = + "ff631ea2" + ++ XOR ** [ O.Reg I1; O.Imm 1023; O.Reg L1 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands ANDN Parse Test`` () = + "0a802cb4" + ++ ANDN ** [ O.Reg L2; O.Reg O2; O.Reg I2 ] ||> test + + [] + member __.``[SPARC] Two Reg Operands NEG Parse Test`` () = + "0a002096" + ++ SUB ** [ O.Reg G0; O.Reg O2; O.Reg O3 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands SLL Parse Test`` () = + "0fa02a89" + ++ SLL ** [ O.Reg O2; O.Imm 15; O.Reg G4 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands SRL Parse Test`` () = + "16c03693" + ++ SRL ** [ O.Reg I3; O.Reg L6; O.Reg O1 ] ||> test + + [] + member __.``[SPARC] Two Reg Ops, One Imme Op 64-bit SRAX Parse Test`` () = + "3f303c83" + ++ SRAX ** [ O.Reg L0; O.Imm 63; O.Reg G1 ] ||> test + + [] + member __.``[SPARC] One Reg Op, One Imm Op SETHI Parse Test`` () = + "ffff3f23" + ++ SETHI ** [ O.Imm -1024; O.Reg L1 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands LDSB Parse Test`` () = + "ffbf4efc" + ++ LDSB ** [ O.Reg I2; O.Imm -1; O.Reg I6 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands LDUH Parse Test`` () = + "124017d8" + ++ LDUH ** [ O.Reg I5; O.Reg L2; O.Reg O4 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands LDD Parse Test`` () = + "ff3f18ee" + ++ LDD ** [ O.Reg G0; O.Imm -1; O.Reg L7 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands STB Parse Test`` () = + "552128e8" + ++ STB ** [ O.Reg L4; O.Reg G0; O.Imm 341 ] ||> test + + [] + member __.``[SPARC] Two Reg Op, One Imm Op ST Parse Test`` () = + "2ae024f8" + ++ STW ** [ O.Reg I4; O.Reg L3; O.Imm 42] ||> test + + [] + member __.``[SPARC] Three Reg Operands STD Parse Test`` () = + "0a403cc2" + ++ STD ** [ O.Reg G1; O.Reg L1; O.Reg O2 ] ||> test + + [] + member __.``[SPARC] Three Reg Operands JMPL Parse Test`` () = + "0600c09f" + ++ JMPL ** [ O.Reg G0; O.Reg G6; O.Reg O7 ] ||> test + + [] + member __.``[SPARC] Two Reg Op, One Imm Op JMPL Parse Test`` () = + "08e0c781" + ++ JMPL ** [ O.Reg I7; O.Imm 8; O.Reg G0 ] ||> test + + [] + member __.``[SPARC] Two Reg Operands BNE Parse Test`` () = + "04008012" + ++ BNE ** [ O.Imm 0; O.Addr 16 ] ||> test + + [] + member __.``[SPARC] No Operands NOP Parse Test`` () = + "00000001" + ++ NOP ** [ ] ||> test + + [] + member __.``[SPARC] Two Reg Operands FMOVS Parse Test`` () = + "2200a085" + ++ FMOVs ** [ O.Reg F2; O.Reg F2 ] ||> test + + [] + member __.``[SPARC] One Imm Op, One FLoat Reg Op LD Parse Test`` () = + "002000f7" + ++ LDF ** [ O.Reg G0; O.Imm 0; O.Reg F27 ] ||> test + + [] + member __.``[SPARC] One FLoat Reg Op, One Imm Op STDF Parse Test`` () = + "0a2038cd" + ++ STDF ** [ O.Reg F6; O.Reg G0; O.Imm 10 ] ||> test + + [] + member __.``[SPARC] Three Float Reg Op Single FADDs Parse Test`` () = + "2108a085" + ++ FADDs ** [ O.Reg F0; O.Reg F1; O.Reg F2 ] ||> test + + [] + member __.``[SPARC] Two Float Reg Op FNEGd Parse Test`` () = + "c100a085" + ++ FNEGd ** [ O.Reg F32; O.Reg F2 ] ||> test + + [] + member __.``[SPARC] Two Float Reg Op FSQRTq Parse Test`` () = + "6505a089" + ++ FSQRTq ** [ O.Reg F36; O.Reg F4 ] ||> test + + [] + member __.``[SPARC] Two Float Reg Op FiTOs Parse Test`` () = + "8218a085" + ++ FiTOs ** [ O.Reg F2; O.Reg F2 ] ||> test + + [] + member __.``[SPARC] One CC Op, Two Reg Op FCMPs Parse Test`` () = + "238aa881" + ++ FCMPs ** [ O.CC Fcc0; O.Reg F2; O.Reg F3 ] ||> test + + [] + member __.``[SPARC] One CC Op, Two Reg Op FMOVFsE Parse Test`` () = + "2050aa87" + ++ FMOVFsE ** [ O.CC Fcc2; O.Reg F0; O.Reg F3 ] ||> test + + [] + member __.``[SPARC] Three Reg Op FMOVRqGZ Parse Test`` () = + "e018a881" + ++ FMOVRqGZ ** [ O.Reg G0; O.Reg F0; O.Reg F0 ] ||> test + + [] + member __.``[SPARC] Two Reg Op, 1 Imm STF Parse Test`` () = + "012020c90" + ++ STF ** [ O.Reg F4; O.Reg G0; O.Imm 1 ] ||> test + + [] + member __.``[SPARC] Two Reg Op, 1 Imm Op LDDF Parse Test`` () = + "01a01cc5" + ++ LDDF ** [ O.Reg L2; O.Imm 1; O.Reg F2 ] ||> test + + [] + member __.``[SPARC] Three Reg Op STFQ Parse Test`` () = + "000035f3" + ++ STQF ** [ O.Reg F56; O.Reg L4; O.Reg G0 ] ||> test + + [] + member __.``[SPARC] Three Reg Op LDFSR Parse Test`` () = + "1d000dc1" + ++ LDFSR ** [ O.Reg L4; O.Reg I5; O.Reg FSR ] ||> test \ No newline at end of file diff --git a/src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs b/src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs index 98d171c5..febed201 100644 --- a/src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs +++ b/src/FrontEnd/BinLifter.Tests/TMS320.Parser.Tests.fs @@ -27,80 +27,117 @@ module B2R2.FrontEnd.Tests.TMS320 open Microsoft.VisualStudio.TestTools.UnitTesting open B2R2 open B2R2.FrontEnd.BinLifter.TMS320C6000 +open type Opcode +open type Register -let private test opcode unit oprs bytes = - let reader = BinReader.binReaderLE +/// Shortcut for creating operands. +type O = + static member Reg (r) = + OpReg r + + static member Imm (v) = + Immediate v + + static member RegPair (r1, r2) = + RegisterPair (r1, r2) + + static member Mem (r, modType, offset) = + OprMem (r, modType, offset) + +let private test unit (bytes: byte[]) (opcode, oprs) = + let reader = BinReader.Init Endian.Little let span = System.ReadOnlySpan bytes let mutable inpar = false - let ins = Parser.parse span reader &inpar 0UL + let ins = ParsingMain.parse span reader &inpar 0UL Assert.AreEqual (ins.Info.Opcode, opcode) Assert.AreEqual (ins.Info.FunctionalUnit, unit) Assert.AreEqual (ins.Info.Operands, oprs) +let private operandsFromArray oprList = + let oprs = Array.ofList oprList + match oprs.Length with + | 0 -> NoOperand + | 1 -> OneOperand oprs[0] + | 2 -> TwoOperands (oprs[0], oprs[1]) + | 3 -> ThreeOperands (oprs[0], oprs[1], oprs[2]) + | 4 -> FourOperands (oprs[0], oprs[1], oprs[2], oprs[3]) + | _ -> Utils.impossible () + +let private ( ** ) opcode oprList = (opcode, operandsFromArray oprList) + +let private ( ++ ) byteString pair = (ByteArray.ofHexString byteString, pair) + /// .D Unit Instructions [] type DUnitTest () = [] - member __.``[TMS320] .D Unit Insturctions Parse Test`` () = - test Opcode.ADD D1XUnit - (ThreeOperands (OpReg R.A1, OpReg R.B12, OpReg R.A6)) - [| 0xB0uy; 0x3Auy; 0x30uy; 0x03uy |] + member __.``[TMS320] .D Unit Insturctions Parse Test (1)`` () = + "B03a3003" + ++ ADD ** [ O.Reg A1; O.Reg B12; O.Reg A6 ] + ||> test D1XUnit - test Opcode.LDB D1Unit // *-A5[4],A7 - (TwoOperands (OprMem (R.A5, NegativeOffset, UCst5 4UL), - OpReg R.A7)) - [| 0x24uy; 0x80uy; 0x94uy; 0x03uy |] + [] + member __.``[TMS320] .D Unit Insturctions Parse Test (2)`` () = + "24809403" + ++ LDB ** [ O.Mem (A5, NegativeOffset, UCst5 4UL); O.Reg A7 ] + ||> test D1Unit /// .L Unit Instructions [] type LUnitTest () = [] - member __.``[TMS320] .L Unit Insturctions Parse Test`` () = - test Opcode.ABS2 L1Unit (TwoOperands (OpReg R.A0, OpReg R.A2)) - [| 0x58uy; 0x83uy; 0x00uy; 0x01uy |] + member __.``[TMS320] .L Unit Insturctions Parse Test (1)`` () = + "58830001" + ++ ABS2 ** [ O.Reg A0; O.Reg A2 ] + ||> test L1Unit - test Opcode.SUBDP L1XUnit - (ThreeOperands (RegisterPair (R.A1, R.A0), - RegisterPair (R.B3, R.B2), - RegisterPair (R.A5, R.A4))) - [| 0x38uy; 0x13uy; 0x08uy; 0x02uy |] + [] + member __.``[TMS320] .L Unit Insturctions Parse Test (2)`` () = + "38130802" + ++ SUBDP ** [ O.RegPair (A1, A0); O.RegPair (B3, B2); O.RegPair (A5, A4) ] + ||> test L1XUnit /// .M Unit Instructions [] type MUnitTest () = [] - member __.``[TMS320] .M Unit Insturctions Parse Test`` () = - test Opcode.AVG2 M1Unit - (ThreeOperands (OpReg R.A0, OpReg R.A1, OpReg R.A2)) - [| 0xF0uy; 0x04uy; 0x04uy; 0x01uy |] + member __.``[TMS320] .M Unit Insturctions Parse Test (1)`` () = + "F0040401" + ++ AVG2 ** [ O.Reg A0; O.Reg A1; O.Reg A2 ] + ||> test M1Unit - test Opcode.MPY2IR M1XUnit - (ThreeOperands (OpReg R.A2, OpReg R.B5, - RegisterPair (R.A9, R.A8))) - [| 0xF0uy; 0x53uy; 0x14uy; 0x14uy |] + [] + member __.``[TMS320] .M Unit Insturctions Parse Test (2)`` () = + "F0531414" + ++ MPY2IR ** [ O.Reg A2; O.Reg B5; O.RegPair (A9, A8) ] + ||> test M1XUnit /// .S Unit Instructions [] type SUnitTest () = [] - member __.``[TMS320] .S Unit Insturctions Parse Test`` () = - test Opcode.ABSDP S1Unit - (TwoOperands (RegisterPair (R.A1, R.A0), RegisterPair (R.A3, R.A2))) - [| 0x20uy; 0x0Buy; 0x04uy; 0x01uy |] + member __.``[TMS320] .S Unit Insturctions Parse Test (1)`` () = + "200B0401" + ++ ABSDP ** [ O.RegPair (A1, A0); O.RegPair (A3, A2) ] + ||> test S1Unit - test Opcode.SHRU S1Unit - (ThreeOperands (RegisterPair (R.A5, R.A4), Immediate 0x0UL, - RegisterPair (R.A1, R.A0))) - [| 0x20uy; 0x09uy; 0x10uy; 0x00uy |] + [] + member __.``[TMS320] .S Unit Insturctions Parse Test (2)`` () = + "20091000" + ++ SHRU ** [ O.RegPair (A5, A4); O.Imm 0x0UL; O.RegPair (A1, A0) ] + ||> test S1Unit /// No Unit Instructions [] type NoUnitTest () = [] - member __.``[TMS320] No Unit Insturctions Parse Test`` () = - test Opcode.IDLE NoUnit NoOperand - [| 0x00uy; 0xE0uy; 0x01uy; 0x00uy |] - - test Opcode.NOP NoUnit (OneOperand (Immediate 5UL)) - [| 0x00uy; 0x80uy; 0x00uy; 0x00uy |] + member __.``[TMS320] No Unit Insturctions Parse Test (1)`` () = + "00E00100" + ++ IDLE ** [ ] + ||> test NoUnit + [] + member __.``[TMS320] No Unit Insturctions Parse Test (2)`` () = + "00800000" + ++ NOP ** [ O.Imm 5UL ] + ||> test NoUnit diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32ARMParser.fs b/src/FrontEnd/BinLifter/ARM32/ARM32ARMParser.fs index 94a64041..d20fbbbd 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32ARMParser.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32ARMParser.fs @@ -33,9 +33,9 @@ open B2R2.FrontEnd.BinLifter.ARM32.ARMValidator #endif let render (phlp: ParsingHelper) bin opcode dt oidx = - let struct (oprs, wback, cflags) = phlp.OprParsers.[int oidx].Render bin + let struct (oprs, wback, cflags, oSz) = phlp.OprParsers.[int oidx].Render bin ARM32Instruction (phlp.InsAddr, phlp.Len, phlp.Cond, opcode, oprs, - 0uy, wback, N, dt, phlp.Mode, cflags) + 0uy, wback, N, dt, phlp.Mode, cflags, oSz, phlp.IsAdd) /// Load/Store Dual, Half, Signed Byte (register) on page F4-4221. let parseLoadStoreReg (phlp: ParsingHelper) bin = @@ -128,7 +128,9 @@ let parseLoadStoreReg (phlp: ParsingHelper) bin = /// Load/Store Dual, Half, Signed Byte (immediate, literal) on page F4-4221. let parseLoadStoreImm (phlp: ParsingHelper) bin = let decodeField = (* P:W:o1:op2 *) - concat (concat (pickBit bin 24) (pickTwo bin 20) 2) (pickTwo bin 5) 2 + ((bin >>> 20) &&& 0b10000u) (* 24th bit *) + ||| ((bin >>> 18) &&& 0b01100u) (* 21, 20th bit *) + ||| ((bin >>> 5) &&& 0b00011u) (* 6, 5th bit *) let isNotRn1111 bin = pickFour bin 16 <> 0b1111u match decodeField (* P:W:o1:op2 *) with | 0b00010u when isNotRn1111 bin -> (* LDRD (immediate) *) @@ -733,7 +735,7 @@ let parseHalfMulAndAccumulate (phlp: ParsingHelper) bin = /// Integer Data Processing (three register, immediate shift) on page F4-4227. let parseIntegerDataProcThreeRegImm (phlp: ParsingHelper) bin = - match concat (pickThree bin 21) (pickBit bin 20) 1 (* opc:S *) with + match pickFour bin 20 (* opc:S *) with | 0b0000u -> render phlp bin Op.AND None OD.OprRdRnRmShfA | 0b0001u -> render phlp bin Op.ANDS None OD.OprRdRnRmShfA | 0b0010u -> render phlp bin Op.EOR None OD.OprRdRnRmShfA @@ -1169,10 +1171,8 @@ let changeToAliasOfSTR bin = /// Load/Store Word, Unsigned Byte (immediate, literal) on page F4-4234. let parseCase010 (phlp: ParsingHelper) bin = - let pw = concat (pickBit bin 24) (pickBit bin 21) 1 - let o2o1 = concat (pickBit bin 22) (pickBit bin 20) 1 let rn = pickFour bin 16 - match concat pw o2o1 2 (* P:W:o2:o1 *) with + match pickFourBitsApart bin 24 21 22 20 (* P:W:o2:o1 *) with (* LDR (literal) *) | 0b0001u when rn = 0b1111u -> #if !EMULATION @@ -1290,7 +1290,7 @@ let parseCase010 (phlp: ParsingHelper) bin = /// Load/Store Word, Unsigned Byte (register) on page F4-4235. let parseCase0110 (phlp: ParsingHelper) bin = - match concat (pickBit bin 24) (pickThree bin 20) 3 (* P:o2:W:o1 *) with + match ((bin >>> 21) &&& 0b1000u) ||| (pickThree bin 20) (* P:o2:W:o1 *) with | 0b0000u -> #if !EMULATION chkPCRmRn bin @@ -1568,7 +1568,7 @@ let parseSaturate16bit (phlp: ParsingHelper) bin = /// Reverse Bit/Byte on page F4-4240. let parseReverseBitByte (phlp: ParsingHelper) bin = - match concat (pickBit bin 22) (pickBit bin 7) 1 (* o1:o2 *) with + match pickTwoBitsApart bin 22 7 (* o1:o2 *) with | 0b00u -> #if !EMULATION chkPCRdRm bin @@ -2240,7 +2240,7 @@ let parseAdvSIMDThreeRegSameLenExt (phlp: ParsingHelper) bin = #endif render phlp bin Op.VUSDOT (oneDt SIMDTypS8) OD.OprDdDnDm | 0b01101101u | 0b01101111u (* 011011x1 *) -> raise ParsingFailureException - | 0b01101110u -> (* Armv8.6 *) + | 0b01101110u -> (* Armv8.6 *) #if !EMULATION chkQVdVnVm bin #endif @@ -2558,7 +2558,7 @@ let parseAdvancedSIMDandFP64bitMove (phlp: ParsingHelper) bin = /// System register 64-bit move on page F4-4254. let parseSystemReg64bitMove (phlp: ParsingHelper) bin = - match concat (pickBit bin 22) (pickBit bin 20) 1 (* D:L *) with + match pickTwoBitsApart bin 22 20 (* D:L *) with | 0b00u | 0b01u -> raise ParsingFailureException | 0b10u -> #if !EMULATION @@ -2694,7 +2694,7 @@ let parseSysRegisterLdSt (phlp: ParsingHelper) bin = let isNotRn1111 bin = pickFour bin 16 <> 0b1111u let isCRd0101 bin = (pickFour bin 12) = 0b0101u let puw = concat (pickTwo bin 23) (pickBit bin 21) 1 (* P:U:W *) - let dL = concat (pickBit bin 22) (pickBit bin 20) 1 (* D:L *) + let dL = pickTwoBitsApart bin 22 20 (* D:L *) let cRdCp15 = concat (pickFour bin 12) (pickBit bin 8) 1 (* CRd:cp15 *) match concat dL (pickBit bin 8) 1 (* D:L:cp15 *) with | 0b000u | 0b001u | 0b010u | 0b011u (* 0b0xxu *) @@ -3517,7 +3517,7 @@ let parseFPMoveSpecialReg (phlp: ParsingHelper) bin = render phlp bin Op.VMSR None OD.OprSregRt | _ (* 0b1u *) -> #if !EMULATION - chkPCRt bin + chkPCRtR1 bin #endif render phlp bin Op.VMRS None OD.OprRtSreg @@ -3705,7 +3705,7 @@ let parseCPS (phlp: ParsingHelper) bin = /// Change Process State on page F4-4262. let parseChangeProcessState (phlp: ParsingHelper) bin = - match concat (pickBit bin 16) (pickBit bin 4) 1 (* op:mode<4> *) with + match pickTwoBitsApart bin 16 4 (* op:mode<4> *) with | 0b10u -> render phlp bin Op.SETEND None OD.OprEndianA | 0b00u | 0b01u -> parseCPS phlp bin | _ (* 11 *) -> raise ParsingFailureException @@ -6304,7 +6304,8 @@ let parseAdvSIMDDupScalar (phlp: ParsingHelper) bin = #if !EMULATION chkQVd bin #endif - render phlp bin Op.VDUP dt OD.OprDdDmx + let oprs = if pickBit bin 6 = 0u then OD.OprDdDmx else OD.OprQdDmx + render phlp bin Op.VDUP dt oprs | _ (* 001 or 01x or 1xx *) -> raise ParsingFailureException /// Advanced SIMD three registers of different lengths on page F4-4268. @@ -6401,7 +6402,7 @@ let parseAdvSIMDThreeRegsDiffLen (phlp: ParsingHelper) bin = #endif render phlp bin Op.VRSUBHN dt OD.OprDdQnQm | 0b01100u | 0b01110u | 0b11100u | 0b11110u (* x11x0 *) -> - let dt = getDtA bin |> oneDt + let dt = getDTPolyA bin |> oneDt #if !EMULATION chkVd0 bin #endif @@ -6818,7 +6819,8 @@ let parseAdvSIMDTwoRegsAndShfAmt (phlp: ParsingHelper) bin = | _ (* 1xxx *) -> SIMDTypI64 |> oneDt let oprFn = - if pickBit bin 6 (* Q *) = 0u then OD.OprDdDmImmLeft else OD.OprQdQmImmLeft + if pickBit bin 6 (* Q *) = 0u then OD.OprDdDmImmLeft + else OD.OprQdQmImmLeft render phlp bin Op.VSHL dt oprFn | 0b010000u -> (* if Vm<0> == '1' then UNDEFINED *) @@ -6877,7 +6879,7 @@ let parseAdvSIMDShfAndImmGen (phlp: ParsingHelper) bin = /// Advanced SIMD data-processing on page F4-4262. let parseAdvSIMDDataProc (phlp: ParsingHelper) bin = - match concat (pickBit bin 23) (pickBit bin 4) 1 (* op0:op1 *) with + match pickTwoBitsApart bin 23 4 (* op0:op1 *) with | 0b00u | 0b01u (* 0x *) -> parseAdvSIMDThreeRegsSameLen phlp bin | 0b10u -> parseAdvSIMDTwoThreeRegsDiffLen phlp bin @@ -6904,7 +6906,7 @@ let parseBarriers (phlp: ParsingHelper) bin = /// Preload (immediate) on page F4-4273. let parsePreloadImm (phlp: ParsingHelper) bin = let isRn1111 bin = pickFour bin 16 = 0b1111u - match concat (pickBit bin 24) (pickBit bin 22) 1 (* D:R *) with + match pickTwoBitsApart bin 24 22 (* D:R *) with | 0b00u -> render phlp bin Op.NOP None OD.OprNo | 0b01u -> render phlp bin Op.PLI None OD.OprLabel12A | 0b10u | 0b11u when isRn1111 bin -> @@ -6914,7 +6916,7 @@ let parsePreloadImm (phlp: ParsingHelper) bin = /// Preload (register) on page F4-4274. let parsePreloadReg (phlp: ParsingHelper) bin = - match concat (pickBit bin 24) (pickBit bin 22) 1 (* D:o2 *) with + match pickTwoBitsApart bin 24 22 (* D:o2 *) with | 0b00u -> render phlp bin Op.NOP None OD.OprNo | 0b01u -> #if !EMULATION @@ -7234,6 +7236,7 @@ let parseUncondInstr (phlp: ParsingHelper) bin = let parse (phlp: ParsingHelper) bin = let cond = pickFour bin 28 |> byte |> parseCond phlp.Cond <- cond + phlp.IsAdd <- true match pickTwo bin 26 (* op0<2:1> *) with | 0b00u when cond <> Condition.UN -> parseCase00 phlp bin | 0b01u when cond <> Condition.UN -> parseCase01 phlp bin diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs index 7d7ed8ca..4e9a1a5a 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Disasm.fs @@ -599,7 +599,7 @@ let inline appendSIMDDataTypes (ins: InsInfo) (sb: StringBuilder) = | Some (TwoDT (dt1, dt2)) -> (sb.Append (SIMDTypToStr dt1)).Append (SIMDTypToStr dt2) -let inline buildOpcode (ins: InsInfo) (builder: DisasmBuilder<_>) = +let inline buildOpcode (ins: InsInfo) (builder: DisasmBuilder) = let sb = StringBuilder () let sb = sb.Append (opCodeToString ins.Opcode) let sb = sb.Append (condToString ins.Condition) @@ -616,7 +616,7 @@ let isRFEorSRS = function | Op.SRS | Op.SRSDA | Op.SRSDB | Op.SRSIA | Op.SRSIB -> true | _ -> false -let buildReg (ins: InsInfo) isRegList reg (builder: DisasmBuilder<_>) = +let buildReg (ins: InsInfo) isRegList reg (builder: DisasmBuilder) = let reg = Register.toString reg match ins.WriteBack with | true when existRegList ins.Operands && not isRegList -> @@ -657,7 +657,7 @@ let specRegToString ins reg pFlag builder = buildReg ins false reg builder builder.Accumulate AsmWordKind.String (flagToString f) -let regListToString ins list (builder: DisasmBuilder<_>) = +let regListToString ins list (builder: DisasmBuilder) = builder.Accumulate AsmWordKind.String "{" let len = List.length list list @@ -716,17 +716,17 @@ let signToString = function | Some Plus -> "" | Some Minus -> "-" -let immToString imm sign (builder: DisasmBuilder<_>) = +let immToString imm sign (builder: DisasmBuilder) = builder.Accumulate AsmWordKind.String "#" builder.Accumulate AsmWordKind.String (signToString sign) - builder.Accumulate AsmWordKind.Value (String.i64ToHex imm) + builder.Accumulate AsmWordKind.Value (HexString.ofInt64 imm) -let fpImmToString (fp: float) (builder: DisasmBuilder<_>) = +let fpImmToString (fp: float) (builder: DisasmBuilder) = builder.Accumulate AsmWordKind.String "#" - builder.Accumulate AsmWordKind.Value (fp.ToString ("N8")) + builder.Accumulate AsmWordKind.Value (fp.ToString "N8") -let optionToString (opt: int64) (builder: DisasmBuilder<_>) = - builder.Accumulate AsmWordKind.Value (String.i64ToHex opt) +let optionToString opt (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value (HexString.ofInt64 opt) let srTypeToString = function | SRTypeLSL -> "lsl" @@ -735,7 +735,7 @@ let srTypeToString = function | SRTypeROR -> "ror" | SRTypeRRX -> "rrx" -let prependDelimiter delimiter (builder: DisasmBuilder<_>) = +let prependDelimiter delimiter (builder: DisasmBuilder) = match delimiter with | None -> () | Some delim -> builder.Accumulate AsmWordKind.String delim @@ -749,7 +749,7 @@ let shiftToString shift delim builder = builder.Accumulate AsmWordKind.String " " immToString (int64 i) None builder -let regShiftToString ins shift reg (builder: DisasmBuilder<_>) = +let regShiftToString ins shift reg (builder: DisasmBuilder) = builder.Accumulate AsmWordKind.String (srTypeToString shift) builder.Accumulate AsmWordKind.String " " buildReg ins false reg builder @@ -815,25 +815,35 @@ let processAddrExn32 (ins: InsInfo) addr = | Op.B | Op.BX -> pc | Op.BL | Op.BLX -> ParseUtils.align pc 4UL | Op.ADR -> ParseUtils.align pc 4UL + | Op.LDR | Op.LDRB | Op.LDRD | Op.LDRH | Op.LDRSB | Op.LDRSH | Op.PLD + | Op.PLDW | Op.PLI | Op.VLDR -> ParseUtils.align pc 4UL | _ -> addr -let calculateRelativePC lbl addr = int32 addr + int32 lbl |> uint64 +let calculateRelativePC (ins: InsInfo) lbl addr = + let addr = if ins.IsAdd then addr + uint64 lbl else addr - uint64 lbl + addr |> uint32 |> uint64 -let commentWithSymbol helper addr addrStr (builder: DisasmBuilder<_>) = +let commentWithSymbol reader addr addrStr (builder: DisasmBuilder) = if builder.ResolveSymbol then - match (helper: DisasmHelper).FindFunctionSymbol (addr) with - | Error _ -> - builder.Accumulate AsmWordKind.String addrStr - | Ok "" -> () - | Ok name -> - builder.Accumulate AsmWordKind.String (addrStr + " ; <") - builder.Accumulate AsmWordKind.Value name - builder.Accumulate AsmWordKind.String ">" - else () - -let memHead hlp ins addr addrMode (builder: DisasmBuilder<_>) = + match (reader: INameReadable).TryFindFunctionName addr with + | Ok name when name.Length > 0 -> + builder.Accumulate AsmWordKind.Value addrStr + builder.Accumulate AsmWordKind.String (" ; <" + name + ">") + | _ -> + builder.Accumulate AsmWordKind.Value addrStr + else builder.Accumulate AsmWordKind.Value addrStr + +let memToString reader ins addr addrMode (builder: DisasmBuilder) = match addrMode with - | OffsetMode offset | PreIdxMode offset | PostIdxMode offset -> + | OffsetMode offset -> + builder.Accumulate AsmWordKind.String "[" + offsetToString ins addrMode offset builder + builder.Accumulate AsmWordKind.String "]" + | PreIdxMode offset -> + builder.Accumulate AsmWordKind.String "[" + offsetToString ins addrMode offset builder + builder.Accumulate AsmWordKind.String "]!" + | PostIdxMode offset -> builder.Accumulate AsmWordKind.String "[" offsetToString ins addrMode offset builder | UnIdxMode (reg, opt) -> @@ -841,24 +851,16 @@ let memHead hlp ins addr addrMode (builder: DisasmBuilder<_>) = buildReg ins false reg builder builder.Accumulate AsmWordKind.String "], {" optionToString opt builder + builder.Accumulate AsmWordKind.String "}" | LiteralMode lbl -> - let addr = processAddrExn32 ins addr |> calculateRelativePC lbl + let addr = processAddrExn32 ins addr |> calculateRelativePC ins lbl let addrStr = "0x" + addr.ToString ("x") - match ins.Opcode with - | Op.BL | Op.BLX -> commentWithSymbol hlp addr addrStr builder - | _ -> builder.Accumulate AsmWordKind.String addrStr - -let memTail addrMode (builder: DisasmBuilder<_>) = - match addrMode with - | OffsetMode _ -> builder.Accumulate AsmWordKind.String "]" - | PreIdxMode _ -> builder.Accumulate AsmWordKind.String "]!" - | PostIdxMode _ -> () - | UnIdxMode _ -> builder.Accumulate AsmWordKind.String "}" - | LiteralMode _ -> () - -let memToString hlp ins addr addrMode builder = - memHead hlp ins addr addrMode builder - memTail addrMode builder + if ins.IsBranch () then + commentWithSymbol reader addr addrStr builder + else + builder.Accumulate AsmWordKind.String "[" + builder.Accumulate AsmWordKind.Value addrStr + builder.Accumulate AsmWordKind.String "]" let optToString = function | BarrierOption.SY -> "sy" @@ -873,7 +875,7 @@ let optToString = function | BarrierOption.OSH -> "osh" | BarrierOption.OSHST -> "oshst" | BarrierOption.OSHLD -> "oshld" - | _ -> raise ParsingFailureException + | opt -> opt.ToString () (* otherwise *) let iFlagToString = function | A -> "a" @@ -890,7 +892,7 @@ let endToString endian = | Endian.Big -> "be" | _ -> invalidArg (nameof endian) "Invalid endian is given." -let oprToString hlp ins addr operand delim builder = +let oprToString reader ins addr operand delim builder = match operand with | OprReg reg -> prependDelimiter delim builder @@ -917,7 +919,7 @@ let oprToString hlp ins addr operand delim builder = regShiftToString ins s r builder | OprMemory addrMode -> prependDelimiter delim builder - memToString hlp ins addr addrMode builder + memToString reader ins addr addrMode builder | OprOption opt -> prependDelimiter delim builder builder.Accumulate AsmWordKind.String (optToString opt) @@ -932,39 +934,39 @@ let oprToString hlp ins addr operand delim builder = builder.Accumulate AsmWordKind.String (condToString c) | GoToLabel _ -> () -let buildOprs hlp (ins: InsInfo) pc builder = +let buildOprs reader (ins: InsInfo) pc builder = match ins.Operands with | NoOperand -> () | OneOperand opr -> - oprToString hlp ins pc opr (Some " ") builder + oprToString reader ins pc opr (Some " ") builder | TwoOperands (opr1, opr2) -> - oprToString hlp ins pc opr1 (Some " ") builder - oprToString hlp ins pc opr2 (Some ", ") builder + oprToString reader ins pc opr1 (Some " ") builder + oprToString reader ins pc opr2 (Some ", ") builder | ThreeOperands (opr1, opr2, opr3) -> - oprToString hlp ins pc opr1 (Some " ") builder - oprToString hlp ins pc opr2 (Some ", ") builder - oprToString hlp ins pc opr3 (Some ", ") builder + oprToString reader ins pc opr1 (Some " ") builder + oprToString reader ins pc opr2 (Some ", ") builder + oprToString reader ins pc opr3 (Some ", ") builder | FourOperands (opr1, opr2, opr3, opr4) -> - oprToString hlp ins pc opr1 (Some " ") builder - oprToString hlp ins pc opr2 (Some ", ") builder - oprToString hlp ins pc opr3 (Some ", ") builder - oprToString hlp ins pc opr4 (Some ", ") builder + oprToString reader ins pc opr1 (Some " ") builder + oprToString reader ins pc opr2 (Some ", ") builder + oprToString reader ins pc opr3 (Some ", ") builder + oprToString reader ins pc opr4 (Some ", ") builder | FiveOperands (opr1, opr2, opr3, opr4, opr5) -> - oprToString hlp ins pc opr1 (Some " ") builder - oprToString hlp ins pc opr2 (Some ", ") builder - oprToString hlp ins pc opr3 (Some ", ") builder - oprToString hlp ins pc opr4 (Some ", ") builder - oprToString hlp ins pc opr5 (Some ", ") builder + oprToString reader ins pc opr1 (Some " ") builder + oprToString reader ins pc opr2 (Some ", ") builder + oprToString reader ins pc opr3 (Some ", ") builder + oprToString reader ins pc opr4 (Some ", ") builder + oprToString reader ins pc opr5 (Some ", ") builder | SixOperands (opr1, opr2, opr3, opr4, opr5, opr6) -> - oprToString hlp ins pc opr1 (Some " ") builder - oprToString hlp ins pc opr2 (Some ", ") builder - oprToString hlp ins pc opr3 (Some ", ") builder - oprToString hlp ins pc opr4 (Some ", ") builder - oprToString hlp ins pc opr5 (Some ", ") builder - oprToString hlp ins pc opr6 (Some ", ") builder - -let disasm hlp (ins: InsInfo) (builder: DisasmBuilder<_>) = + oprToString reader ins pc opr1 (Some " ") builder + oprToString reader ins pc opr2 (Some ", ") builder + oprToString reader ins pc opr3 (Some ", ") builder + oprToString reader ins pc opr4 (Some ", ") builder + oprToString reader ins pc opr5 (Some ", ") builder + oprToString reader ins pc opr6 (Some ", ") builder + +let disasm reader (ins: InsInfo) (builder: DisasmBuilder) = let pc = ins.Address if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode ins builder - buildOprs hlp ins pc builder + buildOprs reader ins pc builder diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs b/src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs index b2b0534c..d77cb8bc 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32IRHelper.fs @@ -43,96 +43,97 @@ let haveVirtExt () = AST.b0 /// Gets the mask bits for fetching the condition flag bits from the PSR. /// PSR bit[31:28] -let maskPSRForCondbits = AST.num <| BitVector.ofBInt 4026531840I 32 +let maskPSRForCondbits = AST.num <| BitVector.OfBInt 4026531840I 32 /// Gets the mask bits for fetching the N condition flag from the PSR. /// PSR bit[31] -let maskPSRForNbit = AST.num <| BitVector.ofBInt 2147483648I 32 +let maskPSRForNbit = AST.num <| BitVector.OfBInt 2147483648I 32 /// Gets the mask bits for fetching the Z condition flag from the PSR. /// PSR bits[30] -let maskPSRForZbit = AST.num <| BitVector.ofBInt 1073741824I 32 +let maskPSRForZbit = AST.num <| BitVector.OfBInt 1073741824I 32 /// Gets the mask bits for fetching the C condition flag from the PSR. /// PSR bit[29] -let maskPSRForCbit = AST.num <| BitVector.ofBInt 536870912I 32 +let maskPSRForCbit = AST.num <| BitVector.OfBInt 536870912I 32 /// Gets the mask bits for fetching the V condition flag from the PSR. /// PSR bit[28] -let maskPSRForVbit = AST.num <| BitVector.ofBInt 268435456I 32 +let maskPSRForVbit = AST.num <| BitVector.OfBInt 268435456I 32 /// Gets the mask bits for fetching the Q bit from the PSR. /// PSR bit[27] -let maskPSRForQbit = AST.num <| BitVector.ofBInt 134217728I 32 +let maskPSRForQbit = AST.num <| BitVector.OfBInt 134217728I 32 /// Gets the mask bits for fetching the IT[1:0] bits from the PSR. /// PSR bits[26:25] -let maskPSRForIT10bits = AST.num <| BitVector.ofBInt 100663296I 32 +let maskPSRForIT10bits = AST.num <| BitVector.OfBInt 100663296I 32 /// Gets the mask bits for fetching the J bit from the PSR. /// PSR bit[24] -let maskPSRForJbit = AST.num <| BitVector.ofBInt 16777216I 32 +let maskPSRForJbit = AST.num <| BitVector.OfBInt 16777216I 32 /// Gets the mask bits for fetching the GE[3:0] bits from the PSR. /// PSR bits[19:16] -let maskPSRForGEbits = AST.num <| BitVector.ofBInt 983040I 32 +let maskPSRForGEbits = AST.num <| BitVector.OfBInt 983040I 32 /// Gets the mask bits for fetching the IT[7:2] bits from the PSR. /// PSR bits[15:10] -let maskPSRForIT72bits = AST.num <| BitVector.ofBInt 64512I 32 +let maskPSRForIT72bits = AST.num <| BitVector.OfBInt 64512I 32 /// Gets the mask bits for fetching the E bit from the PSR. /// PSR bit[9] -let maskPSRForEbit = AST.num <| BitVector.ofBInt 512I 32 +let maskPSRForEbit = AST.num <| BitVector.OfBInt 512I 32 /// Gets the mask bits for fetching the A bit from the PSR. /// PSR bit[8] -let maskPSRForAbit = AST.num <| BitVector.ofBInt 256I 32 +let maskPSRForAbit = AST.num <| BitVector.OfBInt 256I 32 /// Gets the mask bits for fetching the I bit from the PSR. /// PSR bit[7] -let maskPSRForIbit = AST.num <| BitVector.ofBInt 128I 32 +let maskPSRForIbit = AST.num <| BitVector.OfBInt 128I 32 /// Gets the mask bits for fetching the F bit from the PSR. /// PSR bit[6] -let maskPSRForFbit = AST.num <| BitVector.ofBInt 64I 32 +let maskPSRForFbit = AST.num <| BitVector.OfBInt 64I 32 /// Gets the mask bits for fetching the T bit from the PSR. /// PSR bit[5] -let maskPSRForTbit = AST.num <| BitVector.ofBInt 32I 32 +let maskPSRForTbit = AST.num <| BitVector.OfBInt 32I 32 /// Gets the mask bits for fetching the M[4:0] bits from the PSR. /// PSR bits[4:0] -let maskPSRForMbits = AST.num <| BitVector.ofBInt 31I 32 +let maskPSRForMbits = AST.num <| BitVector.OfBInt 31I 32 /// Get PSR bits without shifting it. let internal getPSR ctxt reg psrType = let psr = getRegVar ctxt reg match psrType with - | PSR_Cond -> psr .& maskPSRForCondbits - | PSR_N -> psr .& maskPSRForNbit - | PSR_Z -> psr .& maskPSRForZbit - | PSR_C -> psr .& maskPSRForCbit - | PSR_V -> psr .& maskPSRForVbit - | PSR_Q -> psr .& maskPSRForQbit - | PSR_IT10 -> psr .& maskPSRForIT10bits - | PSR_J -> psr .& maskPSRForJbit - | PSR_GE -> psr .& maskPSRForGEbits - | PSR_IT72 -> psr .& maskPSRForIT72bits - | PSR_E -> psr .& maskPSRForEbit - | PSR_A -> psr .& maskPSRForAbit - | PSR_I -> psr .& maskPSRForIbit - | PSR_F -> psr .& maskPSRForFbit - | PSR_T -> psr .& maskPSRForTbit - | PSR_M -> psr .& maskPSRForMbits - -let isSetCPSR_N ctxt = getPSR ctxt R.CPSR PSR_N == maskPSRForNbit -let isSetCPSR_Z ctxt = getPSR ctxt R.CPSR PSR_Z == maskPSRForZbit -let isSetCPSR_C ctxt = getPSR ctxt R.CPSR PSR_C == maskPSRForCbit -let isSetCPSR_V ctxt = getPSR ctxt R.CPSR PSR_V == maskPSRForVbit -let isSetCPSR_J ctxt = getPSR ctxt R.CPSR PSR_J == maskPSRForJbit -let isSetCPSR_T ctxt = getPSR ctxt R.CPSR PSR_T == maskPSRForTbit -let isSetCPSR_M ctxt = getPSR ctxt R.CPSR PSR_M == maskPSRForMbits + | PSR.Cond -> psr .& maskPSRForCondbits + | PSR.N -> psr .& maskPSRForNbit + | PSR.Z -> psr .& maskPSRForZbit + | PSR.C -> psr .& maskPSRForCbit + | PSR.V -> psr .& maskPSRForVbit + | PSR.Q -> psr .& maskPSRForQbit + | PSR.IT10 -> psr .& maskPSRForIT10bits + | PSR.J -> psr .& maskPSRForJbit + | PSR.GE -> psr .& maskPSRForGEbits + | PSR.IT72 -> psr .& maskPSRForIT72bits + | PSR.E -> psr .& maskPSRForEbit + | PSR.A -> psr .& maskPSRForAbit + | PSR.I -> psr .& maskPSRForIbit + | PSR.F -> psr .& maskPSRForFbit + | PSR.T -> psr .& maskPSRForTbit + | PSR.M -> psr .& maskPSRForMbits + | _ -> Utils.impossible () + +let isSetCPSRn ctxt = getPSR ctxt R.CPSR PSR.N == maskPSRForNbit +let isSetCPSRz ctxt = getPSR ctxt R.CPSR PSR.Z == maskPSRForZbit +let isSetCPSRc ctxt = getPSR ctxt R.CPSR PSR.C == maskPSRForCbit +let isSetCPSRv ctxt = getPSR ctxt R.CPSR PSR.V == maskPSRForVbit +let isSetCPSRj ctxt = getPSR ctxt R.CPSR PSR.J == maskPSRForJbit +let isSetCPSRt ctxt = getPSR ctxt R.CPSR PSR.T == maskPSRForTbit +let isSetCPSRm ctxt = getPSR ctxt R.CPSR PSR.M == maskPSRForMbits /// Test whether mode number is valid, on page B1-1142. /// function : BadMode() @@ -159,7 +160,7 @@ let isBadMode modeM = /// Returns TRUE if current mode is User or System mode, on page B1-1142. /// function : CurrentModeIsUserOrSystem() let currentModeIsUserOrSystem ctxt = - let modeM = getPSR ctxt R.CPSR PSR_M + let modeM = getPSR ctxt R.CPSR PSR.M let modeCond = isBadMode modeM let ite1 = modeM == (numI32 0b11111 32) let ite2 = AST.ite (modeM == (numI32 0b10000 32)) AST.b1 ite1 @@ -168,18 +169,18 @@ let currentModeIsUserOrSystem ctxt = /// Returns TRUE if current mode is Hyp mode, on page B1-1142. /// function : CurrentModeIsHyp() let currentModeIsHyp ctxt = - let modeM = getPSR ctxt R.CPSR PSR_M + let modeM = getPSR ctxt R.CPSR PSR.M let modeCond = isBadMode modeM let ite1 = modeM == (numI32 0b11010 32) AST.ite modeCond (AST.undef 1 "UNPREDICTABLE") ite1 /// Is this ARM instruction set, on page A2-51. let isInstrSetARM ctxt = - AST.not (isSetCPSR_J ctxt) .& AST.not (isSetCPSR_T ctxt) + AST.not (isSetCPSRj ctxt) .& AST.not (isSetCPSRt ctxt) /// Is this Thumb instruction set, on page A2-51. -let isInstrSetThumb ctxt = AST.not (isSetCPSR_J ctxt) .& (isSetCPSR_T ctxt) +let isInstrSetThumb ctxt = AST.not (isSetCPSRj ctxt) .& (isSetCPSRt ctxt) /// Is this ThumbEE instruction set, on page A2-51. -let isInstrSetThumbEE ctxt = (isSetCPSR_J ctxt) .& (isSetCPSR_T ctxt) +let isInstrSetThumbEE ctxt = (isSetCPSRj ctxt) .& (isSetCPSRt ctxt) diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs index c5c95164..199de6f2 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Instruction.fs @@ -29,11 +29,9 @@ open B2R2.FrontEnd.BinLifter /// The internal representation for an ARM32 instruction used by our /// disassembler and lifter. -type ARM32Instruction (addr, nb, cond, op, opr, its, wb, q, s, m, cf) = +type ARM32Instruction (addr, nb, cond, op, opr, its, wb, q, s, m, cf, oSz, a) = inherit ARM32InternalInstruction (addr, nb, cond, op, opr, - its, wb, q, s, m, cf) - - let dummyHelper = DisasmHelper () + its, wb, q, s, m, cf, oSz, a) override __.IsBranch () = match op with @@ -106,12 +104,16 @@ type ARM32Instruction (addr, nb, cond, op, opr, its, wb, q, s, m, cf) = | _ -> false override __.IsExit () = - Utils.futureFeature () + match op with + | Opcode.HLT + | Opcode.UDF + | Opcode.ERET -> true + | _ -> false override __.IsBBLEnd () = - __.IsDirectBranch () || - __.IsIndirectBranch () || - __.IsInterrupt () + __.IsBranch () + || __.IsInterrupt () + || __.IsExit () override __.DirectBranchTarget (addr: byref) = if __.IsBranch () then @@ -164,18 +166,18 @@ type ARM32Instruction (addr, nb, cond, op, opr, its, wb, q, s, m, cf) = | _ -> m member private __.AddBranchTargetIfExist addrs = - match __.DirectBranchTarget () |> Utils.tupleToOpt with + match __.DirectBranchTarget () |> Utils.tupleResultToOpt with | None -> addrs | Some target -> - Seq.singleton (target, __.GetNextMode ()) |> Seq.append addrs + [| (target, __.GetNextMode ()) |] |> Array.append addrs override __.GetNextInstrAddrs () = - let acc = Seq.singleton (__.Address + uint64 __.Length, m) + let acc = [| (__.Address + uint64 __.Length, m) |] if __.IsCall () then acc |> __.AddBranchTargetIfExist elif __.IsBranch () then if __.IsCondBranch () then acc |> __.AddBranchTargetIfExist - else __.AddBranchTargetIfExist Seq.empty - elif op = Opcode.HLT then Seq.empty + else __.AddBranchTargetIfExist [||] + elif op = Opcode.HLT then [||] else acc override __.InterruptNum (_num: byref) = Utils.futureFeature () @@ -184,28 +186,29 @@ type ARM32Instruction (addr, nb, cond, op, opr, its, wb, q, s, m, cf) = op = Op.NOP override __.Translate ctxt = - (Lifter.translate __ ctxt).ToStmts () + (Lifter.translate __ nb ctxt).ToStmts () override __.TranslateToList ctxt = - Lifter.translate __ ctxt + Lifter.translate __ nb ctxt - override __.Disasm (showAddr, resolveSym, disasmHelper) = + override __.Disasm (showAddr, nameReader) = + let resolveSymb = not (isNull nameReader) let builder = - DisasmStringBuilder (showAddr, resolveSym, WordSize.Bit32, addr, nb) - Disasm.disasm disasmHelper __ builder - builder.Finalize () + DisasmStringBuilder (showAddr, resolveSymb, WordSize.Bit32, addr, nb) + Disasm.disasm nameReader __ builder + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit32, addr, nb) - Disasm.disasm dummyHelper __ builder - builder.Finalize () + Disasm.disasm null __ builder + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, nb, 8) - Disasm.disasm dummyHelper __ builder - builder.Finalize () + Disasm.disasm null __ builder + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs index d816655f..bf04879f 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Lifter.fs @@ -30,14 +30,16 @@ open B2R2.BinIR open B2R2.BinIR.LowUIR open B2R2.BinIR.LowUIR.AST.InfixOp open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators open B2R2.FrontEnd.BinLifter.LiftingUtils open B2R2.FrontEnd.BinLifter.ARM32 open B2R2.FrontEnd.BinLifter.ARM32.IRHelper -let inline private ( 1u | R.R1 -> 2u @@ -77,38 +79,76 @@ let simdToExpr ctxt = function *) | _ -> raise InvalidOperandException -let transOprToExpr ctxt = function +let inline getPseudoRegVar (ctxt: TranslationContext) name pos = + ctxt.GetPseudoRegVar (Register.toRegID name) pos + +let getTwoOprs (ins: InsInfo) = + match ins.Operands with + | TwoOperands (o1, o2) -> struct (o1, o2) + | _ -> raise InvalidOperandException + +let getThreeOprs (ins: InsInfo) = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> struct (o1, o2, o3) + | _ -> raise InvalidOperandException + +let getFourOprs (ins: InsInfo) = + match ins.Operands with + | FourOperands (o1, o2, o3, o4) -> struct (o1, o2, o3, o4) + | _ -> raise InvalidOperandException + +let getImmValue imm = + match imm with + | OprImm imm -> imm + | _ -> raise InvalidOperandException + +let getPseudoRegVar128 ctxt r = + getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1 + +let transOprToExpr128 ctxt = function + | OprSIMD (SFReg (Vector reg)) -> getPseudoRegVar128 ctxt reg + | _ -> raise InvalidOperandException + +let transOprToSclar ctxt = function + | OprSIMD (SFReg (Scalar (reg, Some idx))) -> getRegVar ctxt reg, int32 idx + | _ -> raise InvalidOperandException + +let transOprToExpr (ins: InsInfo) ctxt = function | OprSpecReg (reg, _) | OprReg reg -> getRegVar ctxt reg | OprRegList regs -> regsToExpr regs | OprSIMD simd -> simdToExpr ctxt simd - | OprImm imm -> numI64 imm 32 // FIXME + | OprImm imm -> + let oprSize = if ins.OprSize = 128 then 64 else ins.OprSize + numI64 imm oprSize | _ -> raise InvalidOperandException let transOneOpr (ins: InsInfo) ctxt = match ins.Operands with - | OneOperand opr -> transOprToExpr ctxt opr + | OneOperand opr -> transOprToExpr ins ctxt opr | _ -> raise InvalidOperandException let transTwoOprs (ins: InsInfo) ctxt = match ins.Operands with - | TwoOperands (opr1, opr2) -> transOprToExpr ctxt opr1, - transOprToExpr ctxt opr2 + | TwoOperands (opr1, opr2) -> + struct (transOprToExpr ins ctxt opr1, transOprToExpr ins ctxt opr2) | _ -> raise InvalidOperandException let transThreeOprs (ins: InsInfo) ctxt = match ins.Operands with - | ThreeOperands (opr1, opr2, opr3) -> transOprToExpr ctxt opr1, - transOprToExpr ctxt opr2, - transOprToExpr ctxt opr3 + | ThreeOperands (opr1, opr2, opr3) -> + struct (transOprToExpr ins ctxt opr1, + transOprToExpr ins ctxt opr2, + transOprToExpr ins ctxt opr3) | _ -> raise InvalidOperandException let transFourOprs (ins: InsInfo) ctxt = match ins.Operands with - | FourOperands (o1, o2, o3, o4) -> transOprToExpr ctxt o1, - transOprToExpr ctxt o2, - transOprToExpr ctxt o3, - transOprToExpr ctxt o4 + | FourOperands (o1, o2, o3, o4) -> + struct (transOprToExpr ins ctxt o1, + transOprToExpr ins ctxt o2, + transOprToExpr ins ctxt o3, + transOprToExpr ins ctxt o4) | _ -> raise InvalidOperandException let bvOfBaseAddr addr = numU64 addr 32 @@ -122,7 +162,7 @@ let getNSACR ctxt nsacrType = match nsacrType with | NSACR_RFR -> nsacr .& maskNSACRForRFRbit -let isSetNSACR_RFR ctxt = getNSACR ctxt NSACR_RFR == maskNSACRForRFRbit +let isSetNSACRForRFR ctxt = getNSACR ctxt NSACR_RFR == maskNSACRForRFRbit /// Gets the mask bits for fetching the AW bit from the SCR. /// SCR bit[5] @@ -143,88 +183,93 @@ let getSCR ctxt scrType = | SCR_FW -> scr .& maskSCRForFWbit | SCR_NS -> scr .& maskSCRForNSbit -let isSetSCR_AW ctxt = getSCR ctxt SCR_AW == maskSCRForAWbit -let isSetSCR_FW ctxt = getSCR ctxt SCR_FW == maskSCRForFWbit -let isSetSCR_NS ctxt = getSCR ctxt SCR_NS == maskSCRForNSbit +let isSetSCRForAW ctxt = getSCR ctxt SCR_AW == maskSCRForAWbit +let isSetSCRForFW ctxt = getSCR ctxt SCR_FW == maskSCRForFWbit +let isSetSCRForNS ctxt = getSCR ctxt SCR_NS == maskSCRForNSbit /// Gets the mask bits for fetching the NMFI bit from the SCTLR. /// SCTLR bit[27] -let maskSCTLRForNMFIbit = AST.num <| BitVector.ofBInt 134217728I 32 +let maskSCTLRForNMFIbit = AST.num <| BitVector.OfBInt 134217728I 32 let getSCTLR ctxt sctlrType = let sctlr = getRegVar ctxt R.SCTLR match sctlrType with | SCTLR_NMFI -> sctlr .& maskSCTLRForNMFIbit -let isSetSCTLR_NMFI ctxt = getSCTLR ctxt SCTLR_NMFI == maskSCTLRForNMFIbit +let isSetSCTLRForNMFI ctxt = getSCTLR ctxt SCTLR_NMFI == maskSCTLRForNMFIbit let enablePSRBits ctxt reg psrType = let psr = getRegVar ctxt reg match psrType with - | PSR_Cond -> psr .| maskPSRForCondbits - | PSR_N -> psr .| maskPSRForNbit - | PSR_Z -> psr .| maskPSRForZbit - | PSR_C -> psr .| maskPSRForCbit - | PSR_V -> psr .| maskPSRForVbit - | PSR_Q -> psr .| maskPSRForQbit - | PSR_IT10 -> psr .| maskPSRForIT10bits - | PSR_J -> psr .| maskPSRForJbit - | PSR_GE -> psr .| maskPSRForGEbits - | PSR_IT72 -> psr .| maskPSRForIT72bits - | PSR_E -> psr .| maskPSRForEbit - | PSR_A -> psr .| maskPSRForAbit - | PSR_I -> psr .| maskPSRForIbit - | PSR_F -> psr .| maskPSRForFbit - | PSR_T -> psr .| maskPSRForTbit - | PSR_M -> psr .| maskPSRForMbits + | PSR.Cond -> psr .| maskPSRForCondbits + | PSR.N -> psr .| maskPSRForNbit + | PSR.Z -> psr .| maskPSRForZbit + | PSR.C -> psr .| maskPSRForCbit + | PSR.V -> psr .| maskPSRForVbit + | PSR.Q -> psr .| maskPSRForQbit + | PSR.IT10 -> psr .| maskPSRForIT10bits + | PSR.J -> psr .| maskPSRForJbit + | PSR.GE -> psr .| maskPSRForGEbits + | PSR.IT72 -> psr .| maskPSRForIT72bits + | PSR.E -> psr .| maskPSRForEbit + | PSR.A -> psr .| maskPSRForAbit + | PSR.I -> psr .| maskPSRForIbit + | PSR.F -> psr .| maskPSRForFbit + | PSR.T -> psr .| maskPSRForTbit + | PSR.M -> psr .| maskPSRForMbits + | _ -> Utils.impossible () let disablePSRBits ctxt reg psrType = let psr = getRegVar ctxt reg match psrType with - | PSR_Cond -> psr .& AST.not maskPSRForCondbits - | PSR_N -> psr .& AST.not maskPSRForNbit - | PSR_Z -> psr .& AST.not maskPSRForZbit - | PSR_C -> psr .& AST.not maskPSRForCbit - | PSR_V -> psr .& AST.not maskPSRForVbit - | PSR_Q -> psr .& AST.not maskPSRForQbit - | PSR_IT10 -> psr .& AST.not maskPSRForIT10bits - | PSR_J -> psr .& AST.not maskPSRForJbit - | PSR_GE -> psr .& AST.not maskPSRForGEbits - | PSR_IT72 -> psr .& AST.not maskPSRForIT72bits - | PSR_E -> psr .& AST.not maskPSRForEbit - | PSR_A -> psr .& AST.not maskPSRForAbit - | PSR_I -> psr .& AST.not maskPSRForIbit - | PSR_F -> psr .& AST.not maskPSRForFbit - | PSR_T -> psr .& AST.not maskPSRForTbit - | PSR_M -> psr .& AST.not maskPSRForMbits + | PSR.Cond -> psr .& AST.not maskPSRForCondbits + | PSR.N -> psr .& AST.not maskPSRForNbit + | PSR.Z -> psr .& AST.not maskPSRForZbit + | PSR.C -> psr .& AST.not maskPSRForCbit + | PSR.V -> psr .& AST.not maskPSRForVbit + | PSR.Q -> psr .& AST.not maskPSRForQbit + | PSR.IT10 -> psr .& AST.not maskPSRForIT10bits + | PSR.J -> psr .& AST.not maskPSRForJbit + | PSR.GE -> psr .& AST.not maskPSRForGEbits + | PSR.IT72 -> psr .& AST.not maskPSRForIT72bits + | PSR.E -> psr .& AST.not maskPSRForEbit + | PSR.A -> psr .& AST.not maskPSRForAbit + | PSR.I -> psr .& AST.not maskPSRForIbit + | PSR.F -> psr .& AST.not maskPSRForFbit + | PSR.T -> psr .& AST.not maskPSRForTbit + | PSR.M -> psr .& AST.not maskPSRForMbits + | _ -> Utils.impossible () + +let psrShift psrType expr = + match psrType with + | PSR.Cond -> expr << (numI32 28 32) + | PSR.N -> expr << (numI32 31 32) + | PSR.Z -> expr << (numI32 30 32) + | PSR.C -> expr << (numI32 29 32) + | PSR.V -> expr << (numI32 28 32) + | PSR.Q -> expr << (numI32 27 32) + | PSR.IT10 -> expr << (numI32 25 32) + | PSR.J -> expr << (numI32 24 32) + | PSR.GE -> expr << (numI32 16 32) + | PSR.IT72 -> expr << (numI32 10 32) + | PSR.E -> expr << (numI32 9 32) + | PSR.A -> expr << (numI32 8 32) + | PSR.I -> expr << (numI32 7 32) + | PSR.F -> expr << (numI32 6 32) + | PSR.T -> expr << (numI32 5 32) + | PSR.M -> expr + | _ -> Utils.impossible () let setPSR ctxt reg psrType expr = - let shift expr = - match psrType with - | PSR_Cond -> expr << (numI32 28 32) - | PSR_N -> expr << (numI32 31 32) - | PSR_Z -> expr << (numI32 30 32) - | PSR_C -> expr << (numI32 29 32) - | PSR_V -> expr << (numI32 28 32) - | PSR_Q -> expr << (numI32 27 32) - | PSR_IT10 -> expr << (numI32 25 32) - | PSR_J -> expr << (numI32 24 32) - | PSR_GE -> expr << (numI32 16 32) - | PSR_IT72 -> expr << (numI32 10 32) - | PSR_E -> expr << (numI32 9 32) - | PSR_A -> expr << (numI32 8 32) - | PSR_I -> expr << (numI32 7 32) - | PSR_F -> expr << (numI32 6 32) - | PSR_T -> expr << (numI32 5 32) - | PSR_M -> expr - disablePSRBits ctxt reg psrType .| (AST.zext 32 expr |> shift) + disablePSRBits ctxt reg psrType + .| (AST.zext 32 expr |> psrShift psrType) let getCarryFlag ctxt = - getPSR ctxt R.CPSR PSR_C >> (numI32 29 32) + getPSR ctxt R.CPSR PSR.C >> (numI32 29 32) let getZeroMask maskSize regType = - BitVector.ofBInt (BigInteger.getMask maskSize) regType - |> BitVector.bnot |> AST.num + BitVector.OfBInt (BigInteger.getMask maskSize) regType + |> BitVector.BNot |> AST.num let zMaskAnd e regType maskSize = e .& (getZeroMask maskSize regType) @@ -234,46 +279,48 @@ let maskAndOR e1 e2 regType maskSize = let expr = e1 .& mask expr .| e2 -let getOverflowFlagOnAdd e1 e2 r = - let e1High = AST.xthi 1 e1 +let getOverflowFlagOnAdd e1 e2 r (ir: IRBuilder) = + let struct (e1High, rHigh) = tmpVars2 ir 1 + !!ir (e1High := AST.xthi 1 e1) let e2High = AST.xthi 1 e2 - let rHigh = AST.xthi 1 r - (e1High == e2High) .& (e1High <+> rHigh) + !!ir (rHigh := AST.xthi 1 r) + struct ((e1High == e2High) .& (e1High <+> rHigh), rHigh) let parseCond = function - | Condition.EQ -> 0b000, 0 - | Condition.NE -> 0b000, 1 - | Condition.CS -> 0b001, 0 - | Condition.CC -> 0b001, 1 - | Condition.MI -> 0b010, 0 - | Condition.PL -> 0b010, 1 - | Condition.VS -> 0b011, 0 - | Condition.VC -> 0b011, 1 - | Condition.HI -> 0b100, 0 - | Condition.LS -> 0b100, 1 - | Condition.GE -> 0b101, 0 - | Condition.LT -> 0b101, 1 - | Condition.GT -> 0b110, 0 - | Condition.LE -> 0b110, 1 - | Condition.AL -> 0b111, 0 - | Condition.UN -> 0b111, 1 - | _ -> failwith "Invalid condition" + | Condition.EQ -> struct (0b000, 0) + | Condition.NE -> struct (0b000, 1) + | Condition.CS -> struct (0b001, 0) + | Condition.CC -> struct (0b001, 1) + | Condition.MI -> struct (0b010, 0) + | Condition.PL -> struct (0b010, 1) + | Condition.VS -> struct (0b011, 0) + | Condition.VC -> struct (0b011, 1) + | Condition.HI -> struct (0b100, 0) + | Condition.LS -> struct (0b100, 1) + | Condition.GE -> struct (0b101, 0) + | Condition.LT -> struct (0b101, 1) + | Condition.GT -> struct (0b110, 0) + | Condition.LE -> struct (0b110, 1) + | Condition.AL -> struct (0b111, 0) + | Condition.UN -> struct (0b111, 1) + | _ -> raise InvalidOperandException /// Returns TRUE if the current instruction needs to be executed. See page /// A8-289. function : ConditionPassed() let conditionPassed ctxt cond = - let cond1, cond2 = parseCond cond + let struct (cond1, cond2) = parseCond cond let result = match cond1 with - | 0b000 -> isSetCPSR_Z ctxt - | 0b001 -> isSetCPSR_C ctxt - | 0b010 -> isSetCPSR_N ctxt - | 0b011 -> isSetCPSR_V ctxt - | 0b100 -> isSetCPSR_C ctxt .& AST.not (isSetCPSR_Z ctxt) - | 0b101 -> isSetCPSR_N ctxt == isSetCPSR_V ctxt - | 0b110 -> isSetCPSR_N ctxt == isSetCPSR_V ctxt .& AST.not (isSetCPSR_Z ctxt) + | 0b000 -> isSetCPSRz ctxt + | 0b001 -> isSetCPSRc ctxt + | 0b010 -> isSetCPSRn ctxt + | 0b011 -> isSetCPSRv ctxt + | 0b100 -> isSetCPSRc ctxt .& AST.not (isSetCPSRz ctxt) + | 0b101 -> isSetCPSRn ctxt == isSetCPSRv ctxt + | 0b110 -> + isSetCPSRn ctxt == isSetCPSRv ctxt .& AST.not (isSetCPSRz ctxt) | 0b111 -> AST.b1 - | _ -> failwith "Invalid condition" + | _ -> raise InvalidOperandException if cond1 <> 0b111 && cond2 = 1 then AST.not result else result /// Logical shift left of a bitstring, with carry output, on page A2-41. @@ -339,7 +386,8 @@ let shiftRRXCForRegAmount value regType amount carryIn = let e1 = shiftLSLForRegAmount (AST.zext 32 carryIn) regType (amount1 .- AST.num1 regType) carryIn let e2 = shiftLSRForRegAmount value regType (AST.num1 regType) carryIn - AST.ite chkZero value (e1 .| e2), AST.ite chkZero carryIn (AST.xtlo 1 value) + AST.ite chkZero value (e1 .| e2), + AST.ite chkZero carryIn (AST.xtlo 1 value) /// Rotate right with extend of a bitstring, on page A2-41. for Register amount. /// function : RRX() @@ -360,43 +408,43 @@ let shiftCForRegAmount value regType shiftType amount carryIn = /// Logical shift left of a bitstring, with carry output, on page A2-41. /// function : LSL_C() let shiftLSLC value regType amount = - Utils.assertByCond (amount > 0u) InvalidShiftAmountException + assertByCond (amount > 0u) InvalidShiftAmountException let amount = numU32 amount regType value << amount, value << (amount .- AST.num1 regType ) |> AST.xthi 1 /// Logical shift left of a bitstring, on page A2-41. function : LSL() let shiftLSL value regType amount = - Utils.assertByCond (amount >= 0u) InvalidShiftAmountException + assertByCond (amount >= 0u) InvalidShiftAmountException if amount = 0u then value else shiftLSLC value regType amount |> fst /// Logical shift right of a bitstring, with carry output, on page A2-41. /// function : LSR_C() let shiftLSRC value regType amount = - Utils.assertByCond (amount > 0u) InvalidShiftAmountException + assertByCond (amount > 0u) InvalidShiftAmountException let amount' = numU32 amount regType value >> amount', AST.extract value 1 (amount - 1u |> Convert.ToInt32) /// Logical shift right of a bitstring, on page A2-41. function : LSR() let shiftLSR value regType amount = - Utils.assertByCond (amount >= 0u) InvalidShiftAmountException + assertByCond (amount >= 0u) InvalidShiftAmountException if amount = 0u then value else shiftLSRC value regType amount |> fst /// Arithmetic shift right of a bitstring, with carry output, on page A2-41. /// function : ASR_C() let shiftASRC value regType amount = - Utils.assertByCond (amount > 0u) InvalidShiftAmountException + assertByCond (amount > 0u) InvalidShiftAmountException let amount = numU32 amount regType value ?>> amount, value ?>> (amount .- AST.num1 regType ) |> AST.xtlo 1 /// Logical shift right of a bitstring, on page A2-41. function : ASR() let shiftASR value regType amount = - Utils.assertByCond (amount >= 0u) InvalidShiftAmountException + assertByCond (amount >= 0u) InvalidShiftAmountException if amount = 0u then value else shiftASRC value regType amount |> fst /// Rotate right of a bitstring, with carry output, on page A2-41. /// function : ROR_C() let shiftRORC value regType amount = - Utils.assertByCond (amount <> 0u) InvalidShiftAmountException + assertByCond (amount <> 0u) InvalidShiftAmountException let m = amount % uint32 (RegType.toBitWidth regType) let result = shiftLSR value regType m .| shiftLSL value regType (32u - m) result, AST.xthi 1 result @@ -440,31 +488,34 @@ let shift value regType shiftType amount carryIn = /// Addition of bitstrings, with carry input and carry/overflow outputs, /// on page A2-43. function : AddWithCarry() -let addWithCarry src1 src2 carryIn = - let result = src1 .+ src2 .+ carryIn +let addWithCarry src1 src2 carryIn (ir: IRBuilder) = + let result = !+ir 32 + !!ir (result := src1 .+ src2 .+ carryIn) let carryOut = AST.ite (carryIn == (numU32 1u 32)) (AST.ge src1 (AST.not src2)) (AST.gt src1 (AST.not src2)) - let overflow = getOverflowFlagOnAdd src1 src2 result - result, carryOut, overflow + let struct (overflow, rHigh) = getOverflowFlagOnAdd src1 src2 result ir + struct (result, carryOut, overflow, rHigh) + +let addWithCarryOnlyResult src1 src2 carryIn = src1 .+ src2 .+ carryIn /// Sets the ARM instruction set, on page A2-51. -let selectARMInstrSet ctxt (builder: IRBuilder) = +let selectARMInstrSet ctxt (ir: IRBuilder) = let cpsr = getRegVar ctxt R.CPSR - builder selectARMInstrSet ctxt builder - | _ -> selectThumbInstrSet ctxt builder +let selectInstrSet ctxt ir = function + | ArchOperationMode.ARMMode -> selectARMInstrSet ctxt ir + | _ -> selectThumbInstrSet ctxt ir /// Write value to R.PC, without interworking, on page A2-47. /// function : BranchWritePC() @@ -474,39 +525,39 @@ let branchWritePC ctxt (ins: InsInfo) addr jmpInfo = | ArchOperationMode.ARMMode -> AST.interjmp addr jmpInfo | _ -> AST.interjmp addr jmpInfo -let disableITStateForCondBranches ctxt isUnconditional (builder: IRBuilder) = +let disableITStateForCondBranches ctxt isUnconditional (ir: IRBuilder) = if isUnconditional then () else let cpsr = getRegVar ctxt R.CPSR - builder addr == AST.b1 - disableITStateForCondBranches ctxt isUnconditional builder - builder 1) InterJmpKind.SwitchToThumb) - builder 1) InterJmpKind.SwitchToThumb) + !!ir (AST.lmark lblL1) + selectARMInstrSet ctxt ir + !!ir (AST.interjmp addr InterJmpKind.SwitchToARM) /// Write value to R.PC, with interworking for ARM only from ARMv7 on page /// A2-47. function : ALUWritePC() -let aluWritePC ctxt (ins: InsInfo) isUnconditional addr builder = +let aluWritePC ctxt (ins: InsInfo) isUnconditional addr ir = match ins.Mode with - | ArchOperationMode.ARMMode -> bxWritePC ctxt isUnconditional addr builder - | _ -> builder bxWritePC ctxt isUnconditional addr ir + | _ -> !!ir (branchWritePC ctxt ins addr InterJmpKind.Base) /// Write value to R.PC, with interworking (without it before ARMv5T), /// on page A2-47. function : LoadWritePC() -let loadWritePC ctxt isUnconditional builder result = - bxWritePC ctxt isUnconditional result builder +let loadWritePC ctxt isUnconditional ir result = + bxWritePC ctxt isUnconditional result ir /// Position of rightmost 1 in a bitstring, on page AppxP-2653. /// function : LowestSetBit() @@ -565,7 +616,7 @@ let countLeadingZeroBits b size = size - 1 - highestSetBit b size /// OprMemory access that must be aligned, at specified privilege level, /// on page B2-1294. function : MemA[] -let memAWithPriv addr size value = AST.b0 // FIXME +let memAWithPriv addr size value = AST.b0 // FIXME /// OprMemory access that must be aligned, at current privilege level, /// on page B2-1294. function : MemA_with_priv[] @@ -573,7 +624,7 @@ let memA addr size value = memAWithPriv addr size value /// OprMemory access that must be aligned, at specified privilege level, /// on page B2-1294. function : MemU_with_priv[] -let memUWithPriv addr size value = AST.b0 // FIXME +let memUWithPriv addr size value = AST.b0 // FIXME /// OprMemory access without alignment requirement, at current privilege level, /// on page B2-1295. function : MemU[] @@ -586,174 +637,98 @@ let pcStoreValue ctxt = getPC ctxt /// Returns TRUE in Secure state or if no Security Extensions, on page B1-1157. /// function : IsSecure() let isSecure ctxt = - AST.not (haveSecurityExt ()) .| AST.not (isSetSCR_NS ctxt) .| - (getPSR ctxt R.CPSR PSR_M == (numI32 0b10110 32)) + AST.not (haveSecurityExt ()) .| AST.not (isSetSCRForNS ctxt) .| + (getPSR ctxt R.CPSR PSR.M == (numI32 0b10110 32)) /// Return TRUE if current mode is executes at PL1 or higher, on page B1-1142. /// function : CurrentModeIsNotUser() let currentModeIsNotUser ctxt = - let modeM = getPSR ctxt R.CPSR PSR_M + let modeM = getPSR ctxt R.CPSR PSR.M let modeCond = isBadMode modeM let ite1 = - AST.ite (modeM == (numI32 0b10000 32)) - AST.b0 AST.b1 + AST.ite (modeM == (numI32 0b10000 32)) AST.b0 AST.b1 AST.ite modeCond (AST.undef 1 "UNPREDICTABLE") ite1 /// Bitstring replication, on page AppxP-2652. /// function : Replicate() let replicate expr regType lsb width value = - let v = BitVector.ofBInt (BigInteger.getMask width <<< lsb) regType - if value = 0 then expr .& (v |> BitVector.bnot |> AST.num) else expr .| (v |> AST.num) + let v = BitVector.OfBInt (BigInteger.getMask width <<< lsb) regType + if value = 0 then expr .& (v |> BitVector.BNot |> AST.num) + else expr .| (v |> AST.num) /// All-ones bitstring, on page AppxP-2652. -let ones rt = BitVector.ofBInt (RegType.getMask rt) rt |> AST.num - -let writeModeBits ctxt value isExcptReturn (builder: IRBuilder) = - let lblL8 = builder.NewSymbol "L8" - let lblL9 = builder.NewSymbol "L9" - let lblL10 = builder.NewSymbol "L10" - let lblL11 = builder.NewSymbol "L11" - let lblL12 = builder.NewSymbol "L12" - let lblL13 = builder.NewSymbol "L13" - let lblL14 = builder.NewSymbol "L14" - let lblL15 = builder.NewSymbol "L15" - let lblL16 = builder.NewSymbol "L16" - let lblL17 = builder.NewSymbol "L17" +let ones rt = BitVector.OfBInt (RegType.getMask rt) rt |> AST.num + +let writeModeBits ctxt value isExcptReturn (ir: IRBuilder) = + let lblL8 = !%ir "L8" + let lblL9 = !%ir "L9" + let lblL10 = !%ir "L10" + let lblL11 = !%ir "L11" + let lblL12 = !%ir "L12" + let lblL13 = !%ir "L13" + let lblL14 = !%ir "L14" + let lblL15 = !%ir "L15" + let lblL16 = !%ir "L16" + let lblL17 = !%ir "L17" let valueM = value .& maskPSRForMbits - let cpsrM = getPSR ctxt R.CPSR PSR_M + let cpsrM = getPSR ctxt R.CPSR PSR.M let num11010 = numI32 0b11010 32 let chkSecure = AST.not (isSecure ctxt) let cond1 = chkSecure .& (valueM == (numI32 0b10110 32)) - let cond2 = chkSecure .& isSetNSACR_RFR ctxt .& + let cond2 = chkSecure .& isSetNSACRForRFR ctxt .& (valueM == (numI32 0b10001 32)) let cond3 = chkSecure .& (valueM == num11010) let cond4 = chkSecure .& (cpsrM != num11010) .& (valueM == num11010) let cond5 = (cpsrM == num11010) .& (valueM != num11010) - builder - let cond = privileged .& (AST.not nmfi .| chkValueF) .& - (isSecure ctxt .| isSetSCR_FW ctxt .| haveVirtExt ()) - builder - let e = transOprToExpr ctxt opr1 - let carryIn = getCarryFlag ctxt - shift e 32 typ imm carryIn + let e = transOprToExpr ins ctxt opr1 + shift e 32 typ imm (getCarryFlag ctxt) + | OprReg _, OprRegShift (typ, reg) -> + let e = transOprToExpr ins ctxt opr1 + let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 + shiftForRegAmount e 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException let parseOprOfMVNS (ins: InsInfo) ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> transTwoOprs ins ctxt | ThreeOperands (opr1, opr2, opr3) -> - transOprToExpr ctxt opr1, transShiftOprs ctxt opr2 opr3 + struct (transOprToExpr ins ctxt opr1, transShiftOprs ins ctxt opr2 opr3) | _ -> raise InvalidOperandException let transTwoOprsOfADC (ins: InsInfo) ctxt = match ins.Operands with | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt - e1, e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt) + let struct (e1, e2) = transTwoOprs ins ctxt + struct (e1, e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt)) | _ -> raise InvalidOperandException let transThreeOprsOfADC (ins: InsInfo) ctxt = @@ -761,22 +736,21 @@ let transThreeOprsOfADC (ins: InsInfo) ctxt = | ThreeOperands (_, _, OprImm _) -> transThreeOprs ins ctxt | ThreeOperands (OprReg _, OprReg _, OprReg _) -> let carryIn = getCarryFlag ctxt - let e1, e2, e3 = transThreeOprs ins ctxt + let struct (e1, e2, e3) = transThreeOprs ins ctxt e1, e2, shift e3 32 SRTypeLSL 0u carryIn | _ -> raise InvalidOperandException let transFourOprsOfADC (ins: InsInfo) ctxt = match ins.Operands with - | FourOperands (opr1, opr2, opr3 , (OprShift (_, Imm _) as opr4)) -> - let e1, e2 = - transOprToExpr ctxt opr1, transOprToExpr ctxt opr2 - e1, e2, transShiftOprs ctxt opr3 opr4 - | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - let e3 = transOprToExpr ctxt opr3 + | FourOperands (opr1, opr2, opr3, (OprShift (_, Imm _) as opr4)) -> + let e1, e2 = transOprToExpr ins ctxt opr1, transOprToExpr ins ctxt opr2 + struct (e1, e2, transShiftOprs ins ctxt opr3 opr4) + | FourOperands (opr1, opr2, opr3, OprRegShift (typ, reg)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + let e3 = transOprToExpr ins ctxt opr3 let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 - e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) + struct (e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt)) | _ -> raise InvalidOperandException let parseOprOfADC (ins: InsInfo) ctxt = @@ -786,174 +760,176 @@ let parseOprOfADC (ins: InsInfo) ctxt = | FourOperands _ -> transFourOprsOfADC ins ctxt | _ -> raise InvalidOperandException -let startMark (ins: InsInfo) builder = - builder - let cond = builder.NewTempVar 1 - let nextstate = builder.NewTempVar 32 - let lblThen = builder.NewSymbol "LThen" - let lblElse = builder.NewSymbol "LElse" - let lblEnd = builder.NewSymbol "LEnd" +let itAdvance ctxt (ir: IRBuilder) = + let cond = !+ir 1 + let struct (itstate, nextstate) = tmpVars2 ir 32 + let lblThen = !%ir "LThen" + let lblElse = !%ir "LElse" + let lblEnd = !%ir "LEnd" let cpsr = getRegVar ctxt R.CPSR let cpsrIT10 = - getPSR ctxt R.CPSR PSR_IT10 >> (numI32 25 32) + getPSR ctxt R.CPSR PSR.IT10 >> (numI32 25 32) let cpsrIT72 = - getPSR ctxt R.CPSR PSR_IT72 >> (numI32 8 32) + getPSR ctxt R.CPSR PSR.IT72 >> (numI32 8 32) let mask10 = numI32 0x3 32 (* For ITSTATE[1:0] *) let mask20 = numI32 0x7 32 (* For ITSTATE[2:0] *) let mask40 = numI32 0x1f 32 (* For ITSTATE[4:0] *) let mask42 = numI32 0x1c 32 (* For ITSTATE[4:2] *) let cpsrIT42 = cpsr .& (numI32 0xffffe3ff 32) let num8 = numI32 8 32 - builder )) - builder )) - builder setPSR ctxt R.CPSR PSR_IT10) - builder () - | Some (i: InsInfo) -> - let target = numU64 (i.Address + uint64 i.Length) 32 - builder )) + !!ir (AST.cjmp cond (AST.name lblThen) (AST.name lblElse)) + !!ir (AST.lmark lblThen) + !!ir (cpsr := disablePSRBits ctxt R.CPSR PSR.IT10) + !!ir (cpsr := disablePSRBits ctxt R.CPSR PSR.IT72) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblElse) + !!ir (nextstate := (itstate .& mask40 << AST.num1 32)) + !!ir (cpsr := nextstate .& mask10 |> setPSR ctxt R.CPSR PSR.IT10) + !!ir (cpsr := cpsrIT42 .| ((nextstate .& mask42) << num8)) + !!ir (AST.lmark lblEnd) + +let putEndLabel ctxt lblIgnore ir = + match lblIgnore with + | Some lblIgnore -> + !!ir (AST.lmark lblIgnore) + itAdvance ctxt ir + | None -> () + +let putEndLabelForBranch ctxt lblIgnore (brIns: InsInfo) ir = + match lblIgnore with + | Some lblIgnore -> + !!ir (AST.lmark lblIgnore) + itAdvance ctxt ir + let target = numU64 (brIns.Address + uint64 brIns.Length) 32 + !!ir (AST.interjmp target InterJmpKind.Base) + | None -> () + +let sideEffects insLen ctxt name = + let ir = !*ctxt + !ir insLen + +let nop insLen ctxt = + let ir = !*ctxt + !ir insLen + +let convertPCOpr (ins: InsInfo) insLen ctxt opr = if opr = getPC ctxt then let rel = if ins.Mode = ArchOperationMode.ARMMode then 8 else 4 opr .+ (numI32 rel 32) else opr -let adc isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, src1, src2 = parseOprOfADC ins ctxt - let src1 = convertPCOpr ins ctxt src1 - let src2 = convertPCOpr ins ctxt src2 - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder + !!ir (t1 := src1) + !!ir (t2 := src2) + let struct (result, carryOut, overflow, rHigh) = + addWithCarry t1 t2 (getCarryFlag ctxt) ir + !!ir (dst := result) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := rHigh |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let transTwoOprsOfADD (ins: InsInfo) ctxt = + let result = !+ir 32 + !!ir (result := addWithCarryOnlyResult src1 src2 (getCarryFlag ctxt)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir + else !!ir (dst := result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let transTwoOprsOfADD (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> - let e1, e2 = transTwoOprs ins ctxt in e1, e1, e2 + let struct (e1, e2) = transTwoOprs ins ctxt + struct (e1, e1, e2) | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt - e1, e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt) + let struct (e1, e2) = transTwoOprs ins ctxt + struct (e1, e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt)) | _ -> raise InvalidOperandException -let transThreeOprsOfADD (ins: InsInfo) ctxt = +let transThreeOprsOfADD (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (_, _, OprImm _) -> transThreeOprs ins ctxt | ThreeOperands (OprReg _, OprReg _, OprReg _) -> let carryIn = getCarryFlag ctxt - let e1, e2, e3 = transThreeOprs ins ctxt - e1, e2, shift e3 32 SRTypeLSL 0u carryIn + let struct (e1, e2, e3) = transThreeOprs ins ctxt + struct (e1, e2, shift e3 32 SRTypeLSL 0u carryIn) | _ -> raise InvalidOperandException -let transFourOprsOfADD (ins: InsInfo) ctxt = +let transFourOprsOfADD (ins: InsInfo) insLen ctxt = match ins.Operands with - | FourOperands (opr1, opr2, opr3 , (OprShift (_, Imm _) as opr4)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - e1, e2, transShiftOprs ctxt opr3 opr4 - | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - let e3 = transOprToExpr ctxt opr3 + | FourOperands (opr1, opr2, opr3, (OprShift (_, Imm _) as opr4)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + struct (e1, e2, transShiftOprs ins ctxt opr3 opr4) + | FourOperands (opr1, opr2, opr3, OprRegShift (typ, reg)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + let e3 = transOprToExpr ins ctxt opr3 let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 - e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) + struct (e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt)) | _ -> raise InvalidOperandException -let parseOprOfADD (ins: InsInfo) ctxt = +let parseOprOfADD (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands _ -> transTwoOprsOfADD ins ctxt - | ThreeOperands _ -> transThreeOprsOfADD ins ctxt - | FourOperands _ -> transFourOprsOfADD ins ctxt + | TwoOperands _ -> transTwoOprsOfADD ins insLen ctxt + | ThreeOperands _ -> transThreeOprsOfADD ins insLen ctxt + | FourOperands _ -> transFourOprsOfADD ins insLen ctxt | _ -> raise InvalidOperandException -let add isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, src1, src2 = parseOprOfADD ins ctxt - let src1 = convertPCOpr ins ctxt src1 - let src2 = convertPCOpr ins ctxt src2 - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ) - if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result builder +let add isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src1, src2) = parseOprOfADD ins insLen ctxt + let src1 = convertPCOpr ins insLen ctxt src1 + let src2 = convertPCOpr ins insLen ctxt src2 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (t1 := src1) + !!ir (t2 := src2) + let struct (result, carryOut, overflow, rHigh) = + addWithCarry t1 t2 (AST.num0 32) ir + !!ir (dst := result) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := rHigh |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + let result = !+ir 32 + !!ir (result := addWithCarryOnlyResult src1 src2 (AST.num0 32)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir + else !!ir (dst := result) + putEndLabel ctxt lblIgnore ir + !>ir insLen /// Align integer or bitstring to multiple of an integer, on page AppxP-2655 /// function : Align() @@ -975,540 +951,674 @@ let transLableOprsOfBL ins targetMode imm = let targetModeOfBL (ins: InsInfo) = match ins.Opcode, ins.Mode with - | Op.BL, mode -> mode - | Op.BLX, ArchOperationMode.ARMMode -> ArchOperationMode.ThumbMode - | Op.BLX, ArchOperationMode.ThumbMode -> ArchOperationMode.ARMMode - | _ -> failwith "Invalid ARMMode" + | Op.BL, mode -> struct (mode, InterJmpKind.IsCall) + | Op.BLX, ArchOperationMode.ARMMode -> + struct (ArchOperationMode.ThumbMode, InterJmpKind.SwitchToThumb) + | Op.BLX, ArchOperationMode.ThumbMode -> + struct (ArchOperationMode.ARMMode, InterJmpKind.SwitchToARM) + | _ -> raise InvalidTargetArchModeException let parseOprOfBL ins = - let targetMode = targetModeOfBL ins + let struct (targetMode, callKind) = targetModeOfBL ins match ins.Operands with | OneOperand (OprMemory (LiteralMode imm)) -> - transLableOprsOfBL ins targetMode imm, targetMode + struct (transLableOprsOfBL ins targetMode imm, targetMode, callKind) | _ -> raise InvalidOperandException -let bl ins ctxt = - let builder = IRBuilder (16) - let alignedAddr, targetMode = parseOprOfBL ins +let bl ins insLen ctxt = + let ir = !*ctxt + let struct (alignedAddr, targetMode, callKind) = parseOprOfBL ins let lr = getRegVar ctxt R.LR let retAddr = bvOfBaseAddr ins.Address .+ (numI32 4 32) let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if ins.Mode = ArchOperationMode.ARMMode then builder ) 32 1) - selectInstrSet ctxt builder targetMode - builder ) 32 1) + selectInstrSet ctxt ir targetMode + !!ir (branchWritePC ctxt ins alignedAddr callKind) + putEndLabelForBranch ctxt lblIgnore ins ir + !>ir insLen + +let blxWithReg (ins: InsInfo) insLen reg ctxt = + let ir = !*ctxt let lr = getRegVar ctxt R.LR let addr = bvOfBaseAddr ins.Address let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + !)) + !!ir (lr := addr .+ (numI32 4 32)) else let addr = addr .+ (numI32 2 32) - builder ) 32 1) - bxWritePC ctxt isUnconditional (getRegVar ctxt reg) builder - putEndLabel ctxt lblIgnore isUnconditional (Some ins) builder - endMark ins builder + !!ir (lr := maskAndOR addr (AST.num1 32) 32 1) + bxWritePC ctxt isUnconditional (getRegVar ctxt reg) ir + putEndLabelForBranch ctxt lblIgnore ins ir + !>ir insLen -let branchWithLink (ins: InsInfo) ctxt = +let branchWithLink (ins: InsInfo) insLen ctxt = match ins.Operands with - | OneOperand (OprReg reg) -> blxWithReg ins reg ctxt - | _ -> bl ins ctxt + | OneOperand (OprReg reg) -> blxWithReg ins insLen reg ctxt + | _ -> bl ins insLen ctxt let parseOprOfPUSHPOP (ins: InsInfo) = match ins.Operands with - | OneOperand (OprReg r) -> regsToUInt32 [ r ] //, true (unAlignedAllowed) - | OneOperand (OprRegList regs) -> regsToUInt32 regs //, false (unAlignedAllowed) + | OneOperand (OprReg r) -> regsToUInt32 [ r ] + | OneOperand (OprRegList regs) -> regsToUInt32 regs | _ -> raise InvalidOperandException -let pushLoop ctxt numOfReg addr (builder: IRBuilder) = +let pushLoop ctxt numOfReg addr (ir: IRBuilder) = let loop addr count = if (numOfReg >>> count) &&& 1u = 1u then + let t = !+ir 32 + !!ir (t := addr) if count = 13 && count <> lowestSetBit numOfReg 32 then - builder addr := (AST.undef 32 "UNKNOWN")) + !!ir (AST.loadLE 32 t := (AST.undef 32 "UNKNOWN")) else let reg = count |> uint32 |> OperandHelper.getRegister - builder addr := getRegVar ctxt reg) - addr .+ (numI32 4 32) + !!ir (AST.loadLE 32 t := getRegVar ctxt reg) + t .+ (numI32 4 32) else addr List.fold loop addr [ 0 .. 14 ] -let push ins ctxt = - let builder = IRBuilder (32) - let t0 = builder.NewTempVar 32 +let push ins insLen ctxt = + let ir = !*ctxt + let t0 = !+ir 32 let sp = getRegVar ctxt R.SP let numOfReg = parseOprOfPUSHPOP ins let stackWidth = 4 * bitCount numOfReg 16 let addr = sp .- (numI32 stackWidth 32) let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder >> 15 &&& 1u) = 1u then - builder addr := pcStoreValue ctxt) + !!ir (AST.loadLE 32 addr := pcStoreValue ctxt) else () - builder , builder.NewTempVar 32 - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ) - builder ir insLen + +/// shared/functions/vector/SignedSatQ, on page Armv8 Pseudocode-7927 +let sSatQ ir i n = + let n1 = AST.num1 n + let cond = n1 << (numI32 (RegType.toBitWidth n) n .- n1) + let struct (t1, t2) = tmpVars2 ir n + !!ir (t1 := i) + !!ir (t2 := cond) + let cond1 = t1 .> (t2 .- n1) + let cond2 = t1 .< AST.not t2 + let r = (AST.ite cond1 (t2 .- n1) (AST.ite cond2 (AST.not t2) t1)) + let r = AST.xtlo n r + let sat = AST.ite cond1 AST.b1 (AST.ite cond2 AST.b1 (AST.num0 1)) + struct (r, sat) + +let sSat ir i n = + let struct (r, _) = sSatQ ir i n + r + +let qdadd (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let struct (dou, sat) = + sSatQ ir (numI32 2 32 .* src2) (RegType.fromBitWidth 32) + !!ir (sat1 := sat) + let struct (r, sat) = + sSatQ ir (src1 .+ dou) (RegType.fromBitWidth 32) + !!ir (dst := r) + !!ir (sat2 := sat) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := AST.ite (sat1 .| sat2) (enablePSRBits ctxt R.CPSR PSR.Q) cpsr) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let qdsub (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let struct (dou, sat) = + sSatQ ir (numI32 2 32 .* src2) (RegType.fromBitWidth 32) + !!ir (sat1 := sat) + let struct (r, sat) = sSatQ ir (src1 .- dou) (RegType.fromBitWidth 32) + !!ir (dst := r) + !!ir (sat2 := sat) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := AST.ite (sat1 .| sat2) (enablePSRBits ctxt R.CPSR PSR.Q) cpsr) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let qsax (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let xtlo src = AST.xtlo 16 src + let xthi src = AST.xthi 16 src + !!ir (sum := xtlo src1 .+ xthi src2) + !!ir (diff := xthi src1 .- xtlo src2) + !!ir (sum := sSat ir sum (RegType.fromBitWidth 16)) + !!ir (diff := sSat ir diff (RegType.fromBitWidth 16)) + !!ir (dst := AST.concat diff sum) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let qsub16 (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let xtlo src = AST.xtlo 16 src + let xthi src = AST.xthi 16 src + !!ir (diff1 := xtlo src1 .- xtlo src2) + !!ir (diff2 := xthi src1 .- xthi src2) + !!ir (diff1 := sSat ir diff1 (RegType.fromBitWidth 16)) + !!ir (diff2 := sSat ir diff2 (RegType.fromBitWidth 16)) + !!ir (dst := AST.concat diff2 diff1) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let sub isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src1, src2) = parseOprOfADD ins insLen ctxt + let src1 = convertPCOpr ins insLen ctxt src1 + let src2 = convertPCOpr ins insLen ctxt src2 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (t1 := src1) + !!ir (t2 := src2) + let struct (result, carryOut, overflow, rHigh) = + addWithCarry t1 (AST.not t2) (AST.num1 32) ir + !!ir (dst := result) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := rHigh |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + let result = !+ir 32 + !!ir (result := + addWithCarryOnlyResult src1 (AST.not src2) (AST.num1 32)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir + else !!ir (dst := result) + putEndLabel ctxt lblIgnore ir + !>ir insLen /// B9.3.19 SUBS R.PC, R.LR (Thumb), on page B9-2008 -let subsPCLRThumb ins ctxt = - let builder = IRBuilder (64) - let _, _, src2 = parseOprOfADD ins ctxt +let subsPCLRThumb ins insLen ctxt = + let ir = !*ctxt + let struct (_, _, src2) = parseOprOfADD ins insLen ctxt let pc = getPC ctxt - let result, _, _ = addWithCarry pc (AST.not src2) (AST.num1 32) + let struct (result, _, _, _) = + addWithCarry pc (AST.not src2) (AST.num1 32) ir let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - cpsrWriteByInstr ctxt (getRegVar ctxt R.SPSR) 0b1111 true builder - builder ir insLen let parseResultOfSUBAndRela (ins: InsInfo) ctxt = match ins.Opcode with - | Op.ANDS -> let _, src1, src2 = parseOprOfADC ins ctxt in src1.& src2 - | Op.EORS -> let _, src1, src2 = parseOprOfADC ins ctxt in src1 <+> src2 - | Op.SUBS -> let _, src1, src2 = parseOprOfADC ins ctxt - let r, _, _ = addWithCarry src1 (AST.not src2) (AST.num1 32) in r - | Op.RSBS -> let _, src1, src2 = parseOprOfADC ins ctxt - let r, _, _ = addWithCarry (AST.not src1) src2 (AST.num1 32) in r - | Op.ADDS -> let _, src1, src2 = parseOprOfADC ins ctxt - let r, _, _ = addWithCarry src1 src2 (AST.num0 32) in r - | Op.ADCS -> let _, src1, src2 = parseOprOfADC ins ctxt - let r, _, _ = addWithCarry src1 src2 (getCarryFlag ctxt) in r - | Op.SBCS -> let _, src1, src2 = parseOprOfADC ins ctxt - let r, _, _ = addWithCarry src1 (AST.not src2) (getCarryFlag ctxt) - r - | Op.RSCS -> let _, src1, src2 = parseOprOfADC ins ctxt - let r, _, _ = addWithCarry (AST.not src1) src2 (getCarryFlag ctxt) - r - | Op.ORRS -> let _, src1, src2 = parseOprOfADC ins ctxt in src1 .| src2 - | Op.MOVS -> let _, src = transTwoOprs ins ctxt in src - | Op.ASRS -> let _, src1, src2 = parseOprOfADC ins ctxt - shiftForRegAmount src1 32 SRTypeASR src2 (getCarryFlag ctxt) - | Op.LSLS -> let _, src1, src2 = parseOprOfADC ins ctxt - shiftForRegAmount src1 32 SRTypeLSL src2 (getCarryFlag ctxt) - | Op.LSRS -> let _, src1, src2 = parseOprOfADC ins ctxt - shiftForRegAmount src1 32 SRTypeLSR src2 (getCarryFlag ctxt) - | Op.RORS -> let _, src1, src2 = parseOprOfADC ins ctxt - shiftForRegAmount src1 32 SRTypeROR src2 (getCarryFlag ctxt) + | Op.ANDS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + src1.& src2 + | Op.EORS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + src1 <+> src2 + | Op.SUBS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + addWithCarryOnlyResult src1 (AST.not src2) (AST.num1 32) + | Op.RSBS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + addWithCarryOnlyResult (AST.not src1) src2 (AST.num1 32) + | Op.ADDS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + addWithCarryOnlyResult src1 src2 (AST.num0 32) + | Op.ADCS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + addWithCarryOnlyResult src1 src2 (getCarryFlag ctxt) + | Op.SBCS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + addWithCarryOnlyResult src1 (AST.not src2) (getCarryFlag ctxt) + | Op.RSCS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + addWithCarryOnlyResult (AST.not src1) src2 (getCarryFlag ctxt) + | Op.ORRS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + src1 .| src2 + | Op.MOVS -> + let struct (_, src) = transTwoOprs ins ctxt + src + | Op.ASRS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + shiftForRegAmount src1 32 SRTypeASR src2 (getCarryFlag ctxt) + | Op.LSLS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + shiftForRegAmount src1 32 SRTypeLSL src2 (getCarryFlag ctxt) + | Op.LSRS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + shiftForRegAmount src1 32 SRTypeLSR src2 (getCarryFlag ctxt) + | Op.RORS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + shiftForRegAmount src1 32 SRTypeROR src2 (getCarryFlag ctxt) | Op.RRXS -> - let _, src = transTwoOprs ins ctxt + let struct (_, src) = transTwoOprs ins ctxt shiftForRegAmount src 32 SRTypeRRX (AST.num1 32) (getCarryFlag ctxt) - | Op.BICS -> let _, src1, src2 = parseOprOfADC ins ctxt - src1 .& (AST.not src2) - | Op.MVNS -> let _, src = parseOprOfMVNS ins ctxt in AST.not src + | Op.BICS -> + let struct (_, src1, src2) = parseOprOfADC ins ctxt + src1 .& (AST.not src2) + | Op.MVNS -> + let struct (_, src) = parseOprOfMVNS ins ctxt + AST.not src | _ -> raise InvalidOperandException /// B9.3.20 SUBS R.PC, R.LR and related instruction (ARM), on page B9-2010 -let subsAndRelatedInstr (ins: InsInfo) ctxt = - let builder = IRBuilder (64) - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - cpsrWriteByInstr ctxt (getRegVar ctxt R.SPSR) 0b1111 true builder - builder + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let computeCarryOutFromImmCflag (ins: InsInfo) insLen ctxt = match ins.Cflag with | Some v -> - if v then BitVector.one 1 |> AST.num - else BitVector.zero 1 |> AST.num + if v then BitVector.One 1 |> AST.num + else BitVector.Zero 1 |> AST.num | None -> getCarryFlag ctxt -let translateLogicOp (ins: InsInfo) ctxt (builder: IRBuilder) = +let translateLogicOp (ins: InsInfo) insLen ctxt (ir: IRBuilder) = match ins.Operands with | TwoOperands (OprReg _, OprReg _) -> - let t = builder.NewTempVar 32 - let e1, e2 = transTwoOprs ins ctxt - builder + let struct (e1, e2) = transTwoOprs ins ctxt + !!ir (t := e2) let shifted, carryOut = shiftC t 32 SRTypeLSL 0u (getCarryFlag ctxt) e1, e1, shifted, carryOut | ThreeOperands (_, _, OprImm _) -> - let e1, e2, e3 = transThreeOprs ins ctxt - let carryOut = computeCarryOutFromImmCflag ins ctxt + let struct (e1, e2, e3) = transThreeOprs ins ctxt + let carryOut = computeCarryOutFromImmCflag ins insLen ctxt e1, e2, e3, carryOut - | FourOperands (opr1, opr2, opr3 , OprShift (typ, Imm imm)) -> - let t = builder.NewTempVar 32 + | ThreeOperands (OprReg _, OprReg _, OprReg _) -> + let t = !+ir 32 + let struct (e1, e2, e3) = transThreeOprs ins ctxt + !!ir (t := e3) + let shifted, carryOut = shiftC t 32 SRTypeLSL 0u (getCarryFlag ctxt) + e1, e2, shifted, carryOut + | FourOperands (opr1, opr2, opr3, OprShift (typ, Imm imm)) -> + let t = !+ir 32 let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src1 = transOprToExpr ctxt opr2 - let rm = transOprToExpr ctxt opr3 - builder typ imm carryIn dst, src1, shifted, carryOut - | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let t = builder.NewTempVar 32 + | FourOperands (opr1, opr2, opr3, OprRegShift (typ, reg)) -> + let t = !+ir 32 let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src1 = transOprToExpr ctxt opr2 - let rm = transOprToExpr ctxt opr3 - builder (getRegVar ctxt reg) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount t 32 typ amount carryIn dst, src1, shifted, carryOut | _ -> raise InvalidOperandException -let logicalAnd isSetFlags (ins: InsInfo) ctxt = - let builder = IRBuilder (32) +let logicalAnd isSetFlags (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let dst, src1, src2, carryOut = translateLogicOp ins ctxt builder - let result = builder.NewTempVar 32 - builder + !!ir (result := src1 .& src2) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let mov isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, res = transTwoOprs ins ctxt - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ir insLen + +let parseOprsOfMOV (ins: InsInfo) ctxt = + match ins.Operands with + | TwoOperands _ -> transTwoOprs ins ctxt + | ThreeOperands (opr1, opr2, opr3) -> + struct (transOprToExpr ins ctxt opr1, transShiftOprs ins ctxt opr2 opr3) + | _ -> raise InvalidOperandException + +let mov isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src) = parseOprsOfMOV ins ctxt + let result = !+ir 32 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + let pc = getPC ctxt + !)) + else !!ir (result := src) + if dst = pc then aluWritePC ctxt ins isUnconditional result ir else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let eor isSetFlags (ins: InsInfo) ctxt = - let builder = IRBuilder (32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let dst, src1, src2, carryOut = translateLogicOp ins ctxt builder - let result = builder.NewTempVar 32 - builder src2) - if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result builder + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let eor isSetFlags (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (result := src1 <+> src2) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let transFourOprsOfRSB (ins: InsInfo) ctxt = +let transFourOprsOfRSB (ins: InsInfo) insLen ctxt = match ins.Operands with - | FourOperands (opr1, opr2, opr3 , (OprShift (_, Imm _) as opr4)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - e1, e2, transShiftOprs ctxt opr3 opr4 - | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - let e3 = transOprToExpr ctxt opr3 + | FourOperands (opr1, opr2, opr3, (OprShift (_, Imm _) as opr4)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + struct (e1, e2, transShiftOprs ins ctxt opr3 opr4) + | FourOperands (opr1, opr2, opr3, OprRegShift (typ, reg)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + let e3 = transOprToExpr ins ctxt opr3 let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 - e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) + struct (e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt)) | _ -> raise InvalidOperandException -let parseOprOfRSB (ins: InsInfo) ctxt = +let parseOprOfRSB (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands _ -> transThreeOprs ins ctxt - | FourOperands _ -> transFourOprsOfRSB ins ctxt + | FourOperands _ -> transFourOprsOfRSB ins insLen ctxt | _ -> raise InvalidOperandException -let rsb isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, src1, src2 = parseOprOfRSB ins ctxt - let result = builder.NewTempVar 32 - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ) - builder + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !) ir + !!ir (dst := result) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := rHigh |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let transTwoOprsOfSBC (ins: InsInfo) ctxt = + let result = !+ir 32 + !!ir (result := + addWithCarryOnlyResult (AST.not src1) src2 (AST.num1 32)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir + else !!ir (dst := result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let transTwoOprsOfSBC (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt - e1, e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt) + let struct (e1, e2) = transTwoOprs ins ctxt + struct (e1, e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt)) | _ -> raise InvalidOperandException -let transFourOprsOfSBC (ins: InsInfo) ctxt = +let transFourOprsOfSBC (ins: InsInfo) insLen ctxt = match ins.Operands with - | FourOperands (opr1, opr2, opr3 , (OprShift (_, Imm _) as opr4)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - e1, e2, transShiftOprs ctxt opr3 opr4 - | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - let e3 = transOprToExpr ctxt opr3 + | FourOperands (opr1, opr2, opr3, (OprShift (_, Imm _) as opr4)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + struct (e1, e2, transShiftOprs ins ctxt opr3 opr4) + | FourOperands (opr1, opr2, opr3, OprRegShift (typ, reg)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + let e3 = transOprToExpr ins ctxt opr3 let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 - e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) + struct (e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt)) | _ -> raise InvalidOperandException -let parseOprOfSBC (ins: InsInfo) ctxt = +let parseOprOfSBC (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands _ -> transTwoOprsOfSBC ins ctxt + | TwoOperands _ -> transTwoOprsOfSBC ins insLen ctxt | ThreeOperands _ -> transThreeOprs ins ctxt - | FourOperands _ -> transFourOprsOfSBC ins ctxt + | FourOperands _ -> transFourOprsOfSBC ins insLen ctxt | _ -> raise InvalidOperandException -let sbc isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, src1, src2 = parseOprOfSBC ins ctxt - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let transFourOprsOfRSC (ins: InsInfo) ctxt = + let result = !+ir 32 + !!ir (result := + addWithCarryOnlyResult src1 (AST.not src2) (getCarryFlag ctxt)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir + else !!ir (dst := result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let transFourOprsOfRSC (ins: InsInfo) insLen ctxt = match ins.Operands with - | FourOperands (opr1, opr2, opr3 , (OprShift (_, Imm _) as opr4)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - e1, e2, transShiftOprs ctxt opr3 opr4 - | FourOperands (opr1, opr2, opr3 , OprRegShift (typ, reg)) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 - let e3 = transOprToExpr ctxt opr3 + | FourOperands (opr1, opr2, opr3, (OprShift (_, Imm _) as opr4)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + e1, e2, transShiftOprs ins ctxt opr3 opr4 + | FourOperands (opr1, opr2, opr3, OprRegShift (typ, reg)) -> + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 + let e3 = transOprToExpr ins ctxt opr3 let amount = AST.xtlo 8 (getRegVar ctxt reg) |> AST.zext 32 e1, e2, shiftForRegAmount e3 32 typ amount (getCarryFlag ctxt) | _ -> raise InvalidOperandException -let parseOprOfRSC (ins: InsInfo) ctxt = +let parseOprOfRSC (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands _ -> transThreeOprs ins ctxt - | FourOperands _ -> transFourOprsOfRSB ins ctxt + | FourOperands _ -> transFourOprsOfRSB ins insLen ctxt | _ -> raise InvalidOperandException -let rsc isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, src1, src2 = parseOprOfRSC ins ctxt - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let orr isSetFlags (ins: InsInfo) ctxt = - let builder = IRBuilder (32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let dst, src1, src2, carryOut = translateLogicOp ins ctxt builder - let result = builder.NewTempVar 32 - builder + !!ir (result := + addWithCarryOnlyResult (AST.not src1) src2 (getCarryFlag ctxt)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir + else !!ir (dst := result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let orr isSetFlags (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (result := src1 .| src2) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let orn isSetFlags (ins: InsInfo) ctxt = - let builder = IRBuilder (32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let dst, src1, src2, carryOut = translateLogicOp ins ctxt builder - let result = builder.NewTempVar 32 - builder ir insLen + +let orn isSetFlags (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (result := src1 .| AST.not src2) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let bic isSetFlags (ins: InsInfo) ctxt = - let builder = IRBuilder (32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let dst, src1, src2, carryOut = translateLogicOp ins ctxt builder - let result = builder.NewTempVar 32 - builder ir insLen + +let bic isSetFlags (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (result := src1 .& (AST.not src2)) + if dst = getPC ctxt then aluWritePC ctxt ins isUnconditional result ir else - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let transTwoOprsOfMVN (ins: InsInfo) ctxt = +let transTwoOprsOfMVN (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> - let e1, e2 = transTwoOprs ins ctxt - e1, e2, getCarryFlag ctxt + let struct (e1, e2) = transTwoOprs ins ctxt + struct (e1, e2, getCarryFlag ctxt) | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt + let struct (e1, e2) = transTwoOprs ins ctxt let shifted, carryOut = shiftC e2 32 SRTypeLSL 0u (getCarryFlag ctxt) - e1, shifted, carryOut + struct (e1, shifted, carryOut) | _ -> raise InvalidOperandException -let transThreeOprsOfMVN (ins: InsInfo) ctxt = +let transThreeOprsOfMVN (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (opr1, opr2, OprShift (typ, Imm imm)) -> let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src = transOprToExpr ctxt opr2 + let dst = transOprToExpr ins ctxt opr1 + let src = transOprToExpr ins ctxt opr2 let shifted, carryOut = shiftC src 32 typ imm carryIn - dst, shifted, carryOut + struct (dst, shifted, carryOut) | ThreeOperands (opr1, opr2, OprRegShift (typ, rs)) -> let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src = transOprToExpr ctxt opr2 + let dst = transOprToExpr ins ctxt opr1 + let src = transOprToExpr ins ctxt opr2 let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount src 32 typ amount carryIn - dst, shifted, carryOut + struct (dst, shifted, carryOut) | _ -> raise InvalidOperandException -let parseOprOfMVN (ins: InsInfo) ctxt = +let parseOprOfMVN (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands _ -> transTwoOprsOfMVN ins ctxt - | ThreeOperands _ -> transThreeOprsOfMVN ins ctxt + | TwoOperands _ -> transTwoOprsOfMVN ins insLen ctxt + | ThreeOperands _ -> transThreeOprsOfMVN ins insLen ctxt | _ -> raise InvalidOperandException -let mvn isSetFlags ins ctxt = - let builder = IRBuilder (32) - let dst, src, carryOut = parseOprOfMVN ins ctxt - let result = builder.NewTempVar 32 +let mvn isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src, carryOut) = parseOprOfMVN ins insLen ctxt + let result = !+ir 32 let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let svc (ins: InsInfo) ctxt = +let svc (ins: InsInfo) insLen ctxt = match ins.Operands with - | OneOperand (OprImm n) -> sideEffects ins (Interrupt (int n)) + | OneOperand (OprImm n) -> sideEffects insLen ctxt (Interrupt (int n)) | _ -> raise InvalidOperandException let getImmShiftFromShiftType imm = function @@ -1521,12 +1631,12 @@ let transTwoOprsOfShiftInstr (ins: InsInfo) shiftTyp ctxt tmp = match ins.Operands with | TwoOperands (OprReg _, OprReg _) when shiftTyp = SRTypeRRX -> let carryIn = getCarryFlag ctxt - let e1, e2 = transTwoOprs ins ctxt + let struct (e1, e2) = transTwoOprs ins ctxt let result, carryOut = shiftC tmp 32 shiftTyp 1ul carryIn e1, e2, result, carryOut | TwoOperands (OprReg _, OprReg _) -> let carryIn = getCarryFlag ctxt - let e1, e2 = transTwoOprs ins ctxt + let struct (e1, e2) = transTwoOprs ins ctxt let shiftN = AST.xtlo 8 e2 |> AST.zext 32 let result, carryOut = shiftCForRegAmount tmp 32 shiftTyp shiftN carryIn e1, e1, result, carryOut @@ -1535,15 +1645,15 @@ let transTwoOprsOfShiftInstr (ins: InsInfo) shiftTyp ctxt tmp = let transThreeOprsOfShiftInstr (ins: InsInfo) shiftTyp ctxt tmp = match ins.Operands with | ThreeOperands (opr1, opr2, OprImm imm) -> - let e1 = transOprToExpr ctxt opr1 - let e2 = transOprToExpr ctxt opr2 + let e1 = transOprToExpr ins ctxt opr1 + let e2 = transOprToExpr ins ctxt opr2 let shiftN = getImmShiftFromShiftType (uint32 imm) shiftTyp let shifted, carryOut = shiftC tmp 32 shiftTyp shiftN (getCarryFlag ctxt) e1, e2, shifted, carryOut | ThreeOperands (_, _, OprReg _) -> let carryIn = getCarryFlag ctxt - let e1, e2, e3 = transThreeOprs ins ctxt + let struct (e1, e2, e3) = transThreeOprs ins ctxt let amount = AST.xtlo 8 e3 |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount tmp 32 shiftTyp amount carryIn @@ -1556,460 +1666,555 @@ let parseOprOfShiftInstr (ins: InsInfo) shiftTyp ctxt tmp = | ThreeOperands _ -> transThreeOprsOfShiftInstr ins shiftTyp ctxt tmp | _ -> raise InvalidOperandException -let shiftInstr isSetFlags ins typ ctxt = - let builder = IRBuilder (32) - let srcTmp = builder.NewTempVar 32 - let result = builder.NewTempVar 32 +let shiftInstr isSetFlags ins insLen typ ctxt = + let ir = !*ctxt + let struct (srcTmp, result) = tmpVars2 ir 32 let dst, src, res, carryOut = parseOprOfShiftInstr ins typ ctxt srcTmp let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let subs isSetFlags (ins: InsInfo) ctxt = +let subs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) when ins.Mode = ArchOperationMode.ThumbMode -> - subsPCLRThumb ins ctxt + subsPCLRThumb ins insLen ctxt | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> sub isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> sub isSetFlags ins insLen ctxt -let adds isSetFlags (ins: InsInfo) ctxt = +let adds isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> add isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> add isSetFlags ins insLen ctxt -let adcs isSetFlags (ins: InsInfo) ctxt = +let adcs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> adc isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> adc isSetFlags ins insLen ctxt -let ands isSetFlags (ins: InsInfo) ctxt = +let ands isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> logicalAnd isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> logicalAnd isSetFlags ins insLen ctxt -let movs isSetFlags (ins: InsInfo) ctxt = +let movs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands (OprReg R.PC, _) -> subsAndRelatedInstr ins ctxt - | _ -> mov isSetFlags ins ctxt + | TwoOperands (OprReg R.PC, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> mov isSetFlags ins insLen ctxt -let eors isSetFlags (ins: InsInfo) ctxt = +let eors isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> eor isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> eor isSetFlags ins insLen ctxt -let rsbs isSetFlags (ins: InsInfo) ctxt = +let rsbs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> rsb isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> rsb isSetFlags ins insLen ctxt -let sbcs isSetFlags (ins: InsInfo) ctxt = +let sbcs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> sbc isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> sbc isSetFlags ins insLen ctxt -let rscs isSetFlags (ins: InsInfo) ctxt = +let rscs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> rsc isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> rsc isSetFlags ins insLen ctxt -let orrs isSetFlags (ins: InsInfo) ctxt = +let orrs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> orr isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> orr isSetFlags ins insLen ctxt -let orns isSetFlags (ins: InsInfo) ctxt = +let orns isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> orn isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> orn isSetFlags ins insLen ctxt -let bics isSetFlags (ins: InsInfo) ctxt = +let bics isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg R.PC, _, _) - | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> bic isSetFlags ins ctxt + | FourOperands (OprReg R.PC, _, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> bic isSetFlags ins insLen ctxt -let mvns isSetFlags (ins: InsInfo) ctxt = +let mvns isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg R.PC, _) - | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> mvn isSetFlags ins ctxt + | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> mvn isSetFlags ins insLen ctxt -let asrs isSetFlags (ins: InsInfo) ctxt = +let asrs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> shiftInstr isSetFlags ins SRTypeASR ctxt + | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> shiftInstr isSetFlags ins insLen SRTypeASR ctxt -let lsls isSetFlags (ins: InsInfo) ctxt = +let lsls isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> shiftInstr isSetFlags ins SRTypeLSL ctxt + | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> shiftInstr isSetFlags ins insLen SRTypeLSL ctxt -let lsrs isSetFlags (ins: InsInfo) ctxt = +let lsrs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> shiftInstr isSetFlags ins SRTypeLSR ctxt + | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> shiftInstr isSetFlags ins insLen SRTypeLSR ctxt -let rors isSetFlags (ins: InsInfo) ctxt = +let rors isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins ctxt - | _ -> shiftInstr isSetFlags ins SRTypeROR ctxt + | ThreeOperands (OprReg R.PC, _, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> shiftInstr isSetFlags ins insLen SRTypeROR ctxt -let rrxs isSetFlags (ins: InsInfo) ctxt = +let rrxs isSetFlags (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands (OprReg R.PC, _) -> subsAndRelatedInstr ins ctxt - | _ -> shiftInstr isSetFlags ins SRTypeRRX ctxt - -let clz ins ctxt = - let builder = IRBuilder (32) - let dst, src = transTwoOprs ins ctxt - let lblBoundCheck = builder.NewSymbol "LBoundCheck" - let lblZeroCheck = builder.NewSymbol "LZeroCheck" - let lblCount = builder.NewSymbol "LCount" - let lblEnd = builder.NewSymbol "LEnd" + | TwoOperands (OprReg R.PC, _) -> subsAndRelatedInstr ins insLen ctxt + | _ -> shiftInstr isSetFlags ins insLen SRTypeRRX ctxt + +let clz ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src) = transTwoOprs ins ctxt + let lblBoundCheck = !%ir "LBoundCheck" + let lblZeroCheck = !%ir "LZeroCheck" + let lblCount = !%ir "LCount" + let lblEnd = !%ir "LEnd" let numSize = (numI32 32 32) - let t1 = builder.NewTempVar 32 + let t1 = !+ir 32 let cond1 = t1 == (AST.num0 32) - let cond2 = src .& ((AST.num1 32) << (t1 .- AST.num1 32)) != (AST.num0 32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder )) - builder ) << (t1 .- AST.num1 32)) != (AST.num0 32) + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !)) + !!ir (AST.jmp (AST.name lblBoundCheck)) + !!ir (AST.lmark lblEnd) + !!ir (dst := numSize .- t1) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let transTwoOprsOfCMN (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> transTwoOprs ins ctxt | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt + let struct (e1, e2) = transTwoOprs ins ctxt let shifted = shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt) - e1, shifted + struct (e1, shifted) | _ -> raise InvalidOperandException -let transThreeOprsOfCMN (ins: InsInfo) ctxt = +let transThreeOprsOfCMN (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (opr1, opr2, OprShift (typ, Imm imm)) -> let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src = transOprToExpr ctxt opr2 + let dst = transOprToExpr ins ctxt opr1 + let src = transOprToExpr ins ctxt opr2 let shifted = shift src 32 typ imm carryIn - dst, shifted + struct (dst, shifted) | ThreeOperands (opr1, opr2, OprRegShift (typ, rs)) -> let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src = transOprToExpr ctxt opr2 + let dst = transOprToExpr ins ctxt opr1 + let src = transOprToExpr ins ctxt opr2 let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted = shiftForRegAmount src 32 typ amount carryIn - dst, shifted + struct (dst, shifted) | _ -> raise InvalidOperandException -let parseOprOfCMN (ins: InsInfo) ctxt = +let parseOprOfCMN (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands _ -> transTwoOprsOfCMN ins ctxt - | ThreeOperands _ -> transThreeOprsOfCMN ins ctxt + | TwoOperands _ -> transTwoOprsOfCMN ins insLen ctxt + | ThreeOperands _ -> transThreeOprsOfCMN ins insLen ctxt | _ -> raise InvalidOperandException -let cmn ins ctxt = - let builder = IRBuilder (16) - let dst, src = parseOprOfCMN ins ctxt - let result = builder.NewTempVar 32 - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 +let cmn ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src) = parseOprOfCMN ins insLen ctxt + let struct (t1, t2) = tmpVars2 ir 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ) - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let mla isSetFlags ins ctxt = - let builder = IRBuilder (16) - let rd, rn, rm, ra = transFourOprs ins ctxt - let r = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder (AST.zext 64 rn .* AST.zext 64 rm .+ + !) ir + !!ir (cpsr := rHigh |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let mla isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rn, rm, ra) = transFourOprs ins ctxt + let r = !+ir 32 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! (AST.zext 64 rn .* AST.zext 64 rm .+ AST.zext 64 ra)) - builder r |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + !!ir (cpsr := AST.xthi 1 r |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := r == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let transTwoOprsOfCMP (ins: InsInfo) ctxt = +let transTwoOprsOfCMP (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> transTwoOprs ins ctxt | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt - e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt) + let struct (e1, e2) = transTwoOprs ins ctxt + struct (e1, shift e2 32 SRTypeLSL 0u (getCarryFlag ctxt)) | _ -> raise InvalidOperandException -let transThreeOprsOfCMP (ins: InsInfo) ctxt = +let transThreeOprsOfCMP (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (opr1, opr2, OprShift (typ, Imm imm)) -> let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src = transOprToExpr ctxt opr2 - dst, shift src 32 typ imm carryIn + let dst = transOprToExpr ins ctxt opr1 + let src = transOprToExpr ins ctxt opr2 + struct (dst, shift src 32 typ imm carryIn) | ThreeOperands (opr1, opr2, OprRegShift (typ, rs)) -> let carryIn = getCarryFlag ctxt - let dst = transOprToExpr ctxt opr1 - let src = transOprToExpr ctxt opr2 + let dst = transOprToExpr ins ctxt opr1 + let src = transOprToExpr ins ctxt opr2 let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 - dst, shiftForRegAmount src 32 typ amount carryIn + struct (dst, shiftForRegAmount src 32 typ amount carryIn) | _ -> raise InvalidOperandException -let parseOprOfCMP (ins: InsInfo) ctxt = +let parseOprOfCMP (ins: InsInfo) insLen ctxt = match ins.Operands with - | TwoOperands _ -> transTwoOprsOfCMP ins ctxt - | ThreeOperands _ -> transThreeOprsOfCMP ins ctxt + | TwoOperands _ -> transTwoOprsOfCMP ins insLen ctxt + | ThreeOperands _ -> transThreeOprsOfCMP ins insLen ctxt | _ -> raise InvalidOperandException -let cmp ins ctxt = - let builder = IRBuilder (16) - let rn, rm = parseOprOfCMP ins ctxt - let result = builder.NewTempVar 32 - let t1, t2 = builder.NewTempVar 32, builder.NewTempVar 32 +let cmp ins insLen ctxt = + let ir = !*ctxt + let struct (rn, rm) = parseOprOfCMP ins insLen ctxt + let struct (t1, t2) = tmpVars2 ir 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ) - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - builder setPSR ctxt R.CPSR PSR_V) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let umlal isSetFlags ins ctxt = - let builder = IRBuilder (16) - let rdLo, rdHi, rn, rm = transFourOprs ins ctxt - let result = builder.NewTempVar 64 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder rn .* AST.zext 64 rm .+ AST.concat rdLo rdHi) - builder result) - builder result) + !) ir + !!ir (cpsr := rHigh |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + !!ir (cpsr := overflow |> setPSR ctxt R.CPSR PSR.V) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let umaal ins insLen ctxt = + let ir = !*ctxt + ! + let mul = AST.zext 64 rn .* AST.zext 64 rm + !!ir (res := mul .+ AST.zext 64 rdHi .+ AST.zext 64 rdLo) + !!ir (rdHi := AST.xthi 32 res) + !!ir (rdLo := AST.xtlo 32 res) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let umlal isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (rdLo, rdHi, rn, rm) = transFourOprs ins ctxt + let result = !+ir 64 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rn .* AST.zext 64 rm .+ AST.concat rdHi rdLo) + !!ir (rdHi := AST.xthi 32 result) + !!ir (rdLo := AST.xtlo 32 result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 64 |> setPSR ctxt R.CPSR PSR.Z) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let umull isSetFlags ins ctxt = - let builder = IRBuilder (16) - let rdLo, rdHi, rn, rm = transFourOprs ins ctxt - let result = builder.NewTempVar 64 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder rn .* AST.zext 64 rm) - builder result) - builder result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let umull isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (rdLo, rdHi, rn, rm) = transFourOprs ins ctxt + let result = !+ir 64 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rn .* AST.zext 64 rm) + !!ir (rdHi := AST.xthi 32 result) + !!ir (rdLo := AST.xtlo 32 result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 64 |> setPSR ctxt R.CPSR PSR.Z) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let transOprsOfTEQ (ins: InsInfo) ctxt = +let transOprsOfTEQ (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> - let rn, imm = transTwoOprs ins ctxt + let struct (rn, imm) = transTwoOprs ins ctxt rn, imm, getCarryFlag ctxt | ThreeOperands (opr1, opr2, OprShift (typ, Imm imm)) -> let carryIn = getCarryFlag ctxt - let rn = transOprToExpr ctxt opr1 - let rm = transOprToExpr ctxt opr2 + let rn = transOprToExpr ins ctxt opr1 + let rm = transOprToExpr ins ctxt opr2 let shifted, carryOut = shiftC rm 32 typ imm carryIn rn, shifted, carryOut | ThreeOperands (opr1, opr2, OprRegShift (typ, rs)) -> let carryIn = getCarryFlag ctxt - let rn = transOprToExpr ctxt opr1 - let rm = transOprToExpr ctxt opr2 + let rn = transOprToExpr ins ctxt opr1 + let rm = transOprToExpr ins ctxt opr2 let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount rm 32 typ amount carryIn rn, shifted, carryOut | _ -> raise InvalidOperandException -let teq ins ctxt = - let builder = IRBuilder (16) - let src1, src2, carryOut = transOprsOfTEQ ins ctxt - let result = builder.NewTempVar 32 +let teq ins insLen ctxt = + let ir = !*ctxt + let src1, src2, carryOut = transOprsOfTEQ ins insLen ctxt + let result = !+ir 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder src2) - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let mul isSetFlags ins ctxt = - let builder = IRBuilder (16) - let rd, rn, rm = transThreeOprs ins ctxt - let result = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder (AST.zext 64 rn .* AST.zext 64 rm)) - builder src2) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let mul isSetFlags ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rn, rm) = transThreeOprs ins ctxt + let result = !+ir 32 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! (AST.zext 64 rn .* AST.zext 64 rm)) + !!ir (rd := result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let transOprsOfTST (ins: InsInfo) ctxt = +let transOprsOfTST (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg _, OprImm _) -> - let rn, imm = transTwoOprs ins ctxt - let carryOut = computeCarryOutFromImmCflag ins ctxt - rn, imm, carryOut + let struct (rn, imm) = transTwoOprs ins ctxt + let carryOut = computeCarryOutFromImmCflag ins insLen ctxt + struct (rn, imm, carryOut) | TwoOperands (OprReg _, OprReg _) -> - let e1, e2 = transTwoOprs ins ctxt + let struct (e1, e2) = transTwoOprs ins ctxt let shifted, carryOut = shiftC e2 32 SRTypeLSL 0u (getCarryFlag ctxt) - e1, shifted, carryOut + struct (e1, shifted, carryOut) | ThreeOperands (opr1, opr2, OprShift (typ, Imm imm)) -> let carryIn = getCarryFlag ctxt - let rn = transOprToExpr ctxt opr1 - let rm = transOprToExpr ctxt opr2 + let rn = transOprToExpr ins ctxt opr1 + let rm = transOprToExpr ins ctxt opr2 let shifted, carryOut = shiftC rm 32 typ imm carryIn - rn, shifted, carryOut + struct (rn, shifted, carryOut) | ThreeOperands (opr1, opr2, OprRegShift (typ, rs)) -> let carryIn = getCarryFlag ctxt - let rn = transOprToExpr ctxt opr1 - let rm = transOprToExpr ctxt opr2 + let rn = transOprToExpr ins ctxt opr1 + let rm = transOprToExpr ins ctxt opr2 let amount = AST.xtlo 8 (getRegVar ctxt rs) |> AST.zext 32 let shifted, carryOut = shiftCForRegAmount rm 32 typ amount carryIn - rn, shifted, carryOut + struct (rn, shifted, carryOut) | _ -> raise InvalidOperandException -let tst ins ctxt = - let builder = IRBuilder (16) - let src1, src2, carryOut = transOprsOfTST ins ctxt - let result = builder.NewTempVar 32 +let tst ins insLen ctxt = + let ir = !*ctxt + let struct (src1, src2, carryOut) = transOprsOfTST ins insLen ctxt + let result = !+ir 32 let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) - builder setPSR ctxt R.CPSR PSR_C) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let smulhalf ins ctxt s1top s2top = - let builder = IRBuilder (8) - let rd, rn, rm = transThreeOprs ins ctxt - let t1 = builder.NewTempVar 32 - let t2 = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if s1top then builder rn |> AST.zext 32) - else builder rn |> AST.sext 32) - if s2top then builder rm |> AST.zext 32) - else builder rm |> AST.sext 32) - builder result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 32 |> setPSR ctxt R.CPSR PSR.Z) + !!ir (cpsr := carryOut |> setPSR ctxt R.CPSR PSR.C) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smulhalf ins insLen ctxt s1top s2top = + let ir = !*ctxt + let struct (rd, rn, rm) = transThreeOprs ins ctxt + let struct (t1, t2) = tmpVars2 ir 32 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rn |> AST.zext 32) + else !!ir (t1 := AST.xtlo 16 rn |> AST.sext 32) + if s2top then !!ir (t2 := AST.xthi 16 rm |> AST.zext 32) + else !!ir (t2 := AST.xtlo 16 rm |> AST.sext 32) + !!ir (rd := t1 .* t2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smmla ins insLen ctxt isRound = + let ir = !*ctxt + ! + let isUnconditional = ParseUtils.isUnconditional ins.Condition + let lblIgnore = checkCondition ins ctxt isUnconditional ir + let ra = (AST.sext 64 src3) << numI32 32 64 + !!ir (result := ra .+ AST.sext 64 src1 .* AST.sext 64 src2) + if isRound then !!ir (result := result .+ numU32 0x80000000u 64) + !!ir (dst := AST.xthi 32 result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smmul ins insLen ctxt isRound = + let ir = !*ctxt + ! + let isUnconditional = ParseUtils.isUnconditional ins.Condition + let lblIgnore = checkCondition ins ctxt isUnconditional ir + !!ir (result := AST.sext 64 src1 .* AST.sext 64 src2) + if isRound then !!ir (result := result .+ numU32 0x80000000u 64) + !!ir (dst := AST.xthi 32 result) + putEndLabel ctxt lblIgnore ir + !>ir insLen /// SMULL, SMLAL, etc. -let smulandacc isSetFlags doAcc ins ctxt = - let builder = IRBuilder (16) - let rdLo, rdHi, rn, rm = transFourOprs ins ctxt - let tmpresult = builder.NewTempVar 64 - let result = builder.NewTempVar 64 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder rn .* AST.sext 64 rm) - if doAcc then builder result) - builder result) +let smulandacc isSetFlags doAcc ins insLen ctxt = + let ir = !*ctxt + let struct (rdLo, rdHi, rn, rm) = transFourOprs ins ctxt + let struct (tmpresult, result) = tmpVars2 ir 64 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rn .* AST.sext 64 rm) + if doAcc then !!ir (result := tmpresult .+ AST.concat rdHi rdLo) + else !!ir (result := tmpresult) + !!ir (rdHi := AST.xthi 32 result) + !!ir (rdLo := AST.xtlo 32 result) if isSetFlags then let cpsr = getRegVar ctxt R.CPSR - builder result |> setPSR ctxt R.CPSR PSR_N) - builder |> setPSR ctxt R.CPSR PSR_Z) + !!ir (cpsr := AST.xthi 1 result |> setPSR ctxt R.CPSR PSR.N) + !!ir (cpsr := result == AST.num0 64 |> setPSR ctxt R.CPSR PSR.Z) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let smulacchalf ins ctxt s1top s2top = - let builder = IRBuilder (8) - let rd, rn, rm, ra = transFourOprs ins ctxt - let t1 = builder.NewTempVar 32 - let t2 = builder.NewTempVar 32 - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if s1top then builder rn |> AST.zext 32) - else builder rn |> AST.sext 32) - if s2top then builder rm |> AST.zext 32) - else builder rm |> AST.sext 32) - builder ra) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smulacclongdual (ins: InsInfo) insLen ctxt sign = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let struct (p1, p2, result) = tmpVars3 ir 64 + let rotated = shiftROR src2 32 16u + let xtlo src = AST.xtlo 16 src |> AST.sext 64 + let xthi src = AST.xthi 16 src |> AST.sext 64 + if sign then !!ir (o := rotated) + else !!ir (o := src2) + !!ir (p1 := xtlo src1 .* xtlo o) + !!ir (p2 := xthi src1 .* xthi o) + !!ir (result := p1 .+ p2 .+ AST.concat dst2 dst1) + !!ir (dst2 := AST.xthi 32 result) + !!ir (dst1 := AST.xtlo 32 result) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smulaccwordbyhalf (ins: InsInfo) insLen ctxt sign = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let result = !+ir 64 + let sext src = AST.sext 64 src + if sign then !!ir (o := AST.xthi 16 src2 |> AST.sext 32) + else !!ir (o := AST.xtlo 16 src2 |> AST.sext 32) + !!ir (result := sext src1 .* sext o .+ sext (src3 << numI32 16 32)) + !!ir (dst := AST.extract result 32 16) + let cpsr = getRegVar ctxt R.CPSR + !!ir (cpsr := AST.ite ((result >> numI32 16 64) != sext dst) + (enablePSRBits ctxt R.CPSR PSR.Q) cpsr) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smulacchalf ins insLen ctxt s1top s2top = + let ir = !*ctxt + let struct (rd, rn, rm, ra) = transFourOprs ins ctxt + let struct (t1, t2) = tmpVars2 ir 32 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rn |> AST.zext 32) + else !!ir (t1 := AST.xtlo 16 rn |> AST.sext 32) + if s2top then !!ir (t2 := AST.xthi 16 rm |> AST.zext 32) + else !!ir (t2 := AST.xtlo 16 rm |> AST.sext 32) + !!ir (rd := (t1 .* t2) .+ AST.sext 32 ra) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let smulacclonghalf (ins: InsInfo) insLen ctxt s1top s2top = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + if s1top then !!ir (o1 := AST.xthi 16 src1 |> AST.sext 64) + else !!ir (o1 := AST.xtlo 16 src1 |> AST.sext 64) + if s2top then !!ir (o2 := AST.xthi 16 src2 |> AST.sext 64) + else !!ir (o2 := AST.xtlo 16 src2 |> AST.sext 64) + !!ir (result := o1 .* o2 .+ AST.concat dst2 dst1) + !!ir (dst2 := AST.xthi 32 result) + !!ir (dst1 := AST.xtlo 32 result) + putEndLabel ctxt lblIgnore ir + !>ir insLen let parseOprOfB (ins: InsInfo) = let addr = bvOfBaseAddr (ins.Address + pcOffset ins) @@ -2018,110 +2223,134 @@ let parseOprOfB (ins: InsInfo) = addr .+ (numI64 imm 32) | _ -> raise InvalidOperandException -let b ins ctxt = - let builder = IRBuilder (8) +let b ins insLen ctxt = + let ir = !*ctxt let e = parseOprOfB ins let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ir insLen + +let bx ins insLen ctxt = + let ir = !*ctxt let rm = transOneOpr ins ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - bxWritePC ctxt isUnconditional rm builder - putEndLabel ctxt lblIgnore isUnconditional (Some ins) builder - endMark ins builder + !ir insLen let movtAssign dst src = - let maskHigh16In32 = AST.num <| BitVector.ofBInt 4294901760I 32 + let maskHigh16In32 = AST.num <| BitVector.OfBInt 4294901760I 32 let clearHigh16In32 expr = expr .& AST.not maskHigh16In32 dst := clearHigh16In32 dst .| (src << (numI32 16 32)) -let movt ins ctxt = - let builder = IRBuilder (8) - let dst, res = transTwoOprs ins ctxt +let movt ins insLen ctxt = + let ir = !*ctxt + let struct (dst, res) = transTwoOprs ins ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ir insLen + +let transFourOprsWithBarrelShift (ins: InsInfo) ctxt = + match ins.Operands with + | FourOperands (opr1, opr2, opr3, OprShift (typ, Imm imm)) -> + let carryIn = getCarryFlag ctxt + let dst = transOprToExpr ins ctxt opr1 + let src1 = transOprToExpr ins ctxt opr2 + let src2 = transOprToExpr ins ctxt opr3 + let shifted = shift src2 32 typ imm carryIn + struct (dst, src1, shifted) + | _ -> raise InvalidOperandException -let popLoop ctxt numOfReg addr (builder: IRBuilder) = +let pkh ins insLen ctxt isTbform = + let ir = !*ctxt + ! src1, AST.xtlo 16 src1 + let src2H, src2L = AST.xthi 16 src2, AST.xtlo 16 src2 + let res = if isTbform then AST.concat src1H src2L else AST.concat src2H src1L + !!ir (dst := res) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let popLoop ctxt numOfReg addr (ir: IRBuilder) = let loop addr count = if (numOfReg >>> count) &&& 1u = 1u then let reg = count |> uint32 |> OperandHelper.getRegister - builder addr) + !!ir (getRegVar ctxt reg := AST.loadLE 32 addr) (addr .+ (numI32 4 32)) else addr List.fold loop addr [ 0 .. 14 ] -let pop ins ctxt = - let builder = IRBuilder (32) - let t0 = builder.NewTempVar 32 +let pop ins insLen ctxt = + let ir = !*ctxt + let t0 = !+ir 32 let sp = getRegVar ctxt R.SP let numOfReg = parseOprOfPUSHPOP ins let stackWidth = 4 * bitCount numOfReg 16 let addr = sp let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder >> 13 &&& 1u) = 0u then - builder )) - else builder "UNKNOWN")) + !!ir (sp := sp .+ (numI32 stackWidth 32)) + else !!ir (sp := (AST.undef 32 "UNKNOWN")) if (numOfReg >>> 15 &&& 1u) = 1u then - AST.loadLE 32 addr |> loadWritePC ctxt isUnconditional builder + AST.loadLE 32 addr |> loadWritePC ctxt isUnconditional ir else () - putEndLabel ctxt lblIgnore isUnconditional (Some ins) builder - endMark ins builder + putEndLabelForBranch ctxt lblIgnore ins ir + !>ir insLen let parseOprOfLDM (ins: InsInfo) ctxt = match ins.Operands with | TwoOperands (OprReg reg, OprRegList regs) -> - getRegVar ctxt reg, getRegNum reg, regsToUInt32 regs + struct (getRegVar ctxt reg, getRegNum reg, regsToUInt32 regs) | _ -> raise InvalidOperandException let getLDMStartAddr rn stackWidth = function | Op.LDM | Op.LDMIA -> rn - | Op.LDMDA -> rn .- (numI32 (stackWidth + 4) 32) + | Op.LDMDA -> rn .- (numI32 stackWidth 32) .+ (numI32 4 32) | Op.LDMDB -> rn .- (numI32 stackWidth 32) | Op.LDMIB -> rn .+ (numI32 4 32) | _ -> raise InvalidOpcodeException -let ldm opcode ins ctxt wbackop = - let builder = IRBuilder (32) - let t0 = builder.NewTempVar 32 - let t1 = builder.NewTempVar 32 - let rn, numOfRn, numOfReg = parseOprOfLDM ins ctxt +let ldm opcode ins insLen ctxt wbackop = + let ir = !*ctxt + let struct (t0, t1) = tmpVars2 ir 32 + let struct (rn, numOfRn, numOfReg) = parseOprOfLDM ins ctxt let wback = ins.WriteBack let stackWidth = 4 * bitCount numOfReg 16 let addr = getLDMStartAddr t0 stackWidth opcode let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder >> 15 &&& 1u) = 1u then - AST.loadLE 32 addr |> loadWritePC ctxt isUnconditional builder + AST.loadLE 32 addr |> loadWritePC ctxt isUnconditional ir else () if wback && (numOfReg &&& numOfRn) = 0u then - builder )) + !!ir (rn := wbackop t0 (numI32 stackWidth 32)) else () if wback && (numOfReg &&& numOfRn) = numOfRn then - builder "UNKNOWN")) + !!ir (rn := (AST.undef 32 "UNKNOWN")) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen let getOffAddrWithExpr s r e = if s = Some Plus then r .+ e else r .- e @@ -2131,126 +2360,129 @@ let getOffAddrWithImm s r imm = | Some Minus, Some i -> r .- (numI64 i 32) | _, _ -> r -let parseMemOfLDR ins ctxt = function - | OprMemory (OffsetMode (ImmOffset (rn , s, imm))) -> - let rn = getRegVar ctxt rn |> convertPCOpr ins ctxt - getOffAddrWithImm s rn imm, None - | OprMemory (PreIdxMode (ImmOffset (rn , s, imm))) -> +let parseMemOfLDR ins insLen ctxt = function + | OprMemory (OffsetMode (ImmOffset (rn, s, imm))) -> + let rn = getRegVar ctxt rn |> convertPCOpr ins insLen ctxt + struct (getOffAddrWithImm s rn imm, None) + | OprMemory (PreIdxMode (ImmOffset (rn, s, imm))) -> let rn = getRegVar ctxt rn - let offsetAddr = getOffAddrWithImm s rn imm - offsetAddr, Some (rn, offsetAddr) - | OprMemory (PostIdxMode (ImmOffset (rn , s, imm))) -> + struct (getOffAddrWithImm s rn imm, Some (rn, None)) + | OprMemory (PostIdxMode (ImmOffset (rn, s, imm))) -> let rn = getRegVar ctxt rn - rn, Some (rn, getOffAddrWithImm s rn imm) + struct (rn, Some (rn, Some (getOffAddrWithImm s rn imm))) | OprMemory (LiteralMode imm) -> let addr = bvOfBaseAddr ins.Address let pc = align addr (numI32 4 32) let rel = if ins.Mode = ArchOperationMode.ARMMode then 8u else 4u - pc .+ (numU32 rel 32) - .+ (numI64 imm 32), None + struct (pc .+ (numU32 rel 32) .+ (numI64 imm 32), None) | OprMemory (OffsetMode (RegOffset (n, _, m, None))) -> - let m = getRegVar ctxt m |> convertPCOpr ins ctxt - let n = getRegVar ctxt n |> convertPCOpr ins ctxt - let offset = shift m 32 SRTypeLSL 0u (getCarryFlag ctxt) - n .+ offset, None + let m = getRegVar ctxt m |> convertPCOpr ins insLen ctxt + let n = getRegVar ctxt n |> convertPCOpr ins insLen ctxt + struct (n .+ shift m 32 SRTypeLSL 0u (getCarryFlag ctxt), None) | OprMemory (PreIdxMode (RegOffset (n, s, m, None))) -> let rn = getRegVar ctxt n let offset = shift (getRegVar ctxt m) 32 SRTypeLSL 0u (getCarryFlag ctxt) - let offsetAddr = getOffAddrWithExpr s rn offset - offsetAddr, Some (rn, offsetAddr) + struct (getOffAddrWithExpr s rn offset, Some (rn, None)) | OprMemory (PostIdxMode (RegOffset (n, s, m, None))) -> let rn = getRegVar ctxt n let offset = shift (getRegVar ctxt m) 32 SRTypeLSL 0u (getCarryFlag ctxt) - rn, Some (rn, getOffAddrWithExpr s rn offset) + struct (rn, Some (rn, Some (getOffAddrWithExpr s rn offset))) | OprMemory (OffsetMode (RegOffset (n, s, m, Some (t, Imm i)))) -> - let rn = getRegVar ctxt n |> convertPCOpr ins ctxt - let rm = getRegVar ctxt m |> convertPCOpr ins ctxt + let rn = getRegVar ctxt n |> convertPCOpr ins insLen ctxt + let rm = getRegVar ctxt m |> convertPCOpr ins insLen ctxt let offset = shift rm 32 t i (getCarryFlag ctxt) - getOffAddrWithExpr s rn offset, None + struct (getOffAddrWithExpr s rn offset, None) | OprMemory (PreIdxMode (RegOffset (n, s, m, Some (t, Imm i)))) -> let rn = getRegVar ctxt n let offset = shift (getRegVar ctxt m) 32 t i (getCarryFlag ctxt) - let offsetAddr = getOffAddrWithExpr s rn offset - offsetAddr, Some (rn, offsetAddr) + struct (getOffAddrWithExpr s rn offset, Some (rn, None)) | OprMemory (PostIdxMode (RegOffset (n, s, m, Some (t, Imm i)))) -> let rn = getRegVar ctxt n let offset = shift (getRegVar ctxt m) 32 t i (getCarryFlag ctxt) - rn, Some (rn, getOffAddrWithExpr s rn offset) + struct (rn, Some (rn, Some (getOffAddrWithExpr s rn offset))) | _ -> raise InvalidOperandException -let parseOprOfLDR (ins: InsInfo) ctxt = +let parseOprOfLDR (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg rt, (OprMemory _ as mem)) -> - let addr, writeback = parseMemOfLDR ins ctxt mem - getRegVar ctxt rt, addr, writeback + let struct (addr, writeback) = parseMemOfLDR ins insLen ctxt mem + struct (getRegVar ctxt rt, addr, writeback) | _ -> raise InvalidOperandException /// Load register -let ldr ins ctxt size ext = - let builder = IRBuilder (16) - let data = builder.NewTempVar 32 - let rt, addr, writeback = parseOprOfLDR ins ctxt +let ldr ins insLen ctxt size ext = + let ir = !*ctxt + let data = !+ir 32 + let struct (rt, addr, writeback) = parseOprOfLDR ins insLen ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - let taddr = builder.NewTempVar 32 - let twriteback = builder.NewTempVar 32 - builder ext 32) - builder + let struct (taddr, twriteback) = tmpVars2 ir 32 + !!ir (taddr := addr) + !!ir (twriteback := newoffset) + !!ir (data := AST.loadLE size taddr |> ext 32) + !!ir (basereg := twriteback) + | Some (basereg, None) -> + let taddr = !+ir 32 + !!ir (taddr := addr) + !!ir (data := AST.loadLE size taddr |> ext 32) + !!ir (basereg := taddr) | None -> - builder ext 32) - if rt = getPC ctxt then loadWritePC ctxt isUnconditional builder data - else builder ext 32) + if rt = getPC ctxt then loadWritePC ctxt isUnconditional ir data + else !!ir (rt := data) + putEndLabel ctxt lblIgnore ir + !>ir insLen -let parseMemOfLDRD ins ctxt = function +let parseMemOfLDRD ins insLen ctxt = function | OprMemory (OffsetMode (RegOffset (n, s, m, None))) -> - getOffAddrWithExpr s (getRegVar ctxt n) (getRegVar ctxt m), None + struct (getOffAddrWithExpr s (getRegVar ctxt n) (getRegVar ctxt m), None) | OprMemory (PreIdxMode (RegOffset (n, s, m, None))) -> let rn = getRegVar ctxt n - let offsetAddr = getOffAddrWithExpr s rn (getRegVar ctxt m) - offsetAddr, Some (rn, offsetAddr) + struct (getOffAddrWithExpr s rn (getRegVar ctxt m), Some (rn, None)) | OprMemory (PostIdxMode (RegOffset (n, s, m, None))) -> let rn = getRegVar ctxt n - rn, Some (rn, getOffAddrWithExpr s rn (getRegVar ctxt m)) - | mem -> parseMemOfLDR ins ctxt mem + struct (rn, Some (rn, Some (getOffAddrWithExpr s rn (getRegVar ctxt m)))) + | mem -> parseMemOfLDR ins insLen ctxt mem -let parseOprOfLDRD (ins: InsInfo) ctxt = +let parseOprOfLDRD (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg t, OprReg t2, (OprMemory _ as mem)) -> - let addr, stmt = parseMemOfLDRD ins ctxt mem - getRegVar ctxt t, getRegVar ctxt t2, addr, stmt + let struct (addr, stmt) = parseMemOfLDRD ins insLen ctxt mem + struct (getRegVar ctxt t, getRegVar ctxt t2, addr, stmt) | _ -> raise InvalidOperandException -let ldrd ins ctxt = - let builder = IRBuilder (8) - let taddr = builder.NewTempVar 32 - let rt, rt2, addr, writeback = parseOprOfLDRD ins ctxt +let ldrd ins insLen ctxt = + let ir = !*ctxt + let taddr = !+ir 32 + let struct (rt, rt2, addr, writeback) = parseOprOfLDRD ins insLen ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! match writeback with - | Some (basereg, newoffset) -> - let twriteback = builder.NewTempVar 32 - builder taddr) - builder (taddr .+ n4)) - builder + let twriteback = !+ir 32 + !!ir (taddr := addr) + !!ir (twriteback := newoffset) + !!ir (rt := AST.loadLE 32 taddr) + !!ir (rt2 := AST.loadLE 32 (taddr .+ n4)) + !!ir (basereg := twriteback) + | Some (basereg, None) -> + !!ir (taddr := addr) + !!ir (rt := AST.loadLE 32 taddr) + !!ir (rt2 := AST.loadLE 32 (taddr .+ n4)) + !!ir (basereg := taddr) | None -> - builder taddr) - builder (taddr .+ n4)) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + !!ir (taddr := addr) + !!ir (rt := AST.loadLE 32 taddr) + !!ir (rt2 := AST.loadLE 32 (taddr .+ n4)) + putEndLabel ctxt lblIgnore ir + !>ir insLen let sel8Bits r offset = AST.extract r 8 offset |> AST.zext 32 @@ -2271,139 +2503,171 @@ let combineGEs ge0 ge1 ge2 ge3 = let n3 = numI32 3 32 ge0 .| (ge1 << n1) .| (ge2 << n2) .| (ge3 << n3) -let uadd8 ins ctxt = - let builder = IRBuilder (32) - let rd, rn, rm = transThreeOprs ins ctxt - let sum1 = builder.NewTempVar 32 - let sum2 = builder.NewTempVar 32 - let sum3 = builder.NewTempVar 32 - let sum4 = builder.NewTempVar 32 - let ge0 = builder.NewTempVar 32 - let ge1 = builder.NewTempVar 32 - let ge2 = builder.NewTempVar 32 - let ge3 = builder.NewTempVar 32 +let uadd8 ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rn, rm) = transThreeOprs ins ctxt + let struct (sum1, sum2, sum3, sum4) = tmpVars4 ir 32 + let struct (ge0, ge1, ge2, ge3) = tmpVars4 ir 32 let cpsr = getRegVar ctxt R.CPSR let n100 = numI32 0x100 32 let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ) (AST.num0 32)) - builder ) (AST.num0 32)) - builder ) (AST.num0 32)) - builder ) (AST.num0 32)) - builder setPSR ctxt R.CPSR PSR_GE) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let sel ins ctxt = - let builder = IRBuilder (16) - let t1 = builder.NewTempVar 32 - let t2 = builder.NewTempVar 32 - let t3 = builder.NewTempVar 32 - let t4 = builder.NewTempVar 32 - let rd, rn, rm = transThreeOprs ins ctxt + ! (AST.ge sum1 n100)) + !!ir (ge1 := AST.zext 32 (AST.ge sum2 n100)) + !!ir (ge2 := AST.zext 32 (AST.ge sum3 n100)) + !!ir (ge3 := AST.zext 32 (AST.ge sum4 n100)) + !!ir (cpsr := combineGEs ge0 ge1 ge2 ge3 |> setPSR ctxt R.CPSR PSR.GE) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let sel ins insLen ctxt = + let ir = !*ctxt + let struct (t1, t2, t3, t4) = tmpVars4 ir 32 + let struct (rd, rn, rm) = transThreeOprs ins ctxt let n1 = AST.num1 32 let n2 = numI32 2 32 let n4 = numI32 4 32 let n8 = numI32 8 32 - let ge = getPSR ctxt R.CPSR PSR_GE >> (numI32 16 32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder - let t2 = builder.NewTempVar 32 - let rd, rm = transTwoOprs ins ctxt - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder rd) + let ge = getPSR ctxt R.CPSR PSR.GE >> (numI32 16 32) + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let rbit ins insLen ctxt = + let ir = !*ctxt + let struct (t1, t2) = tmpVars2 ir 32 + let struct (rd, rm) = transTwoOprs ins ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rd) for i = 0 to 31 do - builder i) |> AST.zext 32) - builder ))) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let rev ins ctxt = - let builder = IRBuilder (16) - let t1 = builder.NewTempVar 32 - let t2 = builder.NewTempVar 32 - let t3 = builder.NewTempVar 32 - let t4 = builder.NewTempVar 32 - let rd, rm = transTwoOprs ins ctxt - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder i) |> AST.zext 32) + !!ir (rd := rd .| (t2 << (numI32 (31 - i) 32))) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let rev ins insLen ctxt = + let ir = !*ctxt + let struct (t1, t2, t3, t4) = tmpVars4 ir 32 + let struct (rd, rm) = transTwoOprs ins ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let rev16 ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rm) = transTwoOprs ins ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! 16 + let r2 = AST.extract rm 8 24 + let r3 = AST.extract rm 8 0 + let r4 = AST.extract rm 8 8 + !!ir (rd := AST.concatArr [| r4; r3; r2; r1 |]) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let revsh ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rm) = transTwoOprs ins ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rm |> AST.sext 32) << numI32 8 32 + let r2 = AST.extract rm 8 8 |> AST.zext 32 + !!ir (rd := r1 .| r2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let rfedb (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + !!ir (addr := dst .- numI32 8 32) + !!ir (newPcValue := AST.loadLE 32 addr) + !!ir (spsr := AST.loadLE 32 (addr .+ numI32 4 32)) + match wback with + | true -> !!ir (dst := dst .- numI32 8 32) + | _ -> !!ir (dst := dst) + putEndLabel ctxt lblIgnore ir + !>ir insLen /// Store register. -let str ins ctxt size = - let builder = IRBuilder (16) - let rt, addr, writeback = parseOprOfLDR ins ctxt - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if rt = getPC ctxt then builder addr := pcStoreValue ctxt) - elif size = 32 then builder addr := rt) - else builder addr := pcStoreValue ctxt) + elif size = 32 then !!ir (AST.loadLE 32 addr := rt) + else !!ir (AST.loadLE size addr := AST.xtlo size rt) match writeback with - | Some (basereg, newoffset) -> builder !!ir (basereg := newoffset) + | Some (basereg, None) -> !!ir (basereg := addr) | None -> () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let strex ins ctxt = - let builder = IRBuilder (16) - let rd, rt, addr, writeback = parseOprOfLDRD ins ctxt +let strex ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rt, addr, writeback) = parseOprOfLDRD ins insLen ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if rt = getPC ctxt then builder addr := pcStoreValue ctxt) - else builder addr := rt) + ! addr := pcStoreValue ctxt) + else !!ir (AST.loadLE 32 addr := rt) match writeback with - | Some (basereg, newoffset) -> builder !!ir (basereg := newoffset) + | Some (basereg, None) -> !!ir (basereg := addr) | None -> () - builder ) (* XXX: always succeeds for now *) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let strd ins ctxt = - let builder = IRBuilder (8) - let rt, rt2, addr, writeback = parseOprOfLDRD ins ctxt - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder addr := rt) - builder - (addr .+ (numI32 4 32)) := rt2) + !!ir (rd := AST.num0 32) (* XXX: always succeeds for now *) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let strd ins insLen ctxt = + let ir = !*ctxt + let struct (rt, rt2, addr, writeback) = parseOprOfLDRD ins insLen ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! addr := rt) + !!ir (AST.loadLE 32 (addr .+ (numI32 4 32)) := rt2) match writeback with - | Some (basereg, newoffset) -> builder !!ir (basereg := newoffset) + | Some (basereg, None) -> !!ir (basereg := addr) | None -> () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen -let parseOprOfSTM (ins: InsInfo) ctxt = +let parseOprOfSTM (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg reg, OprRegList regs) -> getRegVar ctxt reg, regsToUInt32 regs @@ -2411,43 +2675,43 @@ let parseOprOfSTM (ins: InsInfo) ctxt = let getSTMStartAddr rn msize = function | Op.STM | Op.STMIA | Op.STMEA -> rn - | Op.STMDA -> rn .- msize .+ (numI32 4 32) + | Op.STMDA -> rn .- msize .+ (numI32 4 32) | Op.STMDB -> rn .- msize | Op.STMIB -> rn .+ (numI32 4 32) | _ -> raise InvalidOpcodeException -let stmLoop ctxt regs wback rn addr (builder: IRBuilder) = +let stmLoop ctxt regs wback rn addr (ir: IRBuilder) = let loop addr count = if (regs >>> count) &&& 1u = 1u then let ri = count |> uint32 |> OperandHelper.getRegister |> getRegVar ctxt if ri = rn && wback && count <> lowestSetBit regs 32 then - builder addr := (AST.undef 32 "UNKNOWN")) + !!ir (AST.loadLE 32 addr := (AST.undef 32 "UNKNOWN")) else - builder addr := ri) + !!ir (AST.loadLE 32 addr := ri) addr .+ (numI32 4 32) else addr List.fold loop addr [ 0 .. 14 ] -let stm opcode ins ctxt wbop = - let builder = IRBuilder (32) - let taddr = builder.NewTempVar 32 - let rn, regs = parseOprOfSTM ins ctxt +let stm opcode ins insLen ctxt wbop = + let ir = !*ctxt + let taddr = !+ir 32 + let rn, regs = parseOprOfSTM ins insLen ctxt let wback = ins.WriteBack let msize = numI32 (4 * bitCount regs 16) 32 let addr = getSTMStartAddr rn msize opcode let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder >> 15 &&& 1u) = 1u then - builder addr := pcStoreValue ctxt) + !!ir (AST.loadLE 32 addr := pcStoreValue ctxt) else () - if wback then builder ir insLen -let parseOprOfCBZ (ins: InsInfo) ctxt = +let parseOprOfCBZ (ins: InsInfo) insLen ctxt = let pc = bvOfBaseAddr ins.Address let offset = pcOffset ins |> int64 match ins.Operands with @@ -2455,127 +2719,127 @@ let parseOprOfCBZ (ins: InsInfo) ctxt = getRegVar ctxt rn, pc .+ (numI64 (imm + offset) 32) | _ -> raise InvalidOperandException -let cbz nonZero ins ctxt = - let builder = IRBuilder (16) - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" +let cbz nonZero ins insLen ctxt = + let ir = !*ctxt + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" let n = if nonZero then AST.num1 1 else AST.num0 1 - let rn, pc = parseOprOfCBZ ins ctxt + let rn, pc = parseOprOfCBZ ins insLen ctxt let cond = n <+> (rn == AST.num0 32) let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder - builder ir insLen -let parseOprOfTableBranch (ins: InsInfo) ctxt = +let parseOprOfTableBranch (ins: InsInfo) insLen ctxt = match ins.Operands with | OneOperand (OprMemory (OffsetMode (RegOffset (rn, None, rm, None)))) -> - let rn = getRegVar ctxt rn |> convertPCOpr ins ctxt - let rm = getRegVar ctxt rm |> convertPCOpr ins ctxt + let rn = getRegVar ctxt rn |> convertPCOpr ins insLen ctxt + let rm = getRegVar ctxt rm |> convertPCOpr ins insLen ctxt let addr = rn .+ rm AST.loadLE 8 addr |> AST.zext 32 | OneOperand (OprMemory (OffsetMode (RegOffset (rn, None, rm, Some (_, Imm i))))) -> - let rn = getRegVar ctxt rn |> convertPCOpr ins ctxt - let rm = getRegVar ctxt rm |> convertPCOpr ins ctxt + let rn = getRegVar ctxt rn |> convertPCOpr ins insLen ctxt + let rm = getRegVar ctxt rm |> convertPCOpr ins insLen ctxt let addr = rn .+ (shiftLSL rm 32 i) AST.loadLE 16 addr |> AST.zext 32 | _ -> raise InvalidOperandException -let tableBranch (ins: InsInfo) ctxt = - let builder = IRBuilder (8) - let pc = bvOfBaseAddr ins.Address - let halfwords = parseOprOfTableBranch ins ctxt +let tableBranch (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let offset = if ins.Mode = ArchOperationMode.ARMMode then 8 else 4 + let pc = bvOfBaseAddr ins.Address .+ (numI32 offset 32) + let halfwords = parseOprOfTableBranch ins insLen ctxt let numTwo = numI32 2 32 let result = pc .+ (numTwo .* halfwords) let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder ir insLen -let parseOprOfBFC (ins: InsInfo) ctxt = +let parseOprOfBFC (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprReg rd, OprImm lsb, OprImm width) -> getRegVar ctxt rd, Convert.ToInt32 lsb, Convert.ToInt32 width | _ -> raise InvalidOperandException -let bfc (ins: InsInfo) ctxt = - let builder = IRBuilder (8) - let rd, lsb, width = parseOprOfBFC ins ctxt +let bfc (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let rd, lsb, width = parseOprOfBFC ins insLen ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder lsb width 0) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + ! lsb width 0) + putEndLabel ctxt lblIgnore ir + !>ir insLen -let parseOprOfRdRnLsbWidth (ins: InsInfo) ctxt = +let parseOprOfRdRnLsbWidth (ins: InsInfo) insLen ctxt = match ins.Operands with | FourOperands (OprReg rd, OprReg rn, OprImm lsb, OprImm width) -> getRegVar ctxt rd, getRegVar ctxt rn, Convert.ToInt32 lsb, Convert.ToInt32 width | _ -> raise InvalidOperandException -let bfi ins ctxt = - let builder = IRBuilder (8) - let rd, rn, lsb, width = parseOprOfRdRnLsbWidth ins ctxt - let t0 = builder.NewTempVar 32 - let t1 = builder.NewTempVar 32 - let n = rn .& - (BitVector.ofBInt (BigInteger.getMask width) 32 |> AST.num) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder )) - builder lsb width 0) - builder + let n = rn .& (BitVector.OfBInt (BigInteger.getMask width) 32 |> AST.num) + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !)) + !!ir (t1 := replicate rd 32 lsb width 0) + !!ir (rd := t0 .| t1) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let bfx ins insLen ctxt signExtend = + let ir = !*ctxt + let rd, rn, lsb, width = parseOprOfRdRnLsbWidth ins insLen ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! 31 || width < 0 then raise InvalidOperandException else () - let v = BitVector.ofBInt (BigInteger.getMask width) 32 |> AST.num - builder > (numI32 lsb 32)) .& v) + let v = BitVector.OfBInt (BigInteger.getMask width) 32 |> AST.num + !!ir (rd := (rn >> (numI32 lsb 32)) .& v) if signExtend && width > 1 then - let msb = builder.NewTempVar 32 - let mask = builder.NewTempVar 32 + let struct (msb, mask) = tmpVars2 ir 32 let msboffset = numI32 (lsb + width - 1) 32 let shift = numI32 width 32 - builder > msboffset) .& AST.num1 32) - builder )) << shift) - builder > msboffset) .& AST.num1 32) + !!ir (mask := (AST.not (msb .- AST.num1 32)) << shift) + !!ir (rd := rd .| mask) else () - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + putEndLabel ctxt lblIgnore ir + !>ir insLen let parseOprOfUqOpr ctxt = function | ThreeOperands (OprReg rd, OprReg rn, OprReg rm) -> getRegVar ctxt rd, getRegVar ctxt rn, getRegVar ctxt rm | _ -> raise InvalidOperandException -let createTemporaries (builder: IRBuilder) cnt regtype = - Array.init cnt (fun _ -> builder.NewTempVar regtype) +let createTemporaries (ir: IRBuilder) cnt regtype = + Array.init cnt (fun _ -> !+ir regtype) let extractUQOps r width = let typ = RegType.fromBitWidth width - [| for w in 0 .. width .. 31 do yield AST.extract r typ w |> AST.zext 32 done |] + [| for w in 0 .. width .. 31 do + yield AST.extract r typ w |> AST.zext 32 + done |] let saturate e width = let max32 = numI32 (pown 2 width - 1) 32 @@ -2590,71 +2854,74 @@ let getUQAssignment tmps width = (AST.zext 32 t) << (numI32 (idx * width) 32)) |> Array.reduce (.|) -let uqopr (ins: InsInfo) ctxt width opr = - let builder = IRBuilder (16) +let uqopr (ins: InsInfo) insLen ctxt width opr = + let ir = !*ctxt let rd, rn, rm = parseOprOfUqOpr ctxt ins.Operands - let tmps = createTemporaries builder (32 / width) 32 - let sats = createTemporaries builder (32 / width) (RegType.fromBitWidth width) + let tmps = createTemporaries ir (32 / width) 32 + let sats = createTemporaries ir (32 / width) (RegType.fromBitWidth width) let rns = extractUQOps rn width let rms = extractUQOps rm width let diffs = Array.map2 opr rns rms let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - Array.iter2 (fun tmp diff -> builder builder !!ir (tmp := diff)) tmps diffs + Array.iter2 (fun s t -> !!ir (s := saturate t width)) sats tmps + !!ir (rd := getUQAssignment sats width) + putEndLabel ctxt lblIgnore ir + !>ir insLen /// ADR For ThumbMode (T1 case) -let parseOprOfADR (ins: InsInfo) ctxt = +let parseOprOfADR (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg rd, OprMemory (LiteralMode imm)) -> let addr = bvOfBaseAddr ins.Address - let addr = addr .+ (numI32 4 32) + let rel = if ins.Mode = ArchOperationMode.ARMMode then 8 else 4 + let addr = addr .+ (numI32 rel 32) let pc = align addr (numI32 4 32) - getRegVar ctxt rd, pc .+ (numI64 imm 32) + let imm = numI64 imm 32 + let pc = if ins.IsAdd then pc .+ imm else pc .- imm + getRegVar ctxt rd, pc | _ -> raise InvalidOperandException -let it (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let it (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let cpsr = getRegVar ctxt R.CPSR let itState = numI32 (int ins.ITState) 32 let mask10 = numI32 0b11 32 let mask72 = (numI32 0b11111100 32) let itState10 = itState .& mask10 let itState72 = (itState .& mask72) >> (numI32 2 32) - startMark ins builder - builder setPSR ctxt R.CPSR PSR_IT10) - builder setPSR ctxt R.CPSR PSR_IT72) - endMark ins builder - -let adr ins ctxt = - let builder = IRBuilder (32) - let rd, result = parseOprOfADR ins ctxt - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if rd = getPC ctxt then aluWritePC ctxt ins isUnconditional result builder - else builder - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder (AST.zext 64 ra .- AST.zext 64 rn .* + ! setPSR ctxt R.CPSR PSR.IT10) + !!ir (cpsr := itState72 |> setPSR ctxt R.CPSR PSR.IT72) + !>ir insLen + +let adr ins insLen ctxt = + let ir = !*ctxt + let rd, result = parseOprOfADR ins insLen ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let mls ins insLen ctxt = + let ir = !*ctxt + let struct (rd, rn, rm, ra) = transFourOprs ins ctxt + let r = !+ir 32 + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! (AST.zext 64 ra .- AST.zext 64 rn .* AST.zext 64 rm)) - builder ir insLen -let parseOprOfExtend (ins: InsInfo) ctxt = +let parseOprOfExtend (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg rd, OprReg rm) -> getRegVar ctxt rd, getRegVar ctxt rm, 0u @@ -2662,33 +2929,46 @@ let parseOprOfExtend (ins: InsInfo) ctxt = getRegVar ctxt rd, getRegVar ctxt rm, i | _ -> raise InvalidOperandException -let extend (ins: InsInfo) ctxt extractfn amount = - let builder = IRBuilder (8) - let rd, rm, rotation = parseOprOfExtend ins ctxt +let extend (ins: InsInfo) insLen ctxt extractfn amount = + let ir = !*ctxt + let rd, rm, rotation = parseOprOfExtend ins insLen ctxt let rotated = shiftROR rm 32 rotation let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder (AST.xtlo amount rotated)) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + ! (AST.xtlo amount rotated)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let uxtb16 ins insLen ctxt = + let ir = !*ctxt + let rd, rm, rotation = parseOprOfExtend ins insLen ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! rotation + let r1 = AST.xtlo 8 rotated |> AST.zext 32 + let r2 = (AST.extract rotated 8 16 |> AST.zext 32) << numI32 16 32 + !!ir (rd := r2 .| r1) + putEndLabel ctxt lblIgnore ir + !>ir insLen -let parseOprOfXTA (ins: InsInfo) ctxt = +let parseOprOfXTA (ins: InsInfo) insLen ctxt = match ins.Operands with | FourOperands (OprReg rd, OprReg rn, OprReg rm, OprShift (_, Imm i)) -> getRegVar ctxt rd, getRegVar ctxt rn, getRegVar ctxt rm, i | _ -> raise InvalidOperandException -let extendAndAdd (ins: InsInfo) ctxt amount = - let builder = IRBuilder (8) - let rd, rn, rm, rotation = parseOprOfXTA ins ctxt +let extendAndAdd (ins: InsInfo) insLen ctxt amount = + let ir = !*ctxt + let rd, rn, rm, rotation = parseOprOfXTA ins insLen ctxt let rotated = shiftROR rm 32 rotation let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder (AST.xtlo amount rotated)) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + ! (AST.xtlo amount rotated)) + putEndLabel ctxt lblIgnore ir + !>ir insLen let checkSingleReg = function | R.S0 | R.S1 | R.S2 | R.S3 | R.S4 | R.S5 | R.S6 | R.S7 | R.S8 | R.S9 @@ -2697,60 +2977,57 @@ let checkSingleReg = function | R.S28 | R.S29 | R.S30 | R.S31 -> true | _ -> false -let parseOprOfVLDR (ins: InsInfo) ctxt = +let parseOprOfVLDR (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (SFReg (Vector d)), - OprMemory (OffsetMode (ImmOffset (rn , s, imm)))) -> - let pc = getRegVar ctxt rn |> convertPCOpr ins ctxt + OprMemory (OffsetMode (ImmOffset (rn, s, imm)))) -> + let pc = getRegVar ctxt rn |> convertPCOpr ins insLen ctxt let baseAddr = align pc (numI32 4 32) getRegVar ctxt d, getOffAddrWithImm s baseAddr imm, checkSingleReg d | _ -> raise InvalidOperandException -let vldr ins ctxt = - let builder = IRBuilder (8) - let rd, addr, isSReg = parseOprOfVLDR ins ctxt +let vldr ins insLen ctxt = + let ir = !*ctxt + let rd, addr, isSReg = parseOprOfVLDR ins insLen ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder addr) - builder + !!ir (data := AST.loadLE 32 addr) + !!ir (rd := data) else - let d1 = builder.NewTempVar 32 - let d2 = builder.NewTempVar 32 - builder addr) - builder (addr .+ (numI32 4 32))) - builder + !!ir (d1 := AST.loadLE 32 addr) + !!ir (d2 := AST.loadLE 32 (addr .+ (numI32 4 32))) + !!ir (rd := if ctxt.Endianness = Endian.Big then AST.concat d1 d2 + else AST.concat d2 d1) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let parseOprOfVSTR (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (SFReg (Vector d)), - OprMemory (OffsetMode (ImmOffset (rn , s, imm)))) -> + OprMemory (OffsetMode (ImmOffset (rn, s, imm)))) -> let baseAddr = getRegVar ctxt rn getRegVar ctxt d, getOffAddrWithImm s baseAddr imm, checkSingleReg d | _ -> raise InvalidOperandException -let vstr (ins: InsInfo) ctxt = - let builder = IRBuilder (8) - let rd, addr, isSReg = parseOprOfVSTR ins ctxt +let vstr (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let rd, addr, isSReg = parseOprOfVSTR ins insLen ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if isSReg then builder addr := rd) + ! addr := rd) else let mem1 = AST.loadLE 32 addr let mem2 = AST.loadLE 32 (addr .+ (numI32 4 32)) let isbig = ctxt.Endianness = Endian.Big - builder rd else AST.xtlo 32 rd) - builder rd else AST.xthi 32 rd) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + !!ir (mem1 := if isbig then AST.xthi 32 rd else AST.xtlo 32 rd) + !!ir (mem2 := if isbig then AST.xtlo 32 rd else AST.xthi 32 rd) + putEndLabel ctxt lblIgnore ir + !>ir insLen let parseOprOfVPUSHVPOP (ins: InsInfo) = match ins.Operands with @@ -2838,12 +3115,12 @@ let parsePUSHPOPsubValue ins = else getVFPDRegisterToInt regs.Head d, imm, isSReg -let vpopLoop ctxt d imm isSReg addr (builder: IRBuilder) = +let vpopLoop ctxt d imm isSReg addr (ir: IRBuilder) = let rec singleRegLoop r addr = if r < imm then let reg = d + r |> byte |> OperandHelper.getVFPSRegister let nextAddr = (addr .+ (numI32 4 32)) - builder addr) + !!ir (getRegVar ctxt reg := AST.loadLE 32 addr) singleRegLoop (r + 1) nextAddr else () let rec nonSingleRegLoop r addr = @@ -2853,34 +3130,34 @@ let vpopLoop ctxt d imm isSReg addr (builder: IRBuilder) = let word2 = AST.loadLE 32 (addr .+ (numI32 4 32)) let nextAddr = addr .+ (numI32 8 32) let isbig = ctxt.Endianness = Endian.Big - builder +let vpop ins insLen ctxt = + let ir = !*ctxt // FIXME + let t0 = !+ir 32 let sp = getRegVar ctxt R.SP let d, imm, isSReg = parsePUSHPOPsubValue ins let addr = sp let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder )) - vpopLoop ctxt d imm isSReg t0 builder - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vpushLoop ctxt d imm isSReg addr (builder: IRBuilder) = + !)) + vpopLoop ctxt d imm isSReg t0 ir + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vpushLoop ctxt d imm isSReg addr (ir: IRBuilder) = let rec singleRegLoop r addr = if r < imm then let reg = d + r |> byte |> OperandHelper.getVFPSRegister let nextAddr = (addr .+ (numI32 4 32)) - builder addr := getRegVar ctxt reg) + !!ir (AST.loadLE 32 addr := getRegVar ctxt reg) singleRegLoop (r + 1) nextAddr else () let rec nonSingleRegLoop r addr = @@ -2892,28 +3169,28 @@ let vpushLoop ctxt d imm isSReg addr (builder: IRBuilder) = let isbig = ctxt.Endianness = Endian.Big let data1 = AST.xthi 32 (getRegVar ctxt reg) let data2 = AST.xtlo 32 (getRegVar ctxt reg) - builder +let vpush ins insLen ctxt = + let ir = !*ctxt // FIXME + let t0 = !+ir 32 let sp = getRegVar ctxt R.SP let d, imm, isSReg = parsePUSHPOPsubValue ins let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder )) - builder )) + !!ir (sp := t0) + vpushLoop ctxt d imm isSReg t0 ir + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let parseOprOfVAND (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprSIMD (SFReg (Vector r1)), OprSIMD (SFReg (Vector r2)), @@ -2921,35 +3198,45 @@ let parseOprOfVAND (ins: InsInfo) ctxt = getRegVar ctxt r1, getRegVar ctxt r2, getRegVar ctxt r3 | _ -> raise InvalidOperandException -let vand (ins: InsInfo) ctxt = - let builder = IRBuilder (8) - let dst, src1, src2 = parseOprOfVAND ins ctxt +let vand (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - builder -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + !!ir (dstA := src1A .& src2A) + !!ir (dstB := src1B .& src2B) + | _ -> + let dst, src1, src2 = parseOprOfVAND ins insLen ctxt + !!ir (dst := src1 .& src2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vmrs ins insLen ctxt = + let ir = !*ctxt + let struct (rt, fpscr) = transTwoOprs ins ctxt let cpsr = getRegVar ctxt R.CPSR let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - if rt <> cpsr then builder - Elements: int - RegIndex: bool option } + ! cpsr then !!ir (rt := fpscr) + else !!ir (cpsr := disablePSRBits ctxt R.CPSR PSR.Cond .| + getPSR ctxt R.FPSCR PSR.Cond) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +type ParsingInfo = { + EBytes: int + ESize: int + RtESize: int + Elements: int + RegIndex: bool option +} let getRegs = function | TwoOperands (OprSIMD (OneReg _), _) -> 1 @@ -2962,11 +3249,14 @@ let getEBytes = function | Some (OneDT SIMDTyp8) | Some (OneDT SIMDTypS8) | Some (OneDT SIMDTypI8) | Some (OneDT SIMDTypU8) | Some (OneDT SIMDTypP8) -> 1 | Some (OneDT SIMDTyp16) | Some (OneDT SIMDTypS16) | Some (OneDT SIMDTypI16) - | Some (OneDT SIMDTypU16) -> 2 + | Some (OneDT SIMDTypU16) | Some (OneDT SIMDTypF16) + | Some (TwoDT (SIMDTypF32, SIMDTypF16)) + | Some (TwoDT (SIMDTypF16, SIMDTypF32)) -> 2 | Some (OneDT SIMDTyp32) | Some (OneDT SIMDTypS32) | Some (OneDT SIMDTypI32) - | Some (OneDT SIMDTypU32) -> 4 + | Some (OneDT SIMDTypU32) | Some (OneDT SIMDTypF32) -> 4 | Some (OneDT SIMDTyp64) | Some (OneDT SIMDTypS64) | Some (OneDT SIMDTypI64) - | Some (OneDT SIMDTypU64) -> 8 + | Some (OneDT SIMDTypU64) | Some (OneDT SIMDTypP64) + | Some (OneDT SIMDTypF64) -> 8 | _ -> raise InvalidOperandException let registerIndex = function @@ -2981,260 +3271,434 @@ let getParsingInfo (ins: InsInfo) = let esize = ebytes * 8 let elements = 8 / ebytes let regIndex = registerIndex ins.Operands - { - EBytes = ebytes + { EBytes = ebytes ESize = esize RtESize = RegType.fromBitWidth esize Elements = elements - RegIndex = regIndex - } + RegIndex = regIndex } -let elem vector e size = AST.extract vector (RegType.fromBitWidth size) (e * size) +let private elem vector e size = + AST.extract vector (RegType.fromBitWidth size) (e * size) let elemForIR vector vSize index size = let index = AST.zext vSize index - let mask = AST.num <| BitVector.ofBInt (BigInteger.getMask size) vSize + let mask = AST.num <| BitVector.OfBInt (BigInteger.getMask size) vSize let eSize = numI32 size vSize (vector >> (index .* eSize)) .& mask |> AST.xtlo (RegType.fromBitWidth size) -let getESzieOfVMOV = function - | Some (OneDT SIMDTyp8) -> 8 - | Some (OneDT SIMDTyp16) -> 16 - | Some (OneDT SIMDTyp32) -> 32 +let isUnsigned = function + | Some (OneDT SIMDTypU8) | Some (OneDT SIMDTypU16) + | Some (OneDT SIMDTypU32) | Some (OneDT SIMDTypU64) -> true + | Some (OneDT SIMDTypS8) | Some (OneDT SIMDTypS16) + | Some (OneDT SIMDTypS32) | Some (OneDT SIMDTypS64) | Some (OneDT SIMDTypP8) + | Some (OneDT SIMDTypP64) | Some (OneDT SIMDTyp8) | Some (OneDT SIMDTyp16) + | Some (OneDT SIMDTyp32) | Some (OneDT SIMDTyp64) -> false | _ -> raise InvalidOperandException -let getIndexOfVMOV = function - | TwoOperands (OprSIMD (SFReg (Scalar (_, Some element))), _) -> int element +let parseOprOfVMOV (ins: InsInfo) ctxt ir = + match ins.Operands with + (* VMOV (immediate) *) + | TwoOperands (OprSIMD _, OprImm _) -> + let struct (dst, imm) = getTwoOprs ins + match ins.OprSize with + | 128 -> + let dstB, dstA = transOprToExpr128 ctxt dst + let imm = transOprToExpr ins ctxt imm + !!ir (dstB := imm) + !!ir (dstA := imm) + | _ -> + let dst = transOprToExpr ins ctxt dst + let imm = transOprToExpr ins ctxt imm + !!ir (dst := imm) + (* VMOV (general-purpose register to scalar) *) + | TwoOperands (OprSIMD (SFReg (Scalar (_, Some element))), OprReg _) -> + let struct (dst, src) = transTwoOprs ins ctxt + let p = getParsingInfo ins + let index = int element + !!ir (elem dst index p.ESize := AST.xtlo p.RtESize src) + (* VMOV (scalar to general-purpose register) *) + | TwoOperands (OprReg _, OprSIMD (SFReg (Scalar (_, Some element)))) -> + let struct (dst, src) = transTwoOprs ins ctxt + let p = getParsingInfo ins + let index = int element + let extend = if isUnsigned ins.SIMDTyp then AST.zext else AST.sext + !!ir (dst := extend 32 (elem src index p.ESize)) + (* VMOV (between general-purpose register and single-precision) *) + | TwoOperands _ -> + let struct (dst, src) = transTwoOprs ins ctxt + !!ir (dst := src) + (* VMOV (between two general-purpose registers and a doubleword + floating-point register) *) + | ThreeOperands (OprSIMD _, OprReg _, OprReg _) -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (AST.xtlo 32 dst := src1) + !!ir (AST.xthi 32 dst := src2) + | ThreeOperands (OprReg _, OprReg _, OprSIMD _) -> + let struct (dst1, dst2, src) = transThreeOprs ins ctxt + !!ir (dst1 := AST.xtlo 32 src) + !!ir (dst2 := AST.xthi 32 src) + (* VMOV (between two general-purpose registers and two single-precision + registers) *) + | FourOperands _ -> + let struct (dst1, dst2, src1, src2) = transFourOprs ins ctxt + !!ir (dst1 := src1) + !!ir (dst2 := src2) | _ -> raise InvalidOperandException -let isQwordReg = function - | R.Q0 | R.Q1 | R.Q2 | R.Q3 | R.Q4 | R.Q5 | R.Q6 | R.Q7 | R.Q8 | R.Q9 | R.Q10 - | R.Q11 | R.Q12 | R.Q13 | R.Q14 | R.Q15 -> true - | _ -> false - -let parseOprOfVMOV (ins: InsInfo) ctxt builder = +let parseOprOfVMOVFP (ins: InsInfo) ctxt ir = match ins.Operands with + (* VMOV (between general-purpose register and half-precision) *) + | TwoOperands (OprSIMD _, OprReg _) | TwoOperands (OprReg _, OprSIMD _) -> + let struct (dst, src) = transTwoOprs ins ctxt + !!ir (dst := AST.zext 32 (AST.xtlo 16 src)) + (* VMOV (register) *) | TwoOperands (OprSIMD _, OprSIMD _) -> - let dst, src = transTwoOprs ins ctxt - builder - if isQwordReg reg then - let dst, imm = transTwoOprs ins ctxt - let imm64 = AST.concat imm imm // FIXME - builder dst := imm64) - builder dst := imm64) - else - let dst, imm = transTwoOprs ins ctxt - let imm64 = AST.concat imm imm // FIXME - builder - let dst, src = transTwoOprs ins ctxt - let index = getIndexOfVMOV ins.Operands - let esize = getESzieOfVMOV ins.SIMDTyp - builder raise InvalidOperandException - -let vmov (ins: InsInfo) ctxt = - let builder = IRBuilder (8) + let struct (dst, src) = transTwoOprs ins ctxt + !!ir (dst := src) + (* VMOV (immediate) *) + | TwoOperands (OprSIMD _, OprImm _) -> + let struct (dst, imm) = transTwoOprs ins ctxt + !!ir (dst := AST.zext ins.OprSize imm) + | _ -> !!ir (AST.sideEffect UnsupportedFP) + +let vmov (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let vmovfp (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - parseOprOfVMOV ins ctxt builder - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + !ir insLen (* VMOV(immediate)/VMOV(register) *) let isF32orF64 = function | Some (OneDT SIMDTypF32) | Some (OneDT SIMDTypF64) -> true | _ -> false -let isAdvSIMDByDT = function - (* VMOV (ARM core register to scalar/scalar to ARM core register) *) - | Some (OneDT SIMDTyp8) | Some (OneDT SIMDTyp16) -> true - | Some (OneDT SIMDTyp32) -> false - (* VMOV (between ARM core register and single-precision register) *) - (* VMOV (between two ARM core registers and two single-precision registers) *) - | None -> false - | _ -> raise UndefinedException - -let isAdvancedSIMD (ins: InsInfo) = - match ins.Operands with - | TwoOperands (OprSIMD _, OprImm _) | TwoOperands (OprSIMD _, OprSIMD _) -> - isF32orF64 ins.SIMDTyp |> not - | TwoOperands (OprSIMD _, OprReg _) | TwoOperands (OprReg _, OprSIMD _) - | FourOperands (OprSIMD _, OprSIMD _, OprReg _, OprReg _) - | FourOperands (OprReg _, OprReg _, OprSIMD _, OprSIMD _) -> - isAdvSIMDByDT ins.SIMDTyp - (* VMOV (between two ARM core registers and a dword extension register) *) - | ThreeOperands (OprSIMD _, OprReg _, OprReg _) - | ThreeOperands (OprReg _, OprReg _, OprSIMD _) -> false +(* VABS(immediate)/VABS(register) *) +let isF16orF32orF64 = function + | Some (OneDT SIMDTypF16) | Some (OneDT SIMDTypF32) | Some (OneDT SIMDTypF64) + -> true | _ -> false -let absExpr expr size = AST.ite (AST.slt expr (AST.num0 size)) (AST.neg expr) (expr) +let private absExpr expr size = + AST.ite (AST.slt expr (AST.num0 size)) (AST.neg expr) (expr) -let vabs (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vabs (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm = transTwoOprs ins ctxt + ! then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + | 128 -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src for e in 0 .. p.Elements - 1 do - builder + let struct (dst, src) = transTwoOprs ins ctxt + for e in 0 .. p.Elements - 1 do + !!ir (elem dst e p.ESize := absExpr (elem src e p.ESize) p.RtESize) + putEndLabel ctxt lblIgnore ir + !>ir insLen -let vadd (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vaddsub (ins: InsInfo) insLen ctxt opFn = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt + ! then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + (* FP, p.ESize 16 *) + | 32 when p.ESize = 16 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := + AST.zext 32 (opFn (AST.xtlo 16 src1) (AST.xtlo 16 src2))) + (* FP, p.ESize 32 *) + | 32 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := opFn src1 src2) + (* FP, p.ESize 64 *) + | 64 when p.ESize = 64 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := opFn src1 src2) + (* SIMD *) + | 64 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. p.Elements - 1 do + let elem value = elem value e p.ESize + !!ir (elem dst := (opFn (elem src1) (elem src2))) + (* SIMD *) + | 128 -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 for e in 0 .. p.Elements - 1 do - builder raise InvalidOperandException + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vaddl (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let isDoubleToSingle = function + | Some (TwoDT (SIMDTypF32, SIMDTypF64)) -> true + | Some (TwoDT (SIMDTypF64, SIMDTypF32)) -> false + | _ -> raise InvalidOperandException -let parseOprOfVDUP (ins: InsInfo) ctxt esize = +let parseOprOfVCVT (ins: InsInfo) ctxt ir = + (* FIXME *) match ins.Operands with - | TwoOperands (OprSIMD (SFReg (Vector rd)), - OprSIMD (SFReg (Scalar (rm, Some idx)))) -> - getRegVar ctxt rd, elem (getRegVar ctxt rm) (int32 idx) esize - | TwoOperands (OprSIMD (SFReg (Vector rd)), OprReg rm) -> - getRegVar ctxt rd, - AST.xtlo (RegType.fromBitWidth esize) (getRegVar ctxt rm) + | TwoOperands(OprSIMD _, OprSIMD _) -> + match ins.OprSize with + (* FIXME *) + (* VCVT (between half-precision and single-precision, Advanced SIMD) *) + | 128 -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src = transOprToExpr ins ctxt src + let p = getParsingInfo ins + let struct (tdstB, tdstA) = tmpVars2 ir 64 + !!ir (tdstA := (dstB << numI32 63 64) .| (dstA >> AST.num1 64)) + !!ir (tdstB := dstB >> AST.num1 64) + for e in 0 .. (p.Elements - 1) / 2 do + !!ir (elem tdstB e 32 := + AST.cast CastKind.FloatCast 32 (elem src (e + 2) 16)) + !!ir (elem tdstA e 32 := + AST.cast CastKind.FloatCast 32 (elem src e 16)) + !!ir (dstB := tdstB) + !!ir (dstA := tdstA) + | 64 -> + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ins ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + let p = getParsingInfo ins + let struct (tsrcB, tsrcA) = tmpVars2 ir 64 + !!ir (tsrcA := (srcB << numI32 63 64) .| (srcA >> AST.num1 64)) + !!ir (tsrcB := srcB >> AST.num1 64) + for e in 0 .. (p.Elements - 1) / 2 do + !!ir (elem dst (e + 2) 16 := + AST.cast CastKind.FloatCast 16 (elem tsrcB e 32)) + !!ir (elem dst e 16 := + AST.cast CastKind.FloatCast 16 (elem tsrcA e 32)) + (* VCVT (between double-precision and single-precision) *) + | _ -> + let struct (dst, src) = transTwoOprs ins ctxt + let cast = + if isDoubleToSingle ins.SIMDTyp then AST.cast CastKind.FloatCast 32 + else AST.cast CastKind.FloatCast 64 + !!ir (dst := cast src) | _ -> raise InvalidOperandException -let vdup (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vcvt (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let esize = 8 * getEBytes ins.SIMDTyp - let rd, scalar = parseOprOfVDUP ins ctxt esize - let elements = 64 / esize - let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - for e in 0 .. elements - 1 do builder ir insLen + +let parseOprOfVDUP (ins: InsInfo) insLen ctxt esize = + match ins.Operands with + | TwoOperands (OprSIMD (SFReg (Vector dst)), + OprSIMD (SFReg (Scalar (src, Some idx)))) -> + getRegVar ctxt dst, elem (getRegVar ctxt src) (int32 idx) esize + | TwoOperands (OprSIMD (SFReg (Vector dst)), OprReg src) -> + getRegVar ctxt dst, + AST.xtlo (RegType.fromBitWidth esize) (getRegVar ctxt src) + | _ -> raise InvalidOperandException + +let parseOprOfVDUP128 (ins: InsInfo) insLen ctxt esize = + match ins.Operands with + | TwoOperands (OprSIMD (SFReg (Vector dst)), + OprSIMD (SFReg (Scalar (src, Some idx)))) -> + getPseudoRegVar128 ctxt dst, elem (getRegVar ctxt src) (int32 idx) esize + | TwoOperands (OprSIMD (SFReg (Vector dst)), OprReg src) -> + getPseudoRegVar128 ctxt dst, + AST.xtlo (RegType.fromBitWidth esize) (getRegVar ctxt src) + | _ -> raise InvalidOperandException + +let vdiv (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := + AST.zext 32 (AST.fdiv (AST.xtlo 16 src1) (AST.xtlo 16 src2))) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := AST.fdiv src1 src2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vdup (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let (dstB, dstA), scalar = parseOprOfVDUP128 ins insLen ctxt p.ESize + for e in 0 .. p.Elements - 1 do + !!ir (elem dstB e p.ESize := scalar) + !!ir (elem dstA e p.ESize := scalar) + | _ -> + let dst, scalar = parseOprOfVDUP ins insLen ctxt p.ESize + for e in 0 .. p.Elements - 1 do !!ir (elem dst e p.ESize := scalar) done + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let highestSetBitForIR dst src width oprSz (ir: IRBuilder) = + let lblLoop = !%ir "Loop" + let lblLoopCont = !%ir "LoopContinue" + let lblUpdateTmp = !%ir "UpdateTmp" + let lblEnd = !%ir "End" + let t = !+ir oprSz let width = (numI32 (width - 1) oprSz) - builder > t == AST.num1 oprSz) + !!ir (t := width) + !!ir (AST.lmark lblLoop) + !!ir (AST.cjmp (src >> t == AST.num1 oprSz) (AST.name lblEnd) (AST.name lblLoopCont)) - builder then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) - for e in 0 .. pInfo.Elements - 1 do - countLeadingZeroBitsForIR (elem rd e pInfo.ESize) (elem rm e pInfo.ESize) - pInfo.RtESize builder - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + !!ir (AST.lmark lblUpdateTmp) + !!ir (t := t .- AST.num1 oprSz) + !!ir (AST.jmp (AST.name lblLoop)) + !!ir (AST.lmark lblEnd) + !!ir (dst := width .- t) + +let countLeadingZeroBitsForIR dst src oprSize ir = + highestSetBitForIR dst src (RegType.toBitWidth oprSize) oprSize ir + +let vclz (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + for e in 0 .. p.Elements - 1 do + countLeadingZeroBitsForIR (elem dstB e p.ESize) + (elem srcB e p.ESize) p.RtESize ir + countLeadingZeroBitsForIR (elem dstA e p.ESize) + (elem srcA e p.ESize) p.RtESize ir + | _ -> + let struct (dst, src) = transTwoOprs ins ctxt + for e in 0 .. p.Elements - 1 do + countLeadingZeroBitsForIR (elem dst e p.ESize) + (elem src e p.ESize) p.RtESize ir + putEndLabel ctxt lblIgnore ir + !>ir insLen let maxExpr isUnsigned expr1 expr2 = - let op = if isUnsigned then AST.gt else AST.sgt in AST.ite (op expr1 expr2) expr1 expr2 + let op = if isUnsigned then AST.gt else AST.sgt + AST.ite (op expr1 expr2) expr1 expr2 let minExpr isUnsigned expr1 expr2 = - let op = if isUnsigned then AST.lt else AST.slt in AST.ite (op expr1 expr2) expr1 expr2 + let op = if isUnsigned then AST.lt else AST.slt + AST.ite (op expr1 expr2) expr1 expr2 -let isUnsigned = function - | Some (OneDT SIMDTypU8) | Some (OneDT SIMDTypU16) - | Some (OneDT SIMDTypU32) | Some (OneDT SIMDTypU64) -> true - | Some (OneDT SIMDTypS8) | Some (OneDT SIMDTypS16) - | Some (OneDT SIMDTypS32) | Some (OneDT SIMDTypS64) | Some (OneDT SIMDTypP8) - -> false - | _ -> raise InvalidOperandException +let private mulZExtend p size expr1 expr2 amtOp = + amtOp (AST.zext (p.RtESize * size) expr1) (AST.zext (p.RtESize * size) expr2) -let vmaxmin (ins: InsInfo) ctxt maximum = - let builder = IRBuilder (32) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt - let pInfo = getParsingInfo ins - let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 - let unsigned = isUnsigned ins.SIMDTyp - for r in 0 .. regs - 1 do - let rn = AST.extract rn 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) - let rd = AST.extract rd 64 (r * 64) - for e in 0 .. pInfo.Elements - 1 do - let op1 = elem rn e pInfo.ESize - let op2 = elem rm e pInfo.ESize - let result = - if maximum then maxExpr unsigned op1 op2 else minExpr unsigned op1 op2 - builder then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + let unsigned = isUnsigned ins.SIMDTyp + match ins.OprSize with + | 128 -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + for e in 0 .. p.Elements - 1 do + let op1B, op2B = elem src1B e p.ESize, elem src2B e p.ESize + let op1A, op2A = elem src1A e p.ESize, elem src2A e p.ESize + let result1 = + if maximum then maxExpr unsigned op1B op2B + else minExpr unsigned op1B op2B + let result2 = + if maximum then maxExpr unsigned op1A op2A + else minExpr unsigned op1A op2A + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize result1) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize result2) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt for e in 0 .. p.Elements - 1 do - builder ir insLen -let parseOprOfVSTLDM (ins: InsInfo) ctxt = +let parseOprOfVSTLDM (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprReg reg, OprRegList regs) -> getRegVar ctxt reg, List.map (getRegVar ctxt) regs | _ -> raise InvalidOperandException -let vstm (ins: InsInfo) ctxt = - let builder = IRBuilder (16) +let vstm (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rn, regList = parseOprOfVSTLDM ins ctxt + ! true @@ -3242,31 +3706,31 @@ let vstm (ins: InsInfo) ctxt = | _ -> raise InvalidOpcodeException let regs = List.length regList let imm32 = numI32 ((regs * 2) <<< 2) 32 - let addr = builder.NewTempVar 32 + let addr = !+ir 32 let updateRn rn = if ins.WriteBack then if add then rn .+ imm32 else rn .- imm32 else rn - builder addr let mem2 = AST.loadLE 32 (addr .+ (numI32 4 32)) let data1 = AST.xtlo 32 regList[r] let data2 = AST.xthi 32 regList[r] let isbig = ctxt.Endianness = Endian.Big - builder )) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vldm (ins: InsInfo) ctxt = - let builder = IRBuilder (16) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rn, regList = parseOprOfVSTLDM ins ctxt + !!ir (mem1 := if isbig then data2 else data1) + !!ir (mem2 := if isbig then data1 else data2) + !!ir (addr := addr .+ (numI32 8 32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vldm (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! true @@ -3274,238 +3738,334 @@ let vldm (ins: InsInfo) ctxt = | _ -> raise InvalidOpcodeException let regs = List.length regList let imm32 = numI32 ((regs * 2) <<< 2) 32 - let addr = builder.NewTempVar 32 + let addr = !+ir 32 let updateRn rn = if ins.WriteBack then if add then rn .+ imm32 else rn .- imm32 else rn - builder addr let word2 = AST.loadLE 32 (addr .+ (numI32 4 32)) let isbig = ctxt.Endianness = Endian.Big - builder )) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vecMulAccOrSub (ins: InsInfo) ctxt add = - let builder = IRBuilder (8) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt - let pInfo = getParsingInfo ins - let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) - for e in 0 .. pInfo.Elements - 1 do - let sext reg = AST.sext pInfo.RtESize (elem reg e pInfo.ESize) - let product = sext rn .* sext rm + !!ir (regList[r] := + if isbig then AST.concat word1 word2 else AST.concat word2 word1) + !!ir (addr := addr .+ (numI32 8 32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vecMulAccOrSub (ins: InsInfo) insLen ctxt add = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + for e in 0 .. p.Elements - 1 do + let sext1A = AST.sext p.RtESize (elem src1A e p.ESize) + let sext1B = AST.sext p.RtESize (elem src1B e p.ESize) + let sext2A = AST.sext p.RtESize (elem src2A e p.ESize) + let sext2B = AST.sext p.RtESize (elem src2B e p.ESize) + let productA = sext1A .* sext2A + let productB = sext1B .* sext2B + let addendA, addendB = + if add then productA, productB else AST.not productA, AST.not productB + !!ir (elem dstB e p.ESize := elem dstB e p.ESize .+ addendB) + !!ir (elem dstA e p.ESize := elem dstA e p.ESize .+ addendA) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. p.Elements - 1 do + let sext1 = AST.sext p.RtESize (elem src1 e p.ESize) + let sext2 = AST.sext p.RtESize (elem src2 e p.ESize) + let product = sext1 .* sext2 let addend = if add then product else AST.not product - builder ir insLen -let vecMulAccOrSubLong (ins: InsInfo) ctxt add = - let builder = IRBuilder (8) +let vecMulAccOrSubLong (ins: InsInfo) insLen ctxt add = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt + ! - getRegVar ctxt rd, getRegVar ctxt rn, (getRegVar ctxt rm, int32 index) - | _ -> raise InvalidOperandException - -let vecMulAccOrSubByScalar (ins: InsInfo) ctxt add = - let builder = IRBuilder (8) + if unsigned then AST.zext (p.RtESize * 2) expr + else AST.sext (p.RtESize * 2) expr + let productA = extend (elem src1 e p.ESize) .* extend (elem src2 e p.ESize) + let productB = extend (elem src1 (e + p.Elements / 2) p.ESize) .* + extend (elem src2 (e + p.Elements / 2) p.ESize) + let addendA, addendB = + if add then productA, productB else AST.not productA, AST.not productB + !!ir (elem dstB e (p.ESize * 2) := elem dstB e (p.ESize * 2) .+ addendB) + !!ir (elem dstA e (p.ESize * 2) := elem dstA e (p.ESize * 2) .+ addendA) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vecMulAccOrSubByScalar (ins: InsInfo) insLen ctxt add = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, (rm, index) = parseOprOfVMulByScalar ins ctxt + ! then 1 else 2 - let op2val = AST.sext p.RtESize (elem rm index p.ESize) - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) + let struct (dst, src1, src2) = getThreeOprs ins + let src2, index = transOprToSclar ctxt src2 + let op2Val = AST.sext p.RtESize (elem src2 index p.ESize) + match ins.OprSize with + | 128 -> + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + for e in 0 .. p.Elements - 1 do + let op1valA = AST.sext p.RtESize (elem src1A e p.ESize) + let op1valB = AST.sext p.RtESize (elem src1B e p.ESize) + let addendA, addendB = + if add then op1valA .* op2Val, op1valB .* op2Val + else AST.not (op1valA .* op2Val), AST.not (op1valB .* op2Val) + !!ir (elem dstB e p.ESize := elem dstB e p.ESize .+ addendB) + !!ir (elem dstA e p.ESize := elem dstA e p.ESize .+ addendA) + | _ -> + let dst = transOprToExpr ins ctxt dst + let src1 = transOprToExpr ins ctxt src1 for e in 0 .. p.Elements - 1 do - let op1val = AST.sext p.RtESize (elem rn e p.ESize) - let addend = if add then op1val .* op2val else AST.not (op1val .* op2val) - builder ir insLen + +let vecMulAccOrSubLongByScalar (ins: InsInfo) insLen ctxt add = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let vmla (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (_, _, OprSIMD (SFReg (Vector _))) -> - vecMulAccOrSub ins ctxt true + vecMulAccOrSub ins insLen ctxt true | ThreeOperands (_, _, OprSIMD (SFReg (Scalar _))) -> - vecMulAccOrSubByScalar ins ctxt true + vecMulAccOrSubByScalar ins insLen ctxt true | _ -> raise InvalidOperandException -let vmlal (ins: InsInfo) ctxt = +let vmlal (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (_, _, OprSIMD (SFReg (Vector _))) -> - vecMulAccOrSubLong ins ctxt true + vecMulAccOrSubLong ins insLen ctxt true | ThreeOperands (_, _, OprSIMD (SFReg (Scalar _))) -> - vecMulAccOrSubLongByScalar ins ctxt true + vecMulAccOrSubLongByScalar ins insLen ctxt true | _ -> raise InvalidOperandException -let vmls (ins: InsInfo) ctxt = +let vmls (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (_, _, OprSIMD (SFReg (Vector _))) -> - vecMulAccOrSub ins ctxt false + vecMulAccOrSub ins insLen ctxt false | ThreeOperands (_, _, OprSIMD (SFReg (Scalar _))) -> - vecMulAccOrSubByScalar ins ctxt false + vecMulAccOrSubByScalar ins insLen ctxt false | _ -> raise InvalidOperandException -let vmlsl (ins: InsInfo) ctxt = +let vmlsl (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (_, _, OprSIMD (SFReg (Vector _))) -> - vecMulAccOrSubLong ins ctxt false + vecMulAccOrSubLong ins insLen ctxt false | ThreeOperands (_, _, OprSIMD (SFReg (Scalar _))) -> - vecMulAccOrSubLongByScalar ins ctxt false + vecMulAccOrSubLongByScalar ins insLen ctxt false | _ -> raise InvalidOperandException let isPolynomial = function - | Some (OneDT SIMDTypP8) -> true + | Some (OneDT SIMDTypP8) | Some (OneDT SIMDTypP64) -> true | _ -> false -// PolynomialMult() -// A2.8.1 Pseudocode details of polynomial multiplication -let polynomialMult op1 op2 size = AST.concat op1 op2 // FIXME -(* A2.8.1 Pseudocode details of polynomial multiplication -bits(M+N) PolynomialMult(bits(M) op1, bits(N) op2) - result = Zeros(M+N); - extended_op2 = Zeros(M) : op2; - for i=0 to M-1 - if op1 == '1' then - result = result EOR LSL(extended_op2, i); - return result; -*) - -let vecMul (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +/// shared/functions/vector/PolynomialMult, in page Armv8 Pseudocode-7927 +let polynomialMult op1 op2 size rtsize res (ir: IRBuilder) = + let extendedOP2 = AST.zext rtsize op2 + for i = 0 to size - 1 do + let cond = AST.extract op1 1 i + !!ir (res := AST.ite cond (res <+> (extendedOP2 << numI32 i rtsize)) res) + +let polynomialMultP64 op1 op2 size rtsize resA resB (ir: IRBuilder) = + for i = 0 to size - 1 do + let cond = AST.extract op1 1 i + !!ir (resA := AST.ite cond (resA <+> (op2 << numI32 i rtsize)) resA) + !!ir (resB := AST.ite cond (resB <+> (op2 >> numI32 (64 - i) rtsize)) resB) + +let vecMul (ins: InsInfo) insLen ctxt opFn = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt + ! then 1 else 2 let polynomial = isPolynomial ins.SIMDTyp - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + let struct (resultA, resultB) = tmpVars2 ir (p.RtESize * 2) + match ins.OprSize with + (* FP, p.ESize 16 *) + | 32 when p.ESize = 16 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := + AST.zext 32 (opFn (AST.xtlo 16 src1) (AST.xtlo 16 src2))) + (* FP, p.ESize 32 *) + | 32 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := opFn src1 src2) + (* FP, p.ESize 64 *) + | 64 when p.ESize = 64 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := opFn src1 src2) + (* SIMD *) + | 64 -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. p.Elements - 1 do + let struct (op1, op2) = elem src1 e p.ESize, elem src2 e p.ESize + if polynomial then + polynomialMult op1 op2 p.ESize (p.RtESize * 2) resultA ir + else !!ir (resultA := mulSExtend p 2 op1 op2 opFn) + !!ir (elem dst e p.ESize := AST.xtlo p.RtESize resultA) + (* SIMD *) + | 128 -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 for e in 0 .. p.Elements - 1 do - let sext reg = AST.sext (p.RtESize * 2) (elem reg e p.ESize) - let product = - if polynomial then polynomialMult rn rm p.ESize else sext rn .* sext rm - builder raise InvalidOperandException + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vecMulLong (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + !ir insLen + +let vecMulByScalar (ins: InsInfo) insLen ctxt opFn = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! then 1 else 2 - let op2val = AST.sext (RegType.fromBitWidth p.ESize) (elem rm index p.ESize) - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) + let struct (dst, src1, src2) = getThreeOprs ins + let src2, index = transOprToSclar ctxt src2 + let op2val = elem src2 index p.ESize + match ins.OprSize with + | 128 -> + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + for e in 0 .. p.Elements - 1 do + let resA = mulSExtend p 1 (elem src1A e p.ESize) op2val opFn + let resB = mulSExtend p 1 (elem src1B e p.ESize) op2val opFn + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize resB) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize resA) + | _ -> + let dst = transOprToExpr ins ctxt dst + let src1 = transOprToExpr ins ctxt src1 for e in 0 .. p.Elements - 1 do - let op1val = AST.sext p.RtESize (elem rn e p.ESize) - builder ir insLen -let vecMulLongByScalar (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vecMulLongByScalar (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, (rm, index) = parseOprOfVMulByScalar ins ctxt + !ir insLen + +let vmul (ins: InsInfo) insLen ctxt opFn = match ins.Operands with | ThreeOperands (_, _, OprSIMD (SFReg (Vector _))) -> - vecMul ins ctxt + vecMul ins insLen ctxt opFn | ThreeOperands (_, _, OprSIMD (SFReg (Scalar _))) -> - vecMulByScalar ins ctxt + vecMulByScalar ins insLen ctxt opFn | _ -> raise InvalidOperandException -let vmull (ins: InsInfo) ctxt = +let vmull (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (_, _, OprSIMD (SFReg (Vector _))) -> - vecMulLong ins ctxt + vecMulLong ins insLen ctxt | ThreeOperands (_, _, OprSIMD (SFReg (Scalar _))) -> - vecMulLongByScalar ins ctxt + vecMulLongByScalar ins insLen ctxt | _ -> raise InvalidOperandException let getSizeStartFromI16 = function @@ -3514,136 +4074,185 @@ let getSizeStartFromI16 = function | Some (OneDT SIMDTypI64) -> 0b10 | _ -> raise InvalidOperandException -let vmovn (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let getSizeStartFrom16 = function + | Some (OneDT SIMDTyp16) -> 0b00 + | Some (OneDT SIMDTyp32) -> 0b01 + | Some (OneDT SIMDTyp64) -> 0b10 + | _ -> raise InvalidOperandException + +let vmovn (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm = transTwoOprs ins ctxt - let esize = 8 <<< getSizeStartFromI16 ins.SIMDTyp + !ir insLen + +let vneg (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm = transTwoOprs ins ctxt + ! then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + | 128 -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + for e in 0 .. p.Elements - 1 do + let result1 = AST.neg <| AST.sext p.RtESize (elem srcB e p.ESize) + let result2 = AST.neg <| AST.sext p.RtESize (elem srcA e p.ESize) + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize result1) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize result2) + | _ -> + let struct (dst, src) = transTwoOprs ins ctxt for e in 0 .. p.Elements - 1 do - let result = AST.neg <| AST.sext p.RtESize (elem rm e p.ESize) - builder ir insLen -let vpadd (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vpadd (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt + ! - builder ) + let dest = !+ir 64 for e in 0 .. h - 1 do let addPair expr = elem expr (2 * e) p.ESize .+ elem expr (2 * e + 1) p.ESize - builder imm + !!ir (elem dest e p.ESize := addPair rn) + !!ir (elem dest (e + h) p.ESize := addPair rm) + !!ir (rd := dest) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vrshr (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! then 1 else 2 let extend = if isUnsigned ins.SIMDTyp then AST.zext else AST.sext - let roundConst = AST.num1 64 << (imm .- AST.num1 64) - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + | 128 -> + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + let imm = AST.zext 64 (transOprToExpr ins ctxt imm) + let roundConst = AST.num1 64 << (imm .- AST.num1 64) + for e in 0 .. p.Elements - 1 do + let result1 = (extend 64 (elem srcB e p.ESize) .+ roundConst) >> imm + let result2 = (extend 64 (elem srcA e p.ESize) .+ roundConst) >> imm + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize result1) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize result2) + | _ -> + let struct (dst, src, imm) = transThreeOprs ins ctxt + let imm = AST.zext 64 imm + let roundConst = AST.num1 64 << (imm .- AST.num1 64) for e in 0 .. p.Elements - 1 do - let result = (extend 64 (elem rm e p.ESize) .+ roundConst) >> imm - builder (elem src e p.ESize) .+ roundConst) >> imm + !!ir (elem dst e p.ESize := AST.xtlo p.RtESize result) + putEndLabel ctxt lblIgnore ir + !>ir insLen -let vshlImm (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vshlImm (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm, imm = transThreeOprs ins ctxt + ! then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + | 128 -> + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + let imm = AST.zext p.RtESize (transOprToExpr ins ctxt imm) + for e in 0 .. p.Elements - 1 do + !!ir (elem dstB e p.ESize := elem srcB e p.ESize << imm) + !!ir (elem dstA e p.ESize := elem srcA e p.ESize << imm) + | _ -> + let struct (dst, src, imm) = transThreeOprs ins ctxt + let imm = AST.zext p.RtESize imm for e in 0 .. p.Elements - 1 do - builder ir insLen -let vshlReg (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vshlReg (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm, rn = transThreeOprs ins ctxt + ! then 1 else 2 let extend = if isUnsigned ins.SIMDTyp then AST.zext else AST.sext - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + | 128 -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 for e in 0 .. p.Elements - 1 do - let shift = AST.sext 64 (AST.xtlo 8 (elem rn e p.ESize)) - let result = extend 64 (elem rm e p.ESize) << shift - builder (AST.xtlo 8 (elem src2B e p.ESize)) + let shift2 = AST.sext 64 (AST.xtlo 8 (elem src2A e p.ESize)) + let result1 = extend 64 (elem src1B e p.ESize) << shift1 + let result2 = extend 64 (elem src1A e p.ESize) << shift2 + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize result1) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize result2) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. p.Elements - 1 do + let shift = AST.sext 64 (AST.xtlo 8 (elem src2 e p.ESize)) + let result = extend 64 (elem src1 e p.ESize) << shift + !!ir (elem dst e p.ESize := AST.xtlo p.RtESize result) + putEndLabel ctxt lblIgnore ir + !>ir insLen -let vshl (ins: InsInfo) ctxt = +let vshl (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands (_, _, OprImm _) -> vshlImm ins ctxt - | ThreeOperands (_, _, OprSIMD _) -> vshlReg ins ctxt + | ThreeOperands (_, _, OprImm _) -> vshlImm ins insLen ctxt + | ThreeOperands (_, _, OprSIMD _) -> vshlReg ins insLen ctxt | _ -> raise InvalidOperandException -let vshr (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vshr (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm, imm = transThreeOprs ins ctxt + ! imm - let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 let extend = if isUnsigned ins.SIMDTyp then AST.zext else AST.sext - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + match ins.OprSize with + | 128 -> + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt dst + let imm = AST.zext 64 (transOprToExpr ins ctxt imm) + for e in 0 .. p.Elements - 1 do + let result1 = extend 64 (elem srcB e p.ESize) >> imm + let result2 = extend 64 (elem srcA e p.ESize) >> imm + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize result1) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize result2) + | _ -> + let struct (dst, src, imm) = transThreeOprs ins ctxt + let imm = AST.zext 64 imm for e in 0 .. p.Elements - 1 do - let result = extend 64 (elem rm e p.ESize) >> imm - builder (elem src e p.ESize) >> imm + !!ir (elem dst e p.ESize := AST.xtlo p.RtESize result) + putEndLabel ctxt lblIgnore ir + !>ir insLen let parseVectors = function | OneReg (Vector d) -> [ d ] @@ -3652,19 +4261,19 @@ let parseVectors = function | FourRegs (Vector d1, Vector d2, Vector d3, Vector d4) -> [ d1; d2; d3; d4 ] | _ -> raise InvalidOperandException -let parseOprOfVecTbl (ins: InsInfo) ctxt = +let parseOprOfVecTbl (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (OprSIMD (SFReg (Vector rd)), OprSIMD regs, OprSIMD (SFReg (Vector rm))) -> getRegVar ctxt rd, parseVectors regs, getRegVar ctxt rm | _ -> raise InvalidOperandException -let vecTbl (ins: InsInfo) ctxt isVtbl = - let builder = IRBuilder (16) +let vecTbl (ins: InsInfo) insLen ctxt isVtbl = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, list, rm = parseOprOfVecTbl ins ctxt + ! List.map (getRegVar ctxt) let length = List.length list let table = AST.concatArr (List.toArray vectors) |> AST.zext 256 @@ -3672,140 +4281,242 @@ let vecTbl (ins: InsInfo) ctxt isVtbl = let index = elem rm i 8 let cond = AST.lt index (numI32 (8 * length) 8) let e = if isVtbl then AST.num0 8 else elem rd i 8 - builder index 8) e) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder + !!ir (elem rd i 8 := AST.ite cond (elemForIR table 256 index 8) e) + putEndLabel ctxt lblIgnore ir + !>ir insLen let isImm = function | Num _ -> true | _ -> false -let vectorCompare (ins: InsInfo) ctxt cmp = - let builder = IRBuilder (8) +let vectorCompareImm (ins: InsInfo) insLen ctxt cmp = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, src1, src2 = transThreeOprs ins ctxt + ! then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let src1 = AST.extract src1 64 (r * 64) + let num0 = AST.num0 p.RtESize + match ins.OprSize with + | 128 -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 for e in 0 .. p.Elements - 1 do - let src2 = if isImm src2.E then AST.num0 p.RtESize - else elem (AST.extract src2 64 (r * 64)) e p.ESize - let t = cmp (elem src1 e p.ESize) src2 - builder + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. p.Elements - 1 do + let t = cmp (elem src1 e p.ESize) num0 + !!ir (elem dst e p.ESize := AST.ite t (ones p.RtESize) num0) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vectorCompareReg (ins: InsInfo) insLen ctxt cmp = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + for e in 0 .. p.Elements - 1 do + let t1 = cmp (elem src1B e p.ESize) (elem src2B e p.ESize) + let t2 = cmp (elem src1A e p.ESize) (elem src2A e p.ESize) + !!ir (elem dstB e p.ESize := AST.ite t1 (ones p.RtESize) num0) + !!ir (elem dstA e p.ESize := AST.ite t2 (ones p.RtESize) num0) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. p.Elements - 1 do + let t = cmp (elem src1 e p.ESize) (elem src2 e p.ESize) + !!ir (elem dst e p.ESize := AST.ite t (ones p.RtESize) num0) + putEndLabel ctxt lblIgnore ir + !>ir insLen let getCmp (ins: InsInfo) unsigned signed = if isUnsigned ins.SIMDTyp then unsigned else signed -let vceq ins ctxt = vectorCompare ins ctxt (==) -let vcge ins ctxt = vectorCompare ins ctxt (getCmp ins AST.ge AST.sge) -let vcgt ins ctxt = vectorCompare ins ctxt (getCmp ins AST.gt AST.sgt) -let vcle ins ctxt = vectorCompare ins ctxt (getCmp ins AST.le AST.sle) -let vclt ins ctxt = vectorCompare ins ctxt (getCmp ins AST.lt AST.slt) +let vceq (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (_, _, OprImm _) -> vectorCompareImm ins insLen ctxt (==) + | ThreeOperands (_, _, OprSIMD _) -> vectorCompareReg ins insLen ctxt (==) + | _ -> raise InvalidOperandException + +let vcge (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (_, _, OprImm _) -> vectorCompareImm ins insLen ctxt + (getCmp ins AST.ge AST.sge) + | ThreeOperands (_, _, OprSIMD _) -> vectorCompareReg ins insLen ctxt + (getCmp ins AST.ge AST.sge) + | _ -> raise InvalidOperandException -let vtst (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vcgt (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (_, _, OprImm _) -> vectorCompareImm ins insLen ctxt + (getCmp ins AST.gt AST.sgt) + | ThreeOperands (_, _, OprSIMD _) -> vectorCompareReg ins insLen ctxt + (getCmp ins AST.gt AST.sgt) + | _ -> raise InvalidOperandException + +let vcle (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (_, _, OprImm _) -> vectorCompareImm ins insLen ctxt + (getCmp ins AST.le AST.sle) + | ThreeOperands (_, _, OprSIMD _) -> vectorCompareReg ins insLen ctxt + (getCmp ins AST.le AST.sle) + | _ -> raise InvalidOperandException + +let vclt (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (_, _, OprImm _) -> vectorCompareImm ins insLen ctxt + (getCmp ins AST.lt AST.slt) + | ThreeOperands (_, _, OprSIMD _) -> vectorCompareReg ins insLen ctxt + (getCmp ins AST.lt AST.slt) + | _ -> raise InvalidOperandException + +let vtst (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt + ! then 1 else 2 - for r in 0 .. regs - 1 do - let rd = AST.extract rd 64 (r * 64) - let rn = AST.extract rn 64 (r * 64) - let rm = AST.extract rm 64 (r * 64) + let n0 = AST.num0 p.RtESize + let n1 = AST.num1 p.RtESize + match ins.OprSize with + | 128 -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + for e in 0 .. p.Elements - 1 do + let c = (elem src1B e p.ESize .& elem src2B e p.ESize) != n0 + let c2 = (elem src1A e p.ESize .& elem src2A e p.ESize) != n0 + !!ir (elem dstB e p.ESize := AST.ite c n1 n0) + !!ir (elem dstA e p.ESize := AST.ite c2 n1 n0) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt for e in 0 .. p.Elements - 1 do - let c = (elem rn e p.ESize .& elem rm e p.ESize) != AST.num0 p.RtESize - builder ir insLen -let vrshrn (ins: InsInfo) ctxt = - let builder = IRBuilder (8) +let vrshrn (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rm, imm = transThreeOprs ins ctxt + !> imm - builder then 1 else 2 - for r in 0 .. regs - 1 do - let reg expr = AST.extract expr 64 (r * 64) - builder then 1 else 2 - for r in 0 .. regs - 1 do - builder (r * 64) := AST.extract rd 64 (r * 64) .| imm) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vorr (ins: InsInfo) ctxt = + for e in 0 .. (elements / 2) - 1 do + let result1 = (elem srcB e (esize * 2) .+ roundConst) >> imm + let result2 = (elem srcA e (esize * 2) .+ roundConst) >> imm + !!ir (elem dst e esize := AST.xtlo rtEsz result1) + !!ir (elem dst e esize := AST.xtlo rtEsz result2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vorrReg (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + !!ir (dstB := src1B .| src2B) + !!ir (dstA := src1A .| src2A) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := src1 .| src2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vorrImm (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, imm) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let imm = + AST.concat (transOprToExpr ins ctxt imm) (transOprToExpr ins ctxt imm) + !!ir (dstB := dstB .| imm) + !!ir (dstA := dstA .| imm) + | _ -> + let struct (dst, imm) = transTwoOprs ins ctxt + let imm = AST.concat imm imm // FIXME: A8-975 + !!ir (dst := dst .| imm) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vorr (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands _ -> vorrReg ins ctxt - | TwoOperands _ -> vorrImm ins ctxt + | ThreeOperands _ -> vorrReg ins insLen ctxt + | TwoOperands _ -> vorrImm ins insLen ctxt | _ -> raise InvalidOperandException -let vornReg (ins: InsInfo) ctxt = - let builder = IRBuilder (8) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder - let rd, rn, rm = transThreeOprs ins ctxt - let regs = if TypeCheck.typeOf rd = 64 then 1 else 2 - for r in 0 .. regs - 1 do - let reg expr = AST.extract expr 64 (r * 64) - builder then 1 else 2 - for r in 0 .. regs - 1 do - builder (r * 64) := AST.extract rd 64 (r * 64) .| AST.not imm) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vorn (ins: InsInfo) ctxt = +let vornReg (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + !!ir (dstB := src1B .| (AST.not <| src2B)) + !!ir (dstA := src1A .| (AST.not <| src2A)) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + !!ir (dst := src1 .| (AST.not <| src2)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vornImm (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, imm) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let imm = + AST.concat (transOprToExpr ins ctxt imm) (transOprToExpr ins ctxt imm) + !!ir (dstB := dstB .| AST.not imm) + !!ir (dstA := dstA .| AST.not imm) + | _ -> + let struct (dst, imm) = transTwoOprs ins ctxt + let imm = AST.concat imm imm // FIXME: A8-975 + !!ir (dst := dst .| AST.not imm) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vorn (ins: InsInfo) insLen ctxt = match ins.Operands with - | ThreeOperands _ -> vornReg ins ctxt - | TwoOperands _ -> vornImm ins ctxt + | ThreeOperands _ -> vornReg ins insLen ctxt + | TwoOperands _ -> vornImm ins insLen ctxt | _ -> raise InvalidOperandException let parseDstList = function @@ -3834,10 +4545,9 @@ let getRnAndRm ctxt = function getRegVar ctxt rn, getRegVar ctxt rm |> Some | _ -> raise InvalidOperandException -let assignByEndian (ctxt: TranslationContext) dst src builder = +let assignByEndian (ctxt: TranslationContext) dst src ir = let isbig = ctxt.Endianness = Endian.Big - builder src else AST.xtlo 32 src) + !!ir (dst := if isbig then AST.xthi 32 src else AST.xtlo 32 src) let parseOprOfVecStAndLd ctxt (ins: InsInfo) = let rdList = parseDstList ins.Operands |> List.map (getRegVar ctxt) @@ -3850,705 +4560,997 @@ let updateRn (ins: InsInfo) rn (rm: Expr option) n (regIdx: bool option) = let incAddr addr n = addr .+ (numI32 n 32) -let vst1Multi (ins: InsInfo) ctxt = - let builder = IRBuilder (16) +let vst1Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (8 * regs) p.RegIndex) for r in 0 .. (regs - 1) do - for e in 0 .. (pInfo.Elements - 1) do - if pInfo.EBytes <> 8 then - let mem = AST.loadLE pInfo.RtESize addr - builder 8 then + let mem = AST.loadLE p.RtESize addr + !!ir (mem := elem rdList[r] e p.ESize) else let mem1 = AST.loadLE 32 addr let mem2 = AST.loadLE 32 (incAddr addr 4) - let reg = elem rdList[r] e pInfo.ESize - assignByEndian ctxt mem1 reg builder - assignByEndian ctxt mem2 reg builder - builder )) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vst1Single (ins: InsInfo) ctxt index = - let builder = IRBuilder (8) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + let reg = elem rdList[r] e p.ESize + assignByEndian ctxt mem1 reg ir + assignByEndian ctxt mem2 reg ir + !!ir (addr := addr .+ (numI32 p.EBytes 32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst1Single (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm p.EBytes p.RegIndex) + let mem = AST.loadLE p.RtESize addr + !!ir (mem := elem rd[0] (int32 index) p.ESize) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst1 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (OneReg (Scalar (_, Some index))), _) -> - vst1Single ins ctxt index + vst1Single ins insLen ctxt index | TwoOperands (OprSIMD (OneReg _), _) | TwoOperands (OprSIMD (TwoRegs _), _) | TwoOperands (OprSIMD (ThreeRegs _), _) - | TwoOperands (OprSIMD (FourRegs _), _) -> vst1Multi ins ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vst1Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vld1SingleOne (ins: InsInfo) ctxt index = - let builder = IRBuilder (8) +let vld1SingleOne (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm p.EBytes p.RegIndex) + let mem = AST.loadLE p.RtESize addr + !!ir (elem rd[0] (int32 index) p.ESize := mem) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld1SingleAll (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder AST.concatArr + let p = getParsingInfo ins + let addr = !+ir 32 + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm p.EBytes p.RegIndex) + let mem = AST.loadLE p.RtESize addr + let repElem = Array.replicate p.Elements mem |> AST.concatArr for r in 0 .. (List.length rdList - 1) do - builder ir insLen -let vld1Multi (ins: InsInfo) ctxt = - let builder = IRBuilder (16) +let vld1Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (8 * regs) p.RegIndex) for r in 0 .. (regs - 1) do - for e in 0 .. (pInfo.Elements - 1) do - if pInfo.EBytes <> 8 then - let data = builder.NewTempVar pInfo.RtESize - builder 8 then + let data = !+ir p.RtESize + !!ir (data := AST.loadLE p.RtESize addr) + !!ir (elem rdList[r] e p.ESize := data) else - let data1 = builder.NewTempVar 32 - let data2 = builder.NewTempVar 32 + let struct (data1, data2) = tmpVars2 ir 32 let mem1 = AST.loadLE 32 addr let mem2 = AST.loadLE 32 (addr .+ (numI32 4 32)) let isbig = ctxt.Endianness = Endian.Big - builder ir insLen + +let vld1 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (OneReg (Scalar (_, Some index))), _) -> - vld1SingleOne ins ctxt index + vld1SingleOne ins insLen ctxt index | TwoOperands (OprSIMD (OneReg (Scalar _)), _) | TwoOperands (OprSIMD (TwoRegs (Scalar _, Scalar _)), _) -> - vld1SingleAll ins ctxt + vld1SingleAll ins insLen ctxt | TwoOperands (OprSIMD (OneReg _), _) | TwoOperands (OprSIMD (TwoRegs _), _) | TwoOperands (OprSIMD (ThreeRegs _), _) - | TwoOperands (OprSIMD (FourRegs _), _) -> vld1Multi ins ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vld1Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vst2Multi (ins: InsInfo) ctxt = - let builder = IRBuilder (16) +let vst2Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (16 * regs) p.RegIndex) for r in 0 .. (regs - 1) do let rd1 = rdList[r * 2] let rd2 = rdList[r * 2 + 1] - for e in 0 .. (pInfo.Elements - 1) do - let mem1 = AST.loadLE pInfo.RtESize addr - let mem2 = AST.loadLE pInfo.RtESize (addr .+ (numI32 pInfo.EBytes 32)) - builder )) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vst2Single (ins: InsInfo) ctxt index = - let builder = IRBuilder (8) - let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + for e in 0 .. (p.Elements - 1) do + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (addr .+ (numI32 p.EBytes 32)) + !!ir (mem1 := elem rd1 e p.ESize) + !!ir (mem2 := elem rd2 e p.ESize) + !!ir (addr := addr .+ (numI32 (2 * p.EBytes) 32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst2Single (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder )) - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (16 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (addr .+ (numI32 p.EBytes 32)) + !!ir (mem1 := elem rdList[0] index p.ESize) + !!ir (mem2 := elem rdList[1] index p.ESize) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst2 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (TwoRegs (Scalar (_, Some index), _)), _) -> - vst2Single ins ctxt (int32 index) + vst2Single ins insLen ctxt (int32 index) | TwoOperands (OprSIMD (OneReg _), _) | TwoOperands (OprSIMD (TwoRegs _), _) | TwoOperands (OprSIMD (ThreeRegs _), _) - | TwoOperands (OprSIMD (FourRegs _), _) -> vst2Multi ins ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vst2Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vst3Multi (ins: InsInfo) ctxt = - let builder = IRBuilder (16) +let vst3Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm 24 p.RegIndex) + for e in 0 .. (p.Elements - 1) do + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + !!ir (mem1 := elem rdList[0] e p.ESize) + !!ir (mem2 := elem rdList[1] e p.ESize) + !!ir (mem3 := elem rdList[2] e p.ESize) + !!ir (addr := incAddr addr (3 * p.EBytes)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst3Single (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (3 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + !!ir (mem1 := elem rdList[0] index p.ESize) + !!ir (mem2 := elem rdList[1] index p.ESize) + !!ir (mem3 := elem rdList[2] index p.ESize) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst3 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (ThreeRegs (Scalar (_, Some index), _, _)), _) -> - vst3Single ins ctxt (int32 index) + vst3Single ins insLen ctxt (int32 index) | TwoOperands (OprSIMD (OneReg _), _) | TwoOperands (OprSIMD (TwoRegs _), _) | TwoOperands (OprSIMD (ThreeRegs _), _) - | TwoOperands (OprSIMD (FourRegs _), _) -> vst3Multi ins ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vst3Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vst4Multi (ins: InsInfo) ctxt = - let builder = IRBuilder (16) +let vst4Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm 32 p.RegIndex) + for e in 0 .. (p.Elements - 1) do + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + let mem4 = AST.loadLE p.RtESize (incAddr addr (3 * p.EBytes)) + !!ir (mem1 := elem rdList[0] e p.ESize) + !!ir (mem2 := elem rdList[1] e p.ESize) + !!ir (mem3 := elem rdList[2] e p.ESize) + !!ir (mem4 := elem rdList[3] e p.ESize) + !!ir (addr := incAddr addr (4 * p.EBytes)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst4Single (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (4 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + let mem4 = AST.loadLE p.RtESize (incAddr addr (3 * p.EBytes)) + !!ir (mem1 := elem rdList[0] index p.ESize) + !!ir (mem2 := elem rdList[1] index p.ESize) + !!ir (mem3 := elem rdList[2] index p.ESize) + !!ir (mem4 := elem rdList[3] index p.ESize) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vst4 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (FourRegs (Scalar (_, Some index), _, _, _)), _) -> - vst4Single ins ctxt (int32 index) + vst4Single ins insLen ctxt (int32 index) | TwoOperands (OprSIMD (OneReg _), _) | TwoOperands (OprSIMD (TwoRegs _), _) | TwoOperands (OprSIMD (ThreeRegs _), _) - | TwoOperands (OprSIMD (FourRegs _), _) -> vst4Multi ins ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vst4Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vld2SingleOne (ins: InsInfo) ctxt index = - let builder = IRBuilder (8) +let vld2SingleOne (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (2 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + !!ir (elem rdList[0] (int32 index) p.ESize := mem1) + !!ir (elem rdList[1] (int32 index) p.ESize := mem2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld2SingleAll (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder AST.concatArr - let repElem2 = Array.replicate pInfo.Elements mem2 |> AST.concatArr - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (2 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let repElem1 = Array.replicate p.Elements mem1 |> AST.concatArr + let repElem2 = Array.replicate p.Elements mem2 |> AST.concatArr + !!ir (rdList[0] := repElem1) + !!ir (rdList[1] := repElem2) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld2Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (16 * regs) p.RegIndex) for r in 0 .. (regs - 1) do let rd1 = rdList[r * 2] let rd2 = rdList[r * 2 + 1] - for e in 0 .. (pInfo.Elements - 1) do - let mem1 = AST.loadLE pInfo.RtESize addr - let mem2 = AST.loadLE pInfo.RtESize (incAddr addr pInfo.EBytes) - builder ir insLen + +let vld2 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (TwoRegs (Scalar (_, Some index), _)), _) -> - vld2SingleOne ins ctxt index + vld2SingleOne ins insLen ctxt index | TwoOperands (OprSIMD (TwoRegs (Scalar _, Scalar _)), _) -> - vld2SingleAll ins ctxt + vld2SingleAll ins insLen ctxt | TwoOperands (OprSIMD (TwoRegs _), _) - | TwoOperands (OprSIMD (FourRegs _), _) -> vld2Multi ins ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vld2Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vld3SingleOne (ins: InsInfo) ctxt index = - let builder = IRBuilder (8) +let vld3SingleOne (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (3 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + !!ir (elem rdList[0] (int32 index) p.ESize := mem1) + !!ir (elem rdList[1] (int32 index) p.ESize := mem2) + !!ir (elem rdList[2] (int32 index) p.ESize := mem3) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld3SingleAll (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder AST.concatArr - let repElem2 = Array.replicate pInfo.Elements mem2 |> AST.concatArr - let repElem3 = Array.replicate pInfo.Elements mem3 |> AST.concatArr - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (3 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + let repElem1 = Array.replicate p.Elements mem1 |> AST.concatArr + let repElem2 = Array.replicate p.Elements mem2 |> AST.concatArr + let repElem3 = Array.replicate p.Elements mem3 |> AST.concatArr + !!ir (rdList[0] := repElem1) + !!ir (rdList[1] := repElem2) + !!ir (rdList[2] := repElem3) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld3Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder )) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vld3 (ins: InsInfo) ctxt = + let p = getParsingInfo ins + let addr = !+ir 32 + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm 24 p.RegIndex) + for e in 0 .. (p.Elements - 1) do + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + !!ir (elem rdList[0] e p.ESize := mem1) + !!ir (elem rdList[1] e p.ESize := mem2) + !!ir (elem rdList[2] e p.ESize := mem3) + !!ir (addr := addr .+ (numI32 (3 * p.EBytes) 32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld3 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (ThreeRegs (Scalar (_, Some index), _, _)), _) -> - vld3SingleOne ins ctxt index + vld3SingleOne ins insLen ctxt index | TwoOperands (OprSIMD (ThreeRegs (Scalar (_, None), _, _)), _) -> - vld3SingleAll ins ctxt - | TwoOperands (OprSIMD (ThreeRegs _), _) -> vld3Multi ins ctxt + vld3SingleAll ins insLen ctxt + | TwoOperands (OprSIMD (ThreeRegs _), _) -> vld3Multi ins insLen ctxt | _ -> raise InvalidOperandException -let vld4SingleOne (ins: InsInfo) ctxt index = - let builder = IRBuilder (8) +let vld4SingleOne (ins: InsInfo) insLen ctxt index = + let ir = !*ctxt let isUnconditional = ParseUtils.isUnconditional ins.Condition - startMark ins builder - let lblIgnore = checkCondition ins ctxt isUnconditional builder + ! - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (4 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + let mem4 = AST.loadLE p.RtESize (incAddr addr (3 * p.EBytes)) + !!ir (elem rdList[0] (int32 index) p.ESize := mem1) + !!ir (elem rdList[1] (int32 index) p.ESize := mem2) + !!ir (elem rdList[2] (int32 index) p.ESize := mem3) + !!ir (elem rdList[3] (int32 index) p.ESize := mem4) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld4SingleAll (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder AST.concatArr - let repElem2 = Array.replicate pInfo.Elements mem2 |> AST.concatArr - let repElem3 = Array.replicate pInfo.Elements mem3 |> AST.concatArr - let repElem4 = Array.replicate pInfo.Elements mem4 |> AST.concatArr - builder + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm (4 * p.EBytes) p.RegIndex) + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + let mem4 = AST.loadLE p.RtESize (incAddr addr (3 * p.EBytes)) + let repElem1 = Array.replicate p.Elements mem1 |> AST.concatArr + let repElem2 = Array.replicate p.Elements mem2 |> AST.concatArr + let repElem3 = Array.replicate p.Elements mem3 |> AST.concatArr + let repElem4 = Array.replicate p.Elements mem4 |> AST.concatArr + !!ir (rdList[0] := repElem1) + !!ir (rdList[1] := repElem2) + !!ir (rdList[2] := repElem3) + !!ir (rdList[3] := repElem4) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld4Multi (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! - builder )) - putEndLabel ctxt lblIgnore isUnconditional None builder - endMark ins builder - -let vld4 (ins: InsInfo) ctxt = + let p = getParsingInfo ins + let addr = !+ir 32 + !!ir (addr := rn) + !!ir (rn := updateRn ins rn rm 24 p.RegIndex) + for e in 0 .. (p.Elements - 1) do + let mem1 = AST.loadLE p.RtESize addr + let mem2 = AST.loadLE p.RtESize (incAddr addr p.EBytes) + let mem3 = AST.loadLE p.RtESize (incAddr addr (2 * p.EBytes)) + let mem4 = AST.loadLE p.RtESize (incAddr addr (3 * p.EBytes)) + !!ir (elem rdList[0] e p.ESize := mem1) + !!ir (elem rdList[1] e p.ESize := mem2) + !!ir (elem rdList[2] e p.ESize := mem3) + !!ir (elem rdList[3] e p.ESize := mem4) + !!ir (addr := addr .+ (numI32 (4 * p.EBytes) 32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vld4 (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (OprSIMD (FourRegs (Scalar (_, Some index), _, _, _)), _) -> - vld4SingleOne ins ctxt index + vld4SingleOne ins insLen ctxt index | TwoOperands (OprSIMD (FourRegs (Scalar (_, None), _, _, _)), _) -> - vld4SingleAll ins ctxt - | TwoOperands (OprSIMD (FourRegs _), _) -> vld4Multi ins ctxt + vld4SingleAll ins insLen ctxt + | TwoOperands (OprSIMD (FourRegs _), _) -> vld4Multi ins insLen ctxt | _ -> raise InvalidOperandException -let udf (ins: InsInfo) = +let udf (ins: InsInfo) insLen ctxt = match ins.Operands with - | OneOperand (OprImm n) -> sideEffects ins (Interrupt (int n)) + | OneOperand (OprImm n) -> sideEffects insLen ctxt (Interrupt (int n)) | _ -> raise InvalidOperandException +let uasx (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let xtlo src = AST.xtlo 16 src |> AST.zext 32 + let xthi src = AST.xthi 16 src |> AST.zext 32 + let struct (ge10, ge32) = tmpVars2 ir 32 + let numI32 n = numI32 n 32 + !!ir (diff := xtlo src1 .- xthi src2) + !!ir (sum := xthi src1 .+ xtlo src2) + !!ir (dst := AST.concat (AST.xtlo 16 sum) (AST.xtlo 16 diff)) + !!ir (ge10 := AST.ite (diff .>= numI32 0) (numI32 0xC0000) (numI32 0)) + !!ir (ge32 := AST.ite (sum .>= numI32 0x10000) (numI32 0x30000) (numI32 0)) + !!ir (cpsr := (cpsr .& (numI32 0xFFF0FFFF)) .| (ge32 .| ge10)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let uhsub16 (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let xtlo src = AST.xtlo 16 src |> AST.zext 32 + let xthi src = AST.xthi 16 src |> AST.zext 32 + let n1 = AST.num1 32 + !!ir (diff1 := xtlo src1 .- xtlo src2) + !!ir (diff2 := xthi src1 .- xthi src2) + !!ir (dst := + AST.concat (AST.xtlo 16 (diff2 >> n1)) (AST.xtlo 16 (diff1 >> n1))) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let uqsax (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let xtlo src = AST.xtlo 16 src |> AST.zext 32 + let xthi src = AST.xthi 16 src |> AST.zext 32 + !!ir (sum := xtlo src1 .+ xthi src2) + !!ir (diff := xthi src1 .- xtlo src2) + !!ir (dst := AST.concat (AST.xtlo 16 diff) (AST.xtlo 16 sum)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let usax (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let xtlo src = AST.xtlo 16 src |> AST.zext 32 + let xthi src = AST.xthi 16 src |> AST.zext 32 + let struct (ge10, ge32) = tmpVars2 ir 32 + let numI32 n = numI32 n 32 + !!ir (sum := xtlo src1 .+ xthi src2) + !!ir (diff := xthi src1 .- xtlo src2) + !!ir (dst := AST.concat (AST.xtlo 16 diff) (AST.xtlo 16 sum)) + !!ir (ge10 := AST.ite (sum .>= numI32 0x10000) (numI32 0x30000) (numI32 0)) + !!ir (ge32 := AST.ite (diff .>= numI32 0) (numI32 0xC0000) (numI32 0)) + !!ir (cpsr := (cpsr .& (numI32 0xFFF0FFFF)) .| (ge10 .| ge32)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vext (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let leftAmt = numI64 (64L - ((8L * imm) % 64L)) 64 + match ins.OprSize with + | 128 -> + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + let struct (tSrc1B, tSrc1A, tSrc2B, tSrc2A) = tmpVars4 ir 64 + !!ir (tSrc1A := src1A) + !!ir (tSrc1B := src1B) + !!ir (tSrc2A := src2A) + !!ir (tSrc2B := src2B) + if 8L * imm < 64 then + !!ir (dstA := (tSrc1B << leftAmt) .| (tSrc1A >> rightAmt)) + !!ir (dstB := (tSrc2A << leftAmt) .| (tSrc1B >> rightAmt)) + else + !!ir (dstA := (tSrc2A << leftAmt) .| (tSrc1B >> rightAmt)) + !!ir (dstB := (tSrc2B << leftAmt) .| (tSrc2A >> rightAmt)) + | _ -> + let struct (dst, src1, src2, _imm) = transFourOprs ins ctxt + let struct (tSrc2, tSrc1) = tmpVars2 ir 64 + !!ir (tSrc1 := src1) + !!ir (tSrc2 := src2) + !!ir (dst := (tSrc2 << leftAmt) .| (tSrc1 >> rightAmt)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vhaddsub (ins: InsInfo) insLen ctxt opFn = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + let struct (op1B, op2B, op1A, op2A) = tmpVars4 ir p.RtESize + for e in 0 .. p.Elements - 1 do + !!ir (op1B := elem src1B e p.ESize) + !!ir (op2B := elem src2B e p.ESize) + !!ir (op1A := elem src1A e p.ESize) + !!ir (op2A := elem src2A e p.ESize) + !!ir (elem dstB e p.ESize := (opFn op1B op2B) >> (AST.num1 p.RtESize)) + !!ir (elem dstA e p.ESize := (opFn op1A op2A) >> (AST.num1 p.RtESize)) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let struct (op1, op2) = tmpVars2 ir p.RtESize + for e in 0 .. p.Elements - 1 do + !!ir (op1 := elem src1 e p.ESize) + !!ir (op2 := elem src2 e p.ESize) + !!ir (elem dst e p.ESize := (opFn op1 op2) >> (AST.num1 p.RtESize)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vrhadd (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let src1B, src1A = transOprToExpr128 ctxt src1 + let src2B, src2A = transOprToExpr128 ctxt src2 + for e in 0 .. (64 / p.ESize) - 1 do + !!ir (op1 := elem src1B e p.ESize .+ elem src2B e p.ESize .+ n1) + !!ir (op2 := elem src1A e p.ESize .+ elem src2A e p.ESize .+ n1) + !!ir (elem dstB e p.ESize := AST.xtlo p.RtESize (op1 >> n1)) + !!ir (elem dstA e p.ESize := AST.xtlo p.RtESize (op2 >> n1)) + | _ -> + let struct (dst, src1, src2) = transThreeOprs ins ctxt + for e in 0 .. (64 / p.ESize) - 1 do + !!ir (op1 := elem src1 e p.ESize) + !!ir (op2 := elem src2 e p.ESize) + let result = op1 .+ op2 .+ n1 + !!ir (elem dst e p.ESize := AST.xtlo p.RtESize (result >> n1)) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vsra (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! -> + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + let imm = transOprToExpr ins ctxt imm + !!ir (shfAmt := if p.RtESize = 64 then AST.zext p.RtESize imm + else AST.xtlo p.RtESize imm) + for e in 0 .. p.Elements - 1 do + !!ir (result1 := srcB >> shfAmt) + !!ir (result2 := srcA >> shfAmt) + !!ir (dstB := dstB .+ result1) + !!ir (dstA := dstA .+ result2) + | _ -> + let struct (dst, src, imm) = transThreeOprs ins ctxt + !!ir (shfAmt := if p.RtESize = 64 then AST.zext p.RtESize imm + else AST.xtlo p.RtESize imm) + for e in 0 .. p.Elements - 1 do + !!ir (result1 := src >> shfAmt) + !!ir (dst := dst .+ result1) + putEndLabel ctxt lblIgnore ir + !>ir insLen + +let vuzp (ins: InsInfo) insLen ctxt = + let ir = !*ctxt + let isUnconditional = ParseUtils.isUnconditional ins.Condition + ! + let elements = (p.Elements - 1) / 2 + match ins.OprSize with + | 128 -> + let struct (dst, src) = getTwoOprs ins + let dstB, dstA = transOprToExpr128 ctxt dst + let srcB, srcA = transOprToExpr128 ctxt src + if dstB = srcB && dstA = srcA then + !!ir (dstB := AST.undef 64 "UNKNOWN") + !!ir (dstA := AST.undef 64 "UNKNOWN") + !!ir (srcB := AST.undef 64 "UNKNOWN") + !!ir (srcA := AST.undef 64 "UNKNOWN") + else + !!ir (zip1B := srcB) + !!ir (zip1A := srcA) + !!ir (zip2B := dstB) + !!ir (zip2A := dstA) + for e in 0 .. elements do + let pos = e + p.Elements / 2 + !!ir (elem dstB pos p.ESize := elem zip1B (e * 2) p.ESize) + !!ir (elem srcB pos p.ESize := elem zip1B (e * 2 + 1) p.ESize) + !!ir (elem dstB e p.ESize := elem zip1A (e * 2) p.ESize) + !!ir (elem srcB e p.ESize := elem zip1A (e * 2 + 1) p.ESize) + !!ir (elem dstA pos p.ESize := elem zip2B (e * 2) p.ESize) + !!ir (elem srcA pos p.ESize := elem zip2B (e * 2 + 1) p.ESize) + !!ir (elem dstA e p.ESize := elem zip2A (e * 2) p.ESize) + !!ir (elem srcA e p.ESize := elem zip2A (e * 2 + 1) p.ESize) + | _ -> + let struct (dst, src) = transTwoOprs ins ctxt + if dst = src then + !!ir (dst := AST.undef ins.OprSize "UNKNOWN") + !!ir (src := AST.undef ins.OprSize "UNKNOWN") + else + !!ir (zip1B := src) + !!ir (zip1A := dst) + for e in 0 .. elements do + let pos = e + p.Elements / 2 + !!ir (elem dst e p.ESize := elem zip1B (e * 2) p.ESize) + !!ir (elem src e p.ESize := elem zip1B (e * 2 + 1) p.ESize) + !!ir (elem dst pos p.ESize := elem zip1A (e * 2) p.ESize) + !!ir (elem src pos p.ESize := elem zip1A (e * 2 + 1) p.ESize) + putEndLabel ctxt lblIgnore ir + !>ir insLen + /// Translate IR. -let translate (ins: InsInfo) ctxt = +let translate (ins: ARM32InternalInstruction) insLen ctxt = match ins.Opcode with - | Op.ADC -> adc false ins ctxt - | Op.ADCS -> adcs true ins ctxt - | Op.ADD | Op.ADDW -> add false ins ctxt - | Op.ADDS -> adds true ins ctxt - | Op.BL -> bl ins ctxt - | Op.BLX -> branchWithLink ins ctxt - | Op.BKPT -> sideEffects ins Breakpoint - | Op.PUSH -> push ins ctxt - | Op.SUB | Op.SUBW -> sub false ins ctxt - | Op.SUBS -> subs true ins ctxt - | Op.AND -> logicalAnd false ins ctxt - | Op.ANDS -> ands true ins ctxt - | Op.MOV | Op.MOVW -> mov false ins ctxt - | Op.MOVS -> movs true ins ctxt - | Op.EOR -> eor false ins ctxt - | Op.EORS -> eors true ins ctxt - | Op.RSB -> rsb false ins ctxt - | Op.RSBS -> rsbs true ins ctxt - | Op.SBC -> sbc false ins ctxt - | Op.SBCS -> sbcs true ins ctxt - | Op.RSC -> rsc false ins ctxt - | Op.RSCS -> rscs true ins ctxt - | Op.ORR -> orr false ins ctxt - | Op.ORRS -> orrs true ins ctxt - | Op.ORN -> orn false ins ctxt - | Op.ORNS -> orns true ins ctxt - | Op.BIC -> bic false ins ctxt - | Op.BICS -> bics true ins ctxt - | Op.MVN -> mvn false ins ctxt - | Op.MVNS -> mvns true ins ctxt - | Op.ASR -> shiftInstr false ins SRTypeASR ctxt - | Op.ASRS -> asrs true ins ctxt - | Op.LSL -> shiftInstr false ins SRTypeLSL ctxt - | Op.LSLS -> lsls true ins ctxt - | Op.LSR -> shiftInstr false ins SRTypeLSR ctxt - | Op.LSRS -> lsrs true ins ctxt - | Op.ROR -> shiftInstr false ins SRTypeROR ctxt - | Op.RORS -> rors true ins ctxt - | Op.RRX -> shiftInstr false ins SRTypeRRX ctxt - | Op.RRXS -> rrxs true ins ctxt - | Op.CLZ -> clz ins ctxt - | Op.CMN -> cmn ins ctxt - | Op.MLA -> mla false ins ctxt - | Op.MLAS -> mla true ins ctxt - | Op.CMP -> cmp ins ctxt - | Op.UMLAL -> umlal false ins ctxt - | Op.UMLALS -> umlal true ins ctxt - | Op.UMULL -> umull false ins ctxt - | Op.UMULLS -> umull true ins ctxt - | Op.TEQ -> teq ins ctxt - | Op.MUL -> mul false ins ctxt - | Op.MULS -> mul true ins ctxt - | Op.TST -> tst ins ctxt - | Op.SMULBB -> smulhalf ins ctxt false false - | Op.SMULBT -> smulhalf ins ctxt false true - | Op.SMULTB -> smulhalf ins ctxt true false - | Op.SMULTT -> smulhalf ins ctxt true true - | Op.SMULL -> smulandacc false false ins ctxt - | Op.SMULLS -> smulandacc true false ins ctxt - | Op.SMLAL -> smulandacc false true ins ctxt - | Op.SMLALS -> smulandacc true true ins ctxt - | Op.SMLABB -> smulacchalf ins ctxt false false - | Op.SMLABT -> smulacchalf ins ctxt false true - | Op.SMLATB -> smulacchalf ins ctxt true false - | Op.SMLATT -> smulacchalf ins ctxt true true - | Op.B -> b ins ctxt - | Op.BX -> bx ins ctxt - | Op.IT | Op.ITT | Op.ITE | Op.ITTT | Op.ITET | Op.ITTE - | Op.ITEE | Op.ITTTT | Op.ITETT | Op.ITTET | Op.ITEET - | Op.ITTTE | Op.ITETE | Op.ITTEE | Op.ITEEE -> it ins ctxt - | Op.NOP -> nop ins - | Op.MOVT -> movt ins ctxt - | Op.POP -> pop ins ctxt - | Op.LDM -> ldm Op.LDM ins ctxt (.+) - | Op.LDMIA -> ldm Op.LDMIA ins ctxt (.+) - | Op.LDMIB -> ldm Op.LDMIB ins ctxt (.+) - | Op.LDMDA -> ldm Op.LDMDA ins ctxt (.-) - | Op.LDMDB -> ldm Op.LDMDB ins ctxt (.-) - | Op.LDR -> ldr ins ctxt 32 AST.zext - | Op.LDRB -> ldr ins ctxt 8 AST.zext - | Op.LDRSB -> ldr ins ctxt 8 AST.sext - | Op.LDRD -> ldrd ins ctxt - | Op.LDRH -> ldr ins ctxt 16 AST.zext - | Op.LDRSH -> ldr ins ctxt 16 AST.sext - | Op.LDREX -> ldr ins ctxt 32 AST.zext - | Op.SEL -> sel ins ctxt - | Op.RBIT -> rbit ins ctxt - | Op.REV -> rev ins ctxt - | Op.STR -> str ins ctxt 32 - | Op.STREX -> strex ins ctxt - | Op.STRB -> str ins ctxt 8 - | Op.STRD -> strd ins ctxt - | Op.STRH -> str ins ctxt 16 - | Op.STM -> stm Op.STM ins ctxt (.+) - | Op.STMIA -> stm Op.STMIA ins ctxt (.+) - | Op.STMEA -> stm Op.STMIA ins ctxt (.+) - | Op.STMDA -> stm Op.STMDA ins ctxt (.-) - | Op.STMDB -> stm Op.STMDB ins ctxt (.-) - | Op.STMIB -> stm Op.STMIB ins ctxt (.+) - | Op.SVC -> svc ins ctxt + | Op.ADC -> adc false ins insLen ctxt + | Op.ADCS -> adcs true ins insLen ctxt + | Op.ADD | Op.ADDW -> add false ins insLen ctxt + | Op.ADDS -> adds true ins insLen ctxt + | Op.ADR -> adr ins insLen ctxt // for Thumb mode + | Op.AND -> logicalAnd false ins insLen ctxt + | Op.ANDS -> ands true ins insLen ctxt + | Op.ASR -> shiftInstr false ins insLen SRTypeASR ctxt + | Op.ASRS -> asrs true ins insLen ctxt + | Op.B -> b ins insLen ctxt + | Op.BFC -> bfc ins insLen ctxt + | Op.BFI -> bfi ins insLen ctxt + | Op.BIC -> bic false ins insLen ctxt + | Op.BICS -> bics true ins insLen ctxt + | Op.BKPT -> sideEffects insLen ctxt Breakpoint + | Op.BL -> bl ins insLen ctxt + | Op.BLX -> branchWithLink ins insLen ctxt + | Op.BX -> bx ins insLen ctxt + | Op.BXJ -> bx ins insLen ctxt + | Op.CBNZ -> cbz true ins insLen ctxt + | Op.CBZ -> cbz false ins insLen ctxt | Op.CDP | Op.CDP2 | Op.LDC | Op.LDC2 | Op.LDC2L | Op.LDCL | Op.MCR | Op.MCR2 - | Op.MCRR | Op.MCRR2 | Op.MRC | Op.MRC2 | Op.MRRC | Op.MRRC2 - | Op.STC | Op.STC2 | Op.STC2L | Op.STCL -> - sideEffects ins UnsupportedExtension (* coprocessor instructions *) - | Op.CBNZ -> cbz true ins ctxt - | Op.CBZ -> cbz false ins ctxt - | Op.TBH | Op.TBB -> tableBranch ins ctxt - | Op.BFC -> bfc ins ctxt - | Op.BFI -> bfi ins ctxt - | Op.UDF -> udf ins - | Op.UADD8 -> uadd8 ins ctxt - | Op.UXTAB -> extendAndAdd ins ctxt 8 - | Op.UXTAH -> extendAndAdd ins ctxt 16 - | Op.SBFX -> bfx ins ctxt true - | Op.UBFX -> bfx ins ctxt false - | Op.UQADD8 -> uqopr ins ctxt 8 (.+) - | Op.UQADD16 -> uqopr ins ctxt 16 (.+) - | Op.UQSUB8 -> uqopr ins ctxt 8 (.-) - | Op.UQSUB16 -> uqopr ins ctxt 16 (.-) - | Op.ADR -> adr ins ctxt // for Thumb mode - | Op.MLS -> mls ins ctxt - | Op.UXTB -> extend ins ctxt AST.zext 8 - | Op.SXTB -> extend ins ctxt AST.sext 8 - | Op.UXTH -> extend ins ctxt AST.zext 16 - | Op.SXTH -> extend ins ctxt AST.sext 16 - | Op.VLDR -> vldr ins ctxt - | Op.VSTR -> vstr ins ctxt - | Op.VPOP -> vpop ins ctxt - | Op.VPUSH -> vpush ins ctxt - | Op.VAND -> vand ins ctxt - | Op.VMRS -> vmrs ins ctxt - | Op.VMOV when Operators.not (isAdvancedSIMD ins) -> - sideEffects ins UnsupportedFP - | Op.VMOV -> vmov ins ctxt - | Op.VST1 -> vst1 ins ctxt - | Op.VLD1 -> vld1 ins ctxt - | Op.VABS when isF32orF64 ins.SIMDTyp -> sideEffects ins UnsupportedFP - | Op.VABS -> vabs ins ctxt - | Op.VADD when isF32orF64 ins.SIMDTyp -> sideEffects ins UnsupportedFP - | Op.VADD -> vadd ins ctxt - | Op.VDUP -> vdup ins ctxt - | Op.VCLZ -> vclz ins ctxt + | Op.MCRR | Op.MCRR2 | Op.MRC | Op.MRC2 | Op.MRRC | Op.MRRC2 | Op.STC + | Op.STC2 | Op.STC2L | Op.STCL -> + sideEffects insLen ctxt UnsupportedExtension (* coprocessor instructions *) + | Op.CLZ -> clz ins insLen ctxt + | Op.CMN -> cmn ins insLen ctxt + | Op.CMP -> cmp ins insLen ctxt + | Op.DMB | Op.DSB | Op.ISB | Op.PLD -> nop insLen ctxt + | Op.EOR -> eor false ins insLen ctxt + | Op.EORS -> eors true ins insLen ctxt + | Op.ERET -> sideEffects insLen ctxt UnsupportedExtension + | Op.IT | Op.ITT | Op.ITE | Op.ITTT | Op.ITET | Op.ITTE | Op.ITEE | Op.ITTTT + | Op.ITETT | Op.ITTET | Op.ITEET | Op.ITTTE | Op.ITETE | Op.ITTEE + | Op.ITEEE -> it ins insLen ctxt + | Op.LDM -> ldm Op.LDM ins insLen ctxt (.+) + | Op.LDMDA -> ldm Op.LDMDA ins insLen ctxt (.-) + | Op.LDMDB -> ldm Op.LDMDB ins insLen ctxt (.-) + | Op.LDMIA -> ldm Op.LDMIA ins insLen ctxt (.+) + | Op.LDMIB -> ldm Op.LDMIB ins insLen ctxt (.+) + | Op.LDR -> ldr ins insLen ctxt 32 AST.zext + | Op.LDRB -> ldr ins insLen ctxt 8 AST.zext + | Op.LDRBT -> ldr ins insLen ctxt 8 AST.zext + | Op.LDRD -> ldrd ins insLen ctxt + | Op.LDREX -> ldr ins insLen ctxt 32 AST.zext + | Op.LDRH -> ldr ins insLen ctxt 16 AST.zext + | Op.LDRHT -> ldr ins insLen ctxt 16 AST.zext + | Op.LDRSB -> ldr ins insLen ctxt 8 AST.sext + | Op.LDRSBT -> ldr ins insLen ctxt 8 AST.sext + | Op.LDRSH -> ldr ins insLen ctxt 16 AST.sext + | Op.LDRSHT -> ldr ins insLen ctxt 16 AST.sext + | Op.LDRT -> ldr ins insLen ctxt 32 AST.zext + | Op.LSL -> shiftInstr false ins insLen SRTypeLSL ctxt + | Op.LSLS -> lsls true ins insLen ctxt + | Op.LSR -> shiftInstr false ins insLen SRTypeLSR ctxt + | Op.LSRS -> lsrs true ins insLen ctxt + | Op.MLA -> mla false ins insLen ctxt + | Op.MLAS -> mla true ins insLen ctxt + | Op.MLS -> mls ins insLen ctxt + | Op.MOV | Op.MOVW -> mov false ins insLen ctxt + | Op.MOVS -> movs true ins insLen ctxt + | Op.MOVT -> movt ins insLen ctxt + | Op.MSR | Op.MRS -> sideEffects insLen ctxt UndefinedInstr + | Op.MUL -> mul false ins insLen ctxt + | Op.MULS -> mul true ins insLen ctxt + | Op.MVN -> mvn false ins insLen ctxt + | Op.MVNS -> mvns true ins insLen ctxt + | Op.NOP -> nop insLen ctxt + | Op.ORN -> orn false ins insLen ctxt + | Op.ORNS -> orns true ins insLen ctxt + | Op.ORR -> orr false ins insLen ctxt + | Op.ORRS -> orrs true ins insLen ctxt + | Op.PKHBT -> pkh ins insLen ctxt false + | Op.PKHTB -> pkh ins insLen ctxt true + | Op.POP -> pop ins insLen ctxt + | Op.PUSH -> push ins insLen ctxt + | Op.QDADD -> qdadd ins insLen ctxt + | Op.QDSUB -> qdsub ins insLen ctxt + | Op.QSAX -> qsax ins insLen ctxt + | Op.QSUB16 -> qsub16 ins insLen ctxt + | Op.RBIT -> rbit ins insLen ctxt + | Op.REV -> rev ins insLen ctxt + | Op.REV16 -> rev16 ins insLen ctxt + | Op.REVSH -> revsh ins insLen ctxt + | Op.RFEDB -> rfedb ins insLen ctxt + | Op.ROR -> shiftInstr false ins insLen SRTypeROR ctxt + | Op.RORS -> rors true ins insLen ctxt + | Op.RRX -> shiftInstr false ins insLen SRTypeRRX ctxt + | Op.RRXS -> rrxs true ins insLen ctxt + | Op.RSB -> rsb false ins insLen ctxt + | Op.RSBS -> rsbs true ins insLen ctxt + | Op.RSC -> rsc false ins insLen ctxt + | Op.RSCS -> rscs true ins insLen ctxt + | Op.SBC -> sbc false ins insLen ctxt + | Op.SBCS -> sbcs true ins insLen ctxt + | Op.SBFX -> bfx ins insLen ctxt true + | Op.SEL -> sel ins insLen ctxt + | Op.SMLABB -> smulacchalf ins insLen ctxt false false + | Op.SMLABT -> smulacchalf ins insLen ctxt false true + | Op.SMLAL -> smulandacc false true ins insLen ctxt + | Op.SMLALS -> smulandacc true true ins insLen ctxt + | Op.SMLATB -> smulacchalf ins insLen ctxt true false + | Op.SMLATT -> smulacchalf ins insLen ctxt true true + | Op.SMLALBT -> smulacclonghalf ins insLen ctxt false true + | Op.SMLALTT -> smulacclonghalf ins insLen ctxt true true + | Op.SMLALD -> smulacclongdual ins insLen ctxt false + | Op.SMLALDX -> smulacclongdual ins insLen ctxt true + | Op.SMLAWB -> smulaccwordbyhalf ins insLen ctxt false + | Op.SMLAWT -> smulaccwordbyhalf ins insLen ctxt true + | Op.SMMLA -> smmla ins insLen ctxt false + | Op.SMMLAR -> smmla ins insLen ctxt true + | Op.SMMUL -> smmul ins insLen ctxt false + | Op.SMMULR -> smmul ins insLen ctxt true + | Op.SMULBB -> smulhalf ins insLen ctxt false false + | Op.SMULBT -> smulhalf ins insLen ctxt false true + | Op.SMULL -> smulandacc false false ins insLen ctxt + | Op.SMULLS -> smulandacc true false ins insLen ctxt + | Op.SMULTB -> smulhalf ins insLen ctxt true false + | Op.SMULTT -> smulhalf ins insLen ctxt true true + | Op.STM -> stm Op.STM ins insLen ctxt (.+) + | Op.STMDA -> stm Op.STMDA ins insLen ctxt (.-) + | Op.STMDB -> stm Op.STMDB ins insLen ctxt (.-) + | Op.STMEA -> stm Op.STMIA ins insLen ctxt (.+) + | Op.STMIA -> stm Op.STMIA ins insLen ctxt (.+) + | Op.STMIB -> stm Op.STMIB ins insLen ctxt (.+) + | Op.STR -> str ins insLen ctxt 32 + | Op.STRB -> str ins insLen ctxt 8 + | Op.STRBT -> str ins insLen ctxt 8 + | Op.STRD -> strd ins insLen ctxt + | Op.STREX -> strex ins insLen ctxt + | Op.STRH -> str ins insLen ctxt 16 + | Op.STRHT -> str ins insLen ctxt 16 + | Op.STRT -> str ins insLen ctxt 32 + | Op.SUB | Op.SUBW -> sub false ins insLen ctxt + | Op.SUBS -> subs true ins insLen ctxt + | Op.SVC -> svc ins insLen ctxt + | Op.SXTB -> extend ins insLen ctxt AST.sext 8 + | Op.SXTH -> extend ins insLen ctxt AST.sext 16 + | Op.TBH | Op.TBB -> tableBranch ins insLen ctxt + | Op.TEQ -> teq ins insLen ctxt + | Op.TST -> tst ins insLen ctxt + | Op.UADD8 -> uadd8 ins insLen ctxt + | Op.UASX -> uasx ins insLen ctxt + | Op.UBFX -> bfx ins insLen ctxt false + | Op.UDF -> udf ins insLen ctxt + | Op.UHSUB16 -> uhsub16 ins insLen ctxt + | Op.UMAAL -> umaal ins insLen ctxt + | Op.UMLAL -> umlal false ins insLen ctxt + | Op.UMLALS -> umlal true ins insLen ctxt + | Op.UMULL -> umull false ins insLen ctxt + | Op.UMULLS -> umull true ins insLen ctxt + | Op.UQADD16 -> uqopr ins insLen ctxt 16 (.+) + | Op.UQADD8 -> uqopr ins insLen ctxt 8 (.+) + | Op.UQSAX -> uqsax ins insLen ctxt + | Op.UQSUB16 -> uqopr ins insLen ctxt 16 (.-) + | Op.UQSUB8 -> uqopr ins insLen ctxt 8 (.-) + | Op.USAX -> usax ins insLen ctxt + | Op.UXTAB -> extendAndAdd ins insLen ctxt 8 + | Op.UXTAH -> extendAndAdd ins insLen ctxt 16 + | Op.UXTB -> extend ins insLen ctxt AST.zext 8 + | Op.UXTB16 -> uxtb16 ins insLen ctxt + | Op.UXTH -> extend ins insLen ctxt AST.zext 16 + | Op.VABS when isF16orF32orF64 ins.SIMDTyp -> + sideEffects insLen ctxt UnsupportedFP + | Op.VABS -> vabs ins insLen ctxt + | Op.VADD when isF16orF32orF64 ins.SIMDTyp -> vaddsub ins insLen ctxt AST.fadd + | Op.VADD -> vaddsub ins insLen ctxt (.+) + | Op.VADDL -> vaddl ins insLen ctxt + | Op.VAND -> vand ins insLen ctxt + | Op.VCEQ | Op.VCGE | Op.VCGT | Op.VCLE | Op.VCLT + when isF32orF64 ins.SIMDTyp -> sideEffects insLen ctxt UnsupportedFP + | Op.VCEQ -> vceq ins insLen ctxt + | Op.VCGE -> vcge ins insLen ctxt + | Op.VCGT -> vcgt ins insLen ctxt + | Op.VCLE -> vcle ins insLen ctxt + | Op.VCLT -> vclt ins insLen ctxt + | Op.VCLZ -> vclz ins insLen ctxt + | Op.VCMLA -> sideEffects insLen ctxt UnsupportedFP + | Op.VCMP | Op.VCMPE | Op.VACGE | Op.VACGT | Op.VACLE | Op.VACLT | Op.VCVTR + | Op.VFMA | Op.VFMS | Op.VFNMA | Op.VFNMS | Op.VMSR | Op.VNMLA | Op.VNMLS + | Op.VNMUL | Op.VSQRT -> sideEffects insLen ctxt UnsupportedFP + | Op.VCVT -> vcvt ins insLen ctxt + | Op.VDIV -> vdiv ins insLen ctxt + | Op.VDUP -> vdup ins insLen ctxt + | Op.VEXT -> vext ins insLen ctxt + | Op.VHADD -> vhaddsub ins insLen ctxt (.+) + | Op.VHSUB -> vhaddsub ins insLen ctxt (.-) + | Op.VLD1 -> vld1 ins insLen ctxt + | Op.VLD2 -> vld2 ins insLen ctxt + | Op.VLD3 -> vld3 ins insLen ctxt + | Op.VLD4 -> vld4 ins insLen ctxt + | Op.VLDM | Op.VLDMIA | Op.VLDMDB -> vldm ins insLen ctxt + | Op.VLDR -> vldr ins insLen ctxt | Op.VMAX | Op.VMIN when isF32orF64 ins.SIMDTyp -> - sideEffects ins UnsupportedFP - | Op.VMAX -> vmaxmin ins ctxt true - | Op.VMIN -> vmaxmin ins ctxt false - | Op.VSUB when isF32orF64 ins.SIMDTyp -> sideEffects ins UnsupportedFP - | Op.VSUB -> vsub ins ctxt - | Op.VSTM | Op.VSTMIA | Op.VSTMDB -> vstm ins ctxt - | Op.VLDM | Op.VLDMIA | Op.VLDMDB -> vldm ins ctxt - | Op.VMLA | Op.VMLS when isF32orF64 ins.SIMDTyp -> - sideEffects ins UnsupportedFP - | Op.VMLA -> vmla ins ctxt - | Op.VMLAL -> vmlal ins ctxt - | Op.VMLS -> vmls ins ctxt - | Op.VMLSL -> vmlsl ins ctxt - | Op.VMUL | Op.VMULL when isF32orF64 ins.SIMDTyp -> - sideEffects ins UnsupportedFP - | Op.VMUL -> vmul ins ctxt - | Op.VMULL -> vmull ins ctxt - | Op.VMOVN -> vmovn ins ctxt - | Op.VNEG when isF32orF64 ins.SIMDTyp -> sideEffects ins UnsupportedFP - | Op.VNEG -> vneg ins ctxt + sideEffects insLen ctxt UnsupportedFP + | Op.VMAX -> vmaxmin ins insLen ctxt true + | Op.VMIN -> vmaxmin ins insLen ctxt false + | Op.VMLA | Op.VMLS when isF16orF32orF64 ins.SIMDTyp -> + sideEffects insLen ctxt UnsupportedFP + | Op.VMLA -> vmla ins insLen ctxt + | Op.VMLAL -> vmlal ins insLen ctxt + | Op.VMLS -> vmls ins insLen ctxt + | Op.VMLSL -> vmlsl ins insLen ctxt + | Op.VMOV when isF16orF32orF64 ins.SIMDTyp -> vmovfp ins insLen ctxt + | Op.VMOV -> vmov ins insLen ctxt + | Op.VMOVN -> vmovn ins insLen ctxt + | Op.VMRS -> vmrs ins insLen ctxt + | Op.VMUL when isF16orF32orF64 ins.SIMDTyp -> vmul ins insLen ctxt AST.fmul + | Op.VMUL -> vmul ins insLen ctxt (.*) + | Op.VMULL -> vmull ins insLen ctxt + | Op.VNEG when isF32orF64 ins.SIMDTyp -> + sideEffects insLen ctxt UnsupportedFP + | Op.VNEG -> vneg ins insLen ctxt + | Op.VORN -> vorn ins insLen ctxt + | Op.VORR -> vorr ins insLen ctxt | Op.VPADD when isF32orF64 ins.SIMDTyp -> - sideEffects ins UnsupportedFP - | Op.VPADD -> vpadd ins ctxt - | Op.VRSHR -> vrshr ins ctxt - | Op.VSHL -> vshl ins ctxt - | Op.VSHR -> vshr ins ctxt - | Op.VTBL -> vecTbl ins ctxt true - | Op.VTBX -> vecTbl ins ctxt false - | Op.VCMP | Op.VCMPE | Op.VACGE | Op.VACGT | Op.VACLE | Op.VACLT | Op.VCVT - | Op.VCVTR | Op.VDIV | Op.VFMA | Op.VFMS | Op.VFNMA | Op.VFNMS | Op.VMSR - | Op.VNMLA | Op.VNMLS | Op.VNMUL | Op.VSQRT -> - sideEffects ins UnsupportedFP - | Op.VCEQ | Op.VCGE | Op.VCGT | Op.VCLE | Op.VCLT - when isF32orF64 ins.SIMDTyp -> sideEffects ins UnsupportedFP - | Op.VCEQ -> vceq ins ctxt - | Op.VCGE -> vcge ins ctxt - | Op.VCGT -> vcgt ins ctxt - | Op.VCLE -> vcle ins ctxt - | Op.VCLT -> vclt ins ctxt - | Op.VTST -> vtst ins ctxt - | Op.VRSHRN -> vrshrn ins ctxt - | Op.VORR -> vorr ins ctxt - | Op.VORN -> vorn ins ctxt - | Op.VST2 -> vst2 ins ctxt - | Op.VST3 -> vst3 ins ctxt - | Op.VST4 -> vst4 ins ctxt - | Op.VLD2 -> vld2 ins ctxt - | Op.VLD3 -> vld3 ins ctxt - | Op.VLD4 -> vld4 ins ctxt - | Op.DMB | Op.DSB | Op.ISB | Op.PLD -> nop ins + sideEffects insLen ctxt UnsupportedFP + | Op.VPADD -> vpadd ins insLen ctxt + | Op.VPOP -> vpop ins insLen ctxt + | Op.VPUSH -> vpush ins insLen ctxt + | Op.VRHADD -> vrhadd ins insLen ctxt + | Op.VRINTP -> sideEffects insLen ctxt UnsupportedFP + | Op.VRSHR -> vrshr ins insLen ctxt + | Op.VRSHRN -> vrshrn ins insLen ctxt + | Op.VSHL -> vshl ins insLen ctxt + | Op.VSHR -> vshr ins insLen ctxt + | Op.VSRA -> vsra ins insLen ctxt + | Op.VST1 -> vst1 ins insLen ctxt + | Op.VST2 -> vst2 ins insLen ctxt + | Op.VST3 -> vst3 ins insLen ctxt + | Op.VST4 -> vst4 ins insLen ctxt + | Op.VSTM | Op.VSTMIA | Op.VSTMDB -> vstm ins insLen ctxt + | Op.VSTR -> vstr ins insLen ctxt + | Op.VSUB when isF16orF32orF64 ins.SIMDTyp -> vaddsub ins insLen ctxt AST.fsub + | Op.VSUB -> vaddsub ins insLen ctxt (.-) + | Op.VTBL -> vecTbl ins insLen ctxt true + | Op.VTBX -> vecTbl ins insLen ctxt false + | Op.VTST -> vtst ins insLen ctxt + | Op.VUZP -> vuzp ins insLen ctxt | Op.InvalidOP -> raise InvalidOpcodeException | o -> #if DEBUG diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs b/src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs index bb660a0d..3b8754aa 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32OperandHelper.fs @@ -64,6 +64,7 @@ let inline checkUnpred cond = if cond then raise UnpredictableException else () let inline checkUndef cond = if cond then raise UndefinedException else () let oneDt dt = Some (OneDT dt) + let twoDt (dt1, dt2) = Some (TwoDT (dt1, dt2)) let getSign s = if s = 1u then Plus else Minus @@ -74,13 +75,14 @@ let getEndian = function let getRegister n: Register = n |> int |> LanguagePrimitives.EnumOfValue -let getRegList b = - let rec loop acc = function - | n when n > 15 -> acc - | n when ((b >>> n) &&& 1u) <> 0u -> - loop (getRegister (uint32 n) :: acc) (n + 1) - | n -> loop acc (n + 1) - loop [] 0 |> List.rev +let rec private getRegListLoop acc b = function + | n when n > 15 -> acc + | n when ((b >>> n) &&& 1u) <> 0u -> + getRegListLoop (getRegister (uint32 n) :: acc) b (n + 1) + | n -> getRegListLoop acc b (n + 1) + +let inline getRegList b = + getRegListLoop [] b 0 |> List.rev (* SIMD vector register list *) let getSIMDVector rLst = diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32Operands.fs b/src/FrontEnd/BinLifter/ARM32/ARM32Operands.fs index c13c29ed..fd63a802 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32Operands.fs +++ b/src/FrontEnd/BinLifter/ARM32/ARM32Operands.fs @@ -410,21 +410,21 @@ module OperandParsingHelper = /// shared/functions/float/vfpexpandimm/VFPExpandImm on page J1-7900. let vfpExpandImm bin imm8 = let size = extract bin 9 8 (* size *) - let E = + let e = match size (* N *) with | 0b01u -> 5 | 0b10u -> 8 | 0b11u -> 11 | _ (* 00 *) -> raise UndefinedException - let F = (8 <<< (int size)) - E - 1 + let f = (8 <<< (int size)) - e - 1 let sign = pickBit imm8 7 |> int64 let exp = - let n = RegType.fromBitWidth (E - 3) - ((~~~ (pickBit imm8 6) &&& 0b1u) |> int64 <<< ((E - 3) + 2)) + + let n = RegType.fromBitWidth (e - 3) + ((~~~ (pickBit imm8 6) &&& 0b1u) |> int64 <<< ((e - 3) + 2)) + ((replicate (pickBit imm8 6 |> int64) 1 n) <<< 2) + ((extract imm8 5 4) |> int64) - let frac = (extract imm8 3 0) <<< (F - 4) |> int64 - (sign <<< (E + F)) + (exp <<< F) + frac + let frac = (extract imm8 3 0) <<< (f - 4) |> int64 + (sign <<< (e + f)) + (exp <<< f) + frac /// aarch32/functions/common/A32ExpandImm_C on page J1-7766. /// Modified immediate constants in A32 instructions on page F2-4136. @@ -436,7 +436,8 @@ module OperandParsingHelper = /// shared/functions/common/SignExtend on page J1-7849. let signExtend bitSize (bits: uint32) = - bits |> uint64 |> signExtend bitSize 32 |> System.Convert.ToInt64 |> memLabel + bits |> uint64 + |> signExtend bitSize 32 |> System.Convert.ToInt64 |> memLabel /// shared/functions/common/BitCount on page J1-7845. let bitCount bits len = @@ -500,7 +501,7 @@ module OperandParsingHelper = let isSign = pickBit bin 24 (* U *) = 0u match concat (pickBit bin 7) (extract bin 21 19) 3 (* L:imm6<5:3> *) with | 0b0000u -> raise ParsingFailureException - | 0b0001u -> if isSign then SIMDTypS8 else SIMDTypU16 + | 0b0001u -> if isSign then SIMDTypS8 else SIMDTypU8 | 0b0010u | 0b0011u -> if isSign then SIMDTypS16 else SIMDTypU16 | 0b0100u | 0b0101u | 0b0110u | 0b0111u -> if isSign then SIMDTypS32 else SIMDTypU32 @@ -584,6 +585,19 @@ module OperandParsingHelper = | _ (* 1xx *) -> SIMDTypS64 |> oneDt + let getDTPolyA b = + (* op:U:size *) + match (pickBit b 9 <<< 3) + (pickBit b 24 <<< 2) + (extract b 21 20) with + | 0b0000u -> SIMDTypS8 + | 0b0001u -> SIMDTypS16 + | 0b0010u -> SIMDTypS32 + | 0b0100u -> SIMDTypU8 + | 0b0101u -> SIMDTypU16 + | 0b0110u -> SIMDTypU32 + | 0b1000u -> SIMDTypP8 + | 0b1010u -> SIMDTypP64 + | _ -> raise UndefinedException + /// Operand functions let getBankedReg r sysM = match concat r sysM 5 with @@ -733,8 +747,8 @@ module OperandParsingHelper = | None -> Condition.AL /// aarch32/functions/common/T32ExpandImm_C on page J1-7767. - // T32ExpandImm_C() - // ================ + /// T32ExpandImm_C() + /// ================ /// Modified immediate constants in A32 inOprInfoions on page F2-4135. let t32ExpandImm imm12 = (* _carryIn = *) if extract imm12 11 10 = 0b00u then @@ -753,10 +767,10 @@ module OperandParsingHelper = (* W == '1' *) let wbackW8 bin = pickBit bin 8 = 0b1u - (* S8 when U = 0, size = 00 + (* S8 when U = 0, size = 00 S16 when U = 0, size = 01 S32 when U = 0, size = 10 - U8 when U = 1, size = 00 + U8 when U = 1, size = 00 U16 when U = 1, size = 01 U32 when U = 1, size = 10 *) let getDtT bin = @@ -776,7 +790,7 @@ module OperandParsingHelper = | 0b10u -> SIMDTypU32 | _ -> raise UndefinedException - (* 8 when L = 0, imm6<5:3> = 001 + (* 8 when L = 0, imm6<5:3> = 001 16 when L = 0, imm6<5:3> = 01x 32 when L = 0, imm6<5:3> = 1xx 64 when L = 1, imm6<5:3> = xxx *) @@ -791,10 +805,10 @@ module OperandParsingHelper = | _ (* 1xxx *) -> if isSign then SIMDTypS64 else SIMDTypU64 |> oneDt - (* S8 when U = 0, imm3H = 001 + (* S8 when U = 0, imm3H = 001 S16 when U = 0, imm3H = 010 S32 when U = 0, imm3H = 100 - U8 when U = 1, imm3H = 001 + U8 when U = 1, imm3H = 001 U16 when U = 1, imm3H = 010 U32 when U = 1, imm3H = 100 *) let getDTUImm3hT bin = @@ -831,7 +845,7 @@ module OperandParsingHelper = | _ (* 1xx *) -> if isSign then SIMDTypS32 else SIMDTypU32 |> oneDt - let getDTPoly b = + let getDTPolyT b = (* op:U:size *) match (pickBit b 9 <<< 3) + (pickBit b 28 <<< 2) + (extract b 21 20) with | 0b0000u -> SIMDTypS8 @@ -929,44 +943,47 @@ module OperandParsingHelper = opcode, itState type [] OperandParser () = - abstract member Render: uint32 -> struct (Operands * bool * bool option) + abstract member Render: uint32 -> + struct (Operands * bool * bool option * RegType) -and ParsingHelper (arch, mode, rd, addr, oprs, len, cond) = - let isARMv7 = (arch = Arch.ARMv7) +and ParsingHelper (arch, mode, rd, addr, oprs, len, cond, isAdd) = + let isARMv7 = (arch = Architecture.ARMv7) let mutable mode: ArchOperationMode = mode let mutable addr: Addr = addr let mutable len: uint32 = len let mutable cond: Condition = cond + let mutable isAdd: bool = isAdd new (arch, reader, oparsers) = ParsingHelper (arch, ArchOperationMode.ARMMode, - reader, 0UL, oparsers, 0u, Condition.UN) - member __.Arch with get(): Arch = arch + reader, 0UL, oparsers, 0u, Condition.UN, true) + member __.Arch with get(): Architecture = arch member __.Mode with get() = mode and set (m) = mode <- m member __.BinReader with get(): IBinReader = rd member __.InsAddr with get() = addr and set(a) = addr <- a member __.OprParsers with get(): OperandParser [] = oprs member __.Len with get() = len and set (l) = len <- l member __.Cond with get() = cond and set (c) = cond <- c + member __.IsAdd with get() = isAdd and set (a) = isAdd <- a member __.IsARMv7 with get() = isARMv7 type internal OprNo () = inherit OperandParser () override __.Render _ = - struct (NoOperand, false, None) + struct (NoOperand, false, None, 0) (* {!} *) type internal OprRn () = inherit OperandParser () override __.Render bin = let rn = extract bin 19 16 |> getRegister |> OprReg - struct (OneOperand rn, wbackW bin, None) + struct (OneOperand rn, wbackW bin, None, 32) (* *) type internal OprRm () = inherit OperandParser () override __.Render bin = let rm = extract bin 3 0 |> getRegister |> OprReg - struct (OneOperand rm, false, None) + struct (OneOperand rm, false, None, 32) (* [ {, #{+/-}}] *) type internal OprMemImm () = @@ -976,13 +993,13 @@ type internal OprMemImm () = let imm12 = extract bin 11 0 |> int64 let rn = extract bin 19 16 |> getRegister let sign = pickBit bin 23 |> getSign |> Some - match concat (pickBit bin 24) (pickBit bin 21) 1 with + match pickTwoBitsApart bin 24 21 with | 0b10u -> memOffsetImm (rn, sign, Some imm12) - | 0b11u -> memPreIdxImm (rn, sign, Some imm12) + | 0b11u -> memPreIdxImm (rn, sign, Some imm12) | _ (* 0b0xu *) -> memPostIdxImm (rn, sign, Some imm12) - struct (OneOperand mem, false, None) + struct (OneOperand mem, false, None, 32) -(* [, {+/-} , RRX] *) +(* [, {+/-}, RRX] *) (* [, {+/-} {, #}] *) type internal OprMemRegA () = inherit OperandParser () @@ -995,32 +1012,34 @@ type internal OprMemRegA () = let shiftOffset = Some (shift, Imm imm) let sign = pickBit bin 23 |> getSign |> Some memOffsetReg (rn, sign, rm, shiftOffset) - struct (OneOperand mem, false, None) + struct (OneOperand mem, false, None, 32) (* {#} *) type internal OprImm16A () = inherit OperandParser () override __.Render bin = let imm = concat (extract bin 19 8) (extract bin 3 0) 4 |> int64 |> OprImm - struct (OneOperand imm, false, None) + struct (OneOperand imm, false, None, 32) (* {#} *) type internal OprImm24 () = inherit OperandParser () override __.Render bin = - struct (extract bin 23 0 |> int64 |> OprImm |> OneOperand, false, None) + let imm = extract bin 23 0 |> int64 |> OprImm |> OneOperand + struct (imm, false, None, 32) (* {#} *) type internal OprImm4A () = inherit OperandParser () override __.Render bin = - struct (extract bin 3 0 |> int64 |> OprImm |> OneOperand, false, None) + let imm = extract bin 3 0 |> int64 |> OprImm |> OneOperand + struct (imm, false, None, 32) (* # *) type internal OprImm1A () = inherit OperandParser () override __.Render bin = - struct (pickBit bin 9 |> int64 |> OprImm |> OneOperand, false, None) + struct (pickBit bin 9 |> int64 |> OprImm |> OneOperand, false, None, 32) (* [ {, #{+/-}}]
type Opcode = - /// Absolute value (vector and scalar form). + /// Absolute value. | ABS = 0 - /// Add with carry. + /// Add with Carry. | ADC = 1 - /// Add with carry and set flags. - | ADCS = 2 - /// Add. - | ADD = 3 - /// Add returning high, narrow (vector form). - | ADDHN = 4 - /// Add returning high, narrow (vector form). - | ADDHN2 = 5 - /// Add pairwise (vector and scalar form). - | ADDP = 6 - /// Add and set flags. - | ADDS = 7 - /// Add (across vector). - | ADDV = 8 - /// Compute address of label at a PC-relative offset. - | ADR = 9 - /// Compute address of 4KB page at a PC-relative offset. - | ADRP = 10 + /// Add with carry long (bottom). + | ADCLB = 2 + /// Add with carry long (top). + | ADCLT = 3 + /// Add with Carry, setting flags. + | ADCS = 4 + /// Add multi-vector to ZA array vector accumulators. + | ADD = 5 + /// Add with Tag. + | ADDG = 6 + /// Add horizontally vector elements to ZA tile. + | ADDHA = 7 + /// Add returning High Narrow. + | ADDHN = 8 + /// Add returning High Narrow. + | ADDHN2 = 9 + /// Add narrow high part (bottom). + | ADDHNB = 10 + /// Add narrow high part (top). + | ADDHNT = 11 + /// Add pairwise. + | ADDP = 12 + /// Add multiple of predicate register size to scalar register. + | ADDPL = 13 + /// Unsigned add reduction of quadword vector segments. + | ADDQV = 14 + /// Add (extended register), setting flags. + | ADDS = 15 + /// Add multiple of Streaming SVE predicate register size to scalar register. + | ADDSPL = 16 + /// Add multiple of Streaming SVE vector register size to scalar register. + | ADDSVL = 17 + /// Add across Vector. + | ADDV = 18 + /// Add vertically vector elements to ZA tile. + | ADDVA = 19 + /// Add multiple of vector register size to scalar register. + | ADDVL = 20 + /// Form PC-relative address. + | ADR = 21 + /// Form PC-relative address to 4KB page. + | ADRP = 22 /// AES single round decryption. - | AESD = 11 + | AESD = 23 /// AES single round encryption. - | AESE = 12 + | AESE = 24 /// AES inverse mix columns. - | AESIMC = 13 + | AESIMC = 25 /// AES mix columns. - | AESMC = 14 - /// Bitwise AND. - | AND = 15 - /// Bitwise AND and set flags. - | ANDS = 16 - /// Arithmetic shift right. - | ASR = 17 - /// Arithmetic shift right variable. - | ASRV = 18 - /// Branch unconditionally. - | B = 19 + | AESMC = 26 + /// Bitwise AND (immediate). + | AND = 27 + /// Bitwise AND reduction of quadword vector segments. + | ANDQV = 28 + /// Bitwise AND predicates, setting the condition flags. + | ANDS = 29 + /// Bitwise AND reduction to scalar. + | ANDV = 30 + /// Arithmetic Shift Right (immediate): an alias of SBFM. + | ASR = 31 + /// Arithmetic shift right for divide by immediate (predicated). + | ASRD = 32 + /// Reversed arithmetic shift right by vector (predicated). + | ASRR = 33 + /// Arithmetic Shift Right Variable. + | ASRV = 34 + /// Address Translate: an alias of SYS. + | AT = 35 + /// Authenticate Data address, using key A. + | AUTDA = 36 + /// Authenticate Data address, using key B. + | AUTDB = 37 + /// Authenticate Data address, using key A. + | AUTDZA = 38 + /// Authenticate Data address, using key B. + | AUTDZB = 39 + /// Authenticate Instruction address, using key A. + | AUTIA = 40 + /// Authenticate Instruction address, using key A. + | AUTIA1716 = 41 + /// Authenticate Instruction address, using key A. + | AUTIASP = 42 + /// Authenticate Instruction address, using key A. + | AUTIAZ = 43 + /// Authenticate Instruction address, using key B. + | AUTIB = 44 + /// Authenticate Instruction address, using key B. + | AUTIB1716 = 45 + /// Authenticate Instruction address, using key B. + | AUTIBSP = 46 + /// Authenticate Instruction address, using key B. + | AUTIBZ = 47 + /// Authenticate Instruction address, using key A. + | AUTIZA = 48 + /// Authenticate Instruction address, using key B. + | AUTIZB = 49 + /// Convert FP condition flags from Arm to external format. + | AXFLAG = 50 + /// Branch. + | B = 51 /// Branch conditionally (AL). - | BAL = 20 + | BAL = 52 + /// Branch Consistent conditionally. + | BC = 53 + /// Bit Clear and XOR. + | BCAX = 54 /// Branch conditionally (CC). - | BCC = 21 + | BCC = 55 /// Branch conditionally (CS). - | BCS = 22 + | BCS = 56 + /// Scatter lower bits into positions selected by bitmask. + | BDEP = 57 /// Branch conditionally (EQ). - | BEQ = 23 - /// Bitfield insert. - | BFI = 24 - // Bitfield move. - | BFM = 25 - /// Bitfield extract and insert low. - | BFXIL = 26 + | BEQ = 58 + /// Gather lower bits from positions selected by bitmask. + | BEXT = 59 + /// BFloat16 FP add multi-vector to ZA array vector accumulators. + | BFADD = 60 + /// Bitfield Clear: an alias of BFM. + | BFC = 61 + /// BFloat16 FP clamp to minimum/maximum number. + | BFCLAMP = 62 + /// FP convert from single-precision to BFloat16 format (scalar). + | BFCVT = 63 + /// FP convert from single-precision to BFloat16 format (vector). + | BFCVTN = 64 + /// FP convert from single-precision to BFloat16 format (vector). + | BFCVTN2 = 65 + /// FP down convert and narrow to BFloat16 (top, predicated). + | BFCVTNT = 66 + /// BFloat16 FP dot product (vector, by element). + | BFDOT = 67 + /// Bitfield Insert: an alias of BFM. + | BFI = 68 + /// Bitfield Move. + | BFM = 69 + /// BFloat16 FP maximum (predicated). + | BFMAX = 70 + /// BFloat16 FP maximum number (predicated). + | BFMAXNM = 71 + /// BFloat16 FP minimum (predicated). + | BFMIN = 72 + /// BFloat16 FP minimum number (predicated). + | BFMINNM = 73 + /// BFloat16 FP fused multiply-add vectors by indexed elements. + | BFMLA = 74 + /// Multi-vector BFloat16 FP multiply-add long by indexed element. + | BFMLAL = 75 + /// BFloat16 FP widening multiply-add long (by element). + | BFMLALB = 76 + /// BFloat16 FP widening multiply-add long (by element). + | BFMLALT = 77 + /// BFloat16 FP fused multiply-subtract vectors by indexed elements. + | BFMLS = 78 + /// Multi-vector BFloat16 FP multiply-subtract long by indexed element. + | BFMLSL = 79 + /// BFloat16 FP mul-subtract long from single-precision (bottom, indexed). + | BFMLSLB = 80 + /// BFloat16 FP multiply-subtract long from single-precision (top, indexed). + | BFMLSLT = 81 + /// BFloat16 FP matrix multiply-accumulate into 2x2 matrix. + | BFMMLA = 82 + /// BFloat16 FP outer product and accumulate. + | BFMOPA = 83 + /// BFloat16 FP outer product and subtract. + | BFMOPS = 84 + /// BFloat16 FP multiply vectors by indexed elements. + | BFMUL = 85 + /// BFloat16 FP subtract multi-vector from ZA array vector accumulators. + | BFSUB = 86 + /// Multi-vector BFloat16 FP vertical dot-product by indexed element. + | BFVDOT = 87 + /// Bitfield extract and insert at low end: an alias of BFM. + | BFXIL = 88 /// Branch conditionally (GE). - | BGE = 27 + | BGE = 89 + /// Group bits to right or left as selected by bitmask. + | BGRP = 90 /// Branch conditionally (GT). - | BGT = 28 + | BGT = 91 /// Branch conditionally (HI). - | BHI = 29 + | BHI = 92 /// Branch conditionally (HS). - | BHS = 30 - /// Bitwise bit clear. - | BIC = 31 - /// Bitwise bit clear and set flags. - | BICS = 32 - /// Bitwise insert if false (vector form). - | BIF = 33 - /// Bitwise insert if true (vector form). - | BIT = 34 - /// Branch with link. - | BL = 35 + | BHS = 93 + /// Bitwise clear bits using immediate (unpredicated): an alias of AND (imm). + | BIC = 94 + /// Bitwise clear predicates, setting the condition flags. + | BICS = 95 + /// Bitwise Insert if False. + | BIF = 96 + /// Bitwise Insert if True. + | BIT = 97 + /// Branch with Link. + | BL = 98 /// Branch conditionally (LE). - | BLE = 36 + | BLE = 99 /// Branch conditionally (LO). - | BLO = 37 - /// Branch with link to register. - | BLR = 38 + | BLO = 100 + /// Branch with Link to Register. + | BLR = 101 + /// Branch with Link to Register, with pointer authentication. + | BLRAA = 102 + /// Branch with Link to Register, with pointer authentication. + | BLRAAZ = 103 + /// Branch with Link to Register, with pointer authentication. + | BLRAB = 104 + /// Branch with Link to Register, with pointer authentication. + | BLRABZ = 105 /// Branch conditionally (LS). - | BLS = 39 + | BLS = 106 /// Branch conditionally (LT). - | BLT = 40 + | BLT = 107 /// Branch conditionally (MI). - | BMI = 41 + | BMI = 108 + /// Bitwise exclusive NOR population count outer product and accumulate. + | BMOPA = 109 + /// Bitwise exclusive NOR population count outer product and subtract. + | BMOPS = 110 /// Branch conditionally (NE). - | BNE = 42 + | BNE = 111 /// Branch conditionally (NV). - | BNV = 43 + | BNV = 112 /// Branch conditionally (PL). - | BPL = 44 - /// Branch to register. - | BR = 45 - /// Breakpoint Instruction. - | BRK = 46 - /// Bitwise select (vector form). - | BSL = 47 + | BPL = 113 + /// Branch to Register. + | BR = 114 + /// Branch to Register, with pointer authentication. + | BRAA = 115 + /// Branch to Register, with pointer authentication. + | BRAAZ = 116 + /// Branch to Register, with pointer authentication. + | BRAB = 117 + /// Branch to Register, with pointer authentication. + | BRABZ = 118 + /// Branch Record Buffer: an alias of SYS. + | BRB = 119 + /// Breakpoint instruction. + | BRK = 120 + /// Break after first true condition. + | BRKA = 121 + /// Break after first true condition, setting the condition flags. + | BRKAS = 122 + /// Break before first true condition. + | BRKB = 123 + /// Break before first true condition, setting the condition flags. + | BRKBS = 124 + /// Propagate break to next partition. + | BRKN = 125 + /// Propagate break to next partition, setting the condition flags. + | BRKNS = 126 + /// Break after first true condition, propagating from previous partition. + | BRKPA = 127 + /// Break after first true condition. + | BRKPAS = 128 + /// Break before first true condition, propagating from previous partition. + | BRKPB = 129 + /// Break before first true cond. + | BRKPBS = 130 + /// Bitwise Select. + | BSL = 131 + /// Bitwise select with first input inverted. + | BSL1N = 132 + /// Bitwise select with second input inverted. + | BSL2N = 133 + /// Branch Target Identification. + | BTI = 134 /// Branch conditionally (VC). - | BVC = 48 + | BVC = 135 /// Branch conditionally (VS). - | BVS = 49 - /// Compare and branch if nonzero. - | CBNZ = 50 - /// Compare and branch if zero. - | CBZ = 51 - /// Conditional compare negative (register or immediate). - | CCMN = 52 - /// Conditional compare (register or immediate). - | CCMP = 53 - /// Conditional increment. - | CINC = 54 - /// Conditional invert. - | CINV = 55 - /// Clear exclusive monitor. - | CLREX = 56 - /// Count leading sign bits. - | CLS = 57 - /// Count leading zero bits. - | CLZ = 58 - /// Compare bitwise equal (vector and scalar form). - | CMEQ = 59 - /// Compare signed greater than or equal (vector and scalar form). - | CMGE = 60 - /// Compare signed greater than (vector and scalar form). - | CMGT = 61 - /// Compare unsigned higher (vector and scalar form). - | CMHI = 62 - /// Compare unsigned higher or same (vector and scalar form). - | CMHS = 63 - /// Compare signed less than or equal to zero (vector and scalar form). - | CMLE = 64 - /// Compare signed less than zero (vector and scalar form). - | CMLT = 65 - /// Compare negative. - | CMN = 66 - /// Compare negative. - | CMP = 67 - /// Compare bitwise test bits nonzero (vector and scalar form). - | CMTST = 68 - /// Conditional negate. - | CNEG = 69 - /// Population count per byte (vector form). - | CNT = 70 - /// CRC-32 sum from byte. - | CRC32B = 71 - /// CRC-32C sum from byte. - | CRC32CB = 72 - /// CRC-32C sum from halfword. - | CRC32CH = 73 - /// CRC-32C sum from word. - | CRC32CW = 74 - /// CRC-32C sum from doubleword. - | CRC32CX = 75 - /// CRC-32 sum from halfword. - | CRC32H = 76 - /// CRC-32 sum from word. - | CRC32W = 77 - /// CRC-32 sum from doubleword. - | CRC32X = 78 - /// Conditional select. - | CSEL = 79 - /// Conditional set. - | CSET = 80 - /// Conditional set mask. - | CSETM = 81 - /// Conditional select increment. - | CSINC = 82 - /// Conditional select inversion. - | CSINV = 83 - /// Conditional select negation. - | CSNEG = 84 - /// Data cache maintenance - | DC = 85 + | BVS = 136 + /// Complex integer add with rotate. + | CADD = 137 + /// Compare and Swap word or doubleword in memory. + | CAS = 138 + /// Compare and Swap word or doubleword in memory. + | CASA = 139 + /// Compare and Swap byte in memory. + | CASAB = 140 + /// Compare and Swap halfword in memory. + | CASAH = 141 + /// Compare and Swap word or doubleword in memory. + | CASAL = 142 + /// Compare and Swap byte in memory. + | CASALB = 143 + /// Compare and Swap halfword in memory. + | CASALH = 144 + /// Compare and Swap byte in memory. + | CASB = 145 + /// Compare and Swap halfword in memory. + | CASH = 146 + /// Compare and Swap word or doubleword in memory. + | CASL = 147 + /// Compare and Swap byte in memory. + | CASLB = 148 + /// Compare and Swap halfword in memory. + | CASLH = 149 + /// Compare and Swap Pair of words or doublewords in memory. + | CASP = 150 + /// Compare and Swap Pair of words or doublewords in memory. + | CASPA = 151 + /// Compare and Swap Pair of words or doublewords in memory. + | CASPAL = 152 + /// Compare and Swap Pair of words or doublewords in memory. + | CASPL = 153 + /// Compare and Branch on Nonzero. + | CBNZ = 154 + /// Compare and Branch on Zero. + | CBZ = 155 + /// Conditional Compare Negative (immediate). + | CCMN = 156 + /// Conditional Compare (immediate). + | CCMP = 157 + /// Complex integer dot product (indexed). + | CDOT = 158 + /// Invert Carry Flag. + | CFINV = 159 + /// Control Flow Prediction Restriction by Context: an alias of SYS. + | CFP = 160 + /// Conditional Increment: an alias of CSINC. + | CINC = 161 + /// Conditional Invert: an alias of CSINV. + | CINV = 162 + /// Conditionally extract element after last to general-purpose register. + | CLASTA = 163 + /// Conditionally extract last element to general-purpose register. + | CLASTB = 164 + /// Clear Branch History. + | CLRBHB = 165 + /// Clear Exclusive. + | CLREX = 166 + /// Count Leading Sign bits. + | CLS = 167 + /// Count Leading Zeros. + | CLZ = 168 + /// Compare bitwise Equal (vector). + | CMEQ = 169 + /// Compare signed Greater than or Equal (vector). + | CMGE = 170 + /// Compare signed Greater than (vector). + | CMGT = 171 + /// Compare unsigned Higher (vector). + | CMHI = 172 + /// Compare unsigned Higher or Same (vector). + | CMHS = 173 + /// Complex integer multiply-add with rotate (indexed). + | CMLA = 174 + /// Compare signed Less than or Equal to zero (vector). + | CMLE = 175 + /// Compare signed Less than zero (vector). + | CMLT = 176 + /// Compare Negative (extended reg): an alias of ADDS (extended register). + | CMN = 177 + /// Compare (extended register): an alias of SUBS (extended register). + | CMP = 178 + /// Compare signed less than or equal to vector, setting the condition flags. + | CMPLE = 179 + /// Compare unsigned lower than vector, setting the condition flags. + | CMPLO = 180 + /// Compare unsigned lower or same as vector, setting the condition flags. + | CMPLS = 181 + /// Compare signed less than vector, setting the condition flags. + | CMPLT = 182 + /// Compare with Tag: an alias of SUBPS. + | CMPP = 183 + /// Compare bitwise Test bits nonzero (vector). + | CMTST = 184 + /// Conditional Negate: an alias of CSNEG. + | CNEG = 185 + /// Logically invert boolean condition in vector (predicated). + | CNOT = 186 + /// Count bits. + | CNT = 187 + /// Set scalar to multiple of predicate constraint element count. + | CNTB = 188 + /// Set scalar to multiple of predicate constraint element count. + | CNTD = 189 + /// Set scalar to multiple of predicate constraint element count. + | CNTH = 190 + /// Set scalar to count from predicate-as-counter. + | CNTP = 191 + /// Set scalar to multiple of predicate constraint element count. + | CNTW = 192 + /// Shuffle active elements of vector to the right and fill with zero. + | COMPACT = 193 + /// Clear Other Speculative Predictions by Context: an alias of SYS. + | COSP = 194 + /// Cache Prefetch Prediction Restriction by Context: an alias of SYS. + | CPP = 195 + /// Copy signed integer immediate to vector elements (merging). + | CPY = 196 + /// Memory Copy. + | CPYE = 197 + /// Memory Copy, reads and writes non-temporal. + | CPYEN = 198 + /// Memory Copy, reads non-temporal. + | CPYERN = 199 + /// Memory Copy, reads unprivileged. + | CPYERT = 200 + /// Memory Copy, reads unprivileged, reads and writes non-temporal. + | CPYERTN = 201 + /// Memory Copy, reads unprivileged and non-temporal. + | CPYERTRN = 202 + /// Memory Copy, reads unprivileged, writes non-temporal. + | CPYERTWN = 203 + /// Memory Copy, reads and writes unprivileged. + | CPYET = 204 + /// Memory Copy, reads and writes unprivileged and non-temporal. + | CPYETN = 205 + /// Memory Copy, reads and writes unprivileged, reads non-temporal. + | CPYETRN = 206 + /// Memory Copy, reads and writes unprivileged, writes non-temporal. + | CPYETWN = 207 + /// Memory Copy, writes non-temporal. + | CPYEWN = 208 + /// Memory Copy, writes unprivileged. + | CPYEWT = 209 + /// Memory Copy, writes unprivileged, reads and writes non-temporal. + | CPYEWTN = 210 + /// Memory Copy, writes unprivileged, reads non-temporal. + | CPYEWTRN = 211 + /// Memory Copy, writes unprivileged and non-temporal. + | CPYEWTWN = 212 + /// Memory Copy Forward-only. + | CPYFE = 213 + /// Memory Copy Forward-only, reads and writes non-temporal. + | CPYFEN = 214 + /// Memory Copy Forward-only, reads non-temporal. + | CPYFERN = 215 + /// Memory Copy Forward-only, reads unprivileged. + | CPYFERT = 216 + /// Memory Copy Forward-only, reads unpriv, reads and writes non-temporal. + | CPYFERTN = 217 + /// Memory Copy Forward-only, reads unprivileged and non-temporal. + | CPYFERTRN = 218 + /// Memory Copy Forward-only, reads unprivileged, writes non-temporal. + | CPYFERTWN = 219 + /// Memory Copy Forward-only, reads and writes unprivileged. + | CPYFET = 220 + /// Memory Copy Forward-only, reads and writes unprivileged and non-temporal. + | CPYFETN = 221 + /// Memory Copy Forward-only, reads and writes unpriv, reads non-temporal. + | CPYFETRN = 222 + /// Memory Copy Forward-only, reads and writes unpriv, writes non-temporal. + | CPYFETWN = 223 + /// Memory Copy Forward-only, writes non-temporal. + | CPYFEWN = 224 + /// Memory Copy Forward-only, writes unprivileged. + | CPYFEWT = 225 + /// Memory Copy Forward-only, writes unpriv, reads and writes non-temporal. + | CPYFEWTN = 226 + /// Memory Copy Forward-only, writes unprivileged, reads non-temporal. + | CPYFEWTRN = 227 + /// Memory Copy Forward-only, writes unprivileged and non-temporal. + | CPYFEWTWN = 228 + /// Memory Copy Forward-only. + | CPYFM = 229 + /// Memory Copy Forward-only, reads and writes non-temporal. + | CPYFMN = 230 + /// Memory Copy Forward-only, reads non-temporal. + | CPYFMRN = 231 + /// Memory Copy Forward-only, reads unprivileged. + | CPYFMRT = 232 + /// Memory Copy Forward-only, reads unpriv, reads and writes non-temporal. + | CPYFMRTN = 233 + /// Memory Copy Forward-only, reads unprivileged and non-temporal. + | CPYFMRTRN = 234 + /// Memory Copy Forward-only, reads unprivileged, writes non-temporal. + | CPYFMRTWN = 235 + /// Memory Copy Forward-only, reads and writes unprivileged. + | CPYFMT = 236 + /// Memory Copy Forward-only, reads and writes unprivileged and non-temporal. + | CPYFMTN = 237 + /// Memory Copy Forward-only, reads and writes unpriv, reads non-temporal. + | CPYFMTRN = 238 + /// Memory Copy Forward-only, reads and writes unpriv, writes non-temporal. + | CPYFMTWN = 239 + /// Memory Copy Forward-only, writes non-temporal. + | CPYFMWN = 240 + /// Memory Copy Forward-only, writes unprivileged. + | CPYFMWT = 241 + /// Memory Copy Forward-only, writes unpriv, reads and writes non-temporal. + | CPYFMWTN = 242 + /// Memory Copy Forward-only, writes unprivileged, reads non-temporal. + | CPYFMWTRN = 243 + /// Memory Copy Forward-only, writes unprivileged and non-temporal. + | CPYFMWTWN = 244 + /// Memory Copy Forward-only. + | CPYFP = 245 + /// Memory Copy Forward-only, reads and writes non-temporal. + | CPYFPN = 246 + /// Memory Copy Forward-only, reads non-temporal. + | CPYFPRN = 247 + /// Memory Copy Forward-only, reads unprivileged. + | CPYFPRT = 248 + /// Memory Copy Forward-only, reads unpriv, reads and writes non-temporal. + | CPYFPRTN = 249 + /// Memory Copy Forward-only, reads unprivileged and non-temporal. + | CPYFPRTRN = 250 + /// Memory Copy Forward-only, reads unprivileged, writes non-temporal. + | CPYFPRTWN = 251 + /// Memory Copy Forward-only, reads and writes unprivileged. + | CPYFPT = 252 + /// Memory Copy Forward-only, reads and writes unprivileged and non-temporal. + | CPYFPTN = 253 + /// Memory Copy Forward-only, reads and writes unpriv, reads non-temporal. + | CPYFPTRN = 254 + /// Memory Copy Forward-only, reads and writes unpriv, writes non-temporal. + | CPYFPTWN = 255 + /// Memory Copy Forward-only, writes non-temporal. + | CPYFPWN = 256 + /// Memory Copy Forward-only, writes unprivileged. + | CPYFPWT = 257 + /// Memory Copy Forward-only, writes unpriv, reads and writes non-temporal. + | CPYFPWTN = 258 + /// Memory Copy Forward-only, writes unprivileged, reads non-temporal. + | CPYFPWTRN = 259 + /// Memory Copy Forward-only, writes unprivileged and non-temporal. + | CPYFPWTWN = 260 + /// Memory Copy. + | CPYM = 261 + /// Memory Copy, reads and writes non-temporal. + | CPYMN = 262 + /// Memory Copy, reads non-temporal. + | CPYMRN = 263 + /// Memory Copy, reads unprivileged. + | CPYMRT = 264 + /// Memory Copy, reads unprivileged, reads and writes non-temporal. + | CPYMRTN = 265 + /// Memory Copy, reads unprivileged and non-temporal. + | CPYMRTRN = 266 + /// Memory Copy, reads unprivileged, writes non-temporal. + | CPYMRTWN = 267 + /// Memory Copy, reads and writes unprivileged. + | CPYMT = 268 + /// Memory Copy, reads and writes unprivileged and non-temporal. + | CPYMTN = 269 + /// Memory Copy, reads and writes unprivileged, reads non-temporal. + | CPYMTRN = 270 + /// Memory Copy, reads and writes unprivileged, writes non-temporal. + | CPYMTWN = 271 + /// Memory Copy, writes non-temporal. + | CPYMWN = 272 + /// Memory Copy, writes unprivileged. + | CPYMWT = 273 + /// Memory Copy, writes unprivileged, reads and writes non-temporal. + | CPYMWTN = 274 + /// Memory Copy, writes unprivileged, reads non-temporal. + | CPYMWTRN = 275 + /// Memory Copy, writes unprivileged and non-temporal. + | CPYMWTWN = 276 + /// Memory Copy. + | CPYP = 277 + /// Memory Copy, reads and writes non-temporal. + | CPYPN = 278 + /// Memory Copy, reads non-temporal. + | CPYPRN = 279 + /// Memory Copy, reads unprivileged. + | CPYPRT = 280 + /// Memory Copy, reads unprivileged, reads and writes non-temporal. + | CPYPRTN = 281 + /// Memory Copy, reads unprivileged and non-temporal. + | CPYPRTRN = 282 + /// Memory Copy, reads unprivileged, writes non-temporal. + | CPYPRTWN = 283 + /// Memory Copy, reads and writes unprivileged. + | CPYPT = 284 + /// Memory Copy, reads and writes unprivileged and non-temporal. + | CPYPTN = 285 + /// Memory Copy, reads and writes unprivileged, reads non-temporal. + | CPYPTRN = 286 + /// Memory Copy, reads and writes unprivileged, writes non-temporal. + | CPYPTWN = 287 + /// Memory Copy, writes non-temporal. + | CPYPWN = 288 + /// Memory Copy, writes unprivileged. + | CPYPWT = 289 + /// Memory Copy, writes unprivileged, reads and writes non-temporal. + | CPYPWTN = 290 + /// Memory Copy, writes unprivileged, reads non-temporal. + | CPYPWTRN = 291 + /// Memory Copy, writes unprivileged and non-temporal. + | CPYPWTWN = 292 + /// CRC32 checksum. + | CRC32B = 293 + /// CRC32C checksum. + | CRC32CB = 294 + /// CRC32C checksum. + | CRC32CH = 295 + /// CRC32C checksum. + | CRC32CW = 296 + /// CRC32C checksum. + | CRC32CX = 297 + /// CRC32 checksum. + | CRC32H = 298 + /// CRC32 checksum. + | CRC32W = 299 + /// CRC32 checksum. + | CRC32X = 300 + /// Consumption of Speculative Data Barrier. + | CSDB = 301 + /// Conditional Select. + | CSEL = 302 + /// Conditional Set: an alias of CSINC. + | CSET = 303 + /// Conditional Set Mask: an alias of CSINV. + | CSETM = 304 + /// Conditional Select Increment. + | CSINC = 305 + /// Conditional Select Invert. + | CSINV = 306 + /// Conditional Select Negation. + | CSNEG = 307 + /// Compare and terminate loop. + | CTERMEQ = 308 + /// Compare and terminate loop. + | CTERMNE = 309 + /// Count Trailing Zeros. + | CTZ = 310 + /// Data Cache operation: an alias of SYS. + | DC = 311 + /// Clean of Data and Allocation Tags by Set/Way. + | DCCGDSW = 312 + /// Clean of Data and Allocation Tags by VA to PoC. + | DCCGDVAC = 313 + /// Clean of Data and Allocation Tags by VA to PoDP. + | DCCGDVADP = 314 + /// Clean of Data and Allocation Tags by VA to PoP. + | DCCGDVAP = 315 + /// Clean of Allocation Tags by Set/Way. + | DCCGSW = 316 + /// Clean of Allocation Tags by VA to PoC. + | DCCGVAC = 317 + /// Clean of Allocation Tags by VA to PoDP. + | DCCGVADP = 318 + /// Clean of Allocation Tags by VA to PoP. + | DCCGVAP = 319 + /// Clean and Invalidate of Data and Allocation Tags by Set/Way. + | DCCIGDSW = 320 + /// Clean and Invalidate of Data and Allocation Tags by VA to PoC. + | DCCIGDVAC = 321 + /// Clean and Invalidate of Allocation Tags by Set/Way. + | DCCIGSW = 322 + /// Clean and Invalidate of Allocation Tags by VA to PoC. + | DCCIGVAC = 323 + /// Data or unified Cache line Clean and Invalidate by Set/Way. + | DCCISW = 324 + /// Data or unified Cache line Clean and Invalidate by VA to PoC. + | DCCIVAC = 325 + /// Data or unified Cache line Clean by Set/Way. + | DCCSW = 326 + /// Data or unified Cache line Clean by VA to PoC. + | DCCVAC = 327 + /// Data or unified Cache line Clean by VA to PoDP. + | DCCVADP = 328 + /// Data or unified Cache line Clean by VA to PoP. + | DCCVAP = 329 + /// Data or unified Cache line Clean by VA to PoU. + | DCCVAU = 330 + /// Data Cache set Allocation Tag by VA. + | DCGVA = 331 + /// Data Cache set Allocation Tags and Zero by VA. + | DCGZVA = 332 + /// Invalidate of Data and Allocation Tags by Set/Way. + | DCIGDSW = 333 + /// Invalidate of Data and Allocation Tags by VA to PoC. + | DCIGDVAC = 334 + /// Invalidate of Allocation Tags by Set/Way. + | DCIGSW = 335 + /// Invalidate of Allocation Tags by VA to PoC. + | DCIGVAC = 336 + /// Data or unified Cache line Invalidate by Set/Way. + | DCISW = 337 + /// Data or unified Cache line Invalidate by VA to PoC. + | DCIVAC = 338 /// Debug switch to Exception level 1. - | DCPS1 = 86 + | DCPS1 = 339 /// Debug switch to Exception level 2. - | DCPS2 = 87 + | DCPS2 = 340 /// Debug switch to Exception level 3. - | DCPS3 = 88 - /// Data memory barrier. - | DMB = 89 - /// Debug restore PE state. - | DRPS = 90 - /// Data synchronization barrier. - | DSB = 91 - /// Duplicate general-purpose register to vector. - | DUP = 92 - /// Bitwise exclusive OR NOT. - | EON = 93 - /// Bitwise exclusive OR. - | EOR = 94 - /// Exception return using current ELR and SPSR. - | ERET = 95 - /// Extract vector from a pair of vectors. - | EXT = 96 - /// Extract register from pair. - | EXTR = 97 - /// Floating-point absolute difference (vector and scalar form). - | FABD = 98 - /// Floating-point absolute (vector form). - | FABS = 99 - /// Floating-point absolute compare greater than or equal. - | FACGE = 100 - /// Floating-point absolute compare greater than (vector and scalar form). - | FACGT = 101 - /// Floating-point add (vector form). - | FADD = 102 - /// Floating-point add pairwise (vector and scalar form). - | FADDP = 103 - /// Floating-point conditional quiet compare. - | FCCMP = 104 - /// Floating-point conditional signaling compare. - | FCCMPE = 105 - /// Floating-point compare equal (vector and scalar form). - | FCMEQ = 106 - /// Floating-point compare greater than or equal (vector and scalar form). - | FCMGE = 107 - /// Floating-point compare greater than (vector and scalar form). - | FCMGT = 108 - /// Floating-point compare less than or equal to zero (vector and scalar). - | FCMLE = 109 - /// Floating-point compare less than zero (vector and scalar form). - | FCMLT = 110 - /// Floating-point quiet compare. - | FCMP = 111 - /// Floating-point signaling compare. - | FCMPE = 112 - /// Floating-point scalar conditional select. - | FCSEL = 113 - /// Floating-point convert precision (scalar). - | FCVT = 114 - /// FP convert to signed integer, rounding to nearest with ties to away. - | FCVTAS = 115 - /// FP convert to unsigned integer, rounding to nearest with ties to away. - | FCVTAU = 116 - /// Floating-point convert to higher precision long (vector form). - | FCVTL = 117 - /// Floating-point convert to higher precision long (vector form). - | FCVTL2 = 118 - /// Floating-point convert to signed integer, rounding toward minus infinity. - | FCVTMS = 119 - /// FP convert to unsigned integer, rounding toward minus infinity. - | FCVTMU = 120 - /// Floating-point convert to lower precision narrow (vector form). - | FCVTN = 121 - /// Floating-point convert to lower precision narrow (vector form). - | FCVTN2 = 122 - /// FP convert to signed integer, rounding to nearest with ties to even. - | FCVTNS = 123 - /// FP convert to unsigned integer, rounding to nearest with ties to even. - | FCVTNU = 124 - /// FP convert to signed integer, rounding toward positive infinity. - | FCVTPS = 125 - /// FP convert to unsigned integer, rounding toward positive infinity. - | FCVTPU = 126 - /// FP convert to lower precision narrow, rounding to odd (vector and scalar). - | FCVTXN = 127 - /// FP convert to lower precision narrow, rounding to odd (vector and scalar). - | FCVTXN2 = 128 - /// FP convert to signed integer, rounding toward zero (vector and scalar). - | FCVTZS = 129 - /// FP convert to unsigned integer, rounding toward zero (vector and scalar). - | FCVTZU = 130 - /// Floating-point divide. - | FDIV = 131 - /// Floating-point scalar fused multiply-add. - | FMADD = 132 - /// Floating-point maximum. - | FMAX = 133 - /// Floating-point maximum number. - | FMAXNM = 134 - /// Floating-point maximum number pairwise (vector and scalar form). - | FMAXNMP = 135 - /// Floating-point maximum number (across vector). - | FMAXNMV = 136 - /// Floating-point maximum pairwise (vector and scalar form). - | FMAXP = 137 - /// Floating-point maximum (across vector). - | FMAXV = 138 - /// Floating-point minimum. - | FMIN = 139 - /// Floating-point minimum number. - | FMINNM = 140 - /// Floating-point minimum number pairwise (vector and scalar form). - | FMINNMP = 141 - /// Floating-point minimum number (across vector). - | FMINNMV = 142 - /// Floating-point minimum pairwise (vector and scalar form). - | FMINP = 143 - /// Floating-point minimum (across vector). - | FMINV = 144 - /// Floating-point fused multiply-add. - | FMLA = 145 - /// Floating-point fused multiply-subtract. - | FMLS = 146 - /// Floating-point move immediate. - | FMOV = 147 - /// Floating-point scalar fused multiply-subtract. - | FMSUB = 148 - /// Floating-point multiply. - | FMUL = 149 - /// Floating-point multiply extended. - | FMULX = 150 - /// Floating-point negate. - | FNEG = 151 - /// Floating-point scalar negated fused multiply-add. - | FNMADD = 152 - /// Floating-point scalar negated fused multiply-subtract. - | FNMSUB = 153 - /// Floating-point scalar multiply-negate. - | FNMUL = 154 - /// Floating-point reciprocal estimate (vector and scalar form). - | FRECPE = 155 - /// Floating-point reciprocal step (vector and scalar form). - | FRECPS = 156 - /// Floating-point reciprocal square root (scalar form). - | FRECPX = 157 - /// Floating-point round to integral, to nearest with ties to away. - | FRINTA = 158 - /// Floating-point round to integral, using current rounding mode. - | FRINTI = 159 - /// Floating-point round to integral, toward minus infinity. - | FRINTM = 160 - /// Floating-point round to integral, to nearest with ties to even. - | FRINTN = 161 - /// Floating-point round to integral, toward positive infinity. - | FRINTP = 162 - /// Floating-point round to integral exact, using current rounding mode. - | FRINTX = 163 - /// Floating-point round to integral, toward zero. - | FRINTZ = 164 - /// Floating-point reciprocal square root estimate. - | FRSQRTE = 165 - /// Floating-point reciprocal square root step (vector and scalar form). - | FRSQRTS = 166 - /// Floating-point square root, - | FSQRT = 167 - /// Floating-point subtract. - | FSUB = 168 - /// Unallocated hint. - | HINT = 169 - /// Halt Instruction. - | HLT = 170 - /// Generate exception targeting Exception level 2. - | HVC = 171 - /// Insert vector element from general-purpose register. - | INS = 172 - /// Instruction synchronization barrier. - | ISB = 173 - /// Load single 1-element structure to one lane of one register. - | LD1 = 174 - /// Load single 1-element structure and replicate to all lanes of one reg. - | LD1R = 175 - /// Load multiple 2-element structures to two consecutive registers. - | LD2 = 176 - /// Load single 2-element structure and replicate to all lanes of two regs. - | LD2R = 177 - /// Load multiple 3-element structures to three consecutive registers. - | LD3 = 178 - /// Load single 3-element structure and replicate to all lanes of three regs. - | LD3R = 179 - /// Load multiple 4-element structures to four consecutive registers. - | LD4 = 180 - /// Load single 4-element structure and replicate to all lanes of four regs. - | LD4R = 181 - /// Load-Acquire register. - | LDAR = 182 - /// Load-Acquire byte. - | LDARB = 183 - /// Load-Acquire halfword. - | LDARH = 184 - /// Load-Acquire Exclusive pair. - | LDAXP = 185 - /// Load-Acquire Exclusive register. - | LDAXR = 186 - /// Load-Acquire Exclusive byte. - | LDAXRB = 187 - /// Load-Acquire Exclusive halfword. - | LDAXRH = 188 - /// Load Non-temporal Pair. - | LDNP = 189 - /// Load Pair. - | LDP = 190 - /// Load Pair signed words. - | LDPSW = 191 - /// Load register. - | LDR = 192 - /// Load byte. - | LDRB = 193 - /// Load halfword. - | LDRH = 194 - /// Load signed byte. - | LDRSB = 195 - /// Load signed halfword. - | LDRSH = 196 - /// Load signed word. - | LDRSW = 197 - /// Load unprivileged register. - | LDTR = 198 - /// Load unprivileged byte. - | LDTRB = 199 - /// Load unprivileged halfword. - | LDTRH = 200 - /// Load unprivileged signed byte. - | LDTRSB = 201 - /// Load unprivileged signed halfword. - | LDTRSH = 202 - /// Load unprivileged signed word. - | LDTRSW = 203 - /// Load register (unscaled offset). - | LDUR = 204 - /// Load byte (unscaled offset). - | LDURB = 205 - /// Load halfword (unscaled offset). - | LDURH = 206 - /// Load signed byte (unscaled offset). - | LDURSB = 207 - /// Load signed halfword (unscaled offset). - | LDURSH = 208 - /// Load signed word (unscaled offset). - | LDURSW = 209 - /// Load Exclusive pair. - | LDXP = 210 - /// Load Exclusive register. - | LDXR = 211 - /// Load Exclusive byte. - | LDXRB = 212 - /// Load Exclusive halfword. - | LDXRH = 213 - /// Logical shift left. - | LSL = 214 - /// Logical shift left variable. - | LSLV = 215 - /// Logical shift right. - | LSR = 216 - /// Logical shift right variable. - | LSRV = 217 - /// Multiply-add. - | MADD = 218 - /// Multiply-add to accumulator. - | MLA = 219 - /// Multiply-subtract from accumulator. - | MLS = 220 - /// Multiply-negate. - | MNEG = 221 - /// Move. - | MOV = 222 - /// Move immediate. - | MOVI = 223 + | DCPS3 = 341 + /// Data Cache Zero by VA. + | DCZVA = 342 + /// Decrement scalar by multiple of predicate constraint element count. + | DECB = 343 + /// Decrement scalar by multiple of predicate constraint element count. + | DECD = 344 + /// Decrement scalar by multiple of predicate constraint element count. + | DECH = 345 + /// Decrement scalar by count of true predicate elements. + | DECP = 346 + /// Decrement scalar by multiple of predicate constraint element count. + | DECW = 347 + /// Data Gathering Hint. + | DGH = 348 + /// Data Memory Barrier. + | DMB = 349 + /// Debug restore process state. + | DRPS = 350 + /// Data Synchronization Barrier. + | DSB = 351 + /// Duplicate vector element to vector or scalar. + | DUP = 352 + /// Broadcast logical bitmask immediate to vector (unpredicated). + | DUPM = 353 + /// Broadcast indexed element within each qword vector segment (unpred). + | DUPQ = 354 + /// Data Value Prediction Restriction by Context: an alias of SYS. + | DVP = 355 + /// Bitwise exclusive OR with inverted immediate (unpredicated). + | EON = 356 + /// Bitwise Exclusive OR (immediate). + | EOR = 357 + /// Three-way Exclusive OR. + | EOR3 = 358 + /// Interleaving exclusive OR (bottom, top). + | EORBT = 359 + /// Bitwise exclusive OR reduction of quadword vector segments. + | EORQV = 360 + /// Bitwise exclusive OR predicates, setting the condition flags. + | EORS = 361 + /// Interleaving exclusive OR (top, bottom). + | EORTB = 362 + /// Bitwise exclusive OR reduction to scalar. + | EORV = 363 + /// Exception Return. + | ERET = 364 + /// Exception Return, with pointer authentication. + | ERETAA = 365 + /// Exception Return, with pointer authentication. + | ERETAB = 366 + /// Error Synchronization Barrier. + | ESB = 367 + /// Extract vector from pair of vectors. + | EXT = 368 + /// Extract vector segment from each pair of quadword vector segments. + | EXTQ = 369 + /// Extract register. + | EXTR = 370 + /// FP Absolute Difference (vector). + | FABD = 371 + /// FP absolute value (predicated). + | FABS = 372 + /// FP absolute compare vectors. + | FAC = 373 + /// FP Absolute Compare Greater than or Equal (vector). + | FACGE = 374 + /// FP Absolute Compare Greater than (vector). + | FACGT = 375 + /// FP absolute compare less than or equal: an alias of FAC. + | FACLE = 376 + /// FP absolute compare less than: an alias of FAC. + | FACLT = 377 + /// FP add multi-vector to ZA array vector accumulators. + | FADD = 378 + /// FP add strictly-ordered reduction, accumulating in scalar. + | FADDA = 379 + /// FP add pairwise. + | FADDP = 380 + /// FP add recursive reduction of quadword vector segments. + | FADDQV = 381 + /// FP add recursive reduction to scalar. + | FADDV = 382 + /// FP Complex Add. + | FCADD = 383 + /// FP Conditional quiet Compare (scalar). + | FCCMP = 384 + /// FP Conditional signaling Compare (scalar). + | FCCMPE = 385 + /// FP clamp to minimum/maximum number. + | FCLAMP = 386 + /// FP compare vectors. + | FCM = 387 + /// FP Compare Equal (vector). + | FCMEQ = 388 + /// FP Compare Greater than or Equal (vector). + | FCMGE = 389 + /// FP Compare Greater than (vector). + | FCMGT = 390 + /// FP Complex Multiply Accumulate. + | FCMLA = 391 + /// FP compare less than or equal to vector: an alias of FCM (vectors). + | FCMLE = 392 + /// FP compare less than vector: an alias of FCM (vectors). + | FCMLT = 393 + /// FP quiet Compare (scalar). + | FCMP = 394 + /// FP signaling Compare (scalar). + | FCMPE = 395 + /// Copy 8-bit FP immediate to vector elements (predicated). + | FCPY = 396 + /// FP Conditional Select (scalar). + | FCSEL = 397 + /// FP Convert precision (scalar). + | FCVT = 398 + /// FP Convert to Signed int, rounding to nearest with ties to Away (scalar). + | FCVTAS = 399 + /// FP Conv to Unsigned int, rounding to nearest with ties to Away (scalar). + | FCVTAU = 400 + /// FP Convert to higher precision Long (vector). + | FCVTL = 401 + /// FP Convert to higher precision Long (vector). + | FCVTL2 = 402 + /// FP up convert long (top, predicated). + | FCVTLT = 403 + /// FP Convert to Signed integer, rounding toward Minus infinity (scalar). + | FCVTMS = 404 + /// FP Convert to Unsigned integer, rounding toward Minus infinity (scalar). + | FCVTMU = 405 + /// FP Convert to lower precision Narrow (vector). + | FCVTN = 406 + /// FP Convert to lower precision Narrow (vector). + | FCVTN2 = 407 + /// FP Convert to Signed int, rounding to nearest with ties to even (scalar). + | FCVTNS = 408 + /// FP down convert and narrow (top, predicated). + | FCVTNT = 409 + /// FP Conv to Unsigned int, rounding to nearest with ties to even (scalar). + | FCVTNU = 410 + /// FP Convert to Signed integer, rounding toward Plus infinity (scalar). + | FCVTPS = 411 + /// FP Convert to Unsigned integer, rounding toward Plus infinity (scalar). + | FCVTPU = 412 + /// FP down convert, rounding to odd (predicated). + | FCVTX = 413 + /// FP Convert to lower precision Narrow, rounding to odd (vector). + | FCVTXN = 414 + /// FP Convert to lower precision Narrow, rounding to odd (vector). + | FCVTXN2 = 415 + /// FP down convert, rounding to odd (top, predicated). + | FCVTXNT = 416 + /// FP convert to signed integer, rounding toward zero (predicated). + | FCVTZS = 417 + /// FP convert to unsigned integer, rounding toward zero (predicated). + | FCVTZU = 418 + /// FP divide by vector (predicated). + | FDIV = 419 + /// FP reversed divide by vector (predicated). + | FDIVR = 420 + /// Half-precision FP indexed dot product. + | FDOT = 421 + /// Broadcast 8-bit FP immediate to vector elements (unpredicated). + | FDUP = 422 + /// FP exponential accelerator. + | FEXPA = 423 + /// FP Javascript Convert to Signed fixed-point, rounding toward Zero. + | FJCVTZS = 424 + /// FP base 2 logarithm as integer. + | FLOGB = 425 + /// FP fused multiply-add vectors (predicated). + | FMAD = 426 + /// FP fused Multiply-Add (scalar). + | FMADD = 427 + /// FP maximum with immediate (predicated). + | FMAX = 428 + /// FP maximum number with immediate (predicated). + | FMAXNM = 429 + /// FP maximum number pairwise. + | FMAXNMP = 430 + /// FP maximum number recursive reduction of quadword vector segments. + | FMAXNMQV = 431 + /// FP Maximum Number across Vector. + | FMAXNMV = 432 + /// FP maximum pairwise. + | FMAXP = 433 + /// FP maximum reduction of quadword vector segments. + | FMAXQV = 434 + /// FP Maximum across Vector. + | FMAXV = 435 + /// FP minimum with immediate (predicated). + | FMIN = 436 + /// FP minimum number with immediate (predicated). + | FMINNM = 437 + /// FP minimum number pairwise. + | FMINNMP = 438 + /// FP minimum number recursive reduction of quadword vector segments. + | FMINNMQV = 439 + /// FP Minimum Number across Vector. + | FMINNMV = 440 + /// FP minimum pairwise. + | FMINP = 441 + /// FP minimum recursive reduction of quadword vector segments. + | FMINQV = 442 + /// FP Minimum across Vector. + | FMINV = 443 + /// FP fused Multiply-Add to accumulator (by element). + | FMLA = 444 + /// FP fused Multiply-Add Long to accumulator (by element). + | FMLAL = 445 + /// FP fused Multiply-Add Long to accumulator (by element). + | FMLAL2 = 446 + /// Half-precision FP mul-add long to single-precision (bottom, indexed). + | FMLALB = 447 + /// Half-precision FP multiply-add long to single-precision (top, indexed). + | FMLALT = 448 + /// FP fused Multiply-Subtract from accumulator (by element). + | FMLS = 449 + /// FP fused Multiply-Subtract Long from accumulator (by element). + | FMLSL = 450 + /// FP fused Multiply-Subtract Long from accumulator (by element). + | FMLSL2 = 451 + /// Half-precision FP mul-sub long from single-precision (bottom, indexed). + | FMLSLB = 452 + /// Half-precision FP mul-sub long from single-precision (top, indexed). + | FMLSLT = 453 + /// FP matrix multiply-accumulate. + | FMMLA = 454 + /// FP outer product and accumulate. + | FMOPA = 455 + /// FP outer product and subtract. + | FMOPS = 456 + /// FP Move to or from general-purpose register without conversion. + | FMOV = 457 + /// FP fused multiply-subtract vectors (predicated). + | FMSB = 458 + /// FP Fused Multiply-Subtract (scalar). + | FMSUB = 459 + /// FP Multiply (by element). + | FMUL = 460 + /// FP Multiply extended. + | FMULX = 461 + /// FP negate (predicated). + | FNEG = 462 + /// FP negated fused multiply-add vectors (predicated). + | FNMAD = 463 + /// FP Negated fused Multiply-Add (scalar). + | FNMADD = 464 + /// FP negated fused multiply-add vectors (predicated). + | FNMLA = 465 + /// FP negated fused multiply-subtract vectors (predicated). + | FNMLS = 466 + /// FP negated fused multiply-subtract vectors (predicated). + | FNMSB = 467 + /// FP Negated fused Multiply-Subtract (scalar). + | FNMSUB = 468 + /// FP Multiply-Negate (scalar). + | FNMUL = 469 + /// FP Reciprocal Estimate. + | FRECPE = 470 + /// FP Reciprocal Step. + | FRECPS = 471 + /// FP Reciprocal exponent (scalar). + | FRECPX = 472 + /// FP round to integral value (predicated). + | FRINT = 473 + /// FP Round to 32-bit Integer, using current rounding mode (scalar). + | FRINT32X = 474 + /// FP Round to 32-bit Integer toward Zero (scalar). + | FRINT32Z = 475 + /// FP Round to 64-bit Integer, using current rounding mode (scalar). + | FRINT64X = 476 + /// FP Round to 64-bit Integer toward Zero (scalar). + | FRINT64Z = 477 + /// Multi-vector FP round to int val, to nearest with ties away from zero. + | FRINTA = 478 + /// FP Round to Integral, using current rounding mode (scalar). + | FRINTI = 479 + /// Multi-vector FP round to integral value, toward minus Infinity. + | FRINTM = 480 + /// Multi-vector FP round to integral value, to nearest with ties to even. + | FRINTN = 481 + /// Multi-vector FP round to integral value, toward plus Infinity. + | FRINTP = 482 + /// FP Round to Integral exact, using current rounding mode (scalar). + | FRINTX = 483 + /// FP Round to Integral, toward Zero (scalar). + | FRINTZ = 484 + /// FP Reciprocal Square Root Estimate. + | FRSQRTE = 485 + /// FP Reciprocal Square Root Step. + | FRSQRTS = 486 + /// FP adjust exponent by vector (predicated). + | FSCALE = 487 + /// FP square root (predicated). + | FSQRT = 488 + /// FP subtract multi-vector from ZA array vector accumulators. + | FSUB = 489 + /// FP reversed subtract from immediate (predicated). + | FSUBR = 490 + /// FP trigonometric multiply-add coefficient. + | FTMAD = 491 + /// FP trigonometric starting value. + | FTSMUL = 492 + /// FP trigonometric select coefficient. + | FTSSEL = 493 + /// Multi-vector half-precision FP vertical dot-product by indexed element. + | FVDOT = 494 + /// Tag Mask Insert. + | GMI = 495 + /// Hint instruction. + | HINT = 496 + /// Count matching elements in vector. + | HISTCNT = 497 + /// Count matching elements in vector segments. + | HISTSEG = 498 + /// Halt instruction. + | HLT = 499 + /// Hypervisor Call. + | HVC = 500 + /// Instruction Cache operation: an alias of SYS. + | IC = 501 + /// Increment scalar by multiple of predicate constraint element count. + | INCB = 502 + /// Increment scalar by multiple of predicate constraint element count. + | INCD = 503 + /// Increment scalar by multiple of predicate constraint element count. + | INCH = 504 + /// Increment scalar by count of true predicate elements. + | INCP = 505 + /// Increment scalar by multiple of predicate constraint element count. + | INCW = 506 + /// Create index starting from imm and incremented by general-purpose reg. + | INDEX = 507 + /// Insert vector element from another vector element. + | INS = 508 + /// Insert general-purpose register in shifted vector. + | INSR = 509 + /// Insert Random Tag. + | IRG = 510 + /// Instruction Synchronization Barrier. + | ISB = 511 + /// Extract element after last to general-purpose register. + | LASTA = 512 + /// Extract last element to general-purpose register. + | LASTB = 513 + /// Load multiple single-element structures to one, two, three, or four regs. + | LD1 = 514 + /// Contiguous load of bytes to mul consecutive vectors (immediate index). + | LD1B = 515 + /// Contiguous load of dwords to mul consecutive vectors (immediate index). + | LD1D = 516 + /// Contiguous load of hwords to mult consecutive vectors (immediate index). + | LD1H = 517 + /// Gather load quadwords. + | LD1Q = 518 + /// Load one single-element struct and Replicate to all lanes (of one reg). + | LD1R = 519 + /// Load and broadcast unsigned byte to vector. + | LD1RB = 520 + /// Load and broadcast doubleword to vector. + | LD1RD = 521 + /// Load and broadcast unsigned halfword to vector. + | LD1RH = 522 + /// Contiguous load and replicate thirty-two bytes (immediate index). + | LD1ROB = 523 + /// Contiguous load and replicate four doublewords (immediate index). + | LD1ROD = 524 + /// Contiguous load and replicate sixteen halfwords (immediate index). + | LD1ROH = 525 + /// Contiguous load and replicate eight words (immediate index). + | LD1ROW = 526 + /// Contiguous load and replicate sixteen bytes (immediate index). + | LD1RQB = 527 + /// Contiguous load and replicate two doublewords (immediate index). + | LD1RQD = 528 + /// Contiguous load and replicate eight halfwords (immediate index). + | LD1RQH = 529 + /// Contiguous load and replicate four words (immediate index). + | LD1RQW = 530 + /// Load and broadcast signed byte to vector. + | LD1RSB = 531 + /// Load and broadcast signed halfword to vector. + | LD1RSH = 532 + /// Load and broadcast signed word to vector. + | LD1RSW = 533 + /// Load and broadcast unsigned word to vector. + | LD1RW = 534 + /// Contiguous load signed bytes to vector (immediate index). + | LD1SB = 535 + /// Contiguous load signed halfwords to vector (immediate index). + | LD1SH = 536 + /// Contiguous load signed words to vector (immediate index). + | LD1SW = 537 + /// Contiguous load of words to mul consecutive vectors (immediate index). + | LD1W = 538 + /// Load multiple 2-element structures to two registers. + | LD2 = 539 + /// Contiguous load two-byte structures to two vectors (immediate index). + | LD2B = 540 + /// Contiguous load two-doubleword struct to two vectors (immediate index). + | LD2D = 541 + /// Contiguous load two-halfword structures to two vectors (immediate index). + | LD2H = 542 + /// Contiguous load two-quadword structures to two vectors (immediate index). + | LD2Q = 543 + /// Load single 2-element struct and Replicate to all lanes of two registers. + | LD2R = 544 + /// Contiguous load two-word structures to two vectors (immediate index). + | LD2W = 545 + /// Load multiple 3-element structures to three registers. + | LD3 = 546 + /// Contiguous load three-byte structures to three vectors (immediate index). + | LD3B = 547 + /// Contiguous load three-dword structs to three vectors (immediate index). + | LD3D = 548 + /// Contiguous load three-halfword structs to three vectors (immediate index). + | LD3H = 549 + /// Contiguous load three-quadword structs to three vectors (immediate index). + | LD3Q = 550 + /// Load single 3-element struct and Replicate to all lanes of three regs. + | LD3R = 551 + /// Contiguous load three-word structures to three vectors (immediate index). + | LD3W = 552 + /// Load multiple 4-element structures to four registers. + | LD4 = 553 + /// Contiguous load four-byte structures to four vectors (immediate index). + | LD4B = 554 + /// Contiguous load four-doubleword structs to four vectors (immediate index). + | LD4D = 555 + /// Contiguous load four-halfword struct to four vectors (immediate index). + | LD4H = 556 + /// Contiguous load four-quadword struct to four vectors (immediate index). + | LD4Q = 557 + /// Load single 4-element struct and Replicate to all lanes of four regis. + | LD4R = 558 + /// Contiguous load four-word structures to four vectors (immediate index). + | LD4W = 559 + /// Single-copy Atomic 64-byte Load. + | LD64B = 560 + /// Atomic add on word or doubleword in memory. + | LDADD = 561 + /// Atomic add on word or doubleword in memory. + | LDADDA = 562 + /// Atomic add on byte in memory. + | LDADDAB = 563 + /// Atomic add on halfword in memory. + | LDADDAH = 564 + /// Atomic add on word or doubleword in memory. + | LDADDAL = 565 + /// Atomic add on byte in memory. + | LDADDALB = 566 + /// Atomic add on halfword in memory. + | LDADDALH = 567 + /// Atomic add on byte in memory. + | LDADDB = 568 + /// Atomic add on halfword in memory. + | LDADDH = 569 + /// Atomic add on word or doubleword in memory. + | LDADDL = 570 + /// Atomic add on byte in memory. + | LDADDLB = 571 + /// Atomic add on halfword in memory. + | LDADDLH = 572 + /// Load-Acquire RCpc one single-element struct to one lane of one register. + | LDAP1 = 573 + /// Load-Acquire RCpc Register. + | LDAPR = 574 + /// Load-Acquire RCpc Register Byte. + | LDAPRB = 575 + /// Load-Acquire RCpc Register Halfword. + | LDAPRH = 576 + /// Load-Acquire RCpc Register (unscaled). + | LDAPUR = 577 + /// Load-Acquire RCpc Register Byte (unscaled). + | LDAPURB = 578 + /// Load-Acquire RCpc Register Halfword (unscaled). + | LDAPURH = 579 + /// Load-Acquire RCpc Register Signed Byte (unscaled). + | LDAPURSB = 580 + /// Load-Acquire RCpc Register Signed Halfword (unscaled). + | LDAPURSH = 581 + /// Load-Acquire RCpc Register Signed Word (unscaled). + | LDAPURSW = 582 + /// Load-Acquire Register. + | LDAR = 583 + /// Load-Acquire Register Byte. + | LDARB = 584 + /// Load-Acquire Register Halfword. + | LDARH = 585 + /// Load-Acquire Exclusive Pair of Registers. + | LDAXP = 586 + /// Load-Acquire Exclusive Register. + | LDAXR = 587 + /// Load-Acquire Exclusive Register Byte. + | LDAXRB = 588 + /// Load-Acquire Exclusive Register Halfword. + | LDAXRH = 589 + /// Atomic bit clear on word or doubleword in memory. + | LDCLR = 590 + /// Atomic bit clear on word or doubleword in memory. + | LDCLRA = 591 + /// Atomic bit clear on byte in memory. + | LDCLRAB = 592 + /// Atomic bit clear on halfword in memory. + | LDCLRAH = 593 + /// Atomic bit clear on word or doubleword in memory. + | LDCLRAL = 594 + /// Atomic bit clear on byte in memory. + | LDCLRALB = 595 + /// Atomic bit clear on halfword in memory. + | LDCLRALH = 596 + /// Atomic bit clear on byte in memory. + | LDCLRB = 597 + /// Atomic bit clear on halfword in memory. + | LDCLRH = 598 + /// Atomic bit clear on word or doubleword in memory. + | LDCLRL = 599 + /// Atomic bit clear on byte in memory. + | LDCLRLB = 600 + /// Atomic bit clear on halfword in memory. + | LDCLRLH = 601 + /// Atomic bit clear on quadword in memory. + | LDCLRP = 602 + /// Atomic bit clear on quadword in memory. + | LDCLRPA = 603 + /// Atomic bit clear on quadword in memory. + | LDCLRPAL = 604 + /// Atomic bit clear on quadword in memory. + | LDCLRPL = 605 + /// Atomic exclusive OR on word or doubleword in memory. + | LDEOR = 606 + /// Atomic exclusive OR on word or doubleword in memory. + | LDEORA = 607 + /// Atomic exclusive OR on byte in memory. + | LDEORAB = 608 + /// Atomic exclusive OR on halfword in memory. + | LDEORAH = 609 + /// Atomic exclusive OR on word or doubleword in memory. + | LDEORAL = 610 + /// Atomic exclusive OR on byte in memory. + | LDEORALB = 611 + /// Atomic exclusive OR on halfword in memory. + | LDEORALH = 612 + /// Atomic exclusive OR on byte in memory. + | LDEORB = 613 + /// Atomic exclusive OR on halfword in memory. + | LDEORH = 614 + /// Atomic exclusive OR on word or doubleword in memory. + | LDEORL = 615 + /// Atomic exclusive OR on byte in memory. + | LDEORLB = 616 + /// Atomic exclusive OR on halfword in memory. + | LDEORLH = 617 + /// Contiguous load first-fault unsigned bytes to vector (scalar index). + | LDFF1B = 618 + /// Contiguous load first-fault doublewords to vector (scalar index). + | LDFF1D = 619 + /// Contiguous load first-fault unsigned halfwords to vector (scalar index). + | LDFF1H = 620 + /// Contiguous load first-fault signed bytes to vector (scalar index). + | LDFF1SB = 621 + /// Contiguous load first-fault signed halfwords to vector (scalar index). + | LDFF1SH = 622 + /// Contiguous load first-fault signed words to vector (scalar index). + | LDFF1SW = 623 + /// Contiguous load first-fault unsigned words to vector (scalar index). + | LDFF1W = 624 + /// Load Allocation Tag. + | LDG = 625 + /// Load Tag Multiple. + | LDGM = 626 + /// Load-Acquire RCpc ordered Pair of registers. + | LDIAPP = 627 + /// Load LOAcquire Register. + | LDLAR = 628 + /// Load LOAcquire Register Byte. + | LDLARB = 629 + /// Load LOAcquire Register Halfword. + | LDLARH = 630 + /// Contiguous load non-fault unsigned bytes to vector. + | LDNF1B = 631 + /// Contiguous load non-fault doublewords to vector. + | LDNF1D = 632 + /// Contiguous load non-fault unsigned halfwords to vector. + | LDNF1H = 633 + /// Contiguous load non-fault signed bytes to vector. + | LDNF1SB = 634 + /// Contiguous load non-fault signed halfwords to vector. + | LDNF1SH = 635 + /// Contiguous load non-fault signed words to vector. + | LDNF1SW = 636 + /// Contiguous load non-fault unsigned words to vector. + | LDNF1W = 637 + /// Load Pair of Registers, with non-temporal hint. + | LDNP = 638 + /// Contiguous load non-temporal of bytes to multiple consecutive vectors. + | LDNT1B = 639 + /// Contiguous load non-temporal of dwords to multiple consecutive vectors. + | LDNT1D = 640 + /// Contiguous load non-temporal of hwords to multiple consecutive vectors. + | LDNT1H = 641 + /// Gather load non-temporal signed bytes. + | LDNT1SB = 642 + /// Gather load non-temporal signed halfwords. + | LDNT1SH = 643 + /// Gather load non-temporal signed words. + | LDNT1SW = 644 + /// Contiguous load non-temporal of words to multiple consecutive vectors. + | LDNT1W = 645 + /// Load Pair of Registers. + | LDP = 646 + /// Load Pair of Registers Signed Word. + | LDPSW = 647 + /// Load Register (immediate). + | LDR = 648 + /// Load Register, with pointer authentication. + | LDRAA = 649 + /// Load Register, with pointer authentication. + | LDRAB = 650 + /// Load Register Byte (immediate). + | LDRB = 651 + /// Load Register Halfword (immediate). + | LDRH = 652 + /// Load Register Signed Byte (immediate). + | LDRSB = 653 + /// Load Register Signed Halfword (immediate). + | LDRSH = 654 + /// Load Register Signed Word (immediate). + | LDRSW = 655 + /// Atomic bit set on word or doubleword in memory. + | LDSET = 656 + /// Atomic bit set on word or doubleword in memory. + | LDSETA = 657 + /// Atomic bit set on byte in memory. + | LDSETAB = 658 + /// Atomic bit set on halfword in memory. + | LDSETAH = 659 + /// Atomic bit set on word or doubleword in memory. + | LDSETAL = 660 + /// Atomic bit set on byte in memory. + | LDSETALB = 661 + /// Atomic bit set on halfword in memory. + | LDSETALH = 662 + /// Atomic bit set on byte in memory. + | LDSETB = 663 + /// Atomic bit set on halfword in memory. + | LDSETH = 664 + /// Atomic bit set on word or doubleword in memory. + | LDSETL = 665 + /// Atomic bit set on byte in memory. + | LDSETLB = 666 + /// Atomic bit set on halfword in memory. + | LDSETLH = 667 + /// Atomic bit set on quadword in memory. + | LDSETP = 668 + /// Atomic bit set on quadword in memory. + | LDSETPA = 669 + /// Atomic bit set on quadword in memory. + | LDSETPAL = 670 + /// Atomic bit set on quadword in memory. + | LDSETPL = 671 + /// Atomic signed maximum on word or doubleword in memory. + | LDSMAX = 672 + /// Atomic signed maximum on word or doubleword in memory. + | LDSMAXA = 673 + /// Atomic signed maximum on byte in memory. + | LDSMAXAB = 674 + /// Atomic signed maximum on halfword in memory. + | LDSMAXAH = 675 + /// Atomic signed maximum on word or doubleword in memory. + | LDSMAXAL = 676 + /// Atomic signed maximum on byte in memory. + | LDSMAXALB = 677 + /// Atomic signed maximum on halfword in memory. + | LDSMAXALH = 678 + /// Atomic signed maximum on byte in memory. + | LDSMAXB = 679 + /// Atomic signed maximum on halfword in memory. + | LDSMAXH = 680 + /// Atomic signed maximum on word or doubleword in memory. + | LDSMAXL = 681 + /// Atomic signed maximum on byte in memory. + | LDSMAXLB = 682 + /// Atomic signed maximum on halfword in memory. + | LDSMAXLH = 683 + /// Atomic signed minimum on word or doubleword in memory. + | LDSMIN = 684 + /// Atomic signed minimum on word or doubleword in memory. + | LDSMINA = 685 + /// Atomic signed minimum on byte in memory. + | LDSMINAB = 686 + /// Atomic signed minimum on halfword in memory. + | LDSMINAH = 687 + /// Atomic signed minimum on word or doubleword in memory. + | LDSMINAL = 688 + /// Atomic signed minimum on byte in memory. + | LDSMINALB = 689 + /// Atomic signed minimum on halfword in memory. + | LDSMINALH = 690 + /// Atomic signed minimum on byte in memory. + | LDSMINB = 691 + /// Atomic signed minimum on halfword in memory. + | LDSMINH = 692 + /// Atomic signed minimum on word or doubleword in memory. + | LDSMINL = 693 + /// Atomic signed minimum on byte in memory. + | LDSMINLB = 694 + /// Atomic signed minimum on halfword in memory. + | LDSMINLH = 695 + /// Load Register (unprivileged). + | LDTR = 696 + /// Load Register Byte (unprivileged). + | LDTRB = 697 + /// Load Register Halfword (unprivileged). + | LDTRH = 698 + /// Load Register Signed Byte (unprivileged). + | LDTRSB = 699 + /// Load Register Signed Halfword (unprivileged). + | LDTRSH = 700 + /// Load Register Signed Word (unprivileged). + | LDTRSW = 701 + /// Atomic unsigned maximum on word or doubleword in memory. + | LDUMAX = 702 + /// Atomic unsigned maximum on word or doubleword in memory. + | LDUMAXA = 703 + /// Atomic unsigned maximum on byte in memory. + | LDUMAXAB = 704 + /// Atomic unsigned maximum on halfword in memory. + | LDUMAXAH = 705 + /// Atomic unsigned maximum on word or doubleword in memory. + | LDUMAXAL = 706 + /// Atomic unsigned maximum on byte in memory. + | LDUMAXALB = 707 + /// Atomic unsigned maximum on halfword in memory. + | LDUMAXALH = 708 + /// Atomic unsigned maximum on byte in memory. + | LDUMAXB = 709 + /// Atomic unsigned maximum on halfword in memory. + | LDUMAXH = 710 + /// Atomic unsigned maximum on word or doubleword in memory. + | LDUMAXL = 711 + /// Atomic unsigned maximum on byte in memory. + | LDUMAXLB = 712 + /// Atomic unsigned maximum on halfword in memory. + | LDUMAXLH = 713 + /// Atomic unsigned minimum on word or doubleword in memory. + | LDUMIN = 714 + /// Atomic unsigned minimum on word or doubleword in memory. + | LDUMINA = 715 + /// Atomic unsigned minimum on byte in memory. + | LDUMINAB = 716 + /// Atomic unsigned minimum on halfword in memory. + | LDUMINAH = 717 + /// Atomic unsigned minimum on word or doubleword in memory. + | LDUMINAL = 718 + /// Atomic unsigned minimum on byte in memory. + | LDUMINALB = 719 + /// Atomic unsigned minimum on halfword in memory. + | LDUMINALH = 720 + /// Atomic unsigned minimum on byte in memory. + | LDUMINB = 721 + /// Atomic unsigned minimum on halfword in memory. + | LDUMINH = 722 + /// Atomic unsigned minimum on word or doubleword in memory. + | LDUMINL = 723 + /// Atomic unsigned minimum on byte in memory. + | LDUMINLB = 724 + /// Atomic unsigned minimum on halfword in memory. + | LDUMINLH = 725 + /// Load Register (unscaled). + | LDUR = 726 + /// Load Register Byte (unscaled). + | LDURB = 727 + /// Load Register Halfword (unscaled). + | LDURH = 728 + /// Load Register Signed Byte (unscaled). + | LDURSB = 729 + /// Load Register Signed Halfword (unscaled). + | LDURSH = 730 + /// Load Register Signed Word (unscaled). + | LDURSW = 731 + /// Load Exclusive Pair of Registers. + | LDXP = 732 + /// Load Exclusive Register. + | LDXR = 733 + /// Load Exclusive Register Byte. + | LDXRB = 734 + /// Load Exclusive Register Halfword. + | LDXRH = 735 + /// Logical Shift Left (immediate): an alias of UBFM. + | LSL = 736 + /// Reversed logical shift left by vector (predicated). + | LSLR = 737 + /// Logical Shift Left Variable. + | LSLV = 738 + /// Logical Shift Right (immediate): an alias of UBFM. + | LSR = 739 + /// Reversed logical shift right by vector (predicated). + | LSRR = 740 + /// Logical Shift Right Variable. + | LSRV = 741 + /// Lookup table read with 2-bit indexes. + | LUTI2 = 742 + /// Lookup table read with 4-bit indexes. + | LUTI4 = 743 + /// Multiply-add vectors (predicated). + | MAD = 744 + /// Multiply-Add. + | MADD = 745 + /// Detect any matching elements, setting the condition flags. + | MATCH = 746 + /// Multiply-Add to accumulator (vector, by element). + | MLA = 747 + /// Multiply-Subtract from accumulator (vector, by element). + | MLS = 748 + /// Multiply-Negate: an alias of MSUB. + | MNEG = 749 + /// Move logical bitmask immediate to vector (unpredicated): an alias of DUPM. + | MOV = 750 + /// Move four ZA single-vector groups to four vector registers. + | MOVA = 751 + /// Move and zero four ZA single-vector groups to vector registers. + | MOVAZ = 752 + /// Move Immediate (vector). + | MOVI = 753 /// Move wide with keep. - | MOVK = 224 + | MOVK = 754 /// Move wide with NOT. - | MOVN = 225 + | MOVN = 755 + /// Move prefix (predicated). + | MOVPRFX = 756 + /// Move predicates (zeroing), setting the condition flags: an alias of ANDS. + | MOVS = 757 + /// Move 8 bytes from general-purpose register to ZT0. + | MOVT = 758 /// Move wide with zero. - | MOVZ = 226 - /// Move System register to general-purpose register. - | MRS = 227 - /// Move general-purpose register to System register. - | MSR = 228 - /// Multiply-subtract. - | MSUB = 229 - /// Multiply. - | MUL = 230 - /// Bitwise NOT. - | MVN = 231 - /// Move inverted immediate. - | MVNI = 232 - /// Negate. - | NEG = 233 - /// Negate and set flags. - | NEGS = 234 - /// Negate with carry. - | NGC = 235 - /// Negate with carry and set flags. - | NGCS = 236 - /// No operation. - | NOP = 237 - /// Bitwise NOT. - | NOT = 238 - /// Bitwise inclusive OR NOT. - | ORN = 239 - /// Bitwise inclusive OR. - | ORR = 240 - /// Polynomial multiply (vector form). - | PMUL = 241 - /// Polynomial multiply long (vector form). - | PMULL = 242 - /// Polynomial multiply long (vector form). - | PMULL2 = 243 - /// Prefetch memory. - | PRFM = 244 - /// Prefetch memory (unscaled offset). - | PRFUM = 245 - /// Rounding add returning high, narrow (vector form). - | RADDHN = 246 - /// Rounding add returning high, narrow (vector form). - | RADDHN2 = 247 - /// Reverse bit order. - | RBIT = 248 + | MOVZ = 759 + /// Move System Register to two adjacent general-purpose registers. + | MRRS = 760 + /// Move System Register to general-purpose register. + | MRS = 761 + /// Multiply-subtract vectors (predicated). + | MSB = 762 + /// Move immediate value to Special Register. + | MSR = 763 + /// Move two adjacent general-purpose registers to System Register. + | MSRR = 764 + /// Multiply-Subtract. + | MSUB = 765 + /// Multiply: an alias of MADD. + | MUL = 766 + /// Bitwise NOT: an alias of ORN (shifted register). + | MVN = 767 + /// Move inverted Immediate (vector). + | MVNI = 768 + /// Bitwise NAND predicates. + | NAND = 769 + /// Bitwise NAND predicates, setting the condition flags. + | NANDS = 770 + /// Bitwise inverted select. + | NBSL = 771 + /// Negate (predicated). + | NEG = 772 + /// Negate, setting flags: an alias of SUBS (shifted register). + | NEGS = 773 + /// Negate with Carry: an alias of SBC. + | NGC = 774 + /// Negate with Carry, setting flags: an alias of SBCS. + | NGCS = 775 + /// Detect no matching elements, setting the condition flags. + | NMATCH = 776 + /// No Operation. + | NOP = 777 + /// Bitwise NOR predicates. + | NOR = 778 + /// Bitwise NOR predicates, setting the condition flags. + | NORS = 779 + /// Bitwise NOT (vector). + | NOT = 780 + /// Bitwise invert predicate, setting the condition flags: an alias of EORS. + | NOTS = 781 + /// Bitwise inclusive OR with inverted immediate (unpredicated). + | ORN = 782 + /// Bitwise inclusive OR inverted predicate, setting the condition flags. + | ORNS = 783 + /// Bitwise inclusive OR reduction of quadword vector segments. + | ORQV = 784 + /// Bitwise OR (immediate). + | ORR = 785 + /// Bitwise inclusive OR predicates, setting the condition flags. + | ORRS = 786 + /// Bitwise inclusive OR reduction to scalar. + | ORV = 787 + /// Pointer Authentication Code for Data address, using key A. + | PACDA = 788 + /// Pointer Authentication Code for Data address, using key B. + | PACDB = 789 + /// Pointer Authentication Code for Data address, using key A. + | PACDZA = 790 + /// Pointer Authentication Code for Data address, using key B. + | PACDZB = 791 + /// Pointer Authentication Code, using Generic key. + | PACGA = 792 + /// Pointer Authentication Code for Instruction address, using key A. + | PACIA = 793 + /// Pointer Authentication Code for Instruction address, using key A. + | PACIA1716 = 794 + /// Pointer Authentication Code for Instruction address, using key A. + | PACIASP = 795 + /// Pointer Authentication Code for Instruction address, using key A. + | PACIAZ = 796 + /// Pointer Authentication Code for Instruction address, using key B. + | PACIB = 797 + /// Pointer Authentication Code for Instruction address, using key B. + | PACIB1716 = 798 + /// Pointer Authentication Code for Instruction address, using key B. + | PACIBSP = 799 + /// Pointer Authentication Code for Instruction address, using key B. + | PACIBZ = 800 + /// Pointer Authentication Code for Instruction address, using key A. + | PACIZA = 801 + /// Pointer Authentication Code for Instruction address, using key B. + | PACIZB = 802 + /// Set pair of predicates from predicate-as-counter. + | PEXT = 803 + /// Set all predicate elements to false. + | PFALSE = 804 + /// Set the first active predicate element to true. + | PFIRST = 805 + /// Move predicate from vector. + | PMOV = 806 + /// Polynomial Multiply. + | PMUL = 807 + /// Polynomial Multiply Long. + | PMULL = 808 + /// Polynomial Multiply Long. + | PMULL2 = 809 + /// Polynomial multiply long (bottom). + | PMULLB = 810 + /// Polynomial multiply long (top). + | PMULLT = 811 + /// Find next active predicate. + | PNEXT = 812 + /// Contiguous prefetch bytes (immediate index). + | PRFB = 813 + /// Contiguous prefetch doublewords (immediate index). + | PRFD = 814 + /// Contiguous prefetch halfwords (immediate index). + | PRFH = 815 + /// Prefetch Memory (immediate). + | PRFM = 816 + /// Prefetch Memory (unscaled offset). + | PRFUM = 817 + /// Contiguous prefetch words (immediate index). + | PRFW = 818 + /// Profiling Synchronization Barrier. + | PSB = 819 + /// Predicate select between predicate register or all-false. + | PSEL = 820 + /// Physical Speculative Store Bypass Barrier: an alias of DSB. + | PSSBB = 821 + /// Set condition flags for predicate. + | PTEST = 822 + /// Initialise predicate-as-counter to all active. + | PTRUE = 823 + /// Initialise predicate from named constraint and set the condition flags. + | PTRUES = 824 + /// Unpack and widen half of predicate. + | PUNPKHI = 825 + /// Unpack and widen half of predicate. + | PUNPKLO = 826 + /// Rounding Add returning High Narrow. + | RADDHN = 827 + /// Rounding Add returning High Narrow. + | RADDHN2 = 828 + /// Rounding add narrow high part (bottom). + | RADDHNB = 829 + /// Rounding add narrow high part (top). + | RADDHNT = 830 + /// Rotate and Exclusive OR. + | RAX1 = 831 + /// Reverse Bits. + | RBIT = 832 + /// Read Check Write Compare and Swap doubleword in memory. + | RCWCAS = 833 + /// Read Check Write Compare and Swap doubleword in memory. + | RCWCASA = 834 + /// Read Check Write Compare and Swap doubleword in memory. + | RCWCASAL = 835 + /// Read Check Write Compare and Swap doubleword in memory. + | RCWCASL = 836 + /// Read Check Write Compare and Swap quadword in memory. + | RCWCASP = 837 + /// Read Check Write Compare and Swap quadword in memory. + | RCWCASPA = 838 + /// Read Check Write Compare and Swap quadword in memory. + | RCWCASPAL = 839 + /// Read Check Write Compare and Swap quadword in memory. + | RCWCASPL = 840 + /// Read Check Write atomic bit Clear on doubleword in memory. + | RCWCLR = 841 + /// Read Check Write atomic bit Clear on doubleword in memory. + | RCWCLRA = 842 + /// Read Check Write atomic bit Clear on doubleword in memory. + | RCWCLRAL = 843 + /// Read Check Write atomic bit Clear on doubleword in memory. + | RCWCLRL = 844 + /// Read Check Write atomic bit Clear on quadword in memory. + | RCWCLRP = 845 + /// Read Check Write atomic bit Clear on quadword in memory. + | RCWCLRPA = 846 + /// Read Check Write atomic bit Clear on quadword in memory. + | RCWCLRPAL = 847 + /// Read Check Write atomic bit Clear on quadword in memory. + | RCWCLRPL = 848 + /// Read Check Write Software Compare and Swap doubleword in memory. + | RCWSCAS = 849 + /// Read Check Write Software Compare and Swap doubleword in memory. + | RCWSCASA = 850 + /// Read Check Write Software Compare and Swap doubleword in memory. + | RCWSCASAL = 851 + /// Read Check Write Software Compare and Swap doubleword in memory. + | RCWSCASL = 852 + /// Read Check Write Software Compare and Swap quadword in memory. + | RCWSCASP = 853 + /// Read Check Write Software Compare and Swap quadword in memory. + | RCWSCASPA = 854 + /// Read Check Write Software Compare and Swap quadword in memory. + | RCWSCASPAL = 855 + /// Read Check Write Software Compare and Swap quadword in memory. + | RCWSCASPL = 856 + /// Read Check Write Software atomic bit Clear on doubleword in memory. + | RCWSCLR = 857 + /// Read Check Write Software atomic bit Clear on doubleword in memory. + | RCWSCLRA = 858 + /// Read Check Write Software atomic bit Clear on doubleword in memory. + | RCWSCLRAL = 859 + /// Read Check Write Software atomic bit Clear on doubleword in memory. + | RCWSCLRL = 860 + /// Read Check Write Software atomic bit Clear on quadword in memory. + | RCWSCLRP = 861 + /// Read Check Write Software atomic bit Clear on quadword in memory. + | RCWSCLRPA = 862 + /// Read Check Write Software atomic bit Clear on quadword in memory. + | RCWSCLRPAL = 863 + /// Read Check Write Software atomic bit Clear on quadword in memory. + | RCWSCLRPL = 864 + /// Read Check Write atomic bit Set on doubleword in memory. + | RCWSET = 865 + /// Read Check Write atomic bit Set on doubleword in memory. + | RCWSETA = 866 + /// Read Check Write atomic bit Set on doubleword in memory. + | RCWSETAL = 867 + /// Read Check Write atomic bit Set on doubleword in memory. + | RCWSETL = 868 + /// Read Check Write atomic bit Set on quadword in memory. + | RCWSETP = 869 + /// Read Check Write atomic bit Set on quadword in memory. + | RCWSETPA = 870 + /// Read Check Write atomic bit Set on quadword in memory. + | RCWSETPAL = 871 + /// Read Check Write atomic bit Set on quadword in memory. + | RCWSETPL = 872 + /// Read Check Write Software atomic bit Set on doubleword in memory. + | RCWSSET = 873 + /// Read Check Write Software atomic bit Set on doubleword in memory. + | RCWSSETA = 874 + /// Read Check Write Software atomic bit Set on doubleword in memory. + | RCWSSETAL = 875 + /// Read Check Write Software atomic bit Set on doubleword in memory. + | RCWSSETL = 876 + /// Read Check Write Software atomic bit Set on quadword in memory. + | RCWSSETP = 877 + /// Read Check Write Software atomic bit Set on quadword in memory. + | RCWSSETPA = 878 + /// Read Check Write Software atomic bit Set on quadword in memory. + | RCWSSETPAL = 879 + /// Read Check Write Software atomic bit Set on quadword in memory. + | RCWSSETPL = 880 + /// Read Check Write Software Swap doubleword in memory. + | RCWSSWP = 881 + /// Read Check Write Software Swap doubleword in memory. + | RCWSSWPA = 882 + /// Read Check Write Software Swap doubleword in memory. + | RCWSSWPAL = 883 + /// Read Check Write Software Swap doubleword in memory. + | RCWSSWPL = 884 + /// Read Check Write Software Swap quadword in memory. + | RCWSSWPP = 885 + /// Read Check Write Software Swap quadword in memory. + | RCWSSWPPA = 886 + /// Read Check Write Software Swap quadword in memory. + | RCWSSWPPAL = 887 + /// Read Check Write Software Swap quadword in memory. + | RCWSSWPPL = 888 + /// Read Check Write Swap doubleword in memory. + | RCWSWP = 889 + /// Read Check Write Swap doubleword in memory. + | RCWSWPA = 890 + /// Read Check Write Swap doubleword in memory. + | RCWSWPAL = 891 + /// Read Check Write Swap doubleword in memory. + | RCWSWPL = 892 + /// Read Check Write Swap quadword in memory. + | RCWSWPP = 893 + /// Read Check Write Swap quadword in memory. + | RCWSWPPA = 894 + /// Read Check Write Swap quadword in memory. + | RCWSWPPAL = 895 + /// Read Check Write Swap quadword in memory. + | RCWSWPPL = 896 + /// Return predicate of succesfully loaded elements. + | RDFFR = 897 + /// Return predicate of succesfully loaded elements, setting the cond flags. + | RDFFRS = 898 + /// Read multiple of Streaming SVE vector register size to scalar register. + | RDSVL = 899 + /// Read multiple of vector register size to scalar register. + | RDVL = 900 /// Return from subroutine. - | RET = 249 - /// Reverse bytes in register. - | REV = 250 - /// Reverse bytes in halfwords. - | REV16 = 251 - /// Reverses bytes in words. - | REV32 = 252 - /// Reverse elements in 64-bit doublewords (vector form). - | REV64 = 253 - /// Rotate right. - | ROR = 254 - /// Rotate right variable. - | RORV = 255 - /// Rounding shift right narrow immediate (vector form). - | RSHRN = 256 - /// Rounding shift right narrow immediate (vector form). - | RSHRN2 = 257 - /// Rounding subtract returning high, narrow (vector form). - | RSUBHN = 258 - /// Rounding subtract returning high, narrow (vector form). - | RSUBHN2 = 259 - /// Signed absolute difference and accumulate (vector form). - | SABA = 260 - /// Signed absolute difference and accumulate long (vector form). - | SABAL = 261 - /// Signed absolute difference and accumulate long (vector form). - | SABAL2 = 262 - /// Signed absolute difference (vector form). - | SABD = 263 - /// Signed absolute difference long (vector form). - | SABDL = 264 - /// Signed absolute difference long (vector form). - | SABDL2 = 265 - /// Signed add and accumulate long pairwise (vector form). - | SADALP = 266 - /// Signed add long (vector form). - | SADDL = 267 - /// Signed add long (vector form). - | SADDL2 = 268 - /// Signed add long pairwise (vector form). - | SADDLP = 269 - /// Signed add long (across vector). - | SADDLV = 270 - /// Signed add wide (vector form). - | SADDW = 271 - /// Signed add wide (vector form). - | SADDW2 = 272 - /// Subtract with carry. - | SBC = 273 - /// Subtract with carry and set flags. - | SBCS = 274 - /// Signed bitfield insert in zero. - | SBFIZ = 275 - /// Signed bitfield move. - | SBFM = 276 - /// Signed bitfield extract. - | SBFX = 277 - /// Signed integer scalar convert to FP, using the current rounding mode. - | SCVTF = 278 - /// Signed divide. - | SDIV = 279 - /// Send event. - | SEV = 280 - /// Send event local. - | SEVL = 281 + | RET = 901 + /// Return from subroutine, with pointer authentication. + | RETAA = 902 + /// Return from subroutine, with pointer authentication. + | RETAB = 903 + /// Reverse Bytes. + | REV = 904 + /// Reverse bytes in 16-bit halfwords. + | REV16 = 905 + /// Reverse bytes in 32-bit words. + | REV32 = 906 + /// Reverse Bytes: an alias of REV. + | REV64 = 907 + /// Reverse bytes / halfwords / words within elements (predicated). + | REVB = 908 + /// Reverse 64-bit doublewords in elements (predicated). + | REVD = 909 + /// Reverse bytes / halfwords / words within elements (predicated). + | REVH = 910 + /// Reverse bytes / halfwords / words within elements (predicated). + | REVW = 911 + /// Rotate, Mask Insert Flags. + | RMIF = 912 + /// Rotate right (immediate): an alias of EXTR. + | ROR = 913 + /// Rotate Right Variable. + | RORV = 914 + /// Range Prefetch Memory. + | RPRFM = 915 + /// Rounding Shift Right Narrow (immediate). + | RSHRN = 916 + /// Rounding Shift Right Narrow (immediate). + | RSHRN2 = 917 + /// Rounding shift right narrow by immediate (bottom). + | RSHRNB = 918 + /// Rounding shift right narrow by immediate (top). + | RSHRNT = 919 + /// Rounding Subtract returning High Narrow. + | RSUBHN = 920 + /// Rounding Subtract returning High Narrow. + | RSUBHN2 = 921 + /// Rounding subtract narrow high part (bottom). + | RSUBHNB = 922 + /// Rounding subtract narrow high part (top). + | RSUBHNT = 923 + /// Signed Absolute difference and Accumulate. + | SABA = 924 + /// Signed Absolute difference and Accumulate Long. + | SABAL = 925 + /// Signed Absolute difference and Accumulate Long. + | SABAL2 = 926 + /// Signed absolute difference and accumulate long (bottom). + | SABALB = 927 + /// Signed absolute difference and accumulate long (top). + | SABALT = 928 + /// Signed Absolute Difference. + | SABD = 929 + /// Signed Absolute Difference Long. + | SABDL = 930 + /// Signed Absolute Difference Long. + | SABDL2 = 931 + /// Signed absolute difference long (bottom). + | SABDLB = 932 + /// Signed absolute difference long (top). + | SABDLT = 933 + /// Signed Add and Accumulate Long Pairwise. + | SADALP = 934 + /// Signed Add Long (vector). + | SADDL = 935 + /// Signed Add Long (vector). + | SADDL2 = 936 + /// Signed add long (bottom). + | SADDLB = 937 + /// Signed add long (bottom + top). + | SADDLBT = 938 + /// Signed Add Long Pairwise. + | SADDLP = 939 + /// Signed add long (top). + | SADDLT = 940 + /// Signed Add Long across Vector. + | SADDLV = 941 + /// Signed add reduction to scalar. + | SADDV = 942 + /// Signed Add Wide. + | SADDW = 943 + /// Signed Add Wide. + | SADDW2 = 944 + /// Signed add wide (bottom). + | SADDWB = 945 + /// Signed add wide (top). + | SADDWT = 946 + /// Speculation Barrier. + | SB = 947 + /// Subtract with Carry. + | SBC = 948 + /// Subtract with carry long (bottom). + | SBCLB = 949 + /// Subtract with carry long (top). + | SBCLT = 950 + /// Subtract with Carry, setting flags. + | SBCS = 951 + /// Signed Bitfield Insert in Zero: an alias of SBFM. + | SBFIZ = 952 + /// Signed Bitfield Move. + | SBFM = 953 + /// Signed Bitfield Extract: an alias of SBFM. + | SBFX = 954 + /// Signed clamp to minimum/maximum vector. + | SCLAMP = 955 + /// Signed integer convert to FP (predicated). + | SCVTF = 956 + /// Signed Divide. + | SDIV = 957 + /// Signed reversed divide (predicated). + | SDIVR = 958 + /// Signed integer indexed dot product. + | SDOT = 959 + /// Multi-vector conditionally select elements from two vectors. + | SEL = 960 + /// Memory Set. + | SETE = 961 + /// Memory Set, non-temporal. + | SETEN = 962 + /// Memory Set, unprivileged. + | SETET = 963 + /// Memory Set, unprivileged and non-temporal. + | SETETN = 964 + /// Evaluation of 8 or 16 bit flag values. + | SETF16 = 965 + /// Evaluation of 8 or 16 bit flag values. + | SETF8 = 966 + /// Initialise the first-fault register to all true. + | SETFFR = 967 + /// Memory Set with tag setting. + | SETGE = 968 + /// Memory Set with tag setting, non-temporal. + | SETGEN = 969 + /// Memory Set with tag setting, unprivileged. + | SETGET = 970 + /// Memory Set with tag setting, unprivileged and non-temporal. + | SETGETN = 971 + /// Memory Set with tag setting. + | SETGM = 972 + /// Memory Set with tag setting, non-temporal. + | SETGMN = 973 + /// Memory Set with tag setting, unprivileged. + | SETGMT = 974 + /// Memory Set with tag setting, unprivileged and non-temporal. + | SETGMTN = 975 + /// Memory Set with tag setting. + | SETGP = 976 + /// Memory Set with tag setting, non-temporal. + | SETGPN = 977 + /// Memory Set with tag setting, unprivileged. + | SETGPT = 978 + /// Memory Set with tag setting, unprivileged and non-temporal. + | SETGPTN = 979 + /// Memory Set. + | SETM = 980 + /// Memory Set, non-temporal. + | SETMN = 981 + /// Memory Set, unprivileged. + | SETMT = 982 + /// Memory Set, unprivileged and non-temporal. + | SETMTN = 983 + /// Memory Set. + | SETP = 984 + /// Memory Set, non-temporal. + | SETPN = 985 + /// Memory Set, unprivileged. + | SETPT = 986 + /// Memory Set, unprivileged and non-temporal. + | SETPTN = 987 + /// Send Event. + | SEV = 988 + /// Send Event Local. + | SEVL = 989 /// SHA1 hash update (choose). - | SHA1C = 282 + | SHA1C = 990 /// SHA1 fixed rotate. - | SHA1H = 283 + | SHA1H = 991 /// SHA1 hash update (majority). - | SHA1M = 284 + | SHA1M = 992 /// SHA1 hash update (parity). - | SHA1P = 285 + | SHA1P = 993 /// SHA1 schedule update 0. - | SHA1SU0 = 286 + | SHA1SU0 = 994 /// SHA1 schedule update 1. - | SHA1SU1 = 287 + | SHA1SU1 = 995 /// SHA256 hash update (part 1). - | SHA256H = 288 + | SHA256H = 996 /// SHA256 hash update (part 2). - | SHA256H2 = 289 + | SHA256H2 = 997 /// SHA256 schedule update 0. - | SHA256SU0 = 290 + | SHA256SU0 = 998 /// SHA256 schedule update 1. - | SHA256SU1 = 291 - /// Signed halving add (vector form). - | SHADD = 292 - /// Shift left immediate (vector and scalar form). - | SHL = 293 - /// Shift left long (by element size) (vector form). - | SHLL = 294 - /// Shift left long (by element size) (vector form). - | SHLL2 = 295 - /// Shift right narrow immediate (vector form). - | SHRN = 296 - /// Shift right narrow immediate (vector form). - | SHRN2 = 297 - /// Signed halving subtract (vector form). - | SHSUB = 298 - /// Shift left and insert immediate (vector and scalar form). - | SLI = 299 - /// Signed multiply-add long. - | SMADDL = 300 - /// Signed maximum (vector form). - | SMAX = 301 - /// Signed maximum pairwise. - | SMAXP = 302 - /// Signed maximum (across vector). - | SMAXV = 303 - /// Generate exception targeting Exception level 3. - | SMC = 304 - /// Signed minimum (vector form). - | SMIN = 305 - /// Signed minimum pairwise. - | SMINP = 306 - /// Signed minimum (across vector). - | SMINV = 307 - /// Signed multiply-add long. - | SMLAL = 308 - /// Signed multiply-add long. - | SMLAL2 = 309 - /// Signed multiply-subtract long. - | SMLSL = 310 - /// Signed multiply-subtract long. - | SMLSL2 = 311 - /// Signed multiply-negate long. - | SMNEGL = 312 - /// Signed move vector element to general-purpose register. - | SMOV = 313 - /// Signed multiply-subtract long. - | SMSUBL = 314 - /// Signed multiply high. - | SMULH = 315 - /// Signed multiply long. - | SMULL = 316 - /// Signed multiply long. - | SMULL2 = 317 - /// Signed saturating absolute value. - | SQABS = 318 - /// Signed saturating add. - | SQADD = 319 - /// Signed saturating doubling multiply-add long. - | SQDMLAL = 320 - /// Signed saturating doubling multiply-add long. - | SQDMLAL2 = 321 - /// Signed saturating doubling multiply-subtract long. - | SQDMLSL = 322 - /// Signed saturating doubling multiply-subtract long. - | SQDMLSL2 = 323 - /// Signed saturating doubling multiply returning high half. - | SQDMULH = 324 - /// Signed saturating doubling multiply long. - | SQDMULL = 325 - /// Signed saturating doubling multiply long. - | SQDMULL2 = 326 - /// Signed saturating negate. - | SQNEG = 327 - /// Signed saturating rounding doubling multiply returning high half. - | SQRDMULH = 328 - /// Signed saturating rounding shift left (register). - | SQRSHL = 329 - /// Signed saturating rounded shift right narrow immediate. - | SQRSHRN = 330 - /// Signed saturating rounded shift right narrow immediate. - | SQRSHRN2 = 331 - /// Signed saturating shift right unsigned narrow immediate. - | SQRSHRUN = 332 - /// Signed saturating shift right unsigned narrow immediate. - | SQRSHRUN2 = 333 - /// Signed saturating shift left. - | SQSHL = 334 - /// Signed saturating shift left unsigned immediate. - | SQSHLU = 335 - /// Signed saturating shift right narrow immediate. - | SQSHRN = 336 - /// Signed saturating shift right narrow immediate. - | SQSHRN2 = 337 - /// Signed saturating shift right unsigned narrow immediate. - | SQSHRUN = 338 - /// Signed saturating shift right unsigned narrow immediate. - | SQSHRUN2 = 339 - /// Signed saturating subtract. - | SQSUB = 340 - /// Signed saturating extract narrow. - | SQXTN = 341 - /// Signed saturating extract narrow. - | SQXTN2 = 342 - /// Signed saturating extract unsigned narrow. - | SQXTUN = 343 - /// Signed saturating extract unsigned narrow. - | SQXTUN2 = 344 - /// Signed rounding halving add. - | SRHADD = 345 - /// Shift right and insert immediate. - | SRI = 346 - /// Signed rounding shift left (register). - | SRSHL = 347 - /// Signed rounding shift right immediate. - | SRSHR = 348 - /// Signed rounding shift right and accumulate immediate. - | SRSRA = 349 - /// Signed shift left (register). - | SSHL = 350 - /// Signed shift left long immediate. - | SSHLL = 351 - /// Signed shift left long immediate. - | SSHLL2 = 352 - /// Signed shift right immediate. - | SSHR = 353 - /// Signed integer shift right and accumulate immediate. - | SSRA = 354 - /// Signed subtract long. - | SSUBL = 355 - /// Signed subtract long. - | SSUBL2 = 356 - /// Signed subtract wide. - | SSUBW = 357 - /// Signed subtract wide. - | SSUBW2 = 358 - /// Store single 1-element structure from one lane of one register. - | ST1 = 359 - /// Store multiple 2-element structures from two consecutive registers. - | ST2 = 360 - /// Store multiple 3-element structures from three consecutive registers. - | ST3 = 361 - /// Store multiple 4-element structures from four consecutive registers. - | ST4 = 362 - /// Store-Release register. - | STLR = 363 - /// Store-Release byte. - | STLRB = 364 - /// Store-Release halfword. - | STLRH = 365 - /// Store-Release Exclusive pair. - | STLXP = 366 - /// Store-Release Exclusive register. - | STLXR = 367 - /// Store-Release Exclusive byte. - | STLXRB = 368 - /// Store-Release Exclusive halfword. - | STLXRH = 369 - /// Store Non-temporal Pair. - | STNP = 370 - /// Store Pair. - | STP = 371 - /// Store register. - | STR = 372 - /// Store byte. - | STRB = 373 - /// Store halfword. - | STRH = 374 - /// Store unprivileged register. - | STTR = 375 - /// Store unprivileged byte. - | STTRB = 376 - /// Store unprivileged halfword. - | STTRH = 377 - /// Store register (unscaled offset). - | STUR = 378 - /// Store byte (unscaled offset). - | STURB = 379 - /// Store halfword (unscaled offset). - | STURH = 380 - /// Store Exclusive pair. - | STXP = 381 - /// Store Exclusive register. - | STXR = 382 - /// Store Exclusive byte. - | STXRB = 383 - /// Store Exclusive halfword. - | STXRH = 384 - /// Subtract. - | SUB = 385 - /// Subtract returning high, narrow. - | SUBHN = 386 - /// Subtract returning high, narrow. - | SUBHN2 = 387 - /// Subtract and set flags. - | SUBS = 388 - /// Signed saturating accumulate of unsigned value. - | SUQADD = 389 - /// Generate exception targeting Exception level 1. - | SVC = 390 - /// Sign-extend byte. - | SXTB = 391 - /// Sign-extend halfword. - | SXTH = 392 - /// Sign-extend word. - | SXTW = 393 + | SHA256SU1 = 999 + /// SHA512 Hash update part 1. + | SHA512H = 1000 + /// SHA512 Hash update part 2. + | SHA512H2 = 1001 + /// SHA512 Schedule Update 0. + | SHA512SU0 = 1002 + /// SHA512 Schedule Update 1. + | SHA512SU1 = 1003 + /// Signed Halving Add. + | SHADD = 1004 + /// Shift Left (immediate). + | SHL = 1005 + /// Shift Left Long (by element size). + | SHLL = 1006 + /// Shift Left Long (by element size). + | SHLL2 = 1007 + /// Shift Right Narrow (immediate). + | SHRN = 1008 + /// Shift Right Narrow (immediate). + | SHRN2 = 1009 + /// Shift right narrow by immediate (bottom). + | SHRNB = 1010 + /// Shift right narrow by immediate (top). + | SHRNT = 1011 + /// Signed Halving Subtract. + | SHSUB = 1012 + /// Signed halving subtract reversed vectors. + | SHSUBR = 1013 + /// Shift Left and Insert (immediate). + | SLI = 1014 + /// SM3PARTW1. + | SM3PARTW1 = 1015 + /// SM3PARTW2. + | SM3PARTW2 = 1016 + /// SM3SS1. + | SM3SS1 = 1017 + /// SM3TT1A. + | SM3TT1A = 1018 + /// SM3TT1B. + | SM3TT1B = 1019 + /// SM3TT2A. + | SM3TT2A = 1020 + /// SM3TT2B. + | SM3TT2B = 1021 + /// SM4 Encode. + | SM4E = 1022 + /// SM4 Key. + | SM4EKEY = 1023 + /// Signed Multiply-Add Long. + | SMADDL = 1024 + /// Signed Maximum (vector). + | SMAX = 1025 + /// Signed Maximum Pairwise. + | SMAXP = 1026 + /// Signed maximum reduction of quadword vector segments. + | SMAXQV = 1027 + /// Signed Maximum across Vector. + | SMAXV = 1028 + /// Secure Monitor Call. + | SMC = 1029 + /// Signed Minimum (vector). + | SMIN = 1030 + /// Signed Minimum Pairwise. + | SMINP = 1031 + /// Signed minimum reduction of quadword vector segments. + | SMINQV = 1032 + /// Signed Minimum across Vector. + | SMINV = 1033 + /// Signed Multiply-Add Long (vector, by element). + | SMLAL = 1034 + /// Signed Multiply-Add Long (vector, by element). + | SMLAL2 = 1035 + /// Signed multiply-add long to accumulator (bottom, indexed). + | SMLALB = 1036 + /// Multi-vector signed integer multiply-add long long by indexed element. + | SMLALL = 1037 + /// Signed multiply-add long to accumulator (top, indexed). + | SMLALT = 1038 + /// Signed Multiply-Subtract Long (vector, by element). + | SMLSL = 1039 + /// Signed Multiply-Subtract Long (vector, by element). + | SMLSL2 = 1040 + /// Signed multiply-subtract long from accumulator (bottom, indexed). + | SMLSLB = 1041 + /// Multi-vector signed integer multiply-subtract long long by indexed elem. + | SMLSLL = 1042 + /// Signed multiply-subtract long from accumulator (top, indexed). + | SMLSLT = 1043 + /// Signed integer matrix multiply-accumulate. + | SMMLA = 1044 + /// Signed Multiply-Negate Long: an alias of SMSUBL. + | SMNEGL = 1045 + /// Signed integer sum of outer products and accumulate. + | SMOPA = 1046 + /// Signed integer sum of outer products and subtract. + | SMOPS = 1047 + /// Signed Move vector element to general-purpose register. + | SMOV = 1048 + /// Enables access to Streaming SVE mode and SME architectural state. + | SMSTART = 1049 + /// Disables access to Streaming SVE mode and SME architectural state. + | SMSTOP = 1050 + /// Signed Multiply-Subtract Long. + | SMSUBL = 1051 + /// Signed Multiply High. + | SMULH = 1052 + /// Signed Multiply Long: an alias of SMADDL. + | SMULL = 1053 + /// Signed Multiply Long (vector, by element). + | SMULL2 = 1054 + /// Signed multiply long (bottom, indexed). + | SMULLB = 1055 + /// Signed multiply long (top, indexed). + | SMULLT = 1056 + /// Splice two vectors under predicate control. + | SPLICE = 1057 + /// Signed saturating Absolute value. + | SQABS = 1058 + /// Signed saturating Add. + | SQADD = 1059 + /// Saturating complex integer add with rotate. + | SQCADD = 1060 + /// Multi-vector signed saturating extract narrow. + | SQCVT = 1061 + /// Signed saturating extract narrow and interleave. + | SQCVTN = 1062 + /// Multi-vector signed saturating unsigned extract narrow. + | SQCVTU = 1063 + /// Signed saturating unsigned extract narrow and interleave. + | SQCVTUN = 1064 + /// Signed saturating decr scalar by mul of 8-bit pred constraint elem count. + | SQDECB = 1065 + /// Signed saturating decr scalar by mul of 64-bit pred constraint elem count. + | SQDECD = 1066 + /// Signed saturating decr scalar by mul of 16-bit pred constraint elem count. + | SQDECH = 1067 + /// Signed saturating decr scalar by count of true predicate elements. + | SQDECP = 1068 + /// Signed saturating decr scalar by mul of 32-bit pred constraint elem count. + | SQDECW = 1069 + /// Signed saturating Doubling Multiply-Add Long (by element). + | SQDMLAL = 1070 + /// Signed saturating Doubling Multiply-Add Long (by element). + | SQDMLAL2 = 1071 + /// Signed saturating doubling mul-add long to accumulator (bottom, indexed). + | SQDMLALB = 1072 + /// Signed saturating doubling mul-add long to accumulator (bottom �� top). + | SQDMLALBT = 1073 + /// Signed saturating doubling mul-add long to accumulator (top, indexed). + | SQDMLALT = 1074 + /// Signed saturating Doubling Multiply-Subtract Long (by element). + | SQDMLSL = 1075 + /// Signed saturating Doubling Multiply-Subtract Long (by element). + | SQDMLSL2 = 1076 + /// Signed saturating doubling multiply-subtract long from accumulator. + | SQDMLSLB = 1077 + /// Signed saturating doubling multiply-subtract long from accumulator. + | SQDMLSLBT = 1078 + /// Signed saturating doubling multiply-subtract long from accumulator. + | SQDMLSLT = 1079 + /// Signed saturating Doubling Multiply returning High half (by element). + | SQDMULH = 1080 + /// Signed saturating Doubling Multiply Long (by element). + | SQDMULL = 1081 + /// Signed saturating Doubling Multiply Long (by element). + | SQDMULL2 = 1082 + /// Signed saturating doubling multiply long (bottom, indexed). + | SQDMULLB = 1083 + /// Signed saturating doubling multiply long (top, indexed). + | SQDMULLT = 1084 + /// Signed saturating incr scalar by mul of 8-bit pred constraint elem count. + | SQINCB = 1085 + /// Signed saturating incr scalar by mul of 64-bit pred constraint elem count. + | SQINCD = 1086 + /// Signed saturating incr scalar by mul of 16-bit pred constraint elem count. + | SQINCH = 1087 + /// Signed saturating incr scalar by count of true predicate elements. + | SQINCP = 1088 + /// Signed saturating incr scalar by mul of 32-bit pred constraint elem count. + | SQINCW = 1089 + /// Signed saturating Negate. + | SQNEG = 1090 + /// Saturating rounding doubling complex int multiply-add high with rotate. + | SQRDCMLAH = 1091 + /// Signed Saturating Rounding Doubling Mul Accumulate returning High Half. + | SQRDMLAH = 1092 + /// Signed Saturating Rounding Doubling Mul Subtract returning High Half. + | SQRDMLSH = 1093 + /// Signed saturating Rounding Doubling Multiply returning High half. + | SQRDMULH = 1094 + /// Signed saturating Rounding Shift Left (register). + | SQRSHL = 1095 + /// Signed saturating rounding shift left reversed vectors (predicated). + | SQRSHLR = 1096 + /// Multi-vector signed saturating rounding shift right narrow by immediate. + | SQRSHR = 1097 + /// Signed saturating Rounded Shift Right Narrow (immediate). + | SQRSHRN = 1098 + /// Signed saturating Rounded Shift Right Narrow (immediate). + | SQRSHRN2 = 1099 + /// Signed saturating rounding shift right narrow by immediate (bottom). + | SQRSHRNB = 1100 + /// Signed saturating rounding shift right narrow by immediate (top). + | SQRSHRNT = 1101 + /// Multi-vector signed saturating rounding shf right unsigned narrow by imm. + | SQRSHRU = 1102 + /// Signed saturating Rounded Shift Right Unsigned Narrow (immediate). + | SQRSHRUN = 1103 + /// Signed saturating Rounded Shift Right Unsigned Narrow (immediate). + | SQRSHRUN2 = 1104 + /// Signed saturating rounding shift right unsigned narrow by imm (bottom). + | SQRSHRUNB = 1105 + /// Signed saturating rounding shift right unsigned narrow by immediate (top). + | SQRSHRUNT = 1106 + /// Signed saturating Shift Left (immediate). + | SQSHL = 1107 + /// Signed saturating shift left reversed vectors (predicated). + | SQSHLR = 1108 + /// Signed saturating Shift Left Unsigned (immediate). + | SQSHLU = 1109 + /// Signed saturating Shift Right Narrow (immediate). + | SQSHRN = 1110 + /// Signed saturating Shift Right Narrow (immediate). + | SQSHRN2 = 1111 + /// Signed saturating shift right narrow by immediate (bottom). + | SQSHRNB = 1112 + /// Signed saturating shift right narrow by immediate (top). + | SQSHRNT = 1113 + /// Signed saturating Shift Right Unsigned Narrow (immediate). + | SQSHRUN = 1114 + /// Signed saturating Shift Right Unsigned Narrow (immediate). + | SQSHRUN2 = 1115 + /// Signed saturating shift right unsigned narrow by immediate (bottom). + | SQSHRUNB = 1116 + /// Signed saturating shift right unsigned narrow by immediate (top). + | SQSHRUNT = 1117 + /// Signed saturating Subtract. + | SQSUB = 1118 + /// Signed saturating subtraction reversed vectors (predicated). + | SQSUBR = 1119 + /// Signed saturating extract Narrow. + | SQXTN = 1120 + /// Signed saturating extract Narrow. + | SQXTN2 = 1121 + /// Signed saturating extract narrow (bottom). + | SQXTNB = 1122 + /// Signed saturating extract narrow (top). + | SQXTNT = 1123 + /// Signed saturating extract Unsigned Narrow. + | SQXTUN = 1124 + /// Signed saturating extract Unsigned Narrow. + | SQXTUN2 = 1125 + /// Signed saturating unsigned extract narrow (bottom). + | SQXTUNB = 1126 + /// Signed saturating unsigned extract narrow (top). + | SQXTUNT = 1127 + /// Signed Rounding Halving Add. + | SRHADD = 1128 + /// Shift Right and Insert (immediate). + | SRI = 1129 + /// Signed Rounding Shift Left (register). + | SRSHL = 1130 + /// Signed rounding shift left reversed vectors (predicated). + | SRSHLR = 1131 + /// Signed Rounding Shift Right (immediate). + | SRSHR = 1132 + /// Signed Rounding Shift Right and Accumulate (immediate). + | SRSRA = 1133 + /// Speculative Store Bypass Barrier: an alias of DSB. + | SSBB = 1134 + /// Signed Shift Left (register). + | SSHL = 1135 + /// Signed Shift Left Long (immediate). + | SSHLL = 1136 + /// Signed Shift Left Long (immediate). + | SSHLL2 = 1137 + /// Signed shift left long by immediate (bottom). + | SSHLLB = 1138 + /// Signed shift left long by immediate (top). + | SSHLLT = 1139 + /// Signed Shift Right (immediate). + | SSHR = 1140 + /// Signed Shift Right and Accumulate (immediate). + | SSRA = 1141 + /// Signed Subtract Long. + | SSUBL = 1142 + /// Signed Subtract Long. + | SSUBL2 = 1143 + /// Signed subtract long (bottom). + | SSUBLB = 1144 + /// Signed subtract long (bottom - top). + | SSUBLBT = 1145 + /// Signed subtract long (top). + | SSUBLT = 1146 + /// Signed subtract long (top - bottom). + | SSUBLTB = 1147 + /// Signed Subtract Wide. + | SSUBW = 1148 + /// Signed Subtract Wide. + | SSUBW2 = 1149 + /// Signed subtract wide (bottom). + | SSUBWB = 1150 + /// Signed subtract wide (top). + | SSUBWT = 1151 + /// Store multiple single-element struct from one, two, three, or four regs. + | ST1 = 1152 + /// Contiguous store of bytes from multiple consecutive vectors. + | ST1B = 1153 + /// Contiguous store of doublewords from multiple consecutive vectors. + | ST1D = 1154 + /// Contiguous store of halfwords from multiple consecutive vectors. + | ST1H = 1155 + /// Scatter store quadwords. + | ST1Q = 1156 + /// Contiguous store of words from multiple consecutive vectors. + | ST1W = 1157 + /// Store multiple 2-element structures from two registers. + | ST2 = 1158 + /// Contiguous store two-byte structures from two vectors. + | ST2B = 1159 + /// Contiguous store two-doubleword structures from two vectors. + | ST2D = 1160 + /// Store Allocation Tags. + | ST2G = 1161 + /// Contiguous store two-halfword structures from two vectors. + | ST2H = 1162 + /// Contiguous store two-quadword structures from two vectors. + | ST2Q = 1163 + /// Contiguous store two-word structures from two vectors. + | ST2W = 1164 + /// Store multiple 3-element structures from three registers. + | ST3 = 1165 + /// Contiguous store three-byte structures from three vectors. + | ST3B = 1166 + /// Contiguous store three-doubleword structures from three vectors. + | ST3D = 1167 + /// Contiguous store three-halfword structures from three vectors. + | ST3H = 1168 + /// Contiguous store three-quadword structures from three vectors. + | ST3Q = 1169 + /// Contiguous store three-word structures from three vectors. + | ST3W = 1170 + /// Store multiple 4-element structures from four registers. + | ST4 = 1171 + /// Contiguous store four-byte structures from four vectors. + | ST4B = 1172 + /// Contiguous store four-doubleword structures from four vectors. + | ST4D = 1173 + /// Contiguous store four-halfword structures from four vectors. + | ST4H = 1174 + /// Contiguous store four-quadword structures from four vectors. + | ST4Q = 1175 + /// Contiguous store four-word structures from four vectors. + | ST4W = 1176 + /// Single-copy Atomic 64-byte Store without Return. + | ST64B = 1177 + /// Single-copy Atomic 64-byte Store with Return. + | ST64BV = 1178 + /// Single-copy Atomic 64-byte EL0 Store with Return. + | ST64BV0 = 1179 + /// Atomic add on word or doubleword in memory, without return. + | STADD = 1180 + /// Atomic add on byte in memory, without return. + | STADDB = 1181 + /// Atomic add on halfword in memory, without return. + | STADDH = 1182 + /// Atomic add on word or doubleword in memory, without return. + | STADDL = 1183 + /// Atomic add on byte in memory, without return. + | STADDLB = 1184 + /// Atomic add on halfword in memory, without return. + | STADDLH = 1185 + /// Atomic bit clear on word or doubleword in memory, without return. + | STCLR = 1186 + /// Atomic bit clear on byte in memory, without return. + | STCLRB = 1187 + /// Atomic bit clear on halfword in memory, without return. + | STCLRH = 1188 + /// Atomic bit clear on word or doubleword in memory, without return. + | STCLRL = 1189 + /// Atomic bit clear on byte in memory, without return. + | STCLRLB = 1190 + /// Atomic bit clear on halfword in memory, without return. + | STCLRLH = 1191 + /// Atomic exclusive OR on word or doubleword in memory, without return. + | STEOR = 1192 + /// Atomic exclusive OR on byte in memory, without return. + | STEORB = 1193 + /// Atomic exclusive OR on halfword in memory, without return. + | STEORH = 1194 + /// Atomic exclusive OR on word or doubleword in memory, without return. + | STEORL = 1195 + /// Atomic exclusive OR on byte in memory, without return. + | STEORLB = 1196 + /// Atomic exclusive OR on halfword in memory, without return. + | STEORLH = 1197 + /// Store Allocation Tag. + | STG = 1198 + /// Store Tag Multiple. + | STGM = 1199 + /// Store Allocation Tag and Pair of registers. + | STGP = 1200 + /// Store-Release ordered Pair of registers. + | STILP = 1201 + /// Store-Release a single-element structure from one lane of one register. + | STL1 = 1202 + /// Store LORelease Register. + | STLLR = 1203 + /// Store LORelease Register Byte. + | STLLRB = 1204 + /// Store LORelease Register Halfword. + | STLLRH = 1205 + /// Store-Release Register. + | STLR = 1206 + /// Store-Release Register Byte. + | STLRB = 1207 + /// Store-Release Register Halfword. + | STLRH = 1208 + /// Store-Release Register (unscaled). + | STLUR = 1209 + /// Store-Release Register Byte (unscaled). + | STLURB = 1210 + /// Store-Release Register Halfword (unscaled). + | STLURH = 1211 + /// Store-Release Exclusive Pair of registers. + | STLXP = 1212 + /// Store-Release Exclusive Register. + | STLXR = 1213 + /// Store-Release Exclusive Register Byte. + | STLXRB = 1214 + /// Store-Release Exclusive Register Halfword. + | STLXRH = 1215 + /// Store Pair of Registers, with non-temporal hint. + | STNP = 1216 + /// Contiguous store non-temporal of bytes from multiple consecutive vectors. + | STNT1B = 1217 + /// Contiguous store non-temporal of doublewords from mul consecutive vectors. + | STNT1D = 1218 + /// Contiguous store non-temporal of halfwords from mul consecutive vectors. + | STNT1H = 1219 + /// Contiguous store non-temporal of words from multiple consecutive vectors. + | STNT1W = 1220 + /// Store Pair of Registers. + | STP = 1221 + /// Store Register (immediate). + | STR = 1222 + /// Store Register Byte (immediate). + | STRB = 1223 + /// Store Register Halfword (immediate). + | STRH = 1224 + /// Atomic bit set on word or doubleword in memory, without return. + | STSET = 1225 + /// Atomic bit set on byte in memory, without return. + | STSETB = 1226 + /// Atomic bit set on halfword in memory, without return. + | STSETH = 1227 + /// Atomic bit set on word or doubleword in memory, without return. + | STSETL = 1228 + /// Atomic bit set on byte in memory, without return. + | STSETLB = 1229 + /// Atomic bit set on halfword in memory, without return. + | STSETLH = 1230 + /// Atomic signed maximum on word or doubleword in memory, without return. + | STSMAX = 1231 + /// Atomic signed maximum on byte in memory, without return. + | STSMAXB = 1232 + /// Atomic signed maximum on halfword in memory, without return. + | STSMAXH = 1233 + /// Atomic signed maximum on word or doubleword in memory, without return. + | STSMAXL = 1234 + /// Atomic signed maximum on byte in memory, without return. + | STSMAXLB = 1235 + /// Atomic signed maximum on halfword in memory, without return. + | STSMAXLH = 1236 + /// Atomic signed minimum on word or doubleword in memory, without return. + | STSMIN = 1237 + /// Atomic signed minimum on byte in memory, without return. + | STSMINB = 1238 + /// Atomic signed minimum on halfword in memory, without return. + | STSMINH = 1239 + /// Atomic signed minimum on word or doubleword in memory, without return. + | STSMINL = 1240 + /// Atomic signed minimum on byte in memory, without return. + | STSMINLB = 1241 + /// Atomic signed minimum on halfword in memory, without return. + | STSMINLH = 1242 + /// Store Register (unprivileged). + | STTR = 1243 + /// Store Register Byte (unprivileged). + | STTRB = 1244 + /// Store Register Halfword (unprivileged). + | STTRH = 1245 + /// Atomic unsigned maximum on word or doubleword in memory, without return. + | STUMAX = 1246 + /// Atomic unsigned maximum on byte in memory, without return. + | STUMAXB = 1247 + /// Atomic unsigned maximum on halfword in memory, without return. + | STUMAXH = 1248 + /// Atomic unsigned maximum on word or doubleword in memory, without return. + | STUMAXL = 1249 + /// Atomic unsigned maximum on byte in memory, without return. + | STUMAXLB = 1250 + /// Atomic unsigned maximum on halfword in memory, without return. + | STUMAXLH = 1251 + /// Atomic unsigned minimum on word or doubleword in memory, without return. + | STUMIN = 1252 + /// Atomic unsigned minimum on byte in memory, without return. + | STUMINB = 1253 + /// Atomic unsigned minimum on halfword in memory, without return. + | STUMINH = 1254 + /// Atomic unsigned minimum on word or doubleword in memory, without return. + | STUMINL = 1255 + /// Atomic unsigned minimum on byte in memory, without return. + | STUMINLB = 1256 + /// Atomic unsigned minimum on halfword in memory, without return. + | STUMINLH = 1257 + /// Store Register (unscaled). + | STUR = 1258 + /// Store Register Byte (unscaled). + | STURB = 1259 + /// Store Register Halfword (unscaled). + | STURH = 1260 + /// Store Exclusive Pair of registers. + | STXP = 1261 + /// Store Exclusive Register. + | STXR = 1262 + /// Store Exclusive Register Byte. + | STXRB = 1263 + /// Store Exclusive Register Halfword. + | STXRH = 1264 + /// Store Allocation Tags, Zeroing. + | STZ2G = 1265 + /// Store Allocation Tag, Zeroing. + | STZG = 1266 + /// Store Tag and Zero Multiple. + | STZGM = 1267 + /// Subtract multi-vector from ZA array vector accumulators. + | SUB = 1268 + /// Subtract with Tag. + | SUBG = 1269 + /// Subtract returning High Narrow. + | SUBHN = 1270 + /// Subtract returning High Narrow. + | SUBHN2 = 1271 + /// Subtract narrow high part (bottom). + | SUBHNB = 1272 + /// Subtract narrow high part (top). + | SUBHNT = 1273 + /// Subtract Pointer. + | SUBP = 1274 + /// Subtract Pointer, setting Flags. + | SUBPS = 1275 + /// Reversed subtract from immediate (unpredicated). + | SUBR = 1276 + /// Subtract (extended register), setting flags. + | SUBS = 1277 + /// Signed by unsigned integer indexed dot product. + | SUDOT = 1278 + /// Multi-vector signed by unsigned int mul-add long long by indexed element. + | SUMLALL = 1279 + /// Signed by unsigned integer sum of outer products and accumulate. + | SUMOPA = 1280 + /// Signed by unsigned integer sum of outer products and subtract. + | SUMOPS = 1281 + /// Unpack and sign-extend multi-vector elements. + | SUNPK = 1282 + /// Signed unpack and extend half of vector. + | SUNPKHI = 1283 + /// Signed unpack and extend half of vector. + | SUNPKLO = 1284 + /// Signed saturating Accumulate of Unsigned value. + | SUQADD = 1285 + /// Multi-vector signed by unsigned int vertical dot-product by indexed elem. + | SUVDOT = 1286 + /// Supervisor Call. + | SVC = 1287 + /// Multi-vector signed integer vertical dot-product by indexed element. + | SVDOT = 1288 + /// Swap word or doubleword in memory. + | SWP = 1289 + /// Swap word or doubleword in memory. + | SWPA = 1290 + /// Swap byte in memory. + | SWPAB = 1291 + /// Swap halfword in memory. + | SWPAH = 1292 + /// Swap word or doubleword in memory. + | SWPAL = 1293 + /// Swap byte in memory. + | SWPALB = 1294 + /// Swap halfword in memory. + | SWPALH = 1295 + /// Swap byte in memory. + | SWPB = 1296 + /// Swap halfword in memory. + | SWPH = 1297 + /// Swap word or doubleword in memory. + | SWPL = 1298 + /// Swap byte in memory. + | SWPLB = 1299 + /// Swap halfword in memory. + | SWPLH = 1300 + /// Swap quadword in memory. + | SWPP = 1301 + /// Swap quadword in memory. + | SWPPA = 1302 + /// Swap quadword in memory. + | SWPPAL = 1303 + /// Swap quadword in memory. + | SWPPL = 1304 + /// Signed Extend Byte: an alias of SBFM. + | SXTB = 1305 + /// Sign Extend Halfword: an alias of SBFM. + | SXTH = 1306 + /// Signed extend Long: an alias of SSHLL, SSHLL2. + | SXTL = 1307 + /// Signed extend Long: an alias of SSHLL, SSHLL2. + | SXTL2 = 1308 + /// Sign Extend Word: an alias of SBFM. + | SXTW = 1309 /// System instruction. - | SYS = 394 + | SYS = 1310 /// System instruction with result. - | SYSL = 395 - /// Table vector lookup. - | TBL = 396 - /// Test bit and branch if nonzero. - | TBNZ = 397 + | SYSL = 1311 + /// 128-bit System instruction. + | SYSP = 1312 + /// Table vector Lookup. + | TBL = 1313 + /// Programmable table lookup within each quadword vector segment (zeroing). + | TBLQ = 1314 + /// Test bit and Branch if Nonzero. + | TBNZ = 1315 /// Table vector lookup extension. - | TBX = 398 - /// Test bit and branch if zero. - | TBZ = 399 + | TBX = 1316 + /// Programmable table lookup within each quadword vector segment (merging). + | TBXQ = 1317 + /// Test bit and Branch if Zero. + | TBZ = 1318 + /// Cancel current transaction. + | TCANCEL = 1319 + /// Commit current transaction. + | TCOMMIT = 1320 + /// TLB Invalidate operation: an alias of SYS. + | TLBI = 1321 + /// TLB Invalidate Pair operation: an alias of SYSP. + | TLBIP = 1322 + /// Trace Instrumentation: an alias of SYS. + | TRCIT = 1323 /// Transpose vectors (primary). - | TRN1 = 400 + | TRN1 = 1324 /// Transpose vectors (secondary). - | TRN2 = 401 - /// Test bits. - | TST = 402 - /// Unsigned absolute difference and accumulate. - | UABA = 403 - /// Unsigned absolute difference and accumulate long. - | UABAL = 404 - /// Unsigned absolute difference and accumulate long. - | UABAL2 = 405 - /// Unsigned absolute difference. - | UABD = 406 - /// Unsigned absolute difference long. - | UABDL = 407 - /// Unsigned absolute difference long. - | UABDL2 = 408 - /// Unsigned add and accumulate long pairwise. - | UADALP = 409 - /// Unsigned add long. - | UADDL = 410 - /// Unsigned add long. - | UADDL2 = 411 - /// Unsigned add long pairwise. - | UADDLP = 412 - /// Unsigned add long (across vector). - | UADDLV = 413 - /// Unsigned add wide. - | UADDW = 414 - /// Unsigned add wide. - | UADDW2 = 415 - /// Unsigned bitfield insert in zero. - | UBFIZ = 416 - /// Unsigned bitfield move (32-bit). - | UBFM = 417 - /// Unsigned bitfield extract. - | UBFX = 418 - /// Unsigned integer scalar convert to FP, using the current rounding mode. - | UCVTF = 419 - /// Unsigned divide. - | UDIV = 420 - /// Unsigned halving add. - | UHADD = 421 - /// Unsigned halving subtract. - | UHSUB = 422 - /// Unsigned multiply-add long. - | UMADDL = 423 - /// Unsigned maximum. - | UMAX = 424 - /// Unsigned maximum pairwise. - | UMAXP = 425 - /// Unsigned maximum (across vector). - | UMAXV = 426 - /// Unsigned minimum. - | UMIN = 427 - /// Unsigned minimum pairwise. - | UMINP = 428 - /// Unsigned minimum (across vector). - | UMINV = 429 - /// Unsigned multiply-add long. - | UMLAL = 430 - /// Unsigned multiply-add long. - | UMLAL2 = 431 - /// Unsigned multiply-subtract long. - | UMLSL = 432 - /// Unsigned multiply-subtract long. - | UMLSL2 = 433 - /// Unsigned multiply-negate long. - | UMNEGL = 434 - /// Unsigned move vector element to general-purpose register. - | UMOV = 435 - /// Unsigned multiply-subtract long. - | UMSUBL = 436 - /// Unsigned multiply high. - | UMULH = 437 - /// Unsigned multiply long. - | UMULL = 438 - /// Unsigned multiply long. - | UMULL2 = 439 - /// Unsigned saturating add. - | UQADD = 440 - /// Unsigned saturating rounding shift left (register). - | UQRSHL = 441 - /// Unsigned saturating rounded shift right narrow immediate. - | UQRSHRN = 442 - /// Unsigned saturating rounded shift right narrow immediate. - | UQRSHRN2 = 443 - /// Unsigned saturating shift left (register). - | UQSHL = 444 - /// Unsigned saturating shift right narrow immediate. - | UQSHRN = 445 - /// Unsigned saturating shift right narrow immediate. - | UQSHRN2 = 446 - /// Unsigned saturating subtract. - | UQSUB = 447 - /// Unsigned saturating extract narrow. - | UQXTN = 448 - /// Unsigned saturating extract narrow. - | UQXTN2 = 449 - /// Unsigned reciprocal estimate. - | URECPE = 450 - /// Unsigned rounding halving add. - | URHADD = 451 - /// Unsigned rounding shift left (register). - | URSHL = 452 - /// Unsigned rounding shift right immediate. - | URSHR = 453 - /// Unsigned reciprocal square root estimate. - | URSQRTE = 454 - /// Unsigned integer rounding shift right and accumulate immediate. - | URSRA = 455 - /// Unsigned shift left (register). - | USHL = 456 - /// Unsigned shift left long immediate. - | USHLL = 457 - /// Unsigned shift left long immediate. - | USHLL2 = 458 - /// Unsigned shift right immediate. - | USHR = 459 - /// Unsigned saturating accumulate of signed value. - | USQADD = 460 - /// Unsigned shift right and accumulate immediate. - | USRA = 461 - /// Unsigned subtract long. - | USUBL = 462 - /// Unsigned subtract long. - | USUBL2 = 463 - /// Unsigned subtract wide. - | USUBW = 464 - /// Unsigned subtract wide. - | USUBW2 = 465 - /// Unsigned extend byte. - | UXTB = 466 - /// Unsigned extend halfword. - | UXTH = 467 + | TRN2 = 1325 + /// Trace Synchronization Barrier. + | TSB = 1326 + /// Test bits (immediate): an alias of ANDS (immediate). + | TST = 1327 + /// Start transaction. + | TSTART = 1328 + /// Test transaction state. + | TTEST = 1329 + /// Unsigned Absolute difference and Accumulate. + | UABA = 1330 + /// Unsigned Absolute difference and Accumulate Long. + | UABAL = 1331 + /// Unsigned Absolute difference and Accumulate Long. + | UABAL2 = 1332 + /// Unsigned absolute difference and accumulate long (bottom). + | UABALB = 1333 + /// Unsigned absolute difference and accumulate long (top). + | UABALT = 1334 + /// Unsigned Absolute Difference (vector). + | UABD = 1335 + /// Unsigned Absolute Difference Long. + | UABDL = 1336 + /// Unsigned Absolute Difference Long. + | UABDL2 = 1337 + /// Unsigned absolute difference long (bottom). + | UABDLB = 1338 + /// Unsigned absolute difference long (top). + | UABDLT = 1339 + /// Unsigned Add and Accumulate Long Pairwise. + | UADALP = 1340 + /// Unsigned Add Long (vector). + | UADDL = 1341 + /// Unsigned Add Long (vector). + | UADDL2 = 1342 + /// Unsigned add long (bottom). + | UADDLB = 1343 + /// Unsigned Add Long Pairwise. + | UADDLP = 1344 + /// Unsigned add long (top). + | UADDLT = 1345 + /// Unsigned sum Long across Vector. + | UADDLV = 1346 + /// Unsigned add reduction to scalar. + | UADDV = 1347 + /// Unsigned Add Wide. + | UADDW = 1348 + /// Unsigned Add Wide. + | UADDW2 = 1349 + /// Unsigned add wide (bottom). + | UADDWB = 1350 + /// Unsigned add wide (top). + | UADDWT = 1351 + /// Unsigned Bitfield Insert in Zero: an alias of UBFM. + | UBFIZ = 1352 + /// Unsigned Bitfield Move. + | UBFM = 1353 + /// Unsigned Bitfield Extract: an alias of UBFM. + | UBFX = 1354 + /// Unsigned clamp to minimum/maximum vector. + | UCLAMP = 1355 + /// Unsigned integer convert to FP (predicated). + | UCVTF = 1356 + /// Permanently Undefined. + | UDF = 1357 + /// Unsigned Divide. + | UDIV = 1358 + /// Unsigned reversed divide (predicated). + | UDIVR = 1359 + /// Unsigned integer indexed dot product. + | UDOT = 1360 + /// Unsigned Halving Add. + | UHADD = 1361 + /// Unsigned Halving Subtract. + | UHSUB = 1362 + /// Unsigned halving subtract reversed vectors. + | UHSUBR = 1363 + /// Unsigned Multiply-Add Long. + | UMADDL = 1364 + /// Unsigned Maximum (vector). + | UMAX = 1365 + /// Unsigned Maximum Pairwise. + | UMAXP = 1366 + /// Unsigned maximum reduction of quadword vector segments. + | UMAXQV = 1367 + /// Unsigned Maximum across Vector. + | UMAXV = 1368 + /// Unsigned Minimum (vector). + | UMIN = 1369 + /// Unsigned Minimum Pairwise. + | UMINP = 1370 + /// Unsigned minimum reduction of quadword vector segments. + | UMINQV = 1371 + /// Unsigned Minimum across Vector. + | UMINV = 1372 + /// Unsigned Multiply-Add Long (vector, by element). + | UMLAL = 1373 + /// Unsigned Multiply-Add Long (vector, by element). + | UMLAL2 = 1374 + /// Unsigned multiply-add long to accumulator (bottom, indexed). + | UMLALB = 1375 + /// Multi-vector unsigned integer multiply-add long long by indexed element. + | UMLALL = 1376 + /// Unsigned multiply-add long to accumulator (top, indexed). + | UMLALT = 1377 + /// Unsigned Multiply-Subtract Long (vector, by element). + | UMLSL = 1378 + /// Unsigned Multiply-Subtract Long (vector, by element). + | UMLSL2 = 1379 + /// Unsigned multiply-subtract long from accumulator (bottom, indexed). + | UMLSLB = 1380 + /// Multi-vector unsigned int multiply-subtract long long by indexed element. + | UMLSLL = 1381 + /// Unsigned multiply-subtract long from accumulator (top, indexed). + | UMLSLT = 1382 + /// Unsigned integer matrix multiply-accumulate. + | UMMLA = 1383 + /// Unsigned Multiply-Negate Long: an alias of UMSUBL. + | UMNEGL = 1384 + /// Unsigned integer sum of outer products and accumulate. + | UMOPA = 1385 + /// Unsigned integer sum of outer products and subtract. + | UMOPS = 1386 + /// Unsigned Move vector element to general-purpose register. + | UMOV = 1387 + /// Unsigned Multiply-Subtract Long. + | UMSUBL = 1388 + /// Unsigned Multiply High. + | UMULH = 1389 + /// Unsigned Multiply Long: an alias of UMADDL. + | UMULL = 1390 + /// Unsigned Multiply Long (vector, by element). + | UMULL2 = 1391 + /// Unsigned multiply long (bottom, indexed). + | UMULLB = 1392 + /// Unsigned multiply long (top, indexed). + | UMULLT = 1393 + /// Unsigned saturating Add. + | UQADD = 1394 + /// Multi-vector unsigned saturating extract narrow. + | UQCVT = 1395 + /// Unsigned saturating extract narrow and interleave. + | UQCVTN = 1396 + /// Unsigned saturating decr scalar by mul of 8-bit pred constraint elem cnt. + | UQDECB = 1397 + /// Unsigned saturating decr scalar by mul of 64-bit pred constraint elem cnt. + | UQDECD = 1398 + /// Unsigned saturating decr scalar by mul of 16-bit pred constraint elem cnt. + | UQDECH = 1399 + /// Unsigned saturating decrement scalar by count of true predicate elements. + | UQDECP = 1400 + /// Unsigned saturating decr scalar by mul of 32-bit pred constraint elem cnt. + | UQDECW = 1401 + /// Unsigned saturating incr scalar by mul of 8-bit pred constraint elem cnt. + | UQINCB = 1402 + /// Unsigned saturating incr scalar by mul of 64-bit pred constraint elem cnt. + | UQINCD = 1403 + /// Unsigned saturating incr scalar by mul of 16-bit pred constraint elem cnt. + | UQINCH = 1404 + /// Unsigned saturating increment scalar by count of true predicate elements. + | UQINCP = 1405 + /// Unsigned saturating incr scalar by mul of 32-bit pred constraint elem cnt. + | UQINCW = 1406 + /// Unsigned saturating Rounding Shift Left (register). + | UQRSHL = 1407 + /// Unsigned saturating rounding shift left reversed vectors (predicated). + | UQRSHLR = 1408 + /// Multi-vector unsigned saturating rounding shift right narrow by immediate. + | UQRSHR = 1409 + /// Unsigned saturating Rounded Shift Right Narrow (immediate). + | UQRSHRN = 1410 + /// Unsigned saturating Rounded Shift Right Narrow (immediate). + | UQRSHRN2 = 1411 + /// Unsigned saturating rounding shift right narrow by immediate (bottom). + | UQRSHRNB = 1412 + /// Unsigned saturating rounding shift right narrow by immediate (top). + | UQRSHRNT = 1413 + /// Unsigned saturating Shift Left (immediate). + | UQSHL = 1414 + /// Unsigned saturating shift left reversed vectors (predicated). + | UQSHLR = 1415 + /// Unsigned saturating Shift Right Narrow (immediate). + | UQSHRN = 1416 + /// Unsigned saturating Shift Right Narrow (immediate). + | UQSHRN2 = 1417 + /// Unsigned saturating shift right narrow by immediate (bottom). + | UQSHRNB = 1418 + /// Unsigned saturating shift right narrow by immediate (top). + | UQSHRNT = 1419 + /// Unsigned saturating Subtract. + | UQSUB = 1420 + /// Unsigned saturating subtraction reversed vectors (predicated). + | UQSUBR = 1421 + /// Unsigned saturating extract Narrow. + | UQXTN = 1422 + /// Unsigned saturating extract Narrow. + | UQXTN2 = 1423 + /// Unsigned saturating extract narrow (bottom). + | UQXTNB = 1424 + /// Unsigned saturating extract narrow (top). + | UQXTNT = 1425 + /// Unsigned Reciprocal Estimate. + | URECPE = 1426 + /// Unsigned Rounding Halving Add. + | URHADD = 1427 + /// Unsigned Rounding Shift Left (register). + | URSHL = 1428 + /// Unsigned rounding shift left reversed vectors (predicated). + | URSHLR = 1429 + /// Unsigned Rounding Shift Right (immediate). + | URSHR = 1430 + /// Unsigned Reciprocal Square Root Estimate. + | URSQRTE = 1431 + /// Unsigned Rounding Shift Right and Accumulate (immediate). + | URSRA = 1432 + /// Dot Product with unsigned and signed integers (vector, by element). + | USDOT = 1433 + /// Unsigned Shift Left (register). + | USHL = 1434 + /// Unsigned Shift Left Long (immediate). + | USHLL = 1435 + /// Unsigned Shift Left Long (immediate). + | USHLL2 = 1436 + /// Unsigned shift left long by immediate (bottom). + | USHLLB = 1437 + /// Unsigned shift left long by immediate (top). + | USHLLT = 1438 + /// Unsigned Shift Right (immediate). + | USHR = 1439 + /// Multi-vector unsigned by signed int mul-add long long by indexed element. + | USMLALL = 1440 + /// Unsigned by signed integer matrix multiply-accumulate. + | USMMLA = 1441 + /// Unsigned by signed integer sum of outer products and accumulate. + | USMOPA = 1442 + /// Unsigned by signed integer sum of outer products and subtract. + | USMOPS = 1443 + /// Unsigned saturating Accumulate of Signed value. + | USQADD = 1444 + /// Unsigned Shift Right and Accumulate (immediate). + | USRA = 1445 + /// Unsigned Subtract Long. + | USUBL = 1446 + /// Unsigned Subtract Long. + | USUBL2 = 1447 + /// Unsigned subtract long (bottom). + | USUBLB = 1448 + /// Unsigned subtract long (top). + | USUBLT = 1449 + /// Unsigned Subtract Wide. + | USUBW = 1450 + /// Unsigned Subtract Wide. + | USUBW2 = 1451 + /// Unsigned subtract wide (bottom). + | USUBWB = 1452 + /// Unsigned subtract wide (top). + | USUBWT = 1453 + /// Multi-vector unsigned by signed int vertical dot-product by indexed elem. + | USVDOT = 1454 + /// Unpack and zero-extend multi-vector elements. + | UUNPK = 1455 + /// Unsigned unpack and extend half of vector. + | UUNPKHI = 1456 + /// Unsigned unpack and extend half of vector. + | UUNPKLO = 1457 + /// Multi-vector unsigned integer vertical dot-product by indexed element. + | UVDOT = 1458 + /// Unsigned Extend Byte: an alias of UBFM. + | UXTB = 1459 + /// Unsigned Extend Halfword: an alias of UBFM. + | UXTH = 1460 + /// Unsigned extend Long: an alias of USHLL, USHLL2. + | UXTL = 1461 + /// Unsigned extend Long: an alias of USHLL, USHLL2. + | UXTL2 = 1462 + /// Unsigned byte / halfword / word extend (predicated). + | UXTW = 1463 + /// Concatenate elements from four vectors. + | UZP = 1464 /// Unzip vectors (primary). - | UZP1 = 468 + | UZP1 = 1465 /// Unzip vectors (secondary). - | UZP2 = 469 - /// Wait for event. - | WFE = 470 - /// Wait for interrupt. - | WFI = 471 - /// Extract narrow. - | XTN = 472 - /// Extract narrow. - | XTN2 = 473 - | YIELD = 474 + | UZP2 = 1466 + /// Concatenate even elements within each pair of quadword vector segments. + | UZPQ1 = 1467 + /// Concatenate odd elements within each pair of quadword vector segments. + | UZPQ2 = 1468 + /// Wait For Event. + | WFE = 1469 + /// Wait For Event with Timeout. + | WFET = 1470 + /// Wait For Interrupt. + | WFI = 1471 + /// Wait For Interrupt with Timeout. + | WFIT = 1472 + /// While decrementing signed scalar greater than or equal to scalar. + | WHILEGE = 1473 + /// While decrementing signed scalar greater than scalar. + | WHILEGT = 1474 + /// While decrementing unsigned scalar higher than scalar. + | WHILEHI = 1475 + /// While decrementing unsigned scalar higher or same as scalar. + | WHILEHS = 1476 + /// While incrementing signed scalar less than or equal to scalar. + | WHILELE = 1477 + /// While incrementing unsigned scalar lower than scalar. + | WHILELO = 1478 + /// While incrementing unsigned scalar lower or same as scalar. + | WHILELS = 1479 + /// While incrementing signed scalar less than scalar. + | WHILELT = 1480 + /// While free of read-after-write conflicts. + | WHILERW = 1481 + /// While free of write-after-read/write conflicts. + | WHILEWR = 1482 + /// Write the first-fault register. + | WRFFR = 1483 + /// Convert FP condition flags from external format to Arm format. + | XAFLAG = 1484 + /// Exclusive OR and Rotate. + | XAR = 1485 + /// Strip Pointer Authentication Code. + | XPACD = 1486 + /// Strip Pointer Authentication Code. + | XPACI = 1487 + /// Strip Pointer Authentication Code. + | XPACLRI = 1488 + /// Extract Narrow. + | XTN = 1489 + /// Extract Narrow. + | XTN2 = 1490 + /// YIELD. + | YIELD = 1491 + /// Zero ZA double-vector groups. + | ZERO = 1492 + /// Interleave elements from four vectors. + | ZIP = 1493 /// Zip vectors (primary). - | ZIP1 = 475 + | ZIP1 = 1494 /// Zip vectors (secondary). - | ZIP2 = 476 + | ZIP2 = 1495 + /// Interleave elements from low halves of each pair of qword vector segments. + | ZIPQ1 = 1496 + /// Interleave elems from high halves of each pair of qword vector segments. + | ZIPQ2 = 1497 type PrefetchOperation = | PLDL1KEEP @@ -1103,16 +3146,6 @@ type SIMDFPRegister = | SIMDVecReg of SIMDVectorRegister | SIMDVecRegWithIdx of SIMDVectorRegisterWithIndex -type SIMDOperand = - (* SIMD&FP register *) - | SFReg of SIMDFPRegister - (* SIMD vector register list or SIMD vector element list *) - | OneReg of SIMDFPRegister - | TwoRegs of SIMDFPRegister * SIMDFPRegister - | ThreeRegs of SIMDFPRegister * SIMDFPRegister * SIMDFPRegister - | FourRegs of SIMDFPRegister * SIMDFPRegister * SIMDFPRegister - * SIMDFPRegister - type SystemOp = | SysAT | SysDC @@ -1120,19 +3153,6 @@ type SystemOp = | SysTLBI | SysSYS -type DCOpr = - | IVAC - | ISW - | CSW - | CISW - | ZVA - | CVAC - | CVAU - | CIVAC - -type SysOperand = - | DCOpr of DCOpr - type Const = int64 type Amount = @@ -1180,22 +3200,31 @@ type AddressingMode = | PostIdxMode of Offset | LiteralMode of Offset +type RoundMode = + | FPRounding_TIEEVEN + | FPRounding_TIEAWAY + | FPRounding_Zero + | FPRounding_POSINF + | FPRounding_NEGINF + type Operand = | OprRegister of Register - | SIMDOpr of SIMDOperand - | Immediate of Const - | FPImmediate of float - | NZCV of uint8 - | Shift of Shift - | ExtReg of RegisterOffset option - | Memory of AddressingMode - | Option of OptionOpr - | Pstate of Pstate - | PrfOp of PrefetchOperation - | Cond of Condition - | Fbits of uint8 // fractional bits - | LSB of uint8 - | SysOpr of SysOperand + (* SIMD&FP register *) + | OprSIMD of SIMDFPRegister + (* SIMD vector register list or SIMD vector element list *) + | OprSIMDList of SIMDFPRegister list + | OprImm of Const + | OprFPImm of float + | OprNZCV of uint8 + | OprShift of Shift + | OprExtReg of RegisterOffset option + | OprMemory of AddressingMode + | OprOption of OptionOpr + | OprPstate of Pstate + | OprPrfOp of PrefetchOperation + | OprCond of Condition + | OprFbits of uint8 (* fractional bits *) + | OprLSB of uint8 type Operands = | NoOperand diff --git a/src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs b/src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs index 1f7a1186..07d141fa 100644 --- a/src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs +++ b/src/FrontEnd/BinLifter/ARM64/ARM64Utils.fs @@ -72,20 +72,13 @@ let BFXPreferred sf uns imms immr = else if imms = (concat sf 0b11111u 5) then false else if immr = 0b000000u then if sf = 0b0u && (imms = 0b000111u || imms = 0b001111u) then false - else if concat sf uns 1 = 0b10u && - (imms = 0b000111u || imms = 0b001111u || imms = 0b011111u) - then false else true + else + not (concat sf uns 1 = 0b10u + && (imms = 0b000111u || imms = 0b001111u || imms = 0b011111u)) else true // HighestSetBit() // =============== -(* -let highestSetBit nBit num = - let rec loop n = - if n < 0 then failwith "There is no SetBit" - else if pickBit num (uint32 n) = 0b1u then n else loop (n - 1) - loop (nBit - 1) -*) let highestSetBit nBit imm = let rec loop idx = if idx < 0 then failwith "There is no SeBit" @@ -124,10 +117,10 @@ let decodeBitMasks immN imms immr isImm oprSize = if isImm && (imms &&& levels) = levels then failwith "reserved value" else () let eSize = 1 <<< len - let S = imms &&& levels - let R = immr &&& levels + let s = imms &&& levels + let r = immr &&& levels - replicate (RORZeroExtendOnes (int S + 1) eSize (int R)) eSize oprSize + replicate (RORZeroExtendOnes (int s + 1) eSize (int r)) eSize oprSize // aarch64/instrs/system/sysops/sysop/SysOp // SysOp() diff --git a/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj b/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj index e3f4d3b5..6148e654 100644 --- a/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj +++ b/src/FrontEnd/BinLifter/ARM64/B2R2.FrontEnd.BinLifter.ARM64.fsproj @@ -10,18 +10,18 @@ - - + + - + - + diff --git a/src/FrontEnd/BinLifter/AVR/AVR.fs b/src/FrontEnd/BinLifter/AVR/AVR.fs deleted file mode 100644 index b8019686..00000000 --- a/src/FrontEnd/BinLifter/AVR/AVR.fs +++ /dev/null @@ -1,62 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.AVR - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for AVR instructions. -type AVRTranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for AVR instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type AVRParser () = - inherit Parser () - let reader = BinReader.binReaderLE - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader addr :> Instruction - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader addr :> Instruction - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - AVRTranslationContext (isa, regexprs) :> TranslationContext, - AVRRegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs b/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs index 28f56df2..d48ad3e9 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRDisasm.fs @@ -150,28 +150,28 @@ let opCodeToString = function | Opcode.InvalidOp -> "(invalid)" | _ -> Utils.impossible () -let prependDelimiter delimiter (builder: DisasmBuilder<_>) = +let prependDelimiter delimiter (builder: DisasmBuilder) = match delimiter with | None -> () | Some delim -> builder.Accumulate AsmWordKind.String delim -let immToString imm (builder: DisasmBuilder<_>) = - builder.Accumulate AsmWordKind.Value (String.i32ToHex imm) +let immToString imm (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 imm) -let addrToString shift addr (builder: DisasmBuilder<_>) = +let addrToString shift addr (builder: DisasmBuilder) = let relAddr = int(addr) + shift + 2 if shift>=0 then builder.Accumulate AsmWordKind.String ".+" builder.Accumulate AsmWordKind.Value (string shift) builder.Accumulate AsmWordKind.String " ; " - builder.Accumulate AsmWordKind.Value (String.i32ToHex relAddr) + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 relAddr) else builder.Accumulate AsmWordKind.String "." builder.Accumulate AsmWordKind.Value (string shift) builder.Accumulate AsmWordKind.String " ; " - builder.Accumulate AsmWordKind.Value (String.i32ToHex relAddr) + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 relAddr) -let memToString addrMode (builder: DisasmBuilder<_>) = +let memToString addrMode (builder: DisasmBuilder) = match addrMode with | DispMode (reg,c) -> let reg = Register.toString reg @@ -190,7 +190,7 @@ let memToString addrMode (builder: DisasmBuilder<_>) = let reg = Register.toString reg builder.Accumulate AsmWordKind.Variable reg -let buildReg ins reg (builder: DisasmBuilder<_>) = +let buildReg ins reg (builder: DisasmBuilder) = let reg = Register.toString reg builder.Accumulate AsmWordKind.Variable reg @@ -209,7 +209,7 @@ let oprToString ins addr operand delim builder = prependDelimiter delim builder memToString addrMode builder -let buildComment opr1 opr2 (builder: DisasmBuilder<_>) = +let buildComment opr1 opr2 (builder: DisasmBuilder) = match opr1, opr2 with | OprImm imm, _ | _, OprImm imm -> builder.Accumulate AsmWordKind.String " ; " @@ -218,7 +218,7 @@ let buildComment opr1 opr2 (builder: DisasmBuilder<_>) = match addrMode with | DispMode (reg, c) -> builder.Accumulate AsmWordKind.String " ; " - builder.Accumulate AsmWordKind.Value (String.i32ToHex c) + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 c) | _ -> () | _ -> () @@ -232,13 +232,12 @@ let buildOprs ins pc builder = oprToString ins pc opr2 (Some ", ") builder buildComment opr1 opr2 builder -let inline buildOpcode ins (builder: DisasmBuilder<_>) = +let inline buildOpcode ins (builder: DisasmBuilder) = let str = opCodeToString ins.Opcode builder.Accumulate AsmWordKind.Mnemonic str -let disasm insInfo (builder: DisasmBuilder<_>) = +let disasm insInfo (builder: DisasmBuilder) = let pc = insInfo.Address if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode insInfo builder buildOprs insInfo pc builder -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs b/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs index 72cdd1cb..7d971dd2 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRGeneralLifter.fs @@ -162,7 +162,7 @@ let add ins len ctxt = let adiw ins len ctxt = let ir = IRBuilder(8) let struct (t1, t2) = tmpVars2 ir 8 - let t3 = !*ir 16 + let t3 = !+ir 16 let struct (dst, dst1, src) = match ins.Operands with | TwoOperands (OprReg reg1, OprImm imm) -> @@ -189,7 +189,7 @@ let ``and`` ins len ctxt = let struct (dst, src) = transTwoOprs ins ctxt let oprSize = 8 let ir = IRBuilder (16) - let r = !*ir oprSize + let r = !+ir oprSize ! let ir = IRBuilder (16) - let r = !*ir oprSize + let r = !+ir oprSize ! let ir = IRBuilder (16) - let t1 = !*ir oprSize + let t1 = !+ir oprSize !> AST.num1 oprSize) @@ -246,7 +246,7 @@ let bst ins len ctxt = | TwoOperands (_, OprImm imm) -> imm | _ -> Utils.impossible () let ir = IRBuilder (16) - let r = !*ir 1 + let r = !+ir 1 ! imm)) !>ir len @@ -402,7 +402,7 @@ let dec ins len ctxt = let dst = transOneOpr ins ctxt let oprSize = 8 let ir = IRBuilder (16) - let t1 = !*ir oprSize + let t1 = !+ir oprSize ! let ir = IRBuilder (16) let struct (t1, t2, t3) = tmpVars3 ir oprSize - let t4 = !*ir 16 + let t4 = !+ir 16 ! let ir = IRBuilder (16) let struct (t1, t2, t3) = tmpVars3 ir oprSize - let t4 = !*ir 16 + let t4 = !+ir 16 ! let ir = IRBuilder (16) let struct (t1, t2, t3) = tmpVars3 ir oprSize - let t4 = !*ir 16 + let t4 = !+ir 16 ! let ir = IRBuilder (16) - let t1 = !*ir oprSize + let t1 = !+ir oprSize ! let ir = IRBuilder (16) - let t1 = !*ir oprSize + let t1 = !+ir oprSize !> AST.num1 oprSize) @@ -621,7 +621,7 @@ let ror ins len ctxt = let dst = transOneOpr ins ctxt let ir = IRBuilder (16) let oprSize = 8 - let t1 = !*ir oprSize + let t1 = !+ir oprSize !> AST.num1 oprSize) @@ -654,7 +654,7 @@ let sbc ins len ctxt = let sbiw ins len ctxt = let ir = IRBuilder(8) let struct (t1, t2) = tmpVars2 ir 8 - let t3 = !*ir 16 + let t3 = !+ir 16 let struct (dst, dst1, src) = match ins.Operands with | TwoOperands (OprReg reg1, OprImm imm) -> @@ -717,7 +717,7 @@ let sub ins len ctxt = let swap ins len ctxt = let dst = transOneOpr ins ctxt let ir = IRBuilder (4) - let t1 = !*ir 8 + let t1 = !+ir 8 ! 4 := AST.extract dst 4 0) @@ -728,7 +728,7 @@ let swap ins len ctxt = let lac ins len ctxt = let struct (dst, src) = transTwoOprs ins ctxt let ir = IRBuilder (4) - let t1 = !*ir 8 + let t1 = !+ir 8 ! dst) !!ir (AST.loadLE 8 dst := (numI32 0xff .- src) .& AST.loadLE 8 dst) @@ -738,7 +738,7 @@ let lac ins len ctxt = let las ins len ctxt = let struct (dst, src) = transTwoOprs ins ctxt let ir = IRBuilder (4) - let t1 = !*ir 8 + let t1 = !+ir 8 ! dst) !!ir (AST.loadLE 8 dst := src .| AST.loadLE 8 dst) @@ -748,7 +748,7 @@ let las ins len ctxt = let lat ins len ctxt = let struct (dst, src) = transTwoOprs ins ctxt let ir = IRBuilder (4) - let t1 = !*ir 8 + let t1 = !+ir 8 ! dst) !!ir (AST.loadLE 8 dst := src <+> AST.loadLE 8 dst) @@ -764,13 +764,13 @@ let ld ins len ctxt = | 1 -> !!ir (dst := AST.loadLE 8 src) match src.E with - | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + | BinOp (BinOpType.CONCAT, _, exp1, exp2) -> !!ir (exp1 := AST.extract (src .+ numI32PC 1) 8 8) !!ir (exp2 := AST.extract (src .+ numI32PC 1) 8 0) | _ -> Utils.impossible () | -1 -> match src.E with - | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + | BinOp (BinOpType.CONCAT, _, exp1, exp2) -> !!ir (exp1 := AST.extract (src .- numI32PC 1) 8 8) !!ir (exp2 := AST.extract (src .- numI32PC 1) 8 0) | _ -> Utils.impossible () @@ -891,13 +891,13 @@ let st ins len ctxt = | 1 -> !!ir (AST.loadLE 8 dst := src) match dst.E with - | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + | BinOp (BinOpType.CONCAT, _, exp1, exp2) -> !!ir (exp1 := AST.extract (dst .+ numI32PC 1) 8 8) !!ir (exp2 := AST.extract (dst .+ numI32PC 1) 8 0) | _ -> Utils.impossible () | -1 -> match dst.E with - | BinOp (BinOpType.CONCAT, _, exp1, exp2, _) -> + | BinOp (BinOpType.CONCAT, _, exp1, exp2) -> !!ir (exp1 := AST.extract (dst .- numI32PC 1) 8 8) !!ir (exp2 := AST.extract (dst .- numI32PC 1) 8 0) | _ -> Utils.impossible () @@ -923,13 +923,13 @@ let des ins len ctxt = let ir = IRBuilder (4) let dst = transOneOpr ins ctxt !ir len let xch ins len ctxt = let ir = IRBuilder (4) let struct(dst, src) = transTwoOprs ins ctxt - let t1 = !*ir 8 + let t1 = !+ir 8 ! dst) !!ir (AST.loadLE 8 dst := src) diff --git a/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs b/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs index 187fb731..89751e53 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRInstruction.fs @@ -84,23 +84,23 @@ type AVRInstruction (addr, numBytes, insInfo) = override __.TranslateToList ctxt = Lifter.translate __.Info numBytes ctxt - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs b/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs index 70618184..c50dd649 100644 --- a/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs +++ b/src/FrontEnd/BinLifter/AVR/AVROperandHelper.fs @@ -75,14 +75,14 @@ let memUnch offset = OprMemory (UnchMode (offset)) let extract binary n1 n2 = let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 let range = m - n + 1u - if range > 31u then failwith "invaild range" else () + assert (range <= 31u) let mask = pown 2 (int range) - 1 |> uint32 binary >>> int n &&& mask let extract16 binary n1 n2 = let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 let range = m - n + 1us - if range > 31us then failwith "invaild range" else () + assert (range <= 31us) let mask = pown 2 (int range) - 1 |> uint16 binary >>> int n &&& mask @@ -119,7 +119,8 @@ let getConst4K b = extract b 7u 4u |> int32 |> OprImm let getConst6K b = concat (extract b 7u 6u) (b &&& 0b1111u) 4 |> int32 |> OprImm -let getConst8K b = concat (extract b 11u 8u) (b &&& 0b1111u) 4 |> int32 |> OprImm +let getConst8K b = + concat (extract b 11u 8u) (b &&& 0b1111u) 4 |> int32 |> OprImm let getConst3b b = b &&& 0b111u |> int32 |> OprImm diff --git a/src/FrontEnd/BinLifter/AVR/AVRParser.fs b/src/FrontEnd/BinLifter/AVR/AVRParser.fs index d6527c6a..2bccb79f 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRParser.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRParser.fs @@ -22,276 +22,26 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.AVR.Parser +namespace B2R2.FrontEnd.BinLifter.AVR open System open B2R2 -open B2R2.FrontEnd.BinLifter.AVR.OperandHelper +open B2R2.FrontEnd.BinLifter -let isTwoBytes b1 = - let b32 = b1 |> uint32 - match concat (b32 >>> 9) (b32 &&& 0b1111u) 4 with - | 0b10010101110u | 0b1001010111u -> false - | 0b10010101100u | 0b10010101101u -> false - | 0b10010000000u -> false - | 0b10010010000u -> false - | _ -> true +/// Parser for AVR instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type AVRParser () = + let reader = BinReader.Init Endian.Little -/// 1001 000- ---- ---- -let parse1001000 b32 = - match b32 &&& 0b1111u with - | 0b1100u | 0b1101u | 0b1110u | 0b1001u | 0b1010u | 0b0001u | 0b0010u -> - Opcode.LD, parseTwoOpr b32 getRegD getMemLDD - | 0b1111u -> Opcode.POP, parseOneOpr b32 getRegD - | 0b0101u | 0b0100u -> Opcode.LPM, parseTwoOpr b32 getRegD getMemLDD - | 0b0110u | 0b0111u -> Opcode.ELPM, parseTwoOpr b32 getRegD getMemLDD - | _ -> Opcode.InvalidOp, NoOperand + interface IInstructionParsable with + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader addr :> Instruction -/// 1001 001- ---- ---- -let parse1001001 b32 = - match b32 &&& 0b1111u with - | 0b1100u | 0b1101u | 0b1110u | 0b1001u | 0b1010u | 0b0001u | 0b0010u -> - Opcode.ST, parseTwoOpr b32 getMemST getRegD - | 0b1111u -> Opcode.PUSH, parseOneOpr b32 getRegD - | 0b0110u -> Opcode.LAC, TwoOperands (OprReg R.Z, getRegD b32) - | 0b0101u -> Opcode.LAS, TwoOperands (OprReg R.Z, getRegD b32) - | 0b0111u -> Opcode.LAT, TwoOperands (OprReg R.Z, getRegD b32) - | 0b0100u -> Opcode.XCH, TwoOperands (OprReg R.Z, getRegD b32) - | _ -> Opcode.InvalidOp, NoOperand + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader addr :> Instruction -/// 0000 00-- ---- ---- -let parse000000 b32 = - match extract b32 9u 8u with - | 0b01u -> Opcode.MOVW, parseTwoOpr b32 getRegEven4D getRegEvenEnd4D - | 0b10u -> Opcode.MULS, parseTwoOpr b32 getRegEven4D getRegEvenEnd4D - | 0b11u -> - match concat (pickBit b32 7u) (pickBit b32 3u) 1 with - | 0b01u -> Opcode.FMUL, parseTwoOpr b32 getReg3D getReg3DLast - | 0b10u -> Opcode.FMULS, parseTwoOpr b32 getReg3D getReg3DLast - | 0b11u -> Opcode.FMULSU, parseTwoOpr b32 getReg3D getReg3DLast - | 0b00u -> Opcode.MULSU, parseTwoOpr b32 getReg3D getReg3DLast - | _ -> Opcode.InvalidOp, NoOperand - | 0b0u when b32 = 0u -> Opcode.NOP, NoOperand - | _ -> Opcode.InvalidOp, NoOperand + member __.MaxInstructionSize = 4 -/// 1001 010- ---- 1000 with no operands -let parseNoOp1000 b32 = - match extract b32 8u 4u with - | 0b11001u -> Opcode.BREAK, NoOperand - | 0b01000u -> Opcode.CLC, NoOperand - | 0b01101u -> Opcode.CLH, NoOperand - | 0b01111u -> Opcode.CLI, NoOperand - | 0b01010u -> Opcode.CLN, NoOperand - | 0b01100u -> Opcode.CLS, NoOperand - | 0b01110u -> Opcode.CLT, NoOperand - | 0b01011u -> Opcode.CLV, NoOperand - | 0b01001u -> Opcode.CLZ, NoOperand - | 0b10000u -> Opcode.RET, NoOperand - | 0b10001u -> Opcode.RETI, NoOperand - | 0b00000u -> Opcode.SEC, NoOperand - | 0b00101u -> Opcode.SEH, NoOperand - | 0b00111u -> Opcode.SEI, NoOperand - | 0b00010u -> Opcode.SEN, NoOperand - | 0b00100u -> Opcode.SES, NoOperand - | 0b00110u -> Opcode.SET, NoOperand - | 0b00011u -> Opcode.SEV, NoOperand - | 0b00001u -> Opcode.SEZ, NoOperand - | 0b11000u -> Opcode.SLEEP, NoOperand - | 0b11110u -> Opcode.SPM, NoOperand - | 0b11010u -> Opcode.WDR, NoOperand - | 0b11100u -> Opcode.LPM, NoOperand - | 0b11101u -> Opcode.ELPM, NoOperand - | _ -> Opcode.InvalidOp, NoOperand + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () -/// 1001 010- ---- 1001 with no operands -let parseNoOp1001 b32 = - match extract b32 8u 4u with - | 0b10001u -> Opcode.EICALL, NoOperand - | 0b00001u -> Opcode.EIJMP, NoOperand - | 0b10000u -> Opcode.ICALL, NoOperand - | 0b00000u -> Opcode.IJMP, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// 1001 010- ---- ---- -let parse1001010 b32 = - match b32 >>> 9 with - | 0b1001010u -> - match b32 &&& 0b1111u with - | 0b0101u -> Opcode.ASR, parseOneOpr b32 getRegD - | 0b0000u -> Opcode.COM, parseOneOpr b32 getRegD - | 0b1010u -> Opcode.DEC, parseOneOpr b32 getRegD - | 0b0011u -> Opcode.INC, parseOneOpr b32 getRegD - | 0b0110u -> Opcode.LSR, parseOneOpr b32 getRegD - | 0b0001u -> Opcode.NEG, parseOneOpr b32 getRegD - | 0b0111u -> Opcode.ROR, parseOneOpr b32 getRegD - | 0b0010u -> Opcode.SWAP, parseOneOpr b32 getRegD - | 0b1011u when pickBit b32 8u = 0b0u -> - Opcode.DES, parseOneOpr b32 getConst4K - (* | 0b1000u when extract b32 8u 7u = 0b01u -> - Opcode.BCLR, parseOneOpr b32 getConst3bs - | 0b1000u when extract b32 8u 7u = 0b00u -> - Opcode.BSET, parseOneOpr b32 getConst3bs *) - | 0b1000u -> parseNoOp1000 b32 - | 0b1001u -> parseNoOp1001 b32 - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// 1111 1--d dddd 0bbb -let parse11111 b32 = - match concat (extract b32 10u 9u) (pickBit b32 3u) 1 with - | 0b000u -> Opcode.BLD, parseTwoOpr b32 getRegD getConst3b - | 0b010u -> Opcode.BST, parseTwoOpr b32 getRegD getConst3b - | 0b100u -> Opcode.SBRC, parseTwoOpr b32 getRegD getConst3b - | 0b110u -> Opcode.SBRS, parseTwoOpr b32 getRegD getConst3b - | _ -> Opcode.InvalidOp, NoOperand - -/// 1111 0- kk kkkk k--- -let parse11110 b32 = - match pickBit b32 10u with - | 0b0u -> - match b32 &&& 0b111u with - | 0b000u -> Opcode.BRCS, parseOneOpr b32 getAddr7K - | 0b001u -> Opcode.BREQ, parseOneOpr b32 getAddr7K - | 0b101u -> Opcode.BRHS, parseOneOpr b32 getAddr7K - | 0b111u -> Opcode.BRIE, parseOneOpr b32 getAddr7K - (* | 0b000u -> Opcode.BRLO, parseOneOpr b getAddr7K *) - | 0b100u -> Opcode.BRLT, parseOneOpr b32 getAddr7K - | 0b010u -> Opcode.BRMI, parseOneOpr b32 getAddr7K - | 0b110u -> Opcode.BRTS, parseOneOpr b32 getAddr7K - | 0b011u -> Opcode.BRVS, parseOneOpr b32 getAddr7K - | _ -> Opcode.InvalidOp, NoOperand - | 0b1u -> - match b32 &&& 0b111u with - | 0b000u -> Opcode.BRCC, parseOneOpr b32 getAddr7K - | 0b001u -> Opcode.BRNE, parseOneOpr b32 getAddr7K - | 0b101u -> Opcode.BRHC, parseOneOpr b32 getAddr7K - | 0b111u -> Opcode.BRID, parseOneOpr b32 getAddr7K - (* | 0b000u -> Opcode.BRSH, parseOneOpr b getAddr7K *) - | 0b100u -> Opcode.BRGE, parseOneOpr b32 getAddr7K - | 0b010u -> Opcode.BRPL, parseOneOpr b32 getAddr7K - | 0b110u -> Opcode.BRTC, parseOneOpr b32 getAddr7K - | 0b011u -> Opcode.BRVC, parseOneOpr b32 getAddr7K - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -let parse1111 b32 = - match pickBit b32 11u with - | 0b0u -> parse11110 b32 - | 0b1u -> parse11111 b32 - | _ -> Opcode.InvalidOp, NoOperand - -let parse1001 b32 = - match extract b32 11u 8u with - | 0b0100u | 0b0101u -> parse1001010 b32 - | 0b0010u | 0b0011u -> parse1001001 b32 - | 0b0000u | 0b0001u -> parse1001000 b32 - | 0b0110u -> Opcode.ADIW, parseTwoOpr b32 getReg2D getConst6K - | 0b1000u -> Opcode.CBI, parseTwoOpr b32 getIO5 getConst3b - | 0b1010u -> Opcode.SBI, parseTwoOpr b32 getIO5 getConst3b - | 0b1001u -> Opcode.SBIC, parseTwoOpr b32 getIO5 getConst3b - | 0b1011u -> Opcode.SBIS, parseTwoOpr b32 getIO5 getConst3b - | 0b0111u -> Opcode.SBIW, parseTwoOpr b32 getReg2D getConst6K - | op when op &&& 0b1100u = 0b1100u -> - Opcode.MUL, parseTwoOpr b32 getRegD getRegR - | _ -> Opcode.InvalidOp, NoOperand - -let parse1000 b32 = - let isDispZero = getDisp b32 = 0 - match concat (pickBit b32 9u)(pickBit b32 3u) 1 with - | 0b11u -> - if isDispZero then Opcode.ST, parseTwoOpr b32 getMemST getRegD - else Opcode.STD, parseTwoOpr b32 getMemDispY getRegD - | 0b10u -> - if isDispZero then Opcode.ST, parseTwoOpr b32 getMemST getRegD - else Opcode.STD, parseTwoOpr b32 getMemDispZ getRegD - | 0b01u -> - if isDispZero then Opcode.LD, parseTwoOpr b32 getRegD getMemLDD - else Opcode.LDD, parseTwoOpr b32 getRegD getMemDispY - | 0b00u -> - if isDispZero then Opcode.LD, parseTwoOpr b32 getRegD getMemLDD - else Opcode.LDD, parseTwoOpr b32 getRegD getMemDispZ - | _ -> Opcode.InvalidOp, NoOperand - -let parse1010 b32 = - match concat (pickBit b32 9u)(pickBit b32 3u) 1 with - | 0b00u -> Opcode.LDD, parseTwoOpr b32 getRegD getMemDispZ - | 0b01u -> Opcode.LDD, parseTwoOpr b32 getRegD getMemDispY - | 0b10u -> Opcode.STD, parseTwoOpr b32 getMemDispZ getRegD - | 0b11u -> Opcode.STD, parseTwoOpr b32 getMemDispY getRegD - | _ -> Opcode.InvalidOp, NoOperand - -/// Parse the instruction using only the first 6 bits -let parseSixBits b32 = - match b32 >>> 10 with - | 0b000111u -> Opcode.ADC, parseTwoOpr b32 getRegD getRegR - | 0b000011u -> Opcode.ADD, parseTwoOpr b32 getRegD getRegR - | 0b001000u -> Opcode.AND, parseTwoOpr b32 getRegD getRegR - (* | 0b111101u -> Opcode.BRBC - | 0b111100u -> Opcode.BRBS - | 0b001001u -> Opcode.CLR // Same with EOR *) - | 0b000101u -> Opcode.CP, parseTwoOpr b32 getRegD getRegR - | 0b000001u -> Opcode.CPC, parseTwoOpr b32 getRegD getRegR - | 0b000100u -> Opcode.CPSE, parseTwoOpr b32 getRegD getRegR - | 0b001001u -> Opcode.EOR, parseTwoOpr b32 getRegD getRegR - (* | 0b000011u -> Opcode.LSL // Logical shift left *) - | 0b001011u -> Opcode.MOV, parseTwoOpr b32 getRegD getRegR - | 0b000110u -> Opcode.SUB, parseTwoOpr b32 getRegD getRegR - | 0b100111u -> Opcode.MUL, parseTwoOpr b32 getRegD getRegR - | 0b001010u -> Opcode.OR, parseTwoOpr b32 getRegD getRegR - (* | 0b000111u -> Opcode.ROL // Rotate Left through Carry *) - | 0b000010u -> Opcode.SBC, parseTwoOpr b32 getRegD getRegR - (* | 0b001000u -> Opcode.TST *) - | _ -> Opcode.InvalidOp, NoOperand - -/// Parse the instruction using only the first 4 bits -let parseFourBits b32 = - match b32 >>> 12 with - | 0b0111u -> Opcode.ANDI, parseTwoOpr b32 getReg4D getConst8K - | 0b0011u -> Opcode.CPI, parseTwoOpr b32 getReg4D getConst8K - | 0b1110u -> Opcode.LDI, parseTwoOpr b32 getReg4D getConst8K - | 0b0110u -> Opcode.ORI, parseTwoOpr b32 getReg4D getConst8K - | 0b1101u -> Opcode.RCALL, parseOneOpr b32 getAddr12 - | 0b1100u -> Opcode.RJMP, parseOneOpr b32 getAddr12 - | 0b0100u -> Opcode.SBCI, parseTwoOpr b32 getReg4D getConst8K - (* | 0x0110u -> Opcode.SBR, parseTwoOpr b32 getReg4D getConst8K *) - | 0b0101u -> Opcode.SUBI, parseTwoOpr b32 getReg4D getConst8K - | 0b1011u when (pickBit b32 11u) = 0b0u -> - Opcode.IN, parseTwoOpr b32 getRegD getIO6 - | 0b1011u when (pickBit b32 11u) = 0b1u -> - Opcode.OUT, parseTwoOpr b32 getIO6 getRegD - | _ -> parseSixBits b32 - -let parseTwoBytes bin = - match bin >>> 12 with - | 0b0000u when extract bin 11u 10u = 0b0u -> parse000000 bin - | 0b1001u -> parse1001 bin - | 0b1111u -> parse1111 bin - | 0b1000u -> parse1000 bin - | 0b1010u -> parse1010 bin - | _ -> parseFourBits bin - -let parseFourBytes b1= - match concat (b1 >>> 25) ((b1 >>> 16) &&& 0b1111u) 4 with - | 0b10010101110u | 0b10010101111u -> Opcode.CALL, parseOneOpr b1 getConst22 - | 0b10010101100u | 0b10010101101u -> Opcode.JMP, parseOneOpr b1 getConst22 - | 0b10010000000u -> Opcode.LDS, parseTwoOpr b1 getRegD32 getConst16 - | 0b10010010000u -> Opcode.STS, parseTwoOpr b1 getConst16 getRegD32 - | _ -> Opcode.InvalidOp, NoOperand - -let parse (span: ByteSpan) (reader: IBinReader) addr = - let bin = reader.ReadUInt16 (span, 0) - let struct ((op, operands), instrLen) = - match isTwoBytes bin with - | true -> - let bin = uint32 bin - struct (bin |> parseTwoBytes, 2u) - | false -> - let b2 = reader.ReadUInt16 (span, 2) - let bin = ((uint32 bin) <<< 16) + (uint32 b2) - struct (bin |> parseFourBytes, 4u) - let insInfo = - { Address = addr - NumBytes = instrLen - Opcode = op - Operands = operands } - AVRInstruction (addr, instrLen, insInfo) diff --git a/src/FrontEnd/BinLifter/AVR/AVRParsingMain.fs b/src/FrontEnd/BinLifter/AVR/AVRParsingMain.fs new file mode 100644 index 00000000..01babb57 --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRParsingMain.fs @@ -0,0 +1,296 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.AVR.ParsingMain + +open B2R2 +open B2R2.FrontEnd.BinLifter.AVR.OperandHelper + +let isTwoBytes b1 = + let b32 = b1 |> uint32 + match concat (b32 >>> 9) (b32 &&& 0b1111u) 4 with + | 0b10010101110u | 0b1001010111u -> false + | 0b10010101100u | 0b10010101101u -> false + | 0b10010000000u -> false + | 0b10010010000u -> false + | _ -> true + +/// 1001 000- ---- ---- +let parse1001000 b32 = + match b32 &&& 0b1111u with + | 0b1100u | 0b1101u | 0b1110u | 0b1001u | 0b1010u | 0b0001u | 0b0010u -> + Opcode.LD, parseTwoOpr b32 getRegD getMemLDD + | 0b1111u -> Opcode.POP, parseOneOpr b32 getRegD + | 0b0101u | 0b0100u -> Opcode.LPM, parseTwoOpr b32 getRegD getMemLDD + | 0b0110u | 0b0111u -> Opcode.ELPM, parseTwoOpr b32 getRegD getMemLDD + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 001- ---- ---- +let parse1001001 b32 = + match b32 &&& 0b1111u with + | 0b1100u | 0b1101u | 0b1110u | 0b1001u | 0b1010u | 0b0001u | 0b0010u -> + Opcode.ST, parseTwoOpr b32 getMemST getRegD + | 0b1111u -> Opcode.PUSH, parseOneOpr b32 getRegD + | 0b0110u -> Opcode.LAC, TwoOperands (OprReg R.Z, getRegD b32) + | 0b0101u -> Opcode.LAS, TwoOperands (OprReg R.Z, getRegD b32) + | 0b0111u -> Opcode.LAT, TwoOperands (OprReg R.Z, getRegD b32) + | 0b0100u -> Opcode.XCH, TwoOperands (OprReg R.Z, getRegD b32) + | _ -> Opcode.InvalidOp, NoOperand + +/// 0000 00-- ---- ---- +let parse000000 b32 = + match extract b32 9u 8u with + | 0b01u -> Opcode.MOVW, parseTwoOpr b32 getRegEven4D getRegEvenEnd4D + | 0b10u -> Opcode.MULS, parseTwoOpr b32 getRegEven4D getRegEvenEnd4D + | 0b11u -> + match concat (pickBit b32 7u) (pickBit b32 3u) 1 with + | 0b01u -> Opcode.FMUL, parseTwoOpr b32 getReg3D getReg3DLast + | 0b10u -> Opcode.FMULS, parseTwoOpr b32 getReg3D getReg3DLast + | 0b11u -> Opcode.FMULSU, parseTwoOpr b32 getReg3D getReg3DLast + | 0b00u -> Opcode.MULSU, parseTwoOpr b32 getReg3D getReg3DLast + | _ -> Opcode.InvalidOp, NoOperand + | 0b0u when b32 = 0u -> Opcode.NOP, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 010- ---- 1000 with no operands +let parseNoOp1000 b32 = + match extract b32 8u 4u with + | 0b11001u -> Opcode.BREAK, NoOperand + | 0b01000u -> Opcode.CLC, NoOperand + | 0b01101u -> Opcode.CLH, NoOperand + | 0b01111u -> Opcode.CLI, NoOperand + | 0b01010u -> Opcode.CLN, NoOperand + | 0b01100u -> Opcode.CLS, NoOperand + | 0b01110u -> Opcode.CLT, NoOperand + | 0b01011u -> Opcode.CLV, NoOperand + | 0b01001u -> Opcode.CLZ, NoOperand + | 0b10000u -> Opcode.RET, NoOperand + | 0b10001u -> Opcode.RETI, NoOperand + | 0b00000u -> Opcode.SEC, NoOperand + | 0b00101u -> Opcode.SEH, NoOperand + | 0b00111u -> Opcode.SEI, NoOperand + | 0b00010u -> Opcode.SEN, NoOperand + | 0b00100u -> Opcode.SES, NoOperand + | 0b00110u -> Opcode.SET, NoOperand + | 0b00011u -> Opcode.SEV, NoOperand + | 0b00001u -> Opcode.SEZ, NoOperand + | 0b11000u -> Opcode.SLEEP, NoOperand + | 0b11110u -> Opcode.SPM, NoOperand + | 0b11010u -> Opcode.WDR, NoOperand + | 0b11100u -> Opcode.LPM, NoOperand + | 0b11101u -> Opcode.ELPM, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 010- ---- 1001 with no operands +let parseNoOp1001 b32 = + match extract b32 8u 4u with + | 0b10001u -> Opcode.EICALL, NoOperand + | 0b00001u -> Opcode.EIJMP, NoOperand + | 0b10000u -> Opcode.ICALL, NoOperand + | 0b00000u -> Opcode.IJMP, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1001 010- ---- ---- +let parse1001010 b32 = + match b32 >>> 9 with + | 0b1001010u -> + match b32 &&& 0b1111u with + | 0b0101u -> Opcode.ASR, parseOneOpr b32 getRegD + | 0b0000u -> Opcode.COM, parseOneOpr b32 getRegD + | 0b1010u -> Opcode.DEC, parseOneOpr b32 getRegD + | 0b0011u -> Opcode.INC, parseOneOpr b32 getRegD + | 0b0110u -> Opcode.LSR, parseOneOpr b32 getRegD + | 0b0001u -> Opcode.NEG, parseOneOpr b32 getRegD + | 0b0111u -> Opcode.ROR, parseOneOpr b32 getRegD + | 0b0010u -> Opcode.SWAP, parseOneOpr b32 getRegD + | 0b1011u when pickBit b32 8u = 0b0u -> + Opcode.DES, parseOneOpr b32 getConst4K + (* | 0b1000u when extract b32 8u 7u = 0b01u -> + Opcode.BCLR, parseOneOpr b32 getConst3bs + | 0b1000u when extract b32 8u 7u = 0b00u -> + Opcode.BSET, parseOneOpr b32 getConst3bs *) + | 0b1000u -> parseNoOp1000 b32 + | 0b1001u -> parseNoOp1001 b32 + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 1--d dddd 0bbb +let parse11111 b32 = + match concat (extract b32 10u 9u) (pickBit b32 3u) 1 with + | 0b000u -> Opcode.BLD, parseTwoOpr b32 getRegD getConst3b + | 0b010u -> Opcode.BST, parseTwoOpr b32 getRegD getConst3b + | 0b100u -> Opcode.SBRC, parseTwoOpr b32 getRegD getConst3b + | 0b110u -> Opcode.SBRS, parseTwoOpr b32 getRegD getConst3b + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 0- kk kkkk k--- +let parse11110 b32 = + match pickBit b32 10u with + | 0b0u -> + match b32 &&& 0b111u with + | 0b000u -> Opcode.BRCS, parseOneOpr b32 getAddr7K + | 0b001u -> Opcode.BREQ, parseOneOpr b32 getAddr7K + | 0b101u -> Opcode.BRHS, parseOneOpr b32 getAddr7K + | 0b111u -> Opcode.BRIE, parseOneOpr b32 getAddr7K + (* | 0b000u -> Opcode.BRLO, parseOneOpr b getAddr7K *) + | 0b100u -> Opcode.BRLT, parseOneOpr b32 getAddr7K + | 0b010u -> Opcode.BRMI, parseOneOpr b32 getAddr7K + | 0b110u -> Opcode.BRTS, parseOneOpr b32 getAddr7K + | 0b011u -> Opcode.BRVS, parseOneOpr b32 getAddr7K + | _ -> Opcode.InvalidOp, NoOperand + | 0b1u -> + match b32 &&& 0b111u with + | 0b000u -> Opcode.BRCC, parseOneOpr b32 getAddr7K + | 0b001u -> Opcode.BRNE, parseOneOpr b32 getAddr7K + | 0b101u -> Opcode.BRHC, parseOneOpr b32 getAddr7K + | 0b111u -> Opcode.BRID, parseOneOpr b32 getAddr7K + (* | 0b000u -> Opcode.BRSH, parseOneOpr b getAddr7K *) + | 0b100u -> Opcode.BRGE, parseOneOpr b32 getAddr7K + | 0b010u -> Opcode.BRPL, parseOneOpr b32 getAddr7K + | 0b110u -> Opcode.BRTC, parseOneOpr b32 getAddr7K + | 0b011u -> Opcode.BRVC, parseOneOpr b32 getAddr7K + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +let parse1111 b32 = + match pickBit b32 11u with + | 0b0u -> parse11110 b32 + | 0b1u -> parse11111 b32 + | _ -> Opcode.InvalidOp, NoOperand + +let parse1001 b32 = + match extract b32 11u 8u with + | 0b0100u | 0b0101u -> parse1001010 b32 + | 0b0010u | 0b0011u -> parse1001001 b32 + | 0b0000u | 0b0001u -> parse1001000 b32 + | 0b0110u -> Opcode.ADIW, parseTwoOpr b32 getReg2D getConst6K + | 0b1000u -> Opcode.CBI, parseTwoOpr b32 getIO5 getConst3b + | 0b1010u -> Opcode.SBI, parseTwoOpr b32 getIO5 getConst3b + | 0b1001u -> Opcode.SBIC, parseTwoOpr b32 getIO5 getConst3b + | 0b1011u -> Opcode.SBIS, parseTwoOpr b32 getIO5 getConst3b + | 0b0111u -> Opcode.SBIW, parseTwoOpr b32 getReg2D getConst6K + | op when op &&& 0b1100u = 0b1100u -> + Opcode.MUL, parseTwoOpr b32 getRegD getRegR + | _ -> Opcode.InvalidOp, NoOperand + +let parse1000 b32 = + let isDispZero = getDisp b32 = 0 + match concat (pickBit b32 9u)(pickBit b32 3u) 1 with + | 0b11u -> + if isDispZero then Opcode.ST, parseTwoOpr b32 getMemST getRegD + else Opcode.STD, parseTwoOpr b32 getMemDispY getRegD + | 0b10u -> + if isDispZero then Opcode.ST, parseTwoOpr b32 getMemST getRegD + else Opcode.STD, parseTwoOpr b32 getMemDispZ getRegD + | 0b01u -> + if isDispZero then Opcode.LD, parseTwoOpr b32 getRegD getMemLDD + else Opcode.LDD, parseTwoOpr b32 getRegD getMemDispY + | 0b00u -> + if isDispZero then Opcode.LD, parseTwoOpr b32 getRegD getMemLDD + else Opcode.LDD, parseTwoOpr b32 getRegD getMemDispZ + | _ -> Opcode.InvalidOp, NoOperand + +let parse1010 b32 = + match concat (pickBit b32 9u)(pickBit b32 3u) 1 with + | 0b00u -> Opcode.LDD, parseTwoOpr b32 getRegD getMemDispZ + | 0b01u -> Opcode.LDD, parseTwoOpr b32 getRegD getMemDispY + | 0b10u -> Opcode.STD, parseTwoOpr b32 getMemDispZ getRegD + | 0b11u -> Opcode.STD, parseTwoOpr b32 getMemDispY getRegD + | _ -> Opcode.InvalidOp, NoOperand + +/// Parse the instruction using only the first 6 bits +let parseSixBits b32 = + match b32 >>> 10 with + | 0b000111u -> Opcode.ADC, parseTwoOpr b32 getRegD getRegR + | 0b000011u -> Opcode.ADD, parseTwoOpr b32 getRegD getRegR + | 0b001000u -> Opcode.AND, parseTwoOpr b32 getRegD getRegR + (* | 0b111101u -> Opcode.BRBC + | 0b111100u -> Opcode.BRBS + | 0b001001u -> Opcode.CLR // Same with EOR *) + | 0b000101u -> Opcode.CP, parseTwoOpr b32 getRegD getRegR + | 0b000001u -> Opcode.CPC, parseTwoOpr b32 getRegD getRegR + | 0b000100u -> Opcode.CPSE, parseTwoOpr b32 getRegD getRegR + | 0b001001u -> Opcode.EOR, parseTwoOpr b32 getRegD getRegR + (* | 0b000011u -> Opcode.LSL // Logical shift left *) + | 0b001011u -> Opcode.MOV, parseTwoOpr b32 getRegD getRegR + | 0b000110u -> Opcode.SUB, parseTwoOpr b32 getRegD getRegR + | 0b100111u -> Opcode.MUL, parseTwoOpr b32 getRegD getRegR + | 0b001010u -> Opcode.OR, parseTwoOpr b32 getRegD getRegR + (* | 0b000111u -> Opcode.ROL // Rotate Left through Carry *) + | 0b000010u -> Opcode.SBC, parseTwoOpr b32 getRegD getRegR + (* | 0b001000u -> Opcode.TST *) + | _ -> Opcode.InvalidOp, NoOperand + +/// Parse the instruction using only the first 4 bits +let parseFourBits b32 = + match b32 >>> 12 with + | 0b0111u -> Opcode.ANDI, parseTwoOpr b32 getReg4D getConst8K + | 0b0011u -> Opcode.CPI, parseTwoOpr b32 getReg4D getConst8K + | 0b1110u -> Opcode.LDI, parseTwoOpr b32 getReg4D getConst8K + | 0b0110u -> Opcode.ORI, parseTwoOpr b32 getReg4D getConst8K + | 0b1101u -> Opcode.RCALL, parseOneOpr b32 getAddr12 + | 0b1100u -> Opcode.RJMP, parseOneOpr b32 getAddr12 + | 0b0100u -> Opcode.SBCI, parseTwoOpr b32 getReg4D getConst8K + (* | 0x0110u -> Opcode.SBR, parseTwoOpr b32 getReg4D getConst8K *) + | 0b0101u -> Opcode.SUBI, parseTwoOpr b32 getReg4D getConst8K + | 0b1011u when (pickBit b32 11u) = 0b0u -> + Opcode.IN, parseTwoOpr b32 getRegD getIO6 + | 0b1011u when (pickBit b32 11u) = 0b1u -> + Opcode.OUT, parseTwoOpr b32 getIO6 getRegD + | _ -> parseSixBits b32 + +let parseTwoBytes bin = + match bin >>> 12 with + | 0b0000u when extract bin 11u 10u = 0b0u -> parse000000 bin + | 0b1001u -> parse1001 bin + | 0b1111u -> parse1111 bin + | 0b1000u -> parse1000 bin + | 0b1010u -> parse1010 bin + | _ -> parseFourBits bin + +let parseFourBytes b1= + match concat (b1 >>> 25) ((b1 >>> 16) &&& 0b1111u) 4 with + | 0b10010101110u | 0b10010101111u -> Opcode.CALL, parseOneOpr b1 getConst22 + | 0b10010101100u | 0b10010101101u -> Opcode.JMP, parseOneOpr b1 getConst22 + | 0b10010000000u -> Opcode.LDS, parseTwoOpr b1 getRegD32 getConst16 + | 0b10010010000u -> Opcode.STS, parseTwoOpr b1 getConst16 getRegD32 + | _ -> Opcode.InvalidOp, NoOperand + +let parse (span: ByteSpan) (reader: IBinReader) addr = + let bin = reader.ReadUInt16 (span, 0) + let struct ((op, operands), instrLen) = + match isTwoBytes bin with + | true -> + let bin = uint32 bin + struct (bin |> parseTwoBytes, 2u) + | false -> + let b2 = reader.ReadUInt16 (span, 2) + let bin = ((uint32 bin) <<< 16) + (uint32 b2) + struct (bin |> parseFourBytes, 4u) + let insInfo = + { Address = addr + NumBytes = instrLen + Opcode = op + Operands = operands } + AVRInstruction (addr, instrLen, insInfo) diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs b/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs index 2503a82b..75e36840 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRRegExprs.fs @@ -25,10 +25,11 @@ namespace B2R2.FrontEnd.BinLifter.AVR open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (AVRRegisterSet.singleton t) +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name (* Registers *) let regType = WordSize.toRegType wordSize @@ -137,6 +138,6 @@ type internal RegExprs (wordSize) = | R.CF -> __.CF | R.PC -> __.PC | R.SP -> __.SP - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegister.fs b/src/FrontEnd/BinLifter/AVR/AVRRegister.fs index 3d98a609..d4ca4970 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRRegister.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRRegister.fs @@ -86,7 +86,7 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "r1" -> R.R0 | "r2" -> R.R1 | "r3" -> R.R2 diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegisterBay.fs b/src/FrontEnd/BinLifter/AVR/AVRRegisterFactory.fs similarity index 93% rename from src/FrontEnd/BinLifter/AVR/AVRRegisterBay.fs rename to src/FrontEnd/BinLifter/AVR/AVRRegisterFactory.fs index 619da576..8c56ae9b 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRRegisterBay.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRRegisterFactory.fs @@ -28,9 +28,8 @@ open B2R2 open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type AVRRegisterBay () = - - inherit RegisterBay () +type AVRRegisterFactory () = + inherit RegisterFactory () override __.GetAllRegExprs () = Utils.futureFeature () override __.GetAllRegNames () = Utils.futureFeature () @@ -38,8 +37,8 @@ type AVRRegisterBay () = override __.RegIDFromRegExpr (e) = match e.E with - | Var (_, id, _ ,_) -> id (* TODO *) - | _ -> failwith "not a register expression" + | Var (_, id, _) -> id (* TODO *) + | _ -> raise InvalidRegisterException override __.RegIDToRegExpr (id) = Utils.futureFeature () override __.StrToRegExpr _s = Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs b/src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs deleted file mode 100644 index 1c5200c3..00000000 --- a/src/FrontEnd/BinLifter/AVR/AVRRegisterSet.fs +++ /dev/null @@ -1,151 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.AVR - -open B2R2 - -module private RegisterSetLiteral = - let [] ArrLen = 2 - -open RegisterSetLiteral - -type AVRRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = - AVRRegisterSet (RegisterSet.MakeInternalBitArray ArrLen, Set.empty) - - override __.Tag = RegisterSetTag.AVR - - override __.ArrSize = ArrLen - - override __.New arr s = new AVRRegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | R.R0 -> 0 - | R.R1 -> 1 - | R.R2 -> 2 - | R.R3 -> 3 - | R.R4 -> 4 - | R.R5 -> 5 - | R.R6 -> 6 - | R.R7 -> 7 - | R.R8 -> 8 - | R.R9 -> 9 - | R.R10 -> 10 - | R.R11 -> 11 - | R.R12 -> 12 - | R.R13 -> 13 - | R.R14 -> 14 - | R.R15 -> 15 - | R.R16 -> 16 - | R.R17 -> 17 - | R.R18 -> 18 - | R.R19 -> 19 - | R.R20 -> 20 - | R.R21 -> 21 - | R.R22 -> 22 - | R.R23 -> 23 - | R.R24 -> 24 - | R.R25 -> 25 - | R.R26 -> 26 - | R.R27 -> 27 - | R.R28 -> 28 - | R.R29 -> 29 - | R.R30 -> 30 - | R.R31 -> 31 - | R.X -> 32 - | R.Y -> 33 - | R.Z -> 34 - | R.IF -> 35 - | R.TF -> 36 - | R.HF -> 37 - | R.SF -> 38 - | R.VF -> 39 - | R.NF -> 40 - | R.ZF -> 41 - | R.CF -> 42 - | R.PC -> 43 - | R.SP -> 44 - | _ -> -1 - - override __.IndexToRegID index = - match index with - | 0 -> R.R0 - | 1 -> R.R1 - | 2 -> R.R2 - | 3 -> R.R3 - | 4 -> R.R4 - | 5 -> R.R5 - | 6 -> R.R6 - | 7 -> R.R7 - | 8 -> R.R8 - | 9 -> R.R9 - | 10 -> R.R10 - | 11 -> R.R11 - | 12 -> R.R12 - | 13 -> R.R13 - | 14 -> R.R14 - | 15 -> R.R15 - | 16 -> R.R16 - | 17 -> R.R17 - | 18 -> R.R18 - | 19 -> R.R19 - | 20 -> R.R20 - | 21 -> R.R21 - | 22 -> R.R22 - | 23 -> R.R23 - | 24 -> R.R24 - | 25 -> R.R25 - | 26 -> R.R26 - | 27 -> R.R27 - | 28 -> R.R28 - | 29 -> R.R29 - | 30 -> R.R30 - | 31 -> R.R31 - | 32 -> R.X - | 33 -> R.Y - | 34 -> R.Z - | 35 -> R.IF - | 36 -> R.TF - | 37 -> R.HF - | 38 -> R.SF - | 39 -> R.VF - | 40 -> R.NF - | 41 -> R.ZF - | 42 -> R.CF - | 43 -> R.PC - | 44 -> R.SP - | _ -> Utils.impossible () - |> Register.toRegID - - override __.ToString () = - sprintf "AVRRegisterSet<%x, %x>" __.BitArray[0] __.BitArray[1] - -[] -module AVRRegisterSet = - let singleton rid = AVRRegisterSet().Add(rid) - let empty = AVRRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/AVR/AVRTranslationContext.fs b/src/FrontEnd/BinLifter/AVR/AVRTranslationContext.fs new file mode 100644 index 00000000..17d83c8c --- /dev/null +++ b/src/FrontEnd/BinLifter/AVR/AVRTranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.AVR + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for AVR instructions. +type AVRTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs (isa.WordSize) + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/AVR/AVRTypes.fs b/src/FrontEnd/BinLifter/AVR/AVRTypes.fs index 06dacc10..906f30a0 100644 --- a/src/FrontEnd/BinLifter/AVR/AVRTypes.fs +++ b/src/FrontEnd/BinLifter/AVR/AVRTypes.fs @@ -161,7 +161,7 @@ type Opcode = | LAS = 63 /// Load and Toggle | LAT = 64 - /// Load Indirect from Data Space to Register using Index Y and Index Z + /// Load Indirect from Data Space to Register using Index Y and Index Z | LDD = 65 /// Load Immediate | LDI = 66 diff --git a/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj b/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj index f20da26e..16f4af5d 100644 --- a/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj +++ b/src/FrontEnd/BinLifter/AVR/B2R2.FrontEnd.BinLifter.AVR.fsproj @@ -9,17 +9,17 @@ - - + + - + diff --git a/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj b/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj index ff29a7a6..66d0b1ca 100644 --- a/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj +++ b/src/FrontEnd/BinLifter/CIL/B2R2.FrontEnd.BinLifter.CIL.fsproj @@ -9,10 +9,10 @@ - - + + diff --git a/src/FrontEnd/BinLifter/CIL/CIL.fs b/src/FrontEnd/BinLifter/CIL/CIL.fs index f2e7f3f7..c7414a23 100644 --- a/src/FrontEnd/BinLifter/CIL/CIL.fs +++ b/src/FrontEnd/BinLifter/CIL/CIL.fs @@ -24,7 +24,6 @@ namespace B2R2.FrontEnd.BinLifter.CIL -open System open B2R2 open B2R2.FrontEnd.BinLifter @@ -38,20 +37,10 @@ type CILTranslationContext internal (isa, regexprs) = override __.GetPseudoRegVar _id _pos = Utils.impossible () -type CILParser () = - inherit Parser () - override __.Parse (_: byte[], _: Addr): Instruction = - Utils.futureFeature () - - override __.Parse (_: ByteSpan, _: Addr): Instruction = - Utils.futureFeature () - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - module Basis = let init isa = let regexprs = RegExprs () struct ( CILTranslationContext (isa, regexprs) :> TranslationContext, - CILRegisterBay () :> RegisterBay + CILRegisterFactory () :> RegisterFactory ) diff --git a/src/FrontEnd/BinLifter/CIL/CILInstruction.fs b/src/FrontEnd/BinLifter/CIL/CILInstruction.fs index 1273a688..164442ca 100644 --- a/src/FrontEnd/BinLifter/CIL/CILInstruction.fs +++ b/src/FrontEnd/BinLifter/CIL/CILInstruction.fs @@ -51,7 +51,7 @@ type CILInstruction (addr, numBytes, wordSize) = override __.IsNop () = Utils.futureFeature () override __.Translate (_) = Utils.futureFeature () override __.TranslateToList (_) = Utils.futureFeature () - override __.Disasm (_, _, _) = Utils.futureFeature () + override __.Disasm (_, _) = Utils.futureFeature () override __.Disasm () = Utils.futureFeature () override __.Decompose (_) = Utils.futureFeature () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/CIL/CILParser.fs b/src/FrontEnd/BinLifter/CIL/CILParser.fs new file mode 100644 index 00000000..cb5e3072 --- /dev/null +++ b/src/FrontEnd/BinLifter/CIL/CILParser.fs @@ -0,0 +1,41 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.CIL + +open B2R2 +open B2R2.FrontEnd.BinLifter + +type CILParser () = + interface IInstructionParsable with + member __.Parse (_: byte[], _: Addr): Instruction = + Utils.futureFeature () + + member __.Parse (_: ByteSpan, _: Addr): Instruction = + Utils.futureFeature () + + member __.MaxInstructionSize = + Utils.futureFeature () + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/CIL/CILRegExprs.fs b/src/FrontEnd/BinLifter/CIL/CILRegExprs.fs index 125ec1a2..2697905e 100644 --- a/src/FrontEnd/BinLifter/CIL/CILRegExprs.fs +++ b/src/FrontEnd/BinLifter/CIL/CILRegExprs.fs @@ -25,10 +25,11 @@ namespace B2R2.FrontEnd.BinLifter.CIL open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR type internal RegExprs () = - let var sz t name = AST.var sz t name (CILRegisterSet.singleton t) + let var sz t name = AST.var sz t name member val PC = var 256 (Register.toRegID Register.PC) "PC" with get member val SP = var 256 (Register.toRegID Register.SP) "SP" with get @@ -37,4 +38,4 @@ type internal RegExprs () = match name with | Register.PC -> __.PC | Register.SP -> __.SP - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException diff --git a/src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs b/src/FrontEnd/BinLifter/CIL/CILRegisterFactory.fs similarity index 90% rename from src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs rename to src/FrontEnd/BinLifter/CIL/CILRegisterFactory.fs index 5cba2e53..ff2755d7 100644 --- a/src/FrontEnd/BinLifter/CIL/CILRegisterBay.fs +++ b/src/FrontEnd/BinLifter/CIL/CILRegisterFactory.fs @@ -28,9 +28,8 @@ open B2R2 open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type CILRegisterBay () = - - inherit RegisterBay () +type CILRegisterFactory () = + inherit RegisterFactory () override __.GetAllRegExprs () = Utils.futureFeature () @@ -40,11 +39,11 @@ type CILRegisterBay () = override __.RegIDFromRegExpr (e) = match e.E with - | Var (_, id, _ ,_) -> id - | PCVar (_, _) -> Register.toRegID Register.PC - | _ -> failwith "not a register expression" + | Var (_, id, _) -> id + | PCVar _ -> Register.toRegID Register.PC + | _ -> raise InvalidRegisterException - override __.RegIDToRegExpr (id) = Utils.impossible () + override __.RegIDToRegExpr (_id) = Utils.impossible () override __.StrToRegExpr _s = Utils.impossible () diff --git a/src/FrontEnd/BinLifter/CIL/CILTypes.fs b/src/FrontEnd/BinLifter/CIL/CILTypes.fs index aece7faf..4926b00c 100644 --- a/src/FrontEnd/BinLifter/CIL/CILTypes.fs +++ b/src/FrontEnd/BinLifter/CIL/CILTypes.fs @@ -42,7 +42,7 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "pc" -> Register.PC | "sp" -> Register.SP | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinLifter/Core/AsmWord.fs b/src/FrontEnd/BinLifter/Core/AsmWord.fs index 44e73e6b..9e93800f 100644 --- a/src/FrontEnd/BinLifter/Core/AsmWord.fs +++ b/src/FrontEnd/BinLifter/Core/AsmWord.fs @@ -24,8 +24,6 @@ namespace B2R2.FrontEnd.BinLifter -open System.Collections - /// A kind of a term within an assembly statement. type AsmWordKind = /// An address of the given instruction. @@ -56,27 +54,3 @@ with | AsmWordKind.Value -> s, "value" | AsmWordKind.String -> s, "string" | _ -> failwith "Impossible" - -/// Builder for an array of AsmWords. -type AsmWordBuilder = - inherit Generic.List - - /// - /// Initialize an IR statement builder of internal buffer size n. - /// - /// The size of the internal buffer. - new (n: int) = { inherit Generic.List(n) } - - /// - /// Append a new AsmWord to the builder. - /// - /// AsmWord to add. - member __.Append stmt = __.Add (stmt); __ - - /// - /// Create an array of AsmWords from the buffer. - /// - /// - /// Returns an array of AsmWords. - /// - member __.Finish () = __.ToArray () diff --git a/src/FrontEnd/BinLifter/Core/ParseUtils.fs b/src/FrontEnd/BinLifter/Core/AsmWordBuilder.fs similarity index 70% rename from src/FrontEnd/BinLifter/Core/ParseUtils.fs rename to src/FrontEnd/BinLifter/Core/AsmWordBuilder.fs index 48559d57..614e583f 100644 --- a/src/FrontEnd/BinLifter/Core/ParseUtils.fs +++ b/src/FrontEnd/BinLifter/Core/AsmWordBuilder.fs @@ -24,18 +24,20 @@ namespace B2R2.FrontEnd.BinLifter -/// 32-bit binary representation. -type BitData32 = uint32 - -module BitData = - - let extract binary n1 n2 = - let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 - let range = m - n + 1u - if range > 31u then failwith "invaild range" else () - let mask = pown 2 (int range) - 1 |> uint32 - binary >>> int n &&& mask - - let pickBit binary (pos: uint32) = binary >>> int pos &&& 0b1u - - let concat (n1: uint32) (n2: uint32) shift = (n1 <<< shift) + n2 +open System.Collections + +/// Builder for an array of AsmWords. +type AsmWordBuilder = + inherit Generic.List + + /// + /// Initialize an IR statement builder of internal buffer size n. + /// + /// The size of the internal buffer. + new (n: int) = { inherit Generic.List(n) } + + /// + /// Append a new AsmWord to the builder. + /// + /// AsmWord to add. + member __.Append stmt = __.Add (stmt); __ diff --git a/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj b/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj index f2344a69..9d120696 100644 --- a/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj +++ b/src/FrontEnd/BinLifter/Core/B2R2.FrontEnd.BinLifter.Core.fsproj @@ -12,11 +12,14 @@ - - + + + + + - - + + diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSUtils.fs b/src/FrontEnd/BinLifter/Core/BitData.fs similarity index 51% rename from src/FrontEnd/BinLifter/MIPS/MIPSUtils.fs rename to src/FrontEnd/BinLifter/Core/BitData.fs index 274abbeb..4fc947f0 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSUtils.fs +++ b/src/FrontEnd/BinLifter/Core/BitData.fs @@ -22,27 +22,37 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.BinLifter.MIPS.Utils +/// This module provides several useful functions to access a 32-bit bit vector, +/// represented as either a uint32 or a uint64. +module B2R2.FrontEnd.BinLifter.BitData -open B2R2 +open System -let extract binary n1 n2 = - let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 +/// Extract bit values located in between the given two offsets. The order of +/// the offsets does not matter. +let extract (binary: uint32) ofs1 ofs2 = + let m, n = if max ofs1 ofs2 = ofs1 then ofs1, ofs2 else ofs2, ofs1 let range = m - n + 1u - if range > 31u then failwith "invaild range" else () + if range > 31u then invalidOp "Invalid range of offsets given." else () let mask = pown 2 (int range) - 1 |> uint32 binary >>> int n &&& mask -let pickBit binary (pos: uint32) = binary >>> int pos &&& 0b1u - -let concat (n1: uint32) (n2: uint32) shift = (n1 <<< shift) + n2 - -let halve bin = bin &&& 0x0000ffffu, bin >>> 16 - -let signExtend bitSize extSize (imm: uint64) = - assert (bitSize <= extSize) - if imm >>> (bitSize - 1) = 0b0UL then imm - else BigInteger.getMask extSize - BigInteger.getMask bitSize ||| (bigint imm) - |> uint64 - -// vim: set tw=80 sts=2 sw=2: +/// Pick a bit value at the given offset. +let pickBit (binary: uint32) (pos: uint32) = + binary >>> int pos &&& 0b1u + +/// Concatenate n1 and n2 by shifting n1 to the left by the given shift amount. +let concat (n1: uint32) (n2: uint32) shiftAmount = + (n1 <<< shiftAmount) + n2 + +/// Get a bit mask (in uint64) of the given size. +let getBitMask64 size = + assert (size <= 64) + UInt64.MaxValue >>> (64 - size) + +/// Sign-extend the given bit vector `v` of the size `originalSize` to the +/// target size `targetSize`. +let signExtend originalSize targetSize (v: uint64) = + assert (originalSize <= targetSize) + if v >>> (originalSize - 1) = 0b0UL then v + else (getBitMask64 targetSize - getBitMask64 originalSize) ||| v diff --git a/src/FrontEnd/BinLifter/Core/DisasmHelper.fs b/src/FrontEnd/BinLifter/Core/DisasmBuilder.fs similarity index 80% rename from src/FrontEnd/BinLifter/Core/DisasmHelper.fs rename to src/FrontEnd/BinLifter/Core/DisasmBuilder.fs index 7aac11c7..2d511e7a 100644 --- a/src/FrontEnd/BinLifter/Core/DisasmHelper.fs +++ b/src/FrontEnd/BinLifter/Core/DisasmBuilder.fs @@ -27,19 +27,11 @@ namespace B2R2.FrontEnd.BinLifter open System.Text open B2R2 -type DisasmHelper (?fn: Addr -> Result) = - let helper = - match fn with - | Some fn -> fn - | None -> fun _ -> Error ErrorCase.SymbolNotFound - - member __.FindFunctionSymbol (addr: Addr) = helper addr - +/// Builder for disassembled strings. [] -type DisasmBuilder<'Result> (showAddr, resolveSymb, wordSz, addr, len) = +type DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) = abstract member Accumulate: AsmWordKind -> string -> unit abstract member AccumulateAddr: unit -> unit - abstract member Finalize: unit -> 'Result member __.ShowAddr with get(): bool = showAddr member __.ResolveSymbol with get(): bool = resolveSymb member __.WordSize with get(): WordSize = wordSz @@ -47,7 +39,7 @@ type DisasmBuilder<'Result> (showAddr, resolveSymb, wordSz, addr, len) = member __.InsLength with get(): uint32 = len type DisasmStringBuilder (showAddr, resolveSymb, wordSz, addr, len) = - inherit DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) + inherit DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) let sb = StringBuilder () @@ -58,10 +50,10 @@ type DisasmStringBuilder (showAddr, resolveSymb, wordSz, addr, len) = sb.Append (Addr.toString wordSz addr) |> ignore sb.Append (": ") |> ignore - override __.Finalize () = sb.ToString () + override __.ToString () = sb.ToString () type DisasmWordBuilder (showAddr, resolveSymb, wordSz, addr, len, n) = - inherit DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) + inherit DisasmBuilder (showAddr, resolveSymb, wordSz, addr, len) let ab = AsmWordBuilder (n) @@ -74,4 +66,4 @@ type DisasmWordBuilder (showAddr, resolveSymb, wordSz, addr, len, n) = ab.Append ({ AsmWordKind = AsmWordKind.String AsmWordValue = ": " }) |> ignore - override __.Finalize () = ab.Finish () + member __.ToArray () = ab.ToArray () diff --git a/src/FrontEnd/BinLifter/Core/DisasmSyntax.fs b/src/FrontEnd/BinLifter/Core/DisasmSyntax.fs new file mode 100644 index 00000000..a391b7b7 --- /dev/null +++ b/src/FrontEnd/BinLifter/Core/DisasmSyntax.fs @@ -0,0 +1,32 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter + +/// Disassembly syntax. +type DisasmSyntax = + /// Default syntax. + | DefaultSyntax + /// AT&T syntax. + | ATTSyntax diff --git a/src/FrontEnd/BinLifter/Core/Parser.fs b/src/FrontEnd/BinLifter/Core/IInstructionParsable.fs similarity index 90% rename from src/FrontEnd/BinLifter/Core/Parser.fs rename to src/FrontEnd/BinLifter/Core/IInstructionParsable.fs index c2f87a3f..8d709aef 100644 --- a/src/FrontEnd/BinLifter/Core/Parser.fs +++ b/src/FrontEnd/BinLifter/Core/IInstructionParsable.fs @@ -24,12 +24,10 @@ namespace B2R2.FrontEnd.BinLifter -open System open B2R2 -/// A platform-independent instruction parser. -[] -type Parser () = +/// A platform-independent binary instruction parser. +type IInstructionParsable = /// Parse one instruction from the given byte array assuming that the address /// of the instruction is `addr`. abstract member Parse: bs: byte[] * addr: Addr -> Instruction @@ -38,6 +36,9 @@ type Parser () = /// of the instruction is `addr`. abstract member Parse: span: ByteSpan * addr: Addr -> Instruction + /// Return the maximum possible size of an instruction. + abstract member MaxInstructionSize: int + /// The current operation mode of the Parser. This is only useful for ARMv7 /// parsers. abstract member OperationMode: ArchOperationMode with get, set diff --git a/src/FrontEnd/BinLifter/ARM64/ARM64Parser.fsi b/src/FrontEnd/BinLifter/Core/INameReadable.fs similarity index 73% rename from src/FrontEnd/BinLifter/ARM64/ARM64Parser.fsi rename to src/FrontEnd/BinLifter/Core/INameReadable.fs index 2db0f960..7486f4b4 100644 --- a/src/FrontEnd/BinLifter/ARM64/ARM64Parser.fsi +++ b/src/FrontEnd/BinLifter/Core/INameReadable.fs @@ -22,14 +22,18 @@ SOFTWARE. *) -/// ARMv8 instruction parser. -module B2R2.FrontEnd.BinLifter.ARM64.Parser +namespace B2R2.FrontEnd.BinLifter -open System open B2R2 -/// Read in bytes and return a parsed instruction for ARMv8. This function -/// returns ARM64Instruction, which is a specialized type for 64-bit ARM. If you -/// want to handle instructions in a platform-agnostic manner, you'd better use -/// the ARM64Parser class. -val parse: ByteSpan -> IBinReader -> Addr -> ARM64Instruction +/// Interface for reading names in a binary. +[] +type INameReadable = + /// + /// Find the corresponding function name for a given address. + /// + /// + /// Returns a name if the corresponding symbol exists, otherwise returns + /// an Error value. + /// + abstract TryFindFunctionName: Addr -> Result \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/Core/IRBuilder.fs b/src/FrontEnd/BinLifter/Core/IRBuilder.fs index 10a0bbdf..77da282a 100644 --- a/src/FrontEnd/BinLifter/Core/IRBuilder.fs +++ b/src/FrontEnd/BinLifter/Core/IRBuilder.fs @@ -65,9 +65,16 @@ type IRBuilder = member __.Append stmt = __.Add (stmt) /// - /// Create an array of IR statements from the buffer. + /// Create an array of IR statements from the buffer. This function will + /// clear up the buffer and initialize the tempvar count, too. /// /// /// Returns an array of IR statements. /// - member __.ToStmts () = __.ToArray () + member __.ToStmts () = +#if EMULATION + __.TempVarCount <- 0 +#endif + let stmts = __.ToArray () + __.Clear () + stmts diff --git a/src/FrontEnd/BinLifter/Core/Instruction.fs b/src/FrontEnd/BinLifter/Core/Instruction.fs index 49337598..918dc982 100644 --- a/src/FrontEnd/BinLifter/Core/Instruction.fs +++ b/src/FrontEnd/BinLifter/Core/Instruction.fs @@ -200,13 +200,13 @@ type Instruction (addr, len, wordSize) = abstract member Immediate: [] v: byref -> bool /// - /// Return a sequence of possible next instruction addresses along with + /// Return an array of possible next instruction addresses along with /// their ArchOperationMode. For branch instructions, the returned sequence /// includes jump target(s). For regular instructions, the sequence is a /// singleton of the fall-through address. This function does not resolve /// indirect branch targets. /// - abstract member GetNextInstrAddrs: unit -> seq + abstract member GetNextInstrAddrs: unit -> (Addr * ArchOperationMode) array /// /// Return the interrupt number if this is an interrupt instruction. @@ -239,23 +239,17 @@ type Instruction (addr, len, wordSize) = /// /// Whether to show the instruction address in the resulting disassembly. /// - /// - /// Whether to resolve symbols while disassembling the instruction. For - /// example, when there is a call target, we the disassembled string will - /// show the target function name if this parameter is true, and the symbol - /// information exists. - /// - /// - /// The helper allows our disassembler to resolve symbols. + /// + /// When this parameter is given, we disassemble the instruction with the + /// given name reader to resolve symbols in the instruction. For example, + /// when there is a call target, the disassembled string will show the + /// target function name if this parameter is given and the corresponding + /// symbol information exists. This parameter can be null. /// /// /// Returns a disassembled string. /// - abstract member Disasm: - showAddr: bool - * resolveSymbol: bool - * disasmHelper: DisasmHelper - -> string + abstract member Disasm: showAddr: bool * nameReader: INameReadable -> string /// /// Disassemble this instruction without resolving symbols. diff --git a/src/FrontEnd/BinLifter/Core/LiftingOperators.fs b/src/FrontEnd/BinLifter/Core/LiftingOperators.fs index bf8562a5..99a481d0 100644 --- a/src/FrontEnd/BinLifter/Core/LiftingOperators.fs +++ b/src/FrontEnd/BinLifter/Core/LiftingOperators.fs @@ -38,7 +38,10 @@ open B2R2.BinIR.LowUIR let inline ( !! ) (ir: IRBuilder) (s) = ir.Append s /// The special operator for creating a temporary variable. -let inline ( !* ) (ir: IRBuilder) rt = ir.NewTempVar rt +let inline ( !+ ) (ir: IRBuilder) rt = ir.NewTempVar rt + +/// The special operator for creating a symbol. +let inline ( !% ) (ir: IRBuilder) label = ir.NewSymbol label /// The special operator for starting an instruction (ISMark). let inline ( !< ) (ir: IRBuilder) insLen = @@ -52,3 +55,7 @@ let inline ( !> ) (ir: IRBuilder) (insLen: uint32) = /// The special operator for applying a function with a IRBuilder as input. let inline ( !? ) (ir: IRBuilder) fn = fn ir + +/// Fetch IRBuilder from the given translation context. +let inline ( !* ) (ctxt: TranslationContext) = + ctxt.IRBuilder diff --git a/src/FrontEnd/BinLifter/Core/LiftingUtils.fs b/src/FrontEnd/BinLifter/Core/LiftingUtils.fs index 330cfcfa..18f67481 100644 --- a/src/FrontEnd/BinLifter/Core/LiftingUtils.fs +++ b/src/FrontEnd/BinLifter/Core/LiftingUtils.fs @@ -28,19 +28,83 @@ open B2R2 open B2R2.BinIR.LowUIR open B2R2.FrontEnd.BinLifter.LiftingOperators -let inline numU32 n t = BitVector.ofUInt32 n t |> AST.num +let inline numU32 n t = BitVector.OfUInt32 n t |> AST.num -let inline numI32 n t = BitVector.ofInt32 n t |> AST.num +let inline numI32 n t = BitVector.OfInt32 n t |> AST.num -let inline numU64 n t = BitVector.ofUInt64 n t |> AST.num +let inline numU64 n t = BitVector.OfUInt64 n t |> AST.num -let inline numI64 n t = BitVector.ofInt64 n t |> AST.num +let inline numI64 n t = BitVector.OfInt64 n t |> AST.num let inline tmpVars2 ir t = - struct (!*ir t, !*ir t) + struct (!+ir t, !+ir t) let inline tmpVars3 ir t = - struct (!*ir t, !*ir t, !*ir t) + struct (!+ir t, !+ir t, !+ir t) let inline tmpVars4 ir t = - struct (!*ir t, !*ir t, !*ir t, !*ir t) + struct (!+ir t, !+ir t, !+ir t, !+ir t) + +module IEEE754Single = + open B2R2.BinIR.LowUIR.AST.InfixOp + + let inline private hasFraction x = + (x .& numU32 0x7fffffu 32) != AST.num0 32 + + let isNaN x = + let exponent = (x >> numI32 23 32) .& numI32 0xff 32 + let e = numI32 0xff 32 + AST.xtlo 1 ((exponent == e) .& hasFraction x) + + let isSNaN x = + let nanChecker = isNaN x + let signalBit = numU32 (1u <<< 22) 32 + nanChecker .& ((x .& signalBit) == AST.num0 32) + + let isQNaN x = + let nanChecker = isNaN x + let signalBit = numU32 (1u <<< 22) 32 + nanChecker .& ((x .& signalBit) != AST.num0 32) + + let isInfinity x = + let exponent = (x >> numI32 23 32) .& numI32 0xff 32 + let fraction = x .& numU32 0x7fffffu 32 + let e = numI32 0xff 32 + let zero = AST.num0 32 + AST.xtlo 1 ((exponent == e) .& (fraction == zero)) + + let isZero x = + let mask = numU32 0x7fffffffu 32 + AST.eq (x .& mask) (AST.num0 32) + +module IEEE754Double = + open B2R2.BinIR.LowUIR.AST.InfixOp + + let inline private hasFraction x = + (x .& numU64 0xfffff_ffffffffUL 64) != AST.num0 64 + + let isNaN x = + let exponent = (x >> numI32 52 64) .& numI32 0x7ff 64 + let e = numI32 0x7ff 64 + AST.xtlo 1 ((exponent == e) .& hasFraction x) + + let isSNaN x = + let nanChecker = isNaN x + let signalBit = numU64 (1UL <<< 51) 64 + nanChecker .& ((x .& signalBit) == AST.num0 64) + + let isQNaN x = + let nanChecker = isNaN x + let signalBit = numU64 (1UL <<< 51) 64 + nanChecker .& ((x .& signalBit) != AST.num0 64) + + let isInfinity x = + let exponent = (x >> numI32 52 64) .& numI32 0x7ff 64 + let fraction = x .& numU64 0xfffff_ffffffffUL 64 + let e = numI32 0x7ff 64 + let zero = AST.num0 64 + AST.xtlo 1 ((exponent == e) .& (fraction == zero)) + + let isZero x = + let mask = numU64 0x7fffffff_ffffffffUL 64 + AST.eq (x .& mask) (AST.num0 64) diff --git a/src/FrontEnd/BinLifter/Core/RegisterBay.fs b/src/FrontEnd/BinLifter/Core/RegisterFactory.fs similarity index 93% rename from src/FrontEnd/BinLifter/Core/RegisterBay.fs rename to src/FrontEnd/BinLifter/Core/RegisterFactory.fs index 849fcd46..1f4311d5 100644 --- a/src/FrontEnd/BinLifter/Core/RegisterBay.fs +++ b/src/FrontEnd/BinLifter/Core/RegisterFactory.fs @@ -27,10 +27,11 @@ namespace B2R2.FrontEnd.BinLifter open B2R2 open B2R2.BinIR.LowUIR -/// RegisterBay provides a useful interface for accessing register information -/// in a platform-agnostic manner. +/// RegisterFactory provides a useful interface for accessing register related +/// information such as register names, register expressions, register types, +/// and their IDs, in a platform-agnostic manner. [] -type RegisterBay () = +type RegisterFactory () = /// Return all register expressions. abstract member GetAllRegExprs: unit -> Expr list @@ -44,7 +45,7 @@ type RegisterBay () = /// Return RegType from a given RegExpr. member __.RegTypeFromRegExpr (e: Expr) = match e.E with - | Var (rt, _, _ ,_) + | Var (rt, _, _) | PCVar (rt, _) -> rt | _ -> raise InvalidRegisterException diff --git a/src/FrontEnd/BinLifter/Core/TranslationContext.fs b/src/FrontEnd/BinLifter/Core/TranslationContext.fs index 94bda62b..f853067f 100644 --- a/src/FrontEnd/BinLifter/Core/TranslationContext.fs +++ b/src/FrontEnd/BinLifter/Core/TranslationContext.fs @@ -27,15 +27,80 @@ namespace B2R2.FrontEnd.BinLifter open B2R2 open B2R2.BinIR.LowUIR +#if EMULATION +/// Lazily remembered lastly used opcode. +type ConditionCodeOp = + /// Indicator for the start of a trace. + | TraceStart = 0x1 + /// Indicator for EFLAGS computation. This is set only when EFLAGS computation + /// is complete. + | EFlags = 0x2 + | SUBB = 0x3 + | SUBW = 0x4 + | SUBD = 0x5 + | SUBQ = 0x6 + | LOGICB = 0x7 + | LOGICW = 0x8 + | LOGICD = 0x9 + | LOGICQ = 0xA + | ADDB = 0xB + | ADDW = 0xC + | ADDD = 0xD + | ADDQ = 0xE + | SHLB = 0xF + | SHLW = 0x10 + | SHLD = 0x11 + | SHLQ = 0x12 + | SHRB = 0x13 + | SHRW = 0x14 + | SHRD = 0x15 + | SHRQ = 0x16 + | SARB = 0x17 + | SARW = 0x18 + | SARD = 0x19 + | SARQ = 0x1A + | INCB = 0x1B + | INCW = 0x1C + | INCD = 0x1D + | INCQ = 0x1E + | DECB = 0x1F + | DECW = 0x20 + | DECD = 0x21 + | DECQ = 0x22 + /// XOR of the same operands. + | XORXX = 0x23 +#endif + /// A high-level interface for the translation context, which stores several /// states for translating/lifting instructions. [] type TranslationContext (isa) = + let irb = IRBuilder (241) + let mutable delayedJump = InterJmpKind.NotAJmp +#if EMULATION + let mutable conditionCodeOp = ConditionCodeOp.TraceStart +#endif + /// Word size in bits (RegType). - member val WordBitSize: RegType = WordSize.toRegType isa.WordSize + member __.WordBitSize with get(): RegType = WordSize.toRegType isa.WordSize /// The endianness. - member val Endianness: Endian = isa.Endian + member __.Endianness with get(): Endian = isa.Endian + + /// IRBuilder for lifting IRs. + member __.IRBuilder with get() = irb + + /// Remember if a branch is delayed. If delayed, we store its InterJmpKind. + /// Lifting results may vary depending on this variable. + member __.DelayedBranch + with get() = delayedJump and set(f) = delayedJump <- f + +#if EMULATION + /// Remember the lastly used opcode that updates EFLAGS. This is explicitly + /// used for x86 emulation. + member __.ConditionCodeOp + with get() = conditionCodeOp and set(v) = conditionCodeOp <- v +#endif /// /// Get register expression from a given register ID. diff --git a/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj b/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj index 5126efc0..ac1dd6fe 100644 --- a/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj +++ b/src/FrontEnd/BinLifter/EVM/B2R2.FrontEnd.BinLifter.EVM.fsproj @@ -9,14 +9,14 @@ - - + + - + diff --git a/src/FrontEnd/BinLifter/EVM/EVM.fs b/src/FrontEnd/BinLifter/EVM/EVM.fs deleted file mode 100644 index 293962e3..00000000 --- a/src/FrontEnd/BinLifter/EVM/EVM.fs +++ /dev/null @@ -1,73 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.EVM - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for Ethereum Virtual Machine (EVM) instructions. -type EVMTranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for EVM instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type EVMParser (isa: ISA) = - inherit Parser () - let mutable codeOffset: Addr = 0UL - let wordSize = isa.WordSize - let reader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - - member __.CodeOffset with get() = codeOffset and set(o) = codeOffset <- o - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan (bs) - Parser.parse span reader codeOffset wordSize addr - :> Instruction - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader codeOffset wordSize addr - :> Instruction - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - -module Basis = - let init isa = - let regexprs = RegExprs () - struct ( - EVMTranslationContext (isa, regexprs) :> TranslationContext, - EVMRegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs b/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs index bf140632..ec705ece 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMDisasm.fs @@ -70,12 +70,16 @@ let opcodeToStrings = function | EXTCODECOPY -> struct("extcodecopy", None) | RETURNDATASIZE -> struct("returndatasize", None) | RETURNDATACOPY -> struct("returndatacopy", None) + | EXTCODEHASH -> struct("extcodehash", None) | BLOCKHASH -> struct("blockhash", None) | COINBASE -> struct("coinbase", None) | TIMESTAMP -> struct("timestamp", None) | NUMBER -> struct("number", None) | DIFFICULTY -> struct("difficulty", None) | GASLIMIT -> struct("gaslimit", None) + | CHAINID -> struct("chain_id", None) + | SELFBALANCE -> struct("this.balance", None) + | BASEFEE -> struct("block.basefee", None) | POP -> struct("pop", None) | MLOAD -> struct("mload", None) | MSTORE -> struct("mstore", None) @@ -88,38 +92,38 @@ let opcodeToStrings = function | MSIZE -> struct("msize", None) | GAS -> struct("gas", None) | JUMPDEST -> struct("jumpdest", None) - | PUSH1 imm -> struct("push1", BitVector.valToString imm |> Some) - | PUSH2 imm -> struct("push2", BitVector.valToString imm |> Some) - | PUSH3 imm -> struct("push3", BitVector.valToString imm |> Some) - | PUSH4 imm -> struct("push4", BitVector.valToString imm |> Some) - | PUSH5 imm -> struct("push5", BitVector.valToString imm |> Some) - | PUSH6 imm -> struct("push6", BitVector.valToString imm |> Some) - | PUSH7 imm -> struct("push7", BitVector.valToString imm |> Some) - | PUSH8 imm -> struct("push8", BitVector.valToString imm |> Some) - | PUSH9 imm -> struct("push9", BitVector.valToString imm |> Some) - | PUSH10 imm -> struct("push10", BitVector.valToString imm |> Some) - | PUSH11 imm -> struct("push11", BitVector.valToString imm |> Some) - | PUSH12 imm -> struct("push12", BitVector.valToString imm |> Some) - | PUSH13 imm -> struct("push13", BitVector.valToString imm |> Some) - | PUSH14 imm -> struct("push14", BitVector.valToString imm |> Some) - | PUSH15 imm -> struct("push15", BitVector.valToString imm |> Some) - | PUSH16 imm -> struct("push16", BitVector.valToString imm |> Some) - | PUSH17 imm -> struct("push17", BitVector.valToString imm |> Some) - | PUSH18 imm -> struct("push18", BitVector.valToString imm |> Some) - | PUSH19 imm -> struct("push19", BitVector.valToString imm |> Some) - | PUSH20 imm -> struct("push20", BitVector.valToString imm |> Some) - | PUSH21 imm -> struct("push21", BitVector.valToString imm |> Some) - | PUSH22 imm -> struct("push22", BitVector.valToString imm |> Some) - | PUSH23 imm -> struct("push23", BitVector.valToString imm |> Some) - | PUSH24 imm -> struct("push24", BitVector.valToString imm |> Some) - | PUSH25 imm -> struct("push25", BitVector.valToString imm |> Some) - | PUSH26 imm -> struct("push26", BitVector.valToString imm |> Some) - | PUSH27 imm -> struct("push27", BitVector.valToString imm |> Some) - | PUSH28 imm -> struct("push28", BitVector.valToString imm |> Some) - | PUSH29 imm -> struct("push29", BitVector.valToString imm |> Some) - | PUSH30 imm -> struct("push30", BitVector.valToString imm |> Some) - | PUSH31 imm -> struct("push31", BitVector.valToString imm |> Some) - | PUSH32 imm -> struct("push32", BitVector.valToString imm |> Some) + | PUSH1 imm -> struct("push1", BitVector.ValToString imm |> Some) + | PUSH2 imm -> struct("push2", BitVector.ValToString imm |> Some) + | PUSH3 imm -> struct("push3", BitVector.ValToString imm |> Some) + | PUSH4 imm -> struct("push4", BitVector.ValToString imm |> Some) + | PUSH5 imm -> struct("push5", BitVector.ValToString imm |> Some) + | PUSH6 imm -> struct("push6", BitVector.ValToString imm |> Some) + | PUSH7 imm -> struct("push7", BitVector.ValToString imm |> Some) + | PUSH8 imm -> struct("push8", BitVector.ValToString imm |> Some) + | PUSH9 imm -> struct("push9", BitVector.ValToString imm |> Some) + | PUSH10 imm -> struct("push10", BitVector.ValToString imm |> Some) + | PUSH11 imm -> struct("push11", BitVector.ValToString imm |> Some) + | PUSH12 imm -> struct("push12", BitVector.ValToString imm |> Some) + | PUSH13 imm -> struct("push13", BitVector.ValToString imm |> Some) + | PUSH14 imm -> struct("push14", BitVector.ValToString imm |> Some) + | PUSH15 imm -> struct("push15", BitVector.ValToString imm |> Some) + | PUSH16 imm -> struct("push16", BitVector.ValToString imm |> Some) + | PUSH17 imm -> struct("push17", BitVector.ValToString imm |> Some) + | PUSH18 imm -> struct("push18", BitVector.ValToString imm |> Some) + | PUSH19 imm -> struct("push19", BitVector.ValToString imm |> Some) + | PUSH20 imm -> struct("push20", BitVector.ValToString imm |> Some) + | PUSH21 imm -> struct("push21", BitVector.ValToString imm |> Some) + | PUSH22 imm -> struct("push22", BitVector.ValToString imm |> Some) + | PUSH23 imm -> struct("push23", BitVector.ValToString imm |> Some) + | PUSH24 imm -> struct("push24", BitVector.ValToString imm |> Some) + | PUSH25 imm -> struct("push25", BitVector.ValToString imm |> Some) + | PUSH26 imm -> struct("push26", BitVector.ValToString imm |> Some) + | PUSH27 imm -> struct("push27", BitVector.ValToString imm |> Some) + | PUSH28 imm -> struct("push28", BitVector.ValToString imm |> Some) + | PUSH29 imm -> struct("push29", BitVector.ValToString imm |> Some) + | PUSH30 imm -> struct("push30", BitVector.ValToString imm |> Some) + | PUSH31 imm -> struct("push31", BitVector.ValToString imm |> Some) + | PUSH32 imm -> struct("push32", BitVector.ValToString imm |> Some) | DUP1 -> struct("dup1", None) | DUP2 -> struct("dup2", None) | DUP3 -> struct("dup3", None) @@ -168,7 +172,7 @@ let opcodeToStrings = function | INVALID -> struct("invalid", None) | SELFDESTRUCT -> struct("selfdestruct", None) -let inline buildOpcode insInfo (builder: DisasmBuilder<_>) = +let inline buildOpcode insInfo (builder: DisasmBuilder) = let struct (opcode, extra) = opcodeToStrings insInfo.Opcode match extra with | None -> builder.Accumulate AsmWordKind.Mnemonic opcode @@ -177,7 +181,7 @@ let inline buildOpcode insInfo (builder: DisasmBuilder<_>) = builder.Accumulate AsmWordKind.String " " builder.Accumulate AsmWordKind.Value extra -let disasm insInfo (builder: DisasmBuilder<_>) = +let disasm insInfo (builder: DisasmBuilder) = if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode insInfo builder diff --git a/src/FrontEnd/BinLifter/EVM/EVMInstruction.fs b/src/FrontEnd/BinLifter/EVM/EVMInstruction.fs index 494a46d0..7543ac3c 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMInstruction.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMInstruction.fs @@ -65,7 +65,6 @@ type EVMInstruction (addr, numBytes, insInfo, wordSize) = override __.IsRET () = match __.Info.Opcode with - | Opcode.REVERT | Opcode.RETURN -> true | _ -> false @@ -97,8 +96,8 @@ type EVMInstruction (addr, numBytes, insInfo, wordSize) = override __.GetNextInstrAddrs () = let fallthrough = __.Address + uint64 __.Length - let acc = Seq.singleton (fallthrough, ArchOperationMode.NoMode) - if __.IsExit () then Seq.empty + let acc = [| (fallthrough, ArchOperationMode.NoMode) |] + if __.IsExit () then [||] else acc override __.InterruptNum (_num: byref) = Utils.futureFeature () @@ -111,23 +110,23 @@ type EVMInstruction (addr, numBytes, insInfo, wordSize) = override __.TranslateToList ctxt = Lifter.translate __.Info ctxt - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, WordSize.Bit256, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit256, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit256, addr, numBytes, 8) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/EVM/EVMLifter.fs b/src/FrontEnd/BinLifter/EVM/EVMLifter.fs index f19b0f3e..dc09663d 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMLifter.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMLifter.fs @@ -48,13 +48,13 @@ let inline private updateGas ctxt gas builder = builder ) let sideEffects insInfo name = - let builder = new IRBuilder (4) + let builder = IRBuilder (4) startMark insInfo builder builder ) -let shl insInfo ctxt = basicOperation insInfo ctxt (<<) -let shr insInfo ctxt = basicOperation insInfo ctxt (>>) -let sar insInfo ctxt = basicOperation insInfo ctxt (?>>) +let shl insInfo ctxt = shiftOperation insInfo ctxt (<<) +let shr insInfo ctxt = shiftOperation insInfo ctxt (>>) +let sar insInfo ctxt = shiftOperation insInfo ctxt (?>>) let addmod insInfo ctxt = - let builder = new IRBuilder (12) + let builder = IRBuilder (12) startMark insInfo builder let src1 = popFromStack ctxt builder let src2 = popFromStack ctxt builder @@ -136,7 +148,7 @@ let addmod insInfo ctxt = endMark insInfo builder let mulmod insInfo ctxt = - let builder = new IRBuilder (12) + let builder = IRBuilder (12) startMark insInfo builder let src1 = popFromStack ctxt builder let src2 = popFromStack ctxt builder @@ -149,7 +161,7 @@ let mulmod insInfo ctxt = let private makeNum i = numI32 i OperationSize.regType let signextend insInfo ctxt = - let builder = new IRBuilder (12) + let builder = IRBuilder (12) startMark insInfo builder let b = popFromStack ctxt builder let x = popFromStack ctxt builder @@ -160,7 +172,7 @@ let signextend insInfo ctxt = endMark insInfo builder let iszero insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let cond = popFromStack ctxt builder let rt = OperationSize.regType @@ -170,7 +182,7 @@ let iszero insInfo ctxt = endMark insInfo builder let not insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let e = popFromStack ctxt builder let expr = AST.zext OperationSize.regType (AST.not e) @@ -179,7 +191,7 @@ let not insInfo ctxt = endMark insInfo builder let byte insInfo ctxt = - let builder = new IRBuilder (12) + let builder = IRBuilder (12) startMark insInfo builder let n = popFromStack ctxt builder let x = popFromStack ctxt builder @@ -189,14 +201,14 @@ let byte insInfo ctxt = endMark insInfo builder let pop insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder popFromStack ctxt builder |> ignore updateGas ctxt insInfo.GAS builder endMark insInfo builder let mload insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let addr = popFromStack ctxt builder let expr = AST.loadBE OperationSize.regType addr @@ -205,7 +217,7 @@ let mload insInfo ctxt = endMark insInfo builder let mstore insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let addr = popFromStack ctxt builder let value = popFromStack ctxt builder @@ -214,7 +226,7 @@ let mstore insInfo ctxt = endMark insInfo builder let mstore8 insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let addr = popFromStack ctxt builder let value = popFromStack ctxt builder @@ -224,7 +236,7 @@ let mstore8 insInfo ctxt = endMark insInfo builder let jump insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) try startMark insInfo builder let dst = popFromStack ctxt builder @@ -237,7 +249,7 @@ let jump insInfo ctxt = sideEffects insInfo Terminate let jumpi insInfo ctxt = - let builder = new IRBuilder (12) + let builder = IRBuilder (12) startMark insInfo builder let dst = popFromStack ctxt builder let dstAddr = dst .+ (numU64 insInfo.Offset 256) @@ -248,7 +260,7 @@ let jumpi insInfo ctxt = endMark insInfo builder let getpc insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let expr = getRegVar ctxt R.PC |> AST.zext OperationSize.regType pushToStack ctxt expr builder @@ -256,7 +268,7 @@ let getpc insInfo ctxt = endMark insInfo builder let gas insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let expr = AST.zext OperationSize.regType (getRegVar ctxt R.GAS) pushToStack ctxt expr builder @@ -264,15 +276,15 @@ let gas insInfo ctxt = endMark insInfo builder let push insInfo ctxt imm = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder - let expr = BitVector.cast imm 256 |> AST.num + let expr = BitVector.Cast (imm, 256) |> AST.num pushToStack ctxt expr builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let dup insInfo ctxt pos = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) startMark insInfo builder let src = peekStack ctxt pos builder pushToStack ctxt src builder @@ -280,24 +292,24 @@ let dup insInfo ctxt pos = endMark insInfo builder let swap insInfo ctxt pos = - let builder = new IRBuilder (12) + let builder = IRBuilder (12) startMark insInfo builder swapStack ctxt pos builder updateGas ctxt insInfo.GAS builder endMark insInfo builder let callExternFunc insInfo ctxt name argCount doesRet = - let builder = new IRBuilder (15) + let builder = IRBuilder (15) startMark insInfo builder let args = List.init argCount (fun _ -> popFromStack ctxt builder) let expr = AST.app name args OperationSize.regType if doesRet then pushToStack ctxt expr builder - else builder ignore popFromStack ctxt builder |> ignore sideEffects insInfo Terminate let selfdestruct insInfo ctxt = - let builder = new IRBuilder (8) + let builder = IRBuilder (8) popFromStack ctxt builder |> ignore sideEffects insInfo Terminate @@ -367,12 +379,16 @@ let translate insInfo (ctxt: TranslationContext) = | EXTCODECOPY -> callExternFunc insInfo ctxt "extcodecopy" 4 false | RETURNDATASIZE -> callExternFunc insInfo ctxt "returndatasize" 0 true | RETURNDATACOPY -> callExternFunc insInfo ctxt "returndatacopy" 3 false + | EXTCODEHASH -> callExternFunc insInfo ctxt "extcodehash" 1 true | BLOCKHASH -> callExternFunc insInfo ctxt "blockhash" 1 true | COINBASE -> callExternFunc insInfo ctxt "block.coinbase" 0 true | TIMESTAMP -> callExternFunc insInfo ctxt "block.timestamp" 0 true | NUMBER -> callExternFunc insInfo ctxt "block.number" 0 true | DIFFICULTY -> callExternFunc insInfo ctxt "block.difficulty" 0 true | GASLIMIT -> callExternFunc insInfo ctxt "block.gaslimit" 0 true + | CHAINID -> callExternFunc insInfo ctxt "chainid" 0 true + | SELFBALANCE -> callExternFunc insInfo ctxt "selfbalance" 0 true + | BASEFEE -> callExternFunc insInfo ctxt "basefee" 0 true | POP -> pop insInfo ctxt | MLOAD -> mload insInfo ctxt | MSTORE -> mstore insInfo ctxt diff --git a/src/FrontEnd/BinLifter/EVM/EVMParser.fs b/src/FrontEnd/BinLifter/EVM/EVMParser.fs index 93bf14e1..86ccc78c 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMParser.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMParser.fs @@ -22,168 +22,29 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.EVM.Parser +namespace B2R2.FrontEnd.BinLifter.EVM open System open B2R2 open B2R2.FrontEnd.BinLifter -let private parsePush (span: ReadOnlySpan) reader opcode size = - let bytes = (reader: IBinReader).ReadBytes (span, 1, int size) - struct (opcode <| BitVector.ofArr (Array.rev bytes), 3, 1u + size) +/// Parser for EVM instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type EVMParser (isa: ISA) = + let mutable codeOffset: Addr = 0UL + let wordSize = isa.WordSize -let private parseOpcode (span: ReadOnlySpan) (reader: IBinReader) = - let bin = reader.ReadByte (span, 0) - match bin with - | 0x00uy -> struct (STOP, 0, 1u) - | 0x01uy -> struct (ADD, 3, 1u) - | 0x02uy -> struct (MUL, 5, 1u) - | 0x03uy -> struct (SUB, 3, 1u) - | 0x04uy -> struct (DIV, 5, 1u) - | 0x05uy -> struct (SDIV,50, 1u) - | 0x06uy -> struct (MOD, 5, 1u) - | 0x07uy -> struct (SMOD, 5, 1u) - | 0x08uy -> struct (ADDMOD, 8, 1u) - | 0x09uy -> struct (MULMOD, 8, 1u) - | 0x0auy -> struct (EXP, 10, 1u) - | 0x0buy -> struct (SIGNEXTEND, 5, 1u) - | 0x10uy -> struct (LT, 3, 1u) - | 0x11uy -> struct (GT, 3, 1u) - | 0x12uy -> struct (SLT, 3, 1u) - | 0x13uy -> struct (SGT, 3, 1u) - | 0x14uy -> struct (EQ, 3, 1u) - | 0x15uy -> struct (ISZERO, 3, 1u) - | 0x16uy -> struct (AND, 3, 1u) - | 0x17uy -> struct (OR, 3, 1u) - | 0x18uy -> struct (XOR, 3, 1u) - | 0x19uy -> struct (NOT, 3, 1u) - | 0x1auy -> struct (BYTE, 3, 1u) - | 0x1buy -> struct (SHL, 3, 1u) - | 0x1cuy -> struct (SHR, 3, 1u) - | 0x1duy -> struct (SAR, 3, 1u) - | 0x20uy -> struct (SHA3, 30, 1u) - | 0x30uy -> struct (ADDRESS, 2, 1u) - | 0x31uy -> struct (BALANCE, 400, 1u) - | 0x32uy -> struct (ORIGIN, 2, 1u) - | 0x33uy -> struct (CALLER, 2, 1u) - | 0x34uy -> struct (CALLVALUE, 2, 1u) - | 0x35uy -> struct (CALLDATALOAD, 3, 1u) - | 0x36uy -> struct (CALLDATASIZE, 2, 1u) - | 0x37uy -> struct (CALLDATACOPY, 3, 1u) - | 0x38uy -> struct (CODESIZE, 2, 1u) - | 0x39uy -> struct (CODECOPY, 3, 1u) - | 0x3auy -> struct (GASPRICE, 2, 1u) - | 0x3buy -> struct (EXTCODESIZE, 700, 1u) - | 0x3cuy -> struct (EXTCODECOPY, 700, 1u) - | 0x3duy -> struct (RETURNDATASIZE, 2, 1u) - | 0x3euy -> struct (RETURNDATACOPY, 3, 1u) - | 0x40uy -> struct (BLOCKHASH, 20, 1u) - | 0x41uy -> struct (COINBASE, 2, 1u) - | 0x42uy -> struct (TIMESTAMP, 2, 1u) - | 0x43uy -> struct (NUMBER, 2, 1u) - | 0x44uy -> struct (DIFFICULTY, 2, 1u) - | 0x45uy -> struct (GASLIMIT, 2, 1u) - | 0x50uy -> struct (POP, 2, 1u) - | 0x51uy -> struct (MLOAD, 3, 1u) - | 0x52uy -> struct (MSTORE, 3, 1u) - | 0x53uy -> struct (MSTORE8, 3, 1u) - | 0x54uy -> struct (SLOAD, 200, 1u) - | 0x55uy -> struct (SSTORE, 20000, 1u) - | 0x56uy -> struct (JUMP, 8, 1u) - | 0x57uy -> struct (JUMPI, 10, 1u) - | 0x58uy -> struct (GETPC, 2, 1u) - | 0x59uy -> struct (MSIZE, 2, 1u) - | 0x5auy -> struct (GAS, 2, 1u) - | 0x5buy -> struct (JUMPDEST, 1, 1u) - | 0x60uy -> parsePush span reader PUSH1 1u - | 0x61uy -> parsePush span reader PUSH2 2u - | 0x62uy -> parsePush span reader PUSH3 3u - | 0x63uy -> parsePush span reader PUSH4 4u - | 0x64uy -> parsePush span reader PUSH5 5u - | 0x65uy -> parsePush span reader PUSH6 6u - | 0x66uy -> parsePush span reader PUSH7 7u - | 0x67uy -> parsePush span reader PUSH8 8u - | 0x68uy -> parsePush span reader PUSH9 9u - | 0x69uy -> parsePush span reader PUSH10 10u - | 0x6auy -> parsePush span reader PUSH11 11u - | 0x6buy -> parsePush span reader PUSH12 12u - | 0x6cuy -> parsePush span reader PUSH13 13u - | 0x6duy -> parsePush span reader PUSH14 14u - | 0x6euy -> parsePush span reader PUSH15 15u - | 0x6fuy -> parsePush span reader PUSH16 16u - | 0x70uy -> parsePush span reader PUSH17 17u - | 0x71uy -> parsePush span reader PUSH18 18u - | 0x72uy -> parsePush span reader PUSH19 19u - | 0x73uy -> parsePush span reader PUSH20 20u - | 0x74uy -> parsePush span reader PUSH21 21u - | 0x75uy -> parsePush span reader PUSH22 22u - | 0x76uy -> parsePush span reader PUSH23 23u - | 0x77uy -> parsePush span reader PUSH24 24u - | 0x78uy -> parsePush span reader PUSH25 25u - | 0x79uy -> parsePush span reader PUSH26 26u - | 0x7auy -> parsePush span reader PUSH27 27u - | 0x7buy -> parsePush span reader PUSH28 28u - | 0x7cuy -> parsePush span reader PUSH29 29u - | 0x7duy -> parsePush span reader PUSH30 30u - | 0x7euy -> parsePush span reader PUSH31 31u - | 0x7fuy -> parsePush span reader PUSH32 32u - | 0x80uy -> struct (DUP1, 3, 1u) - | 0x81uy -> struct (DUP2, 3, 1u) - | 0x82uy -> struct (DUP3, 3, 1u) - | 0x83uy -> struct (DUP4, 3, 1u) - | 0x84uy -> struct (DUP5, 3, 1u) - | 0x85uy -> struct (DUP6, 3, 1u) - | 0x86uy -> struct (DUP7, 3, 1u) - | 0x87uy -> struct (DUP8, 3, 1u) - | 0x88uy -> struct (DUP9, 3, 1u) - | 0x89uy -> struct (DUP10, 3, 1u) - | 0x8auy -> struct (DUP11, 3, 1u) - | 0x8buy -> struct (DUP12, 3, 1u) - | 0x8cuy -> struct (DUP13, 3, 1u) - | 0x8duy -> struct (DUP14, 3, 1u) - | 0x8euy -> struct (DUP15, 3, 1u) - | 0x8fuy -> struct (DUP16, 3, 1u) - | 0x90uy -> struct (SWAP1, 3, 1u) - | 0x91uy -> struct (SWAP2, 3, 1u) - | 0x92uy -> struct (SWAP3, 3, 1u) - | 0x93uy -> struct (SWAP4, 3, 1u) - | 0x94uy -> struct (SWAP5, 3, 1u) - | 0x95uy -> struct (SWAP6, 3, 1u) - | 0x96uy -> struct (SWAP7, 3, 1u) - | 0x97uy -> struct (SWAP8, 3, 1u) - | 0x98uy -> struct (SWAP9, 3, 1u) - | 0x99uy -> struct (SWAP10, 3, 1u) - | 0x9auy -> struct (SWAP11, 3, 1u) - | 0x9buy -> struct (SWAP12, 3, 1u) - | 0x9cuy -> struct (SWAP13, 3, 1u) - | 0x9duy -> struct (SWAP14, 3, 1u) - | 0x9euy -> struct (SWAP15, 3, 1u) - | 0x9fuy -> struct (SWAP16, 3, 1u) - | 0xa0uy -> struct (LOG0, 375, 1u) - | 0xa1uy -> struct (LOG1, 750, 1u) - | 0xa2uy -> struct (LOG2, 1125, 1u) - | 0xa3uy -> struct (LOG3, 1500, 1u) - | 0xa4uy -> struct (LOG4, 1875, 1u) - | 0xf0uy -> struct (CREATE, 32000, 1u) - | 0xf1uy -> struct (CALL, -1, 1u) - | 0xf2uy -> struct (CALLCODE, -1, 1u) - | 0xf3uy -> struct (RETURN, 0, 1u) - | 0xf4uy -> struct (DELEGATECALL, -1, 1u) - | 0xf5uy -> struct (CREATE2, 0, 1u) - | 0xfauy -> struct (STATICCALL, 4, 1u) - | 0xfduy -> struct (REVERT, 0, 1u) - | 0xfeuy -> struct (INVALID, 0, 1u) - | 0xffuy -> struct (SELFDESTRUCT, 5000, 1u) - | _ -> raise ParsingFailureException + member __.CodeOffset with get() = codeOffset and set(o) = codeOffset <- o -let parse span reader offset wordSize addr = - let struct (opcode, gas, instrLen) = parseOpcode span reader - let insInfo = - { Address = addr - NumBytes = instrLen - Offset = offset - Opcode = opcode - GAS = gas } - EVMInstruction (addr, instrLen, insInfo, wordSize) + interface IInstructionParsable with + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan (bs) + ParsingMain.parse span codeOffset wordSize addr :> Instruction + + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span codeOffset wordSize addr :> Instruction + + member __.MaxInstructionSize = 33 + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMParsingMain.fs b/src/FrontEnd/BinLifter/EVM/EVMParsingMain.fs new file mode 100644 index 00000000..fe7421d7 --- /dev/null +++ b/src/FrontEnd/BinLifter/EVM/EVMParsingMain.fs @@ -0,0 +1,192 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.EVM.ParsingMain + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter + +let private parsePush (span: ReadOnlySpan) opcode size = + let bytes = span.Slice(1, int size).ToArray () + struct (opcode <| BitVector.OfArr (Array.rev bytes), 3, 1u + size) + +let private parseOpcode (span: ReadOnlySpan) = + match span[0] with + | 0x00uy -> struct (STOP, 0, 1u) + | 0x01uy -> struct (ADD, 3, 1u) + | 0x02uy -> struct (MUL, 5, 1u) + | 0x03uy -> struct (SUB, 3, 1u) + | 0x04uy -> struct (DIV, 5, 1u) + | 0x05uy -> struct (SDIV,50, 1u) + | 0x06uy -> struct (MOD, 5, 1u) + | 0x07uy -> struct (SMOD, 5, 1u) + | 0x08uy -> struct (ADDMOD, 8, 1u) + | 0x09uy -> struct (MULMOD, 8, 1u) + | 0x0auy -> struct (EXP, 10, 1u) + | 0x0buy -> struct (SIGNEXTEND, 5, 1u) + | 0x10uy -> struct (LT, 3, 1u) + | 0x11uy -> struct (GT, 3, 1u) + | 0x12uy -> struct (SLT, 3, 1u) + | 0x13uy -> struct (SGT, 3, 1u) + | 0x14uy -> struct (EQ, 3, 1u) + | 0x15uy -> struct (ISZERO, 3, 1u) + | 0x16uy -> struct (AND, 3, 1u) + | 0x17uy -> struct (OR, 3, 1u) + | 0x18uy -> struct (XOR, 3, 1u) + | 0x19uy -> struct (NOT, 3, 1u) + | 0x1auy -> struct (BYTE, 3, 1u) + | 0x1buy -> struct (SHL, 3, 1u) + | 0x1cuy -> struct (SHR, 3, 1u) + | 0x1duy -> struct (SAR, 3, 1u) + | 0x20uy -> struct (SHA3, 30, 1u) + | 0x30uy -> struct (ADDRESS, 2, 1u) + | 0x31uy -> struct (BALANCE, 400, 1u) + | 0x32uy -> struct (ORIGIN, 2, 1u) + | 0x33uy -> struct (CALLER, 2, 1u) + | 0x34uy -> struct (CALLVALUE, 2, 1u) + | 0x35uy -> struct (CALLDATALOAD, 3, 1u) + | 0x36uy -> struct (CALLDATASIZE, 2, 1u) + | 0x37uy -> struct (CALLDATACOPY, 3, 1u) + | 0x38uy -> struct (CODESIZE, 2, 1u) + | 0x39uy -> struct (CODECOPY, 3, 1u) + | 0x3auy -> struct (GASPRICE, 2, 1u) + | 0x3buy -> struct (EXTCODESIZE, 700, 1u) + | 0x3cuy -> struct (EXTCODECOPY, 700, 1u) + | 0x3duy -> struct (RETURNDATASIZE, 2, 1u) + | 0x3euy -> struct (RETURNDATACOPY, 3, 1u) + | 0x3fuy -> struct (EXTCODEHASH, 400, 1u) + | 0x40uy -> struct (BLOCKHASH, 20, 1u) + | 0x41uy -> struct (COINBASE, 2, 1u) + | 0x42uy -> struct (TIMESTAMP, 2, 1u) + | 0x43uy -> struct (NUMBER, 2, 1u) + | 0x44uy -> struct (DIFFICULTY, 2, 1u) + | 0x45uy -> struct (GASLIMIT, 2, 1u) + | 0x46uy -> struct (CHAINID, 2, 1u) + | 0x47uy -> struct (SELFBALANCE, 5, 1u) + | 0x48uy -> struct (BASEFEE, 2, 1u) + | 0x50uy -> struct (POP, 2, 1u) + | 0x51uy -> struct (MLOAD, 3, 1u) + | 0x52uy -> struct (MSTORE, 3, 1u) + | 0x53uy -> struct (MSTORE8, 3, 1u) + | 0x54uy -> struct (SLOAD, 200, 1u) + | 0x55uy -> struct (SSTORE, 20000, 1u) + | 0x56uy -> struct (JUMP, 8, 1u) + | 0x57uy -> struct (JUMPI, 10, 1u) + | 0x58uy -> struct (GETPC, 2, 1u) + | 0x59uy -> struct (MSIZE, 2, 1u) + | 0x5auy -> struct (GAS, 2, 1u) + | 0x5buy -> struct (JUMPDEST, 1, 1u) + | 0x60uy -> parsePush span PUSH1 1u + | 0x61uy -> parsePush span PUSH2 2u + | 0x62uy -> parsePush span PUSH3 3u + | 0x63uy -> parsePush span PUSH4 4u + | 0x64uy -> parsePush span PUSH5 5u + | 0x65uy -> parsePush span PUSH6 6u + | 0x66uy -> parsePush span PUSH7 7u + | 0x67uy -> parsePush span PUSH8 8u + | 0x68uy -> parsePush span PUSH9 9u + | 0x69uy -> parsePush span PUSH10 10u + | 0x6auy -> parsePush span PUSH11 11u + | 0x6buy -> parsePush span PUSH12 12u + | 0x6cuy -> parsePush span PUSH13 13u + | 0x6duy -> parsePush span PUSH14 14u + | 0x6euy -> parsePush span PUSH15 15u + | 0x6fuy -> parsePush span PUSH16 16u + | 0x70uy -> parsePush span PUSH17 17u + | 0x71uy -> parsePush span PUSH18 18u + | 0x72uy -> parsePush span PUSH19 19u + | 0x73uy -> parsePush span PUSH20 20u + | 0x74uy -> parsePush span PUSH21 21u + | 0x75uy -> parsePush span PUSH22 22u + | 0x76uy -> parsePush span PUSH23 23u + | 0x77uy -> parsePush span PUSH24 24u + | 0x78uy -> parsePush span PUSH25 25u + | 0x79uy -> parsePush span PUSH26 26u + | 0x7auy -> parsePush span PUSH27 27u + | 0x7buy -> parsePush span PUSH28 28u + | 0x7cuy -> parsePush span PUSH29 29u + | 0x7duy -> parsePush span PUSH30 30u + | 0x7euy -> parsePush span PUSH31 31u + | 0x7fuy -> parsePush span PUSH32 32u + | 0x80uy -> struct (DUP1, 3, 1u) + | 0x81uy -> struct (DUP2, 3, 1u) + | 0x82uy -> struct (DUP3, 3, 1u) + | 0x83uy -> struct (DUP4, 3, 1u) + | 0x84uy -> struct (DUP5, 3, 1u) + | 0x85uy -> struct (DUP6, 3, 1u) + | 0x86uy -> struct (DUP7, 3, 1u) + | 0x87uy -> struct (DUP8, 3, 1u) + | 0x88uy -> struct (DUP9, 3, 1u) + | 0x89uy -> struct (DUP10, 3, 1u) + | 0x8auy -> struct (DUP11, 3, 1u) + | 0x8buy -> struct (DUP12, 3, 1u) + | 0x8cuy -> struct (DUP13, 3, 1u) + | 0x8duy -> struct (DUP14, 3, 1u) + | 0x8euy -> struct (DUP15, 3, 1u) + | 0x8fuy -> struct (DUP16, 3, 1u) + | 0x90uy -> struct (SWAP1, 3, 1u) + | 0x91uy -> struct (SWAP2, 3, 1u) + | 0x92uy -> struct (SWAP3, 3, 1u) + | 0x93uy -> struct (SWAP4, 3, 1u) + | 0x94uy -> struct (SWAP5, 3, 1u) + | 0x95uy -> struct (SWAP6, 3, 1u) + | 0x96uy -> struct (SWAP7, 3, 1u) + | 0x97uy -> struct (SWAP8, 3, 1u) + | 0x98uy -> struct (SWAP9, 3, 1u) + | 0x99uy -> struct (SWAP10, 3, 1u) + | 0x9auy -> struct (SWAP11, 3, 1u) + | 0x9buy -> struct (SWAP12, 3, 1u) + | 0x9cuy -> struct (SWAP13, 3, 1u) + | 0x9duy -> struct (SWAP14, 3, 1u) + | 0x9euy -> struct (SWAP15, 3, 1u) + | 0x9fuy -> struct (SWAP16, 3, 1u) + | 0xa0uy -> struct (LOG0, 375, 1u) + | 0xa1uy -> struct (LOG1, 750, 1u) + | 0xa2uy -> struct (LOG2, 1125, 1u) + | 0xa3uy -> struct (LOG3, 1500, 1u) + | 0xa4uy -> struct (LOG4, 1875, 1u) + | 0xf0uy -> struct (CREATE, 32000, 1u) + | 0xf1uy -> struct (CALL, -1, 1u) + | 0xf2uy -> struct (CALLCODE, -1, 1u) + | 0xf3uy -> struct (RETURN, 0, 1u) + | 0xf4uy -> struct (DELEGATECALL, -1, 1u) + | 0xf5uy -> struct (CREATE2, 0, 1u) + | 0xfauy -> struct (STATICCALL, 4, 1u) + | 0xfduy -> struct (REVERT, 0, 1u) + | 0xfeuy -> struct (INVALID, 0, 1u) + | 0xffuy -> struct (SELFDESTRUCT, 5000, 1u) + | _ -> raise ParsingFailureException + +let parse span offset wordSize addr = + let struct (opcode, gas, instrLen) = parseOpcode span + let insInfo = + { Address = addr + NumBytes = instrLen + Offset = offset + Opcode = opcode + GAS = gas } + EVMInstruction (addr, instrLen, insInfo, wordSize) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs b/src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs index 550dac87..8b96add6 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMRegExprs.fs @@ -25,10 +25,11 @@ namespace B2R2.FrontEnd.BinLifter.EVM open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type internal RegExprs () = - let var sz t name = AST.var sz t name (EVMRegisterSet.singleton t) +type RegExprs () = + let var sz t name = AST.var sz t name member val PC = var 256 (Register.toRegID Register.PC) "PC" with get member val GAS = var 64 (Register.toRegID Register.GAS) "GAS" with get @@ -39,6 +40,6 @@ type internal RegExprs () = | R.PC -> __.PC | R.GAS -> __.GAS | R.SP -> __.SP - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs b/src/FrontEnd/BinLifter/EVM/EVMRegisterFactory.fs similarity index 92% rename from src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs rename to src/FrontEnd/BinLifter/EVM/EVMRegisterFactory.fs index dd7101b9..884f14b9 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMRegisterBay.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMRegisterFactory.fs @@ -28,9 +28,8 @@ open B2R2 open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type EVMRegisterBay () = - - inherit RegisterBay () +type EVMRegisterFactory () = + inherit RegisterFactory () override __.GetAllRegExprs () = Utils.futureFeature () @@ -40,9 +39,9 @@ type EVMRegisterBay () = override __.RegIDFromRegExpr (e) = match e.E with - | Var (_, id, _ ,_) -> id - | PCVar (_, _) -> Register.toRegID Register.PC - | _ -> failwith "not a register expression" + | Var (_, id, _) -> id + | PCVar _ -> Register.toRegID Register.PC + | _ -> raise InvalidRegisterException override __.RegIDToRegExpr (id) = Utils.impossible () diff --git a/src/FrontEnd/BinLifter/EVM/EVMTranslationContext.fs b/src/FrontEnd/BinLifter/EVM/EVMTranslationContext.fs new file mode 100644 index 00000000..600785a6 --- /dev/null +++ b/src/FrontEnd/BinLifter/EVM/EVMTranslationContext.fs @@ -0,0 +1,43 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.EVM + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for Ethereum Virtual Machine (EVM) instructions. +type EVMTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs () + + /// Register expressions. + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/EVM/EVMTypes.fs b/src/FrontEnd/BinLifter/EVM/EVMTypes.fs index dd5cc831..43a93200 100644 --- a/src/FrontEnd/BinLifter/EVM/EVMTypes.fs +++ b/src/FrontEnd/BinLifter/EVM/EVMTypes.fs @@ -59,7 +59,7 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "PC" -> R.PC | "GAS" -> R.GAS | "SP" -> R.SP @@ -168,6 +168,7 @@ type Opcode = | RETURNDATASIZE /// Copies data from the return data buffer to memory | RETURNDATACOPY + | EXTCODEHASH /// Get the hash of one of the 256 most recent complete blocks | BLOCKHASH /// Get the block's beneficiary address @@ -180,6 +181,9 @@ type Opcode = | DIFFICULTY /// Get the block's gas limit | GASLIMIT + | CHAINID + | SELFBALANCE + | BASEFEE /// Remove word from stack | POP /// Load word from memory diff --git a/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj b/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj index 09a7997c..31f60ae3 100644 --- a/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj +++ b/src/FrontEnd/BinLifter/Intel/B2R2.FrontEnd.BinLifter.Intel.fsproj @@ -9,11 +9,10 @@ - - + @@ -28,7 +27,7 @@ - + diff --git a/src/FrontEnd/BinLifter/Intel/Intel.fs b/src/FrontEnd/BinLifter/Intel/Intel.fs deleted file mode 100644 index 530507ae..00000000 --- a/src/FrontEnd/BinLifter/Intel/Intel.fs +++ /dev/null @@ -1,51 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.Intel - -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for Intel (x86 or x86-64) instructions. -type IntelTranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar id pos = - __.RegExprs.GetPseudoRegVar (Register.ofRegID id ) pos - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - IntelTranslationContext (isa, regexprs) :> TranslationContext, - IntelRegisterBay (isa.WordSize, regexprs) :> RegisterBay - ) - - let initRegBay wordSize = - let regexprs = RegExprs (wordSize) - IntelRegisterBay (wordSize, regexprs) :> RegisterBay - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs index b6a37238..68f14fa8 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelAVXLifter.fs @@ -34,225 +34,134 @@ open B2R2.FrontEnd.BinLifter.LiftingUtils open B2R2.FrontEnd.BinLifter.Intel open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils open B2R2.FrontEnd.BinLifter.Intel.MMXLifter +open B2R2.FrontEnd.BinLifter.Intel.SSELifter let private haveEVEXPrx = function | Some v -> Option.isSome v.EVEXPrx | None -> false -let private r128to256 = function - | OprReg R.XMM0 -> R.YMM0 - | OprReg R.XMM1 -> R.YMM1 - | OprReg R.XMM2 -> R.YMM2 - | OprReg R.XMM3 -> R.YMM3 - | OprReg R.XMM4 -> R.YMM4 - | OprReg R.XMM5 -> R.YMM5 - | OprReg R.XMM6 -> R.YMM6 - | OprReg R.XMM7 -> R.YMM7 - | OprReg R.XMM8 -> R.YMM8 - | OprReg R.XMM9 -> R.YMM9 - | OprReg R.XMM10 -> R.YMM10 - | OprReg R.XMM11 -> R.YMM11 - | OprReg R.XMM12 -> R.YMM12 - | OprReg R.XMM13 -> R.YMM13 - | OprReg R.XMM14 -> R.YMM14 - | OprReg R.XMM15 -> R.YMM15 - | _ -> raise InvalidOperandException - -let private r128to512 = function - | OprReg R.XMM0 -> R.ZMM0 - | OprReg R.XMM1 -> R.ZMM1 - | OprReg R.XMM2 -> R.ZMM2 - | OprReg R.XMM3 -> R.ZMM3 - | OprReg R.XMM4 -> R.ZMM4 - | OprReg R.XMM5 -> R.ZMM5 - | OprReg R.XMM6 -> R.ZMM6 - | OprReg R.XMM7 -> R.ZMM7 - | OprReg R.XMM8 -> R.ZMM8 - | OprReg R.XMM9 -> R.ZMM9 - | OprReg R.XMM10 -> R.ZMM10 - | OprReg R.XMM11 -> R.ZMM11 - | OprReg R.XMM12 -> R.ZMM12 - | OprReg R.XMM13 -> R.ZMM13 - | OprReg R.XMM14 -> R.ZMM14 - | OprReg R.XMM15 -> R.ZMM15 - | _ -> raise InvalidOperandException - -let private r256to512 = function - | OprReg R.YMM0 -> R.ZMM0 - | OprReg R.YMM1 -> R.ZMM1 - | OprReg R.YMM2 -> R.ZMM2 - | OprReg R.YMM3 -> R.ZMM3 - | OprReg R.YMM4 -> R.ZMM4 - | OprReg R.YMM5 -> R.ZMM5 - | OprReg R.YMM6 -> R.ZMM6 - | OprReg R.YMM7 -> R.ZMM7 - | OprReg R.YMM8 -> R.ZMM8 - | OprReg R.YMM9 -> R.ZMM9 - | OprReg R.YMM10 -> R.ZMM10 - | OprReg R.YMM11 -> R.ZMM11 - | OprReg R.YMM12 -> R.ZMM12 - | OprReg R.YMM13 -> R.ZMM13 - | OprReg R.YMM14 -> R.ZMM14 - | OprReg R.YMM15 -> R.ZMM15 - | _ -> raise InvalidOperandException - -let private fillZeroHigh128 ctxt dst ir = - let dst = r128to256 dst - let dstC, dstD = getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4 - let n0 = AST.num0 64 - !!ir (dstC := n0) - !!ir (dstD := n0) - -let private fillZeroHigh256 ctxt dst ir = - let dst = r256to512 dst - let dstE, dstF, dstG, dstH = - getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, - getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6 - let n0 = AST.num0 64 - !!ir (dstE := n0) - !!ir (dstF := n0) - !!ir (dstG := n0) - !!ir (dstH := n0) +let private getEVEXPrx = function + | Some v -> match v.EVEXPrx with + | Some ev -> ev + | None -> Utils.impossible () + | None -> Utils.impossible () -let private vexedPackedFPBinOp32 ins insLen ctxt op = - let ir = IRBuilder (16) - let struct (dst, src1, src2) = getThreeOprs ins - let oprSz = getOperationSize ins - let do32PackedOp dst64 src1 src2 ir = - let dstA, dstB = AST.xtlo 32 dst64, AST.xthi 32 dst64 - let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 - let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 - !!ir (dstA := op src1A src2A) - !!ir (dstB := op src1B src2B) +let private maskWithEPrx ePrx dst rt = + match ePrx.Z with + | Zeroing -> AST.num0 rt + | Merging -> dst + +let private getVectorMoveCond ePrx k idx = + (* no write mask *) + let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 + AST.extract k 1 idx .| noWritemask + +let private makeAssignWithMask ir ePrx k oprSize packSz dst src isMem = + let packNum = oprSize / packSz + let tmp = Array.init packNum (fun _ -> !+ir packSz) + let mask idx dst src = + let cond = getVectorMoveCond ePrx k idx + let fallThrough = if isMem then dst else (maskWithEPrx ePrx dst packSz) + AST.ite cond src fallThrough + Array.mapi2 mask dst src |> Array.iter2 (fun e1 e2 -> !!ir (e1 := e2)) tmp + tmp + +let private makeAssignEVEX ir ePrx k oprSz packSz dst src1 src2 opFn isMem = + let src2A = Array.head src2 (* SRC2[31:0] *) + let packNum = oprSz / packSz + let tmp = Array.init packNum (fun _ -> !+ir packSz) + let mask idx src1 src2 = + let cond = getVectorMoveCond ePrx k idx + let tSrc = + if isMem && ePrx.B (* B *) = 1uy then opFn src1 src2A else opFn src1 src2 + AST.ite cond tSrc (maskWithEPrx ePrx (Array.item idx dst) packSz) + Array.mapi2 mask src1 src2 |> Array.iter2 (fun e1 e2 -> !!ir (e1 := e2)) tmp + tmp + +let private buildPackedFPInstr ins insLen ctxt packSz opFn = + let ir = !*ctxt + let oprSize = getOperationSize ins + let packNum = 64 / packSz ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - do32PackedOp dst1 src1A src2A ir - do32PackedOp dst2 src1B src2B ir - fillZeroHigh128 ctxt dst ir - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 - do32PackedOp dst1 sr1A sr2A ir - do32PackedOp dst2 sr1B sr2B ir - do32PackedOp dst3 sr1C sr2C ir - do32PackedOp dst4 sr1D sr2D ir - | _ -> raise InvalidOperandSizeException - !>ir insLen - -let private vexedPackedFPBinOp64 ins insLen ctxt op = - let ir = IRBuilder (16) let struct (dst, src1, src2) = getThreeOprs ins - let oprSz = getOperationSize ins - ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - !!ir (dst1 := op src1A src2A) - !!ir (dst2 := op src1B src2B) - fillZeroHigh128 ctxt dst ir - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 - !!ir (dst1 := op sr1A sr2A) - !!ir (dst2 := op sr1B sr2B) - !!ir (dst3 := op sr1C sr2C) - !!ir (dst4 := op sr1D sr2D) - | _ -> raise InvalidOperandSizeException + let src1 = transOprToArr ir false ins insLen ctxt packSz packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt packSz packNum oprSize src2 + let src = Array.map2 opFn src1 src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst src + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let private vexedScalarFPBinOp ins insLen ctxt sz op = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let ir = !*ctxt ! -> - let src2 = transOprToExpr32 ins insLen ctxt src2 + let src2 = transOprToExpr32 ir false ins insLen ctxt src2 !!ir (AST.xtlo 32 dst1 := op (AST.xtlo 32 src1A) src2) !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1A) | 64 -> - let src2 = transOprToExpr64 ins insLen ctxt src2 + let src2 = transOprToExpr64 ir false ins insLen ctxt src2 !!ir (dst1 := op src1A src2) | _ -> raise InvalidOperandSizeException !!ir (dst2 := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vsqrtps ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src) = getTwoOprs ins - let oprSz = getOperationSize ins - let do32PackedSqrt dst64 src ir = - let dstA, dstB = AST.xtlo 32 dst64, AST.xthi 32 dst64 - let srcA, srcB = AST.xtlo 32 src, AST.xthi 32 src - !!ir (dstA := AST.fsqrt srcA) - !!ir (dstB := AST.fsqrt srcB) + let ir = !*ctxt + let oprSize = getOperationSize ins + let packNum = 64 / 32 ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - do32PackedSqrt dst1 srcA ir - do32PackedSqrt dst2 srcB ir - fillZeroHigh128 ctxt dst ir - | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let srD, srC, srB, srA = transOprToExpr256 ins insLen ctxt src - do32PackedSqrt dst1 srA ir - do32PackedSqrt dst2 srB ir - do32PackedSqrt dst3 srC ir - do32PackedSqrt dst4 srD ir - | _ -> raise InvalidOperandSizeException + let struct (dst, src) = getTwoOprs ins + let src = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src + let result = Array.map (AST.unop UnOpType.FSQRT) src + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vsqrtpd ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let struct (dst, src) = getTwoOprs ins let oprSz = getOperationSize ins ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insLen ctxt src + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ir false ins insLen ctxt src !!ir (dst1 := AST.fsqrt src1) !!ir (dst2 := AST.fsqrt src2) fillZeroHigh128 ctxt dst ir | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let sr4, sr3, sr2, sr1 = transOprToExpr256 ins insLen ctxt src + let dst4, dst3, dst2, dst1 = transOprToExpr256 ir false ins insLen ctxt dst + let sr4, sr3, sr2, sr1 = transOprToExpr256 ir false ins insLen ctxt src !!ir (dst1 := AST.fsqrt sr1) !!ir (dst2 := AST.fsqrt sr2) !!ir (dst3 := AST.fsqrt sr3) !!ir (dst4 := AST.fsqrt sr4) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir !>ir insLen let private vsqrts ins insLen ctxt sz = - let ir = IRBuilder (16) - let struct (dst, src1, src2) = getThreeOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 + let ir = !*ctxt ! -> - let src2 = transOprToExpr32 ins insLen ctxt src2 + let src2 = transOprToExpr32 ir false ins insLen ctxt src2 !!ir (AST.xtlo 32 dst1 := AST.fsqrt src2) !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1A) | 64 -> - let src2 = transOprToExpr64 ins insLen ctxt src2 + let src2 = transOprToExpr64 ir false ins insLen ctxt src2 !!ir (dst1 := AST.fsqrt src2) | _ -> raise InvalidOperandSizeException !!ir (dst2 := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vsqrtss ins insLen ctxt = @@ -262,12 +171,10 @@ let vsqrtsd ins insLen ctxt = vsqrts ins insLen ctxt 64 let vaddps ins insLen ctxt = - match getOperationSize ins with - | 512 -> GeneralLifter.nop insLen - | _ -> vexedPackedFPBinOp32 ins insLen ctxt AST.fadd + buildPackedFPInstr ins insLen ctxt 32 AST.fadd let vaddpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt AST.fadd + buildPackedFPInstr ins insLen ctxt 64 AST.fadd let vaddss ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 32 AST.fadd @@ -276,12 +183,10 @@ let vaddsd ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 64 AST.fadd let vsubps ins insLen ctxt = - match getOperationSize ins with - | 512 -> GeneralLifter.nop insLen - | _ -> vexedPackedFPBinOp32 ins insLen ctxt AST.fsub + buildPackedFPInstr ins insLen ctxt 32 AST.fsub let vsubpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt AST.fsub + buildPackedFPInstr ins insLen ctxt 64 AST.fsub let vsubss ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 32 AST.fsub @@ -290,10 +195,10 @@ let vsubsd ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 64 AST.fsub let vmulps ins insLen ctxt = - vexedPackedFPBinOp32 ins insLen ctxt AST.fmul + buildPackedFPInstr ins insLen ctxt 32 AST.fmul let vmulpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt AST.fmul + buildPackedFPInstr ins insLen ctxt 64 AST.fmul let vmulss ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 32 AST.fmul @@ -302,12 +207,10 @@ let vmulsd ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 64 AST.fmul let vdivps ins insLen ctxt = - vexedPackedFPBinOp32 ins insLen ctxt AST.fdiv + buildPackedFPInstr ins insLen ctxt 32 AST.fdiv let vdivpd ins insLen ctxt = - match getOperationSize ins with - | 512 -> GeneralLifter.nop insLen (* FIXME: #196 *) - | _ -> vexedPackedFPBinOp64 ins insLen ctxt AST.fdiv + buildPackedFPInstr ins insLen ctxt 64 AST.fdiv let vdivss ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 32 AST.fdiv @@ -316,688 +219,269 @@ let vdivsd ins insLen ctxt = vexedScalarFPBinOp ins insLen ctxt 64 AST.fdiv let vcvtsi2ss ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dstB , dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2 = transOprToExpr ins insLen ctxt src2 + let ir = !*ctxt ! dstA := AST.cast CastKind.IntToFloat 32 src2) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2 = transOprToExpr ir false ins insLen ctxt src2 + !!ir (AST.xtlo 32 dstA := AST.cast CastKind.SIntToFloat 32 src2) !!ir (AST.xthi 32 dstA := AST.xthi 32 src1A) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vcvtsi2sd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dstB , dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let src2 = transOprToExpr ins insLen ctxt src2 + let ir = !*ctxt ! src2) + let struct (dst, src1, src2) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2 = transOprToExpr ir false ins insLen ctxt src2 + !!ir (dstA := AST.cast CastKind.SIntToFloat 64 src2) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vcvtsd2ss ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2 = transOprToExpr64 ins insLen ctxt src2 + let ir = !*ctxt ! dstA := AST.cast CastKind.FloatCast 32 src2) !!ir (AST.xthi 32 dstA := AST.xthi 32 src1A) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vcvtss2sd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let src2 = transOprToExpr32 ins insLen ctxt src2 + let ir = !*ctxt ! src2) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir - !>ir insLen - -let private getEVEXPrx = function - | Some v -> match v.EVEXPrx with - | Some ev -> ev - | None -> Utils.impossible () - | None -> Utils.impossible () - -let private buildVectorMove ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins - let oprSize = getOperationSize ins - ! then - match dst with - | OprReg _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - !!ir (dstA := srcA) - !!ir (dstB := srcB) - fillZeroHigh128 ctxt dst ir - | OprMem _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - !!ir (dstA := srcA) - !!ir (dstB := srcB) - | _ -> raise InvalidOperandException - elif oprSize = 256 then - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - !!ir (dstA := srcA) - !!ir (dstB := srcB) - !!ir (dstC := srcC) - !!ir (dstD := srcD) - elif oprSize = 512 then - let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let kl, vl = 16, 512 - match dst with - | OprReg _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - let ite i src dst extFn = - AST.ite (cond i) (extFn 32 src) (masking (extFn 32 dst)) - !!ir (AST.xtlo 32 dstA := ite 0 srcA dstA AST.xtlo) - !!ir (AST.xthi 32 dstA := ite 1 srcA dstA AST.xthi) - !!ir (AST.xtlo 32 dstB := ite 2 srcB dstB AST.xtlo) - !!ir (AST.xthi 32 dstB := ite 3 srcB dstB AST.xthi) - !!ir (AST.xtlo 32 dstC := ite 4 srcC dstC AST.xtlo) - !!ir (AST.xthi 32 dstC := ite 5 srcC dstC AST.xthi) - !!ir (AST.xtlo 32 dstD := ite 6 srcD dstD AST.xtlo) - !!ir (AST.xthi 32 dstD := ite 7 srcD dstD AST.xthi) - !!ir (AST.xtlo 32 dstE := ite 8 srcE dstE AST.xtlo) - !!ir (AST.xthi 32 dstE := ite 9 srcE dstE AST.xthi) - !!ir (AST.xtlo 32 dstF := ite 10 srcF dstF AST.xtlo) - !!ir (AST.xthi 32 dstF := ite 11 srcF dstF AST.xthi) - !!ir (AST.xtlo 32 dstG := ite 12 srcG dstG AST.xtlo) - !!ir (AST.xthi 32 dstG := ite 13 srcG dstG AST.xthi) - !!ir (AST.xtlo 32 dstH := ite 14 srcH dstH AST.xtlo) - !!ir (AST.xthi 32 dstH := ite 15 srcH dstH AST.xthi) - | OprMem _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - let ite i src dst extFn = - AST.ite (cond i) (extFn 32 src) (extFn 32 dst) - let evAssign src dst idx = - AST.concat (ite (idx + 1) src dst AST.xthi) (ite idx src dst AST.xtlo) - !!ir (dstA := evAssign srcA dstA 0) - !!ir (dstB := evAssign srcB dstB 2) - !!ir (dstC := evAssign srcC dstB 4) - !!ir (dstD := evAssign srcD dstB 6) - !!ir (dstE := evAssign srcE dstB 8) - !!ir (dstF := evAssign srcF dstB 10) - !!ir (dstG := evAssign srcG dstB 12) - !!ir (dstH := evAssign srcH dstB 14) - | _ -> raise InvalidOperandException - else raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vmovd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - let regToReg r1 r2 = - match Register.getKind r1, Register.getKind r2 with - | Register.Kind.XMM, Register.Kind.GP -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = !.ctxt r2 - !!ir (dstAssign 32 dstA src) - !!ir (dstB := n0) - !!ir (dstC := n0) - !!ir (dstD := n0) - | Register.Kind.GP, Register.Kind.XMM -> - let dst = !.ctxt r1 - let srcA = getPseudoRegVar ctxt r2 1 - !!ir (dstAssign oprSize dst (AST.xtlo 32 srcA)) - | _ -> raise InvalidOperandException - match dst, src with - | OprReg r1, OprReg r2 -> regToReg r1 r2 - | OprReg r, OprMem _ -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = transOprToExpr ins insLen ctxt src - !!ir (dstAssign 32 dstA src) - !!ir (dstB := n0) - !!ir (dstC := n0) - !!ir (dstD := n0) - | OprMem _, OprReg r -> - let dst = transOprToExpr ins insLen ctxt dst - let srcA = getPseudoRegVar ctxt r 1 - !!ir (dst := AST.xtlo 32 srcA) + match oprSize with + | 32 -> + let dst = transOprToExpr ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + !!ir (dstAssign oprSize dst (AST.xtlo oprSize srcA)) + | 128 -> + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src + !!ir (dstA := AST.zext 64 src) + !!ir (dstB := AST.num0 64) + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir | _ -> raise InvalidOperandSizeException !>ir insLen let vmovq ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! - let regToReg r1 r2 = + match dst, src with + | OprReg _, OprMem _ -> + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src + !!ir (dstA := src) + !!ir (dstB := n0) + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + | OprMem _, OprReg _ -> + let dst = transOprToExpr ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + !!ir (dst := srcA) + | OprReg r1, OprReg r2 -> match Register.getKind r1, Register.getKind r2 with - | Register.Kind.XMM, Register.Kind.XMM -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let srcA = getPseudoRegVar ctxt r2 1 - !!ir (dstA := srcA) - !!ir (dstB := n0) - !!ir (dstC := n0) - !!ir (dstD := n0) | Register.Kind.XMM, Register.Kind.GP -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = !.ctxt r2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src !!ir (dstA := src) !!ir (dstB := n0) - !!ir (dstC := n0) - !!ir (dstD := n0) + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir | Register.Kind.GP, Register.Kind.XMM -> - let dst = !.ctxt r1 - let srcA = getPseudoRegVar ctxt r2 1 + let dst = transOprToExpr ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src !!ir (dst := srcA) - | _ -> raise InvalidOperandException - match dst, src with - | OprReg r1, OprReg r2 -> regToReg r1 r2 - | OprReg _, OprMem _ -> - let dstD, dstC, dstB, dstA = getPseudoRegVar256 ctxt (r128to256 dst) - let src = transOprToExpr ins insLen ctxt src - !!ir (dstA := src) - !!ir (dstB := n0) - !!ir (dstC := n0) - !!ir (dstD := n0) - | OprMem _, OprReg r -> - let dst = transOprToExpr ins insLen ctxt dst - let srcA = getPseudoRegVar ctxt r 1 - !!ir (dst := srcA) - | _ -> raise InvalidOperandSizeException + | _ -> (* XMM, XMM *) + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + !!ir (dstA := srcA) + !!ir (dstB := n0) + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + | _ -> raise InvalidOperandException !>ir insLen -let vmovdqu ins insLen ctxt = - buildVectorMove ins insLen ctxt - -let private fillZeroFromVLToMaxVL ctxt dst vl maxVl ir = - let n0 = AST.num0 64 - match maxVl, vl with - | 512, 128 -> - let dst = r128to512 dst - let dstC, dstD, dstE, dstF, dstG, dstH = - getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, - getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, - getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 - !!ir (dstC := n0) - !!ir (dstD := n0) - !!ir (dstE := n0) - !!ir (dstF := n0) - !!ir (dstG := n0) - !!ir (dstH := n0) - | 512, 256 -> - let dst = r256to512 dst - let dstE, dstF, dstG, dstH = - getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, - getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 - !!ir (dstE := n0) - !!ir (dstF := n0) - !!ir (dstG := n0) - !!ir (dstH := n0) - | _ -> Utils.impossible () - -let vmovdqu16 ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins - let oprSize = getOperationSize ins - let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 16 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask +let private buildVectorMove ins insLen ctxt packSz = + let ir = !*ctxt ! -> - let kl, vl = 8, 128 - match dst with - | OprReg _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - let assign dst src idx = - let pos = (idx % 4) * 16 - let dst = AST.extract dst 16 pos - dst := AST.ite (cond idx) (AST.extract src 16 pos) (masking dst) - !!ir (assign dstA srcA 0) - !!ir (assign dstA srcA 1) - !!ir (assign dstA srcA 2) - !!ir (assign dstA srcA 3) - !!ir (assign dstB srcB 4) - !!ir (assign dstB srcB 5) - !!ir (assign dstB srcB 6) - !!ir (assign dstB srcB 7) - fillZeroFromVLToMaxVL ctxt dst vl 512 ir - | OprMem _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - let tmps = Array.init 4 (fun _ -> !*ir 16) - let assign dst src idx = - for i in 0 .. 3 do - let pos = i * 16 - let dst = AST.extract dst 16 pos - !!ir (tmps[i] := - AST.ite (cond (idx + i)) (AST.extract src 16 pos) dst) - AST.concatArr tmps - !!ir (dstA := assign dstA srcA 0) - !!ir (dstB := assign dstB srcB 4) - | _ -> raise InvalidOperandException - | 256 -> - let kl, vl = 16, 256 - match dst with - | OprReg _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - let assign dst src idx = - let pos = (idx % 4) * 16 - let dst = AST.extract dst 16 pos - dst := AST.ite (cond idx) (AST.extract src 16 pos) (masking dst) - !!ir (assign dstA srcA 0) - !!ir (assign dstA srcA 1) - !!ir (assign dstA srcA 2) - !!ir (assign dstA srcA 3) - !!ir (assign dstB srcB 4) - !!ir (assign dstB srcB 5) - !!ir (assign dstB srcB 6) - !!ir (assign dstB srcB 7) - !!ir (assign dstC srcC 8) - !!ir (assign dstC srcC 9) - !!ir (assign dstC srcC 10) - !!ir (assign dstC srcC 11) - !!ir (assign dstD srcD 12) - !!ir (assign dstD srcD 13) - !!ir (assign dstD srcD 14) - !!ir (assign dstD srcD 15) - fillZeroFromVLToMaxVL ctxt dst vl 512 ir - | OprMem _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - let tmps = Array.init 4 (fun _ -> !*ir 16) - let assign dst src idx = - for i in 0 .. 3 do - let pos = i * 16 - let dst = AST.extract dst 16 pos - !!ir - (tmps[i] := AST.ite (cond (idx + i)) (AST.extract src 16 pos) dst) - AST.concatArr tmps - !!ir (dstA := assign dstA srcA 0) - !!ir (dstB := assign dstB srcB 4) - !!ir (dstC := assign dstC srcC 8) - !!ir (dstD := assign dstD srcD 12) - | _ -> raise InvalidOperandException - | 512 -> - let kl, vl = 32, 512 - match dst with - | OprReg _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - let assign dst src idx = - let pos = (idx % 4) * 16 - let dst = AST.extract dst 16 pos - dst := AST.ite (cond idx) (AST.extract src 16 pos) (masking dst) - !!ir (assign dstA srcA 0) - !!ir (assign dstA srcA 1) - !!ir (assign dstA srcA 2) - !!ir (assign dstA srcA 3) - !!ir (assign dstB srcB 4) - !!ir (assign dstB srcB 5) - !!ir (assign dstB srcB 6) - !!ir (assign dstB srcB 7) - !!ir (assign dstC srcC 8) - !!ir (assign dstC srcC 9) - !!ir (assign dstC srcC 10) - !!ir (assign dstC srcC 11) - !!ir (assign dstD srcD 12) - !!ir (assign dstD srcD 13) - !!ir (assign dstD srcD 14) - !!ir (assign dstD srcD 15) - !!ir (assign dstE srcE 16) - !!ir (assign dstE srcE 17) - !!ir (assign dstE srcE 18) - !!ir (assign dstE srcE 19) - !!ir (assign dstE srcE 20) - !!ir (assign dstF srcF 21) - !!ir (assign dstF srcF 22) - !!ir (assign dstF srcF 23) - !!ir (assign dstG srcG 24) - !!ir (assign dstG srcG 25) - !!ir (assign dstG srcG 26) - !!ir (assign dstG srcG 27) - !!ir (assign dstH srcH 28) - !!ir (assign dstH srcH 29) - !!ir (assign dstH srcH 30) - !!ir (assign dstH srcH 31) - | OprMem _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - let tmps = Array.init 4 (fun _ -> !*ir 16) - let assign dst src idx = - for i in 0 .. 3 do - let pos = i * 16 - let dst = AST.extract dst 16 pos - !!ir (tmps[i] := - AST.ite (cond (idx + i)) (AST.extract src 16 pos) dst) - AST.concatArr tmps - !!ir (dstA := assign dstA srcA 0) - !!ir (dstB := assign dstB srcB 4) - !!ir (dstC := assign dstC srcC 8) - !!ir (dstD := assign dstD srcD 12) - !!ir (dstE := assign dstE srcE 16) - !!ir (dstF := assign dstF srcF 20) - !!ir (dstG := assign dstG srcG 24) - !!ir (dstH := assign dstH srcH 28) - | _ -> raise InvalidOperandException - | _ -> raise InvalidOperandSizeException - !>ir insLen - -let vmovdqu64 ins insLen ctxt = - let ir = IRBuilder (8) + let oprSz = getOperationSize ins + let isAVX512 = haveEVEXPrx ins.VEXInfo + let packSz, packNum = + if isAVX512 then packSz, 64 / packSz else 64, 64 / 64 let struct (dst, src) = getTwoOprs ins - let oprSize = getOperationSize ins - let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 64 - | Merging -> dst - let cond idx = - if ePrx.AAA = 0uy then AST.num0 1 (* no write mask *) - else AST.extract k 1 idx - ! -> - let kl, vl = 4, 128 - match dst with - | OprReg _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) - fillZeroFromVLToMaxVL ctxt dst vl 512 ir - | OprMem _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA dstA) - !!ir (dstB := AST.ite (cond 1) srcB dstB) - | _ -> raise InvalidOperandException - | 256 -> - let kl, vl = 8, 256 - match dst with - | OprReg _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) - !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) - !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) - fillZeroFromVLToMaxVL ctxt dst vl 512 ir - | OprMem _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA dstA) - !!ir (dstB := AST.ite (cond 1) srcB dstB) - !!ir (dstC := AST.ite (cond 2) srcC dstC) - !!ir (dstD := AST.ite (cond 3) srcD dstD) - | _ -> raise InvalidOperandException - | 512 -> - let kl, vl = 16, 512 - match dst with - | OprReg _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) - !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) - !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) - !!ir (dstE := AST.ite (cond 4) srcE (masking dstE)) - !!ir (dstF := AST.ite (cond 5) srcF (masking dstF)) - !!ir (dstG := AST.ite (cond 6) srcG (masking dstG)) - !!ir (dstH := AST.ite (cond 7) srcH (masking dstH)) - | OprMem _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA dstA) - !!ir (dstB := AST.ite (cond 1) srcB dstB) - !!ir (dstC := AST.ite (cond 2) srcC dstC) - !!ir (dstD := AST.ite (cond 3) srcD dstD) - !!ir (dstE := AST.ite (cond 4) srcE dstE) - !!ir (dstF := AST.ite (cond 5) srcF dstF) - !!ir (dstG := AST.ite (cond 6) srcG dstG) - !!ir (dstH := AST.ite (cond 7) srcH dstH) - | _ -> raise InvalidOperandException - | _ -> raise InvalidOperandSizeException + let src = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src + let result = + if isAVX512 then + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSz dst + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + makeAssignWithMask ir ePrx k oprSz packSz eDst src (isMemOpr dst) + else src + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir !>ir insLen -let vmovdqa ins insLen ctxt = buildVectorMove ins insLen ctxt +let vmovapd ins insLen ctxt = buildVectorMove ins insLen ctxt 64 +let vmovaps ins insLen ctxt = buildVectorMove ins insLen ctxt 32 -let vmovdqa64 ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins +let private buildVectorMoveAVX512 ins insLen ctxt packSz = + let ir = !*ctxt + ! / packSz + let struct (dst, src) = getTwoOprs ins let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 64 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - ! -> - let kl, vl = 2, 128 - match dst with - | OprReg _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) - fillZeroFromVLToMaxVL ctxt dst vl 512 ir - | OprMem _ -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA dstA) - !!ir (dstB := AST.ite (cond 1) srcB dstB) - | _ -> raise InvalidOperandException - | 256 -> - let kl, vl = 4, 256 - match dst with - | OprReg _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) - !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) - !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) - fillZeroFromVLToMaxVL ctxt dst vl 512 ir - | OprMem _ -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA dstA) - !!ir (dstB := AST.ite (cond 1) srcB dstB) - !!ir (dstC := AST.ite (cond 2) srcC dstC) - !!ir (dstD := AST.ite (cond 3) srcD dstD) - | _ -> raise InvalidOperandException - | 512 -> - let kl, vl = 8, 512 - match dst with - | OprReg _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) srcB (masking dstB)) - !!ir (dstC := AST.ite (cond 2) srcC (masking dstC)) - !!ir (dstD := AST.ite (cond 3) srcD (masking dstD)) - !!ir (dstE := AST.ite (cond 4) srcE (masking dstE)) - !!ir (dstF := AST.ite (cond 5) srcF (masking dstF)) - !!ir (dstG := AST.ite (cond 6) srcG (masking dstG)) - !!ir (dstH := AST.ite (cond 7) srcH (masking dstH)) - | OprMem _ -> - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - !!ir (dstA := AST.ite (cond 0) srcA dstA) - !!ir (dstB := AST.ite (cond 1) srcB dstB) - !!ir (dstC := AST.ite (cond 2) srcC dstC) - !!ir (dstD := AST.ite (cond 3) srcD dstD) - !!ir (dstE := AST.ite (cond 4) srcE dstE) - !!ir (dstF := AST.ite (cond 5) srcF dstF) - !!ir (dstG := AST.ite (cond 6) srcG dstG) - !!ir (dstH := AST.ite (cond 7) srcH dstH) - | _ -> raise InvalidOperandException - | _ -> raise InvalidOperandSizeException + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSize dst + let src = transOprToArr ir false ins insLen ctxt packSz packNum oprSize src + let result = + makeAssignWithMask ir ePrx k oprSize packSz eDst src (isMemOpr dst) + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen -let vmovntdq ins insLen ctxt = - SSELifter.buildMove ins insLen ctxt 16 +let vmovdqu ins insLen ctxt = buildVectorMove ins insLen ctxt 64 + +let vmovdqu16 ins insLen ctxt = buildVectorMoveAVX512 ins insLen ctxt 16 +let vmovdqu64 ins insLen ctxt = buildVectorMoveAVX512 ins insLen ctxt 64 -let vmovups ins insLen ctxt = - buildVectorMove ins insLen ctxt +let vmovdqa ins insLen ctxt = buildVectorMove ins insLen ctxt 64 -let vmovupd ins insLen ctxt = - buildVectorMove ins insLen ctxt +let vmovdqa64 ins insLen ctxt = buildVectorMoveAVX512 ins insLen ctxt 64 + +let vmovntdq ins insLen ctxt = + buildMove ins insLen ctxt + +let vmovups ins insLen ctxt = buildVectorMove ins insLen ctxt 32 +let vmovupd ins insLen ctxt = buildVectorMove ins insLen ctxt 64 let vmovddup ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src = transOprToExpr64 ins insLen ctxt src + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr64 ir false ins insLen ctxt src !!ir (dst1 := src) !!ir (dst2 := src) - fillZeroHigh128 ctxt dst ir | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let _src4, src3, _src2, src1 = transOprToExpr256 ins insLen ctxt src + let dst4, dst3, dst2, dst1 = transOprToExpr256 ir false ins insLen ctxt dst + let _src4, src3, _src2, src1 = + transOprToExpr256 ir false ins insLen ctxt src !!ir (dst1 := src1) !!ir (dst2 := src1) !!ir (dst3 := src3) !!ir (dst4 := src3) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vmovntps ins insLen ctxt = - SSELifter.buildMove ins insLen ctxt 16 + buildMove ins insLen ctxt let vmovntpd ins insLen ctxt = - SSELifter.buildMove ins insLen ctxt 16 + buildMove ins insLen ctxt let vmovhlps ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, _src2A = transOprToExpr128 ins insLen ctxt src2 + let ir = !*ctxt !ir insLen let vmovhpd (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt ! if haveEVEXPrx ins.VEXInfo then () else - let dst = transOprToExpr64 ins insLen ctxt dst - let src2, _src1 = transOprToExpr128 ins insLen ctxt src + let dst = transOprToExpr64 ir false ins insLen ctxt dst + let src2, _src1 = transOprToExpr128 ir false ins insLen ctxt src !!ir (dst := src2) | ThreeOperands (dst, src1, src2)-> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2 = transOprToExpr64 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2 = transOprToExpr64 ir false ins insLen ctxt src2 !!ir (dstA := src1A) !!ir (dstB := src2) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir | _ -> raise InvalidOperandException !>ir insLen let vmovlhps ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let ir = !*ctxt !ir insLen let vmovlpd (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt ! - let dst = transOprToExpr64 ins insLen ctxt dst - let _, srcA = transOprToExpr128 ins insLen ctxt src + let dst = transOprToExpr64 ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src !!ir (dst := srcA) | ThreeOperands (dst, src1, src2)-> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let src2 = transOprToExpr ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2 = transOprToExpr ir false ins insLen ctxt src2 !!ir (dstA := src2) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir | _ -> raise InvalidOperandException !>ir insLen let vmovmskpd ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr ins insLen ctxt dst - let dstSz = TypeCheck.typeOf dst let mskpd r = match Register.getKind r with - | Register.Kind.XMM -> SSELifter.movmskpd ins insLen ctxt + | Register.Kind.XMM -> movmskpd ins insLen ctxt | Register.Kind.YMM -> ! src1) let src127 = (AST.sext dstSz (AST.xthi 1 src2)) << AST.num1 dstSz let src191 = (AST.sext dstSz (AST.xthi 1 src3)) << numI32 2 dstSz @@ -1010,16 +494,17 @@ let vmovmskpd ins insLen ctxt = | _ -> raise InvalidOperandSizeException let vmovmskps ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr ins insLen ctxt dst - let dstSz = TypeCheck.typeOf dst let mskpd r = match Register.getKind r with - | Register.Kind.XMM -> SSELifter.movmskps ins insLen ctxt + | Register.Kind.XMM -> movmskps ins insLen ctxt | Register.Kind.YMM -> ! src1, AST.xthi 32 src1 let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 let src3A, src3B = AST.xtlo 32 src3, AST.xthi 32 src3 @@ -1041,43 +526,43 @@ let vmovmskps ins insLen ctxt = | _ -> raise InvalidOperandSizeException let vmovsd (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt ! SSELifter.movsd ins insLen ctxt + | TwoOperands (OprMem _, _) -> movsd ins insLen ctxt | TwoOperands (OprReg _ as dst, src) -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src = transOprToExpr64 ins insLen ctxt src + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr64 ir false ins insLen ctxt src !!ir (dst1 := src) !!ir (dst2 := AST.num0 64) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen | ThreeOperands (dst, src1, src2)-> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ir false ins insLen ctxt src2 !!ir (dstA := src2A) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen | _ -> raise InvalidOperandException let vmovshdup ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let struct (dst, src) = getTwoOprs ins ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insLen ctxt src + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ir false ins insLen ctxt src !!ir (AST.xtlo 32 dst1 := AST.xthi 32 src1) !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1) !!ir (AST.xtlo 32 dst2 := AST.xthi 32 src2) !!ir (AST.xthi 32 dst2 := AST.xthi 32 src2) - fillZeroHigh128 ctxt dst ir | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let src4, src3, src2, src1 = transOprToExpr256 ins insLen ctxt src + let dst4, dst3, dst2, dst1 = transOprToExpr256 ir false ins insLen ctxt dst + let src4, src3, src2, src1 = transOprToExpr256 ir false ins insLen ctxt src !!ir (AST.xtlo 32 dst1 := AST.xthi 32 src1) !!ir (AST.xthi 32 dst1 := AST.xthi 32 src1) !!ir (AST.xtlo 32 dst2 := AST.xthi 32 src2) @@ -1087,24 +572,25 @@ let vmovshdup ins insLen ctxt = !!ir (AST.xtlo 32 dst4 := AST.xthi 32 src4) !!ir (AST.xthi 32 dst4 := AST.xthi 32 src4) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vmovsldup ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let struct (dst, src) = getTwoOprs ins ! -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insLen ctxt src + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst + let src2, src1 = transOprToExpr128 ir false ins insLen ctxt src !!ir (AST.xtlo 32 dst1 := AST.xtlo 32 src1) !!ir (AST.xthi 32 dst1 := AST.xtlo 32 src1) !!ir (AST.xtlo 32 dst2 := AST.xtlo 32 src2) !!ir (AST.xthi 32 dst2 := AST.xtlo 32 src2) - fillZeroHigh128 ctxt dst ir | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst - let src4, src3, src2, src1 = transOprToExpr256 ins insLen ctxt src + let dst4, dst3, dst2, dst1 = transOprToExpr256 ir false ins insLen ctxt dst + let src4, src3, src2, src1 = transOprToExpr256 ir false ins insLen ctxt src !!ir (AST.xtlo 32 dst1 := AST.xtlo 32 src1) !!ir (AST.xthi 32 dst1 := AST.xtlo 32 src1) !!ir (AST.xtlo 32 dst2 := AST.xtlo 32 src2) @@ -1114,238 +600,201 @@ let vmovsldup ins insLen ctxt = !!ir (AST.xtlo 32 dst4 := AST.xtlo 32 src4) !!ir (AST.xthi 32 dst4 := AST.xtlo 32 src4) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vmovss (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt ! SSELifter.movss ins insLen ctxt + | TwoOperands (OprMem _, _) -> movss ins insLen ctxt | TwoOperands (OprReg _ as dst, src) -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src = transOprToExpr32 ins insLen ctxt src + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr32 ir false ins insLen ctxt src !!ir (AST.xtlo 32 dst1 := src) !!ir (AST.xthi 32 dst1 := AST.num0 32) !!ir (dst2 := AST.num0 64) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen | ThreeOperands (dst, src1, src2)-> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ir false ins insLen ctxt src2 !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src2A) !!ir (AST.xthi 32 dstA := AST.xthi 32 src1A) !!ir (dstB := src1B) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen | _ -> raise InvalidOperandException let vandps ins insLen ctxt = - vexedPackedFPBinOp32 ins insLen ctxt (.&) + buildPackedFPInstr ins insLen ctxt 32 (.&) let vandpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt (.&) + buildPackedFPInstr ins insLen ctxt 64 (.&) let private andnpdOp e1 e2 = (AST.not e1) .& e2 let vandnps ins insLen ctxt = - vexedPackedFPBinOp32 ins insLen ctxt andnpdOp + buildPackedFPInstr ins insLen ctxt 32 andnpdOp let vandnpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt andnpdOp + buildPackedFPInstr ins insLen ctxt 64 andnpdOp let vorps ins insLen ctxt = - vexedPackedFPBinOp32 ins insLen ctxt (.|) + buildPackedFPInstr ins insLen ctxt 32 (.|) let vorpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt (.|) + buildPackedFPInstr ins insLen ctxt 64 (.|) let vshufi32x4 ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src1, src2, imm) = getFourOprs ins + let ir = !*ctxt + ! + let packNum = 64 / packSz + let struct (dst, src1, src2, imm) = getFourOprs ins + let isSrc2Mem = + match src2 with + | OprMem _ -> true + | _ -> false + let src1 = transOprToArr ir false ins insLen ctxt packSz packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt packSz packNum oprSize src2 + let imm8 = getImmValue imm let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let i8 = getImmValue imm - ! int |> Register.opmask) + let tmpSrc2 = Array.init (oprSize / packSz) (fun _ -> !+ir 32) + if isSrc2Mem && ePrx.B = 1uy then + let tSrc2 = !+ir 32 + !!ir (tSrc2 := Array.head src2) + Array.iter (fun e -> !!ir (e := tSrc2)) tmpSrc2 + else Array.iter2 (fun e1 e2 -> !!ir (e1 := e2)) tmpSrc2 src2 match oprSize with | 256 -> - let kl, vl = 8, 256 - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let src1D, src1C, src1B, src1A = - transOprToExpr256 ins insLen ctxt src1 - let src2D, src2C, src2B, src2A = - transOprToExpr256 ins insLen ctxt src2 - let struct (tDstD, tDstC, tDstB, tDstA) = tmpVars4 ir 64 - let imm0 (* imm8[0] *) = i8 &&& 0b1L - let imm1 (* imm8[1] *) = (i8 >>> 1) &&& 0b1L - !!ir (tDstA := if imm0 = 0L then src1A else src1C) - !!ir (tDstB := if imm0 = 0L then src1D else src1B) - !!ir (tDstC := if imm1 = 0L then src2C else src2A) - !!ir (tDstD := if imm1 = 0L then src2D else src2B) - let assign dst tDst idx = - let pos = (idx % 2) * 32 - let dst = AST.extract dst 32 pos - dst := AST.ite (cond idx) (AST.extract tDst 32 pos) (masking dst) - !!ir (assign dstA tDstA 0) - !!ir (assign dstA tDstA 1) - !!ir (assign dstB tDstB 2) - !!ir (assign dstB tDstB 3) - !!ir (assign dstC tDstC 4) - !!ir (assign dstC tDstC 5) - !!ir (assign dstD tDstD 6) - !!ir (assign dstD tDstD 7) + let halfPNum = oprSize / packSz / 2 + let orgDst = + transOprToArr ir false ins insLen ctxt packSz packNum oprSize dst + let tDstA = Array.init halfPNum (fun _ -> !+ir packSz) + let tDstB = Array.init halfPNum (fun _ -> !+ir packSz) + let imm0 (* imm8[0] *) = imm8 &&& 0b1L |> int + let imm1 (* imm8[1] *) = (imm8 >>> 1) &&& 0b1L |> int + Array.iteri (fun idx e -> !!ir (e := src1[ (imm0 * halfPNum) + idx ])) tDstA + Array.iteri (fun idx e -> !!ir (e := src2[ (imm1 * halfPNum) + idx ])) tDstB + let tDst = Array.append tDstA tDstB + let result = makeAssignWithMask ir ePrx k oprSize packSz orgDst tDst false + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result | 512 -> - let kl, vl = 16, 512 - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = - transOprToExpr512 ins insLen ctxt src1 - let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = - transOprToExpr512 ins insLen ctxt src2 - let struct (tDstD, tDstC, tDstB, tDstA) = tmpVars4 ir 64 - let struct (tDstH, tDstG, tDstF, tDstE) = tmpVars4 ir 64 - let tS2Arr = Array.init (kl / 2) (fun _ -> !*ir 64) - let src2Arr = [| src2A; src2B; src2C; src2D; src2E; src2F; src2G; src2H |] - match src2 with - | OprMem _ when ePrx.B = 1uy -> - let tSrcA = !*ir 64 - let tSrcA32 (* SRC2[31:0] *) = AST.extract src2A 32 0 - !!ir (tSrcA := AST.concat tSrcA32 tSrcA32) - for i in 0 .. (kl / 2) - 1 do !!ir (tS2Arr[i] := tSrcA) - | _ -> for i in 0 .. (kl / 2) - 1 do !!ir (tS2Arr[i] := src2Arr[i]) - let select4 control srcA srcB srcC srcD = - match control (* control[1:0] *) with - | 0b00L -> srcA - | 0b01L -> srcB - | 0b10L -> srcC - | _ (* 11 *) -> srcD - let ctrl imm8 amt = (imm8 >>> amt) &&& 0b11L - !!ir (tDstA := select4 (ctrl i8 0) src1A src1C src1E src1G) - !!ir (tDstB := select4 (ctrl i8 0) src1B src1D src1F src1H) - !!ir (tDstC := select4 (ctrl i8 2) src1A src1C src1E src1G) - !!ir (tDstD := select4 (ctrl i8 2) src1B src1D src1F src1H) - !!ir (tDstE := select4 (ctrl i8 4) tS2Arr[0] tS2Arr[2] tS2Arr[4] tS2Arr[6]) - !!ir (tDstF := select4 (ctrl i8 4) tS2Arr[1] tS2Arr[3] tS2Arr[5] tS2Arr[7]) - !!ir (tDstG := select4 (ctrl i8 6) tS2Arr[0] tS2Arr[2] tS2Arr[4] tS2Arr[6]) - !!ir (tDstH := select4 (ctrl i8 6) tS2Arr[1] tS2Arr[3] tS2Arr[5] tS2Arr[7]) - let assign dst tDst idx = - let pos = (idx % 2) * 32 - let dst = AST.extract dst 32 pos - dst := AST.ite (cond idx) (AST.extract tDst 32 pos) (masking dst) - !!ir (assign dstA tDstA 0) - !!ir (assign dstA tDstA 1) - !!ir (assign dstB tDstB 2) - !!ir (assign dstB tDstB 3) - !!ir (assign dstC tDstC 4) - !!ir (assign dstC tDstC 5) - !!ir (assign dstD tDstD 6) - !!ir (assign dstD tDstD 7) - !!ir (assign dstE tDstE 8) - !!ir (assign dstE tDstE 9) - !!ir (assign dstF tDstF 10) - !!ir (assign dstF tDstF 11) - !!ir (assign dstG tDstG 12) - !!ir (assign dstG tDstG 13) - !!ir (assign dstH tDstH 14) - !!ir (assign dstH tDstH 15) + let pNum = oprSize / packSz / 4 + let orgDst = + transOprToArr ir false ins insLen ctxt packSz packNum oprSize dst + let tDstA = Array.init pNum (fun _ -> !+ir packSz) + let tDstB = Array.init pNum (fun _ -> !+ir packSz) + let tDstC = Array.init pNum (fun _ -> !+ir packSz) + let tDstD = Array.init pNum (fun _ -> !+ir packSz) + let ctrl0 = (imm8 >>> 0) &&& 0b11L |> int + let ctrl1 = (imm8 >>> 2) &&& 0b11L |> int + let ctrl2 = (imm8 >>> 4) &&& 0b11L |> int + let ctrl3 = (imm8 >>> 6) &&& 0b11L |> int + Array.iteri (fun idx e -> !!ir (e := src1[ (ctrl0 * pNum) + idx ])) tDstA + Array.iteri (fun idx e -> !!ir (e := src1[ (ctrl1 * pNum) + idx ])) tDstB + Array.iteri (fun idx e -> !!ir (e := tmpSrc2[ (ctrl2 * pNum) + idx ])) tDstC + Array.iteri (fun idx e -> !!ir (e := tmpSrc2[ (ctrl3 * pNum) + idx ])) tDstD + let tDst = Array.concat [| tDstA; tDstB; tDstC; tDstD |] + let result = makeAssignWithMask ir ePrx k oprSize packSz orgDst tDst false + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result | _ -> raise InvalidOperandException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen +let private doShuf ir cond dst e1 e2 = + !!ir (dst := AST.num0 32) + !!ir (dst := AST.ite (cond == AST.num0 8) (AST.xtlo 32 e1) dst) + !!ir (dst := AST.ite (cond == AST.num1 8) (AST.xthi 32 e1) dst) + !!ir (dst := AST.ite (cond == numI32 2 8) (AST.xtlo 32 e2) dst) + !!ir (dst := AST.ite (cond == numI32 3 8) (AST.xthi 32 e2) dst) + +let private makeShufCond imm shfAmt = + ((AST.xtlo 8 imm) >> (numI32 shfAmt 8)) .& (numI32 0b11 8) + let vshufps ins insLen ctxt = - let ir = IRBuilder (32) - let struct (dst, src1, src2, imm) = getFourOprs ins - let imm = transOprToExpr ins insLen ctxt imm - let cond1 = AST.xtlo 2 imm - let cond2 = AST.extract imm 2 2 - let cond3 = AST.extract imm 2 4 - let cond4 = AST.extract imm 2 6 - let doShuf cond dst e1 e2 = - !!ir (dst := AST.num0 32) - !!ir (dst := AST.ite (cond == AST.num0 2) (AST.xtlo 32 e1) dst) - !!ir (dst := AST.ite (cond == AST.num1 2) (AST.xthi 32 e1) dst) - !!ir (dst := AST.ite (cond == numI32 2 2) (AST.xtlo 32 e2) dst) - !!ir (dst := AST.ite (cond == numI32 3 2) (AST.xthi 32 e2) dst) + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let sr1B, sr1A = transOprToExpr128 ins insLen ctxt src1 - let sr2B, sr2A = transOprToExpr128 ins insLen ctxt src2 - doShuf cond1 (AST.xtlo 32 dstA) sr1A sr1B - doShuf cond2 (AST.xthi 32 dstA) sr1A sr1B - doShuf cond3 (AST.xtlo 32 dstB) sr2A sr2B - doShuf cond4 (AST.xthi 32 dstB) sr2A sr2B - fillZeroHigh128 ctxt dst ir + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let sr1B, sr1A = transOprToExpr128 ir true ins insLen ctxt src1 + let sr2B, sr2A = transOprToExpr128 ir true ins insLen ctxt src2 + doShuf ir (makeShufCond imm 0) (AST.xtlo 32 dstA) sr1A sr1B + doShuf ir (makeShufCond imm 2) (AST.xthi 32 dstA) sr1A sr1B + doShuf ir (makeShufCond imm 4) (AST.xtlo 32 dstB) sr2A sr2B + doShuf ir (makeShufCond imm 6) (AST.xthi 32 dstB) sr2A sr2B | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 - doShuf cond1 (AST.xtlo 32 dstA) sr1A sr1B - doShuf cond2 (AST.xthi 32 dstA) sr1A sr1B - doShuf cond3 (AST.xtlo 32 dstB) sr2A sr2B - doShuf cond4 (AST.xthi 32 dstB) sr2A sr2B - doShuf cond1 (AST.xtlo 32 dstC) sr1C sr1D - doShuf cond2 (AST.xthi 32 dstC) sr1C sr1D - doShuf cond3 (AST.xtlo 32 dstD) sr2C sr2D - doShuf cond4 (AST.xthi 32 dstD) sr2C sr2D + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ir true ins insLen ctxt src1 + let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ir true ins insLen ctxt src2 + doShuf ir (makeShufCond imm 0) (AST.xtlo 32 dstA) sr1A sr1B + doShuf ir (makeShufCond imm 2) (AST.xthi 32 dstA) sr1A sr1B + doShuf ir (makeShufCond imm 4) (AST.xtlo 32 dstB) sr2A sr2B + doShuf ir (makeShufCond imm 6) (AST.xthi 32 dstB) sr2A sr2B + doShuf ir (makeShufCond imm 0) (AST.xtlo 32 dstC) sr1C sr1D + doShuf ir (makeShufCond imm 2) (AST.xthi 32 dstC) sr1C sr1D + doShuf ir (makeShufCond imm 4) (AST.xtlo 32 dstD) sr2C sr2D + doShuf ir (makeShufCond imm 6) (AST.xthi 32 dstD) sr2C sr2D | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vshufpd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! imm let cond2 = AST.extract imm 1 1 let cond3 = AST.extract imm 1 2 let cond4 = AST.extract imm 1 3 - ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ir true ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ir true ins insLen ctxt src2 !!ir (dstA := AST.ite cond1 src1B src1A) !!ir (dstB := AST.ite cond2 src2B src2A) - fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ins insLen ctxt src1 - let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ins insLen ctxt src2 + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let sr1D, sr1C, sr1B, sr1A = transOprToExpr256 ir true ins insLen ctxt src1 + let sr2D, sr2C, sr2B, sr2A = transOprToExpr256 ir true ins insLen ctxt src2 !!ir (dstA := AST.ite cond1 sr1B sr1A) !!ir (dstB := AST.ite cond2 sr2B sr2A) !!ir (dstC := AST.ite cond3 sr1D sr1C) !!ir (dstD := AST.ite cond4 sr2D sr2C) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vunpckhps ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src1, src2) = getThreeOprs ins + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, _src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2B, _src2A = transOprToExpr128 ir false ins insLen ctxt src2 !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src1B) !!ir (AST.xthi 32 dstA := AST.xtlo 32 src2B) !!ir (AST.xtlo 32 dstB := AST.xthi 32 src1B) !!ir (AST.xthi 32 dstB := AST.xthi 32 src2B) fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let sr1D, _, sr1B, _ = transOprToExpr256 ins insLen ctxt src1 - let sr2D, _, sr2B, _ = transOprToExpr256 ins insLen ctxt src2 + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let sr1D, _, sr1B, _ = transOprToExpr256 ir false ins insLen ctxt src1 + let sr2D, _, sr2B, _ = transOprToExpr256 ir false ins insLen ctxt src2 !!ir (AST.xtlo 32 dstA := AST.xtlo 32 sr1B) !!ir (AST.xthi 32 dstA := AST.xtlo 32 sr2B) !!ir (AST.xtlo 32 dstB := AST.xthi 32 sr1B) @@ -1355,49 +804,53 @@ let vunpckhps ins insLen ctxt = !!ir (AST.xtlo 32 dstD := AST.xthi 32 sr1D) !!ir (AST.xthi 32 dstD := AST.xthi 32 sr2D) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vunpckhpd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, _src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, _src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, _src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2B, _src2A = transOprToExpr128 ir false ins insLen ctxt src2 !!ir (dstA := src1B) !!ir (dstB := src2B) fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let sr1D, _, sr1B, _ = transOprToExpr256 ins insLen ctxt src1 - let sr2D, _, sr2B, _ = transOprToExpr256 ins insLen ctxt src2 + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let sr1D, _, sr1B, _ = transOprToExpr256 ir false ins insLen ctxt src1 + let sr2D, _, sr2B, _ = transOprToExpr256 ir false ins insLen ctxt src2 !!ir (dstA := sr1B) !!ir (dstB := sr2B) !!ir (dstC := sr1D) !!ir (dstD := sr2D) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vunpcklps ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src1, src2) = getThreeOprs ins + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ir true ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ir true ins insLen ctxt src2 !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src1A) !!ir (AST.xthi 32 dstA := AST.xtlo 32 src2A) !!ir (AST.xtlo 32 dstB := AST.xthi 32 src1A) !!ir (AST.xthi 32 dstB := AST.xthi 32 src2A) fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let _, src1C, _, src1A = transOprToExpr256 ins insLen ctxt src1 - let _, src2C, _, src2A = transOprToExpr256 ins insLen ctxt src2 + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let _, src1C, _, src1A = transOprToExpr256 ir true ins insLen ctxt src1 + let _, src2C, _, src2A = transOprToExpr256 ir true ins insLen ctxt src2 !!ir (AST.xtlo 32 dstA := AST.xtlo 32 src1A) !!ir (AST.xthi 32 dstA := AST.xtlo 32 src2A) !!ir (AST.xtlo 32 dstB := AST.xthi 32 src1A) @@ -1407,103 +860,80 @@ let vunpcklps ins insLen ctxt = !!ir (AST.xtlo 32 dstD := AST.xthi 32 src1C) !!ir (AST.xthi 32 dstD := AST.xthi 32 src2C) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vunpcklpd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let _src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let _src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _src1B, src1A = transOprToExpr128 ir true ins insLen ctxt src1 + let _src2B, src2A = transOprToExpr128 ir true ins insLen ctxt src2 !!ir (dstA := src1A) !!ir (dstB := src2A) - fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let _, src1C, _, src1A = transOprToExpr256 ins insLen ctxt src1 - let _, src2C, _, src2A = transOprToExpr256 ins insLen ctxt src2 + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let _, src1C, _, src1A = transOprToExpr256 ir true ins insLen ctxt src1 + let _, src2C, _, src2A = transOprToExpr256 ir true ins insLen ctxt src2 !!ir (dstA := src1A) !!ir (dstB := src2A) !!ir (dstC := src1C) !!ir (dstD := src2C) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vxorps ins insLen ctxt = - match getOperationSize ins with - | 512 -> - let ir = IRBuilder (16) - let struct (dst, src1, src2) = getThreeOprs ins - ! Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = - if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let tmpDest = Array.init 2 (fun _ -> !*ir 32) - let evAssign dst s1 s2 src2A idx = - for i in 0 .. 1 do - let s1 = AST.extract s1 32 (i * 32) - let s2 = AST.extract s2 32 (i * 32) - let dst = AST.extract dst 32 (i * 32) - let tSrc = - match src2 with - | OprMem _ when ePrx.AAA (* B *) = 1uy -> - s1 <+> (AST.extract src2A 32 0) - | _ -> s1 <+> s2 - !!ir (tmpDest[i] := AST.ite (cond (idx + i)) tSrc (masking dst)) - AST.concatArr tmpDest - let kl, vl = 16, 512 - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = - transOprToExpr512 ins insLen ctxt src1 - let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = - transOprToExpr512 ins insLen ctxt src2 - !!ir (dstA := evAssign dstA src1A src2A src2A 0) - !!ir (dstB := evAssign dstB src1B src2B src2A 2) - !!ir (dstC := evAssign dstC src1C src2C src2A 4) - !!ir (dstD := evAssign dstD src1D src2D src2A 6) - !!ir (dstE := evAssign dstE src1E src2E src2A 8) - !!ir (dstF := evAssign dstF src1F src2F src2A 10) - !!ir (dstG := evAssign dstG src1G src2G src2A 12) - !!ir (dstH := evAssign dstH src1H src2H src2A 14) - !>ir insLen - | _ -> vexedPackedFPBinOp32 ins insLen ctxt (<+>) + let ir = !*ctxt + ! + let packNum = 64 / packSz + let struct (dst, src1, src2) = getThreeOprs ins + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSz dst + let tSrc1 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src1 + let tSrc2 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src2 + let result = + if haveEVEXPrx ins.VEXInfo then + let isSrc2Mem = isMemOpr src2 + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + makeAssignEVEX ir ePrx k oprSz packSz eDst tSrc1 tSrc2 (<+>) isSrc2Mem + else Array.map2 (<+>) tSrc1 tSrc2 + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir + !>ir insLen let vxorpd ins insLen ctxt = - vexedPackedFPBinOp64 ins insLen ctxt (<+>) + buildPackedFPInstr ins insLen ctxt 64 (<+>) let vbroadcasti128 ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let ir = !*ctxt !ir insLen let vbroadcastss ins insLen ctxt = - let ir = IRBuilder (32) - let struct (dst, src) = getTwoOprs ins - let src = transOprToExpr32 ins insLen ctxt src - let tmp = !*ir 32 + let ir = !*ctxt ! + let oprSize = getOperationSize ins + match oprSize with | 128 -> - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst + let dst2, dst1 = transOprToExpr128 ir false ins insLen ctxt dst !!ir (tmp := src) !!ir (AST.xtlo 32 dst1 := tmp) !!ir (AST.xthi 32 dst1 := tmp) @@ -1511,7 +941,7 @@ let vbroadcastss ins insLen ctxt = !!ir (AST.xthi 32 dst2 := tmp) fillZeroHigh128 ctxt dst ir | 256 -> - let dst4, dst3, dst2, dst1 = transOprToExpr256 ins insLen ctxt dst + let dst4, dst3, dst2, dst1 = transOprToExpr256 ir false ins insLen ctxt dst !!ir (tmp := src) !!ir (AST.xtlo 32 dst1 := tmp) !!ir (AST.xthi 32 dst1 := tmp) @@ -1523,88 +953,55 @@ let vbroadcastss ins insLen ctxt = !!ir (AST.xthi 32 dst4 := tmp) | 512 -> () | _ -> raise InvalidOperandException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen let vextracti32x8 ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src, imm) = getThreeOprs ins + let ir = !*ctxt + ! + let packNum = 64 / packSz + let allPackNum = oprSize / packSz + let struct (dst, src, imm) = getThreeOprs ins let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let vl = 512 - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src - let imm0 = getImmValue imm &&& 0b1L (* imm8[0] *) - let struct (tDstD, tDstC, tDstB, tDstA) = tmpVars4 ir 64 + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSize dst + let src = + transOprToArr ir false ins insLen ctxt packSz packNum (oprSize * 2) src + let imm0 = getImmValue imm &&& 0b1L |> int (* imm8[0] *) + let tmpDst = Array.sub src (allPackNum * imm0) allPackNum + let result = + makeAssignWithMask ir ePrx k oprSize packSz eDst tmpDst (isMemOpr dst) + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vextracti128 ins insLen ctxt = + let ir = !*ctxt ! - let tmps = Array.init 2 (fun _ -> !*ir 32) - let assign dst src idx = - for i in 0 .. 1 do - let dst = AST.extract dst 32 (i * 32) - let src = AST.extract src 32 (i * 32) - !!ir (tmps[i] := AST.ite (cond (idx + i)) src (masking dst)) - AST.concatArr tmps - !!ir (dstA := assign dstA tDstA 0) - !!ir (dstB := assign dstB tDstB 2) - !!ir (dstC := assign dstC tDstC 4) - !!ir (dstD := assign dstD tDstD 6) - | OprMem _ -> - let tmps = Array.init 2 (fun _ -> !*ir 32) - let assign dst src idx = - for i in 0 .. 1 do - let dst = AST.extract dst 32 (i * 32) - let src = AST.extract src 32 (i * 32) - !!ir (tmps[i] := AST.ite (cond (idx + i)) src dst) - AST.concatArr tmps - !!ir (dstA := assign dstA tDstA 0) - !!ir (dstB := assign dstB tDstB 2) - !!ir (dstC := assign dstC tDstC 4) - !!ir (dstD := assign dstD tDstD 6) - | _ -> raise InvalidOperandException + let struct (dst, src, imm) = getThreeOprs ins + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ir false ins insLen ctxt src + let imm = transOprToExpr ir false ins insLen ctxt imm + let cond = !+ir 1 + !!ir (cond := AST.xtlo 1 imm) + !!ir (dstA := AST.ite cond srcC srcA) + !!ir (dstB := AST.ite cond srcD srcB) + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen let vextracti64x4 ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 64 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let vl = 512 - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst let srcH, srcG, srcF, srcE, srcD, srcC, srcB, srcA = - transOprToExpr512 ins insLen ctxt src + transOprToExpr512 ir false ins insLen ctxt src let imm0 = getImmValue imm &&& 0b1L (* imm8[0] *) let struct (tDstD, tDstC, tDstB, tDstA) = tmpVars4 ir 64 - ! - !!ir (dstA := AST.ite (cond 0) tDstA (masking dstA)) - !!ir (dstB := AST.ite (cond 1) tDstB (masking dstB)) - !!ir (dstC := AST.ite (cond 2) tDstC (masking dstC)) - !!ir (dstD := AST.ite (cond 3) tDstD (masking dstD)) + !!ir (dstA := AST.ite (getVectorMoveCond ePrx k 0) + tDstA (maskWithEPrx ePrx dstA 64)) + !!ir (dstB := AST.ite (getVectorMoveCond ePrx k 1) + tDstB (maskWithEPrx ePrx dstB 64)) + !!ir (dstC := AST.ite (getVectorMoveCond ePrx k 2) + tDstC (maskWithEPrx ePrx dstC 64)) + !!ir (dstD := AST.ite (getVectorMoveCond ePrx k 3) + tDstD (maskWithEPrx ePrx dstD 64)) | OprMem _ -> - !!ir (dstA := AST.ite (cond 0) tDstA dstA) - !!ir (dstB := AST.ite (cond 1) tDstB dstB) - !!ir (dstC := AST.ite (cond 2) tDstC dstC) - !!ir (dstD := AST.ite (cond 3) tDstD dstD) + !!ir (dstA := AST.ite (getVectorMoveCond ePrx k 0) tDstA dstA) + !!ir (dstB := AST.ite (getVectorMoveCond ePrx k 1) tDstB dstB) + !!ir (dstC := AST.ite (getVectorMoveCond ePrx k 2) tDstC dstC) + !!ir (dstD := AST.ite (getVectorMoveCond ePrx k 3) tDstD dstD) | _ -> raise InvalidOperandException !>ir insLen let vinserti128 ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2, imm) = getFourOprs ins - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let src1D, src1C, src1B, src1A = transOprToExpr256 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - let imm = transOprToExpr ins insLen ctxt imm - let cond = !*ir 1 + let ir = !*ctxt ! !!ir (cond := AST.xtlo 1 imm) !!ir (dstA := AST.ite cond src1A src2A) !!ir (dstB := AST.ite cond src1B src2B) @@ -1646,523 +1048,620 @@ let vinserti128 ins insLen ctxt = !>ir insLen let vpaddb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 (opP (.+)) 32 + buildPackedInstr ins insLen ctxt true 8 (opP (.+)) + +let vpmullw ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 16 MMXLifter.opPmullw let vpaddd ins insLen ctxt = - match getOperationSize ins with - | 512 -> - let ir = IRBuilder (16) - let struct (dst, src1, src2) = getThreeOprs ins - ! Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = - if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let tmpDest = Array.init 2 (fun _ -> !*ir 32) - let evAssign dst s1 s2 src2A idx = - for i in 0 .. 1 do - let s1 = AST.extract s1 32 (i * 32) - let s2 = AST.extract s2 32 (i * 32) - let dst = AST.extract dst 32 (i * 32) - let tSrc = - match src2 with - | OprMem _ when ePrx.AAA (* B *) = 1uy -> - s1 .+ (AST.extract src2A 32 0) - | _ -> s1 .+ s2 - !!ir (tmpDest[i] := AST.ite (cond (idx + i)) tSrc (masking dst)) - AST.concatArr tmpDest - let kl, vl = 16, 512 - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = - transOprToExpr512 ins insLen ctxt src1 - let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = - transOprToExpr512 ins insLen ctxt src2 - !!ir (dstA := evAssign dstA src1A src2A src2A 0) - !!ir (dstB := evAssign dstB src1B src2B src2A 2) - !!ir (dstC := evAssign dstC src1C src2C src2A 4) - !!ir (dstD := evAssign dstD src1D src2D src2A 6) - !!ir (dstE := evAssign dstE src1E src2E src2A 8) - !!ir (dstF := evAssign dstF src1F src2F src2A 10) - !!ir (dstG := evAssign dstG src1G src2G src2A 12) - !!ir (dstH := evAssign dstH src1H src2H src2A 14) - !>ir insLen - | _ -> buildPackedInstr ins insLen ctxt 32 (opP (.+)) 16 + let ir = !*ctxt + ! + let packNum = 64 / packSz + let struct (dst, src1, src2) = getThreeOprs ins + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSz dst + let tSrc1 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src1 + let tSrc2 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src2 + let result = + if haveEVEXPrx ins.VEXInfo then + let isSrc2Mem = isMemOpr src2 + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + makeAssignEVEX ir ePrx k oprSz packSz eDst tSrc1 tSrc2 (.+) isSrc2Mem + else Array.map2 (.+) tSrc1 tSrc2 + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir + !>ir insLen let vpaddq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 (opP (.+)) 16 + buildPackedInstr ins insLen ctxt true 64 (opP (.+)) let vpalignr ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! + let packNum = 64 / packSz let struct (dst, src1, src2, imm) = getFourOprs ins - let oprSize = getOperationSize ins - let imm = getImmValue imm - let amount = imm * 8L - let rAmt = numI64 (amount % 64L) 64 (* Right Shift *) - let lAmt = numI64 (64L - (amount % 64L)) 64 (* Left Shift *) - ! then - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - let struct (tSrc1A, tSrc1B, tSrc2A, tSrc2B) = tmpVars4 ir 64 - !!ir (tSrc1A := src1A) - !!ir (tSrc1B := src1B) - !!ir (tSrc2A := src2A) - !!ir (tSrc2B := src2B) - if amount < 64 then - !!ir (dstA := (tSrc2B << lAmt) .| (tSrc2A >> rAmt)) - !!ir (dstB := (tSrc1A << lAmt) .| (tSrc2B >> rAmt)) - elif amount < 128 then - !!ir (dstA := (tSrc1A << lAmt) .| (tSrc2B >> rAmt)) - !!ir (dstB := (tSrc1B << lAmt) .| (tSrc1A >> rAmt)) - elif amount < 192 then - !!ir (dstA := (tSrc1B << lAmt) .| (tSrc1A >> rAmt)) - !!ir (dstB := tSrc1B >> rAmt) + let src1 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src1 + let src2 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src2 + let imm = getImmValue imm |> int + let initRes = Array.init 16 (fun _ -> !+ir 8) + Array.iter (fun e -> !!ir (e := AST.num0 8)) initRes + let result = + if imm >= 32 then + match oprSz with + | 128 -> initRes + | 256 -> Array.append initRes initRes + | _ -> raise InvalidOperandSizeException else - !!ir (dstA := tSrc1B >> rAmt) - !!ir (dstB := AST.num0 64) - fillZeroHigh128 ctxt dst ir - elif oprSize = 256 then - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let src1D, src1C, src1B, src1A = transOprToExpr256 ins insLen ctxt src1 - let src2D, src2C, src2B, src2A = transOprToExpr256 ins insLen ctxt src2 - let struct (tSrc1A, tSrc1B, tSrc1C, tSrc1D) = tmpVars4 ir 64 - let struct (tSrc2A, tSrc2B, tSrc2C, tSrc2D) = tmpVars4 ir 64 - !!ir (tSrc1A := src1A) - !!ir (tSrc1B := src1B) - !!ir (tSrc1C := src1C) - !!ir (tSrc1D := src1D) - !!ir (tSrc2A := src2A) - !!ir (tSrc2B := src2B) - !!ir (tSrc2C := src2C) - !!ir (tSrc2D := src2D) - if amount < 64 then - !!ir (dstA := (tSrc2B << lAmt) .| (tSrc2A >> rAmt)) - !!ir (dstB := (tSrc1A << lAmt) .| (tSrc2B >> rAmt)) - !!ir (dstC := (tSrc2D << lAmt) .| (tSrc2C >> rAmt)) - !!ir (dstD := (tSrc1C << lAmt) .| (tSrc2D >> rAmt)) - elif amount < 128 then - !!ir (dstA := (tSrc1A << lAmt) .| (tSrc2B >> rAmt)) - !!ir (dstB := (tSrc1B << lAmt) .| (tSrc1A >> rAmt)) - !!ir (dstC := (tSrc1C << lAmt) .| (tSrc2D >> rAmt)) - !!ir (dstD := (tSrc1D << lAmt) .| (tSrc1C >> rAmt)) - elif amount < 192 then - !!ir (dstA := (tSrc1B << lAmt) .| (tSrc1A >> rAmt)) - !!ir (dstB := tSrc1B >> rAmt) - !!ir (dstC := (tSrc1D << lAmt) .| (tSrc1C >> rAmt)) - !!ir (dstD := tSrc1D >> rAmt) - else - !!ir (dstA := tSrc1B >> rAmt) - !!ir (dstB := AST.num0 64) - !!ir (dstC := tSrc1D >> rAmt) - !!ir (dstD := AST.num0 64) - else raise InvalidOperandSizeException + let cnt = if imm < 16 then 16 else 32 - imm + let zeroPad = Array.sub initRes 0 (16 - cnt) + match oprSz with + | 128 -> + Array.append (Array.sub (Array.append src2 src1) imm cnt) zeroPad + | 256 -> + let src1L, src1H = Array.splitAt 16 src1 + let src2L, src2H = Array.splitAt 16 src2 + let srcL = Array.sub (Array.append src2L src1L) imm cnt + let srcH = Array.sub (Array.append src2H src1H) imm cnt + Array.concat [| srcL; zeroPad; srcH; zeroPad |] + | _ -> raise InvalidOperandSizeException + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir !>ir insLen let vpand ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPand 16 + buildPackedInstr ins insLen ctxt true 64 opPand let vpandn ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPandn 16 + buildPackedInstr ins insLen ctxt true 64 opPandn -let vpbroadcastb ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins +let vblendvpd ins insLen ctxt = + let ir = !*ctxt + ! -> () (* FIXME: #196 *) - | _ -> - let src = - match src with - | OprReg _ -> transOprToExpr128 ins insLen ctxt src |> snd - | OprMem _ -> transOprToExpr ins insLen ctxt src - | _ -> raise InvalidOperandException - |> AST.xtlo 8 - let tSrc = !*ir 8 - ! !*ir 8) - for i in 0 .. 7 do !!ir (tmps[i] := tSrc) done - let t = !*ir 64 - !!ir (t := AST.concatArr tmps) + let packNum = 64 / 64 + let struct (dst, src1, src2, src3) = getFourOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 64 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 64 packNum oprSize src2 + let src3 = transOprToArr ir false ins insLen ctxt 64 packNum oprSize src3 + let result = packedVblend src2 src1 src3 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vblendvps ins insLen ctxt = + let ir = !*ctxt + ! / 32 + let struct (dst, src1, src2, src3) = getFourOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src2 + let src3 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src3 + let result = packedVblend src2 src1 src3 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vpblendd ins insLen ctxt = + let ir = !*ctxt + ! / 32 + let struct (dst, src1, src2, imm) = getFourOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src2 + let imm = transOprToExpr ir false ins insLen ctxt imm + let result = packedBlend src2 src1 imm + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vpblendw ins insLen ctxt = + let ir = !*ctxt + ! / 16 + let struct (dst, src1, src2, imm) = getFourOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 16 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 16 packNum oprSize src2 + let imm = transOprToExpr ir false ins insLen ctxt imm + let result = packedBlend src2 src1 imm + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vpblendvb ins insLen ctxt = + let ir = !*ctxt + ! / 8 + let struct (dst, src1, src2, src3) = getFourOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 8 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 8 packNum oprSize src2 + let src3 = transOprToArr ir false ins insLen ctxt 8 packNum oprSize src3 + let result = packedVblend src2 src1 src3 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vpackusdw ins insLen ctxt = + let ir = !*ctxt + ! / 32 + let allPackNum = oprSize / 32 + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src2 + let src = match oprSize with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - !!ir (dstA := t) - !!ir (dstB := t) - fillZeroHigh128 ctxt dst ir + | 128 -> Array.append src1 src2 | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - !!ir (dstA := t) - !!ir (dstB := t) - !!ir (dstC := t) - !!ir (dstD := t) + let loSrc1, hiSrc1 = Array.splitAt (allPackNum / 2) src1 + let loSrc2, hiSrc2 = Array.splitAt (allPackNum / 2) src2 + Array.concat [| loSrc1; loSrc2; hiSrc1; hiSrc2 |] | _ -> raise InvalidOperandSizeException + let result = Array.map (packWithSaturation ir 32) src + assignPackedInstr ir false ins insLen ctxt (packNum * 2) oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen -let vpbroadcastd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins +let private saturateSignedWordToUnsignedByte ir expr = (* FIXME: MMXLifter *) + let tExpr = !+ir 16 + !!ir (tExpr := expr) + let checkMin = AST.slt tExpr (numI32 0 16) + let checkMax = AST.sgt tExpr (numI32 255 16) + let minNum = numU32 0u 8 + let maxNum = numU32 0xffu 8 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 8 tExpr)) + +let vpackuswb ins insLen ctxt = + let ir = !*ctxt + ! / 16 + let allPackNum = oprSize / 16 + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir false ins insLen ctxt 16 packNum oprSize src1 + let src2 = transOprToArr ir false ins insLen ctxt 16 packNum oprSize src2 + let src = + match oprSize with + | 128 -> Array.append src1 src2 + | 256 -> + let loSrc1, hiSrc1 = Array.splitAt (allPackNum / 2) src1 + let loSrc2, hiSrc2 = Array.splitAt (allPackNum / 2) src2 + Array.concat [| loSrc1; loSrc2; hiSrc1; hiSrc2 |] + | _ -> raise InvalidOperandSizeException + let result = Array.map (saturateSignedWordToUnsignedByte ir) src + assignPackedInstr ir false ins insLen ctxt (packNum * 2) oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let vpavgb ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 8 SSELifter.opPavgb + +let vpavgw ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 16 SSELifter.opPavgw + +let vpbroadcast ins insLen ctxt packSz = + let ir = !*ctxt + ! + let packNum = 64 / packSz + let allPackNum = oprSize / packSz + let struct (dst, src) = getTwoOprs ins + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSize dst let src = match src with | OprReg r -> match Register.getKind r with | Register.Kind.XMM -> - transOprToExpr128 ins insLen ctxt src |> snd - | Register.Kind.GP -> transOprToExpr ins insLen ctxt src + transOprToExpr128 ir false ins insLen ctxt src |> snd + | Register.Kind.GP -> transOprToExpr ir false ins insLen ctxt src | _ -> raise InvalidOperandException - | OprMem _ -> transOprToExpr ins insLen ctxt src + | OprMem _ -> transOprToExpr ir false ins insLen ctxt src | _ -> raise InvalidOperandException - |> AST.xtlo 32 - ! AST.xtlo packSz + let temp = !+ir packSz !!ir (temp := src) - match oprSize with - | 128 -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - !!ir (AST.extract dstA 32 0 := temp) - !!ir (AST.extract dstA 32 32 := temp) - !!ir (AST.extract dstB 32 0 := temp) - !!ir (AST.extract dstB 32 32 := temp) - fillZeroFromVLToMaxVL ctxt dst 128 512 ir - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - !!ir (AST.extract dstA 32 0 := temp) - !!ir (AST.extract dstA 32 32 := temp) - !!ir (AST.extract dstB 32 0 := temp) - !!ir (AST.extract dstB 32 32 := temp) - !!ir (AST.extract dstC 32 0 := temp) - !!ir (AST.extract dstC 32 32 := temp) - !!ir (AST.extract dstD 32 0 := temp) - !!ir (AST.extract dstD 32 32 := temp) - fillZeroFromVLToMaxVL ctxt dst 256 512 ir - | 512 -> - let kl, vl = 16, 512 - let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = - if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let assign dst idx sPos = - let extDst = AST.extract dst 32 sPos - extDst := AST.ite (cond idx) temp (masking extDst) - !!ir (assign dstA 0 0) - !!ir (assign dstA 1 32) - !!ir (assign dstB 2 0) - !!ir (assign dstB 3 32) - !!ir (assign dstC 4 0) - !!ir (assign dstC 5 32) - !!ir (assign dstD 6 0) - !!ir (assign dstD 7 32) - !!ir (assign dstE 8 0) - !!ir (assign dstE 9 32) - !!ir (assign dstF 10 0) - !!ir (assign dstF 11 32) - !!ir (assign dstG 12 0) - !!ir (assign dstG 13 32) - !!ir (assign dstH 14 0) - !!ir (assign dstH 15 32) - | _ -> raise InvalidOperandSizeException + let src = Array.init allPackNum (fun _ -> temp) + let result = + if haveEVEXPrx ins.VEXInfo then + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + makeAssignWithMask ir ePrx k oprSize packSz eDst src (isMemOpr dst) + else src + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen +let vpbroadcastb ins insLen ctxt = vpbroadcast ins insLen ctxt 8 +let vpbroadcastd ins insLen ctxt = vpbroadcast ins insLen ctxt 32 +let vpbroadcastw ins insLen ctxt = vpbroadcast ins insLen ctxt 16 + let vpcmpeqb ins insLen ctxt = match getOperationSize ins with - | 512 -> GeneralLifter.nop insLen (* FIXME: #197 *) - | _ -> buildPackedInstr ins insLen ctxt 8 opPcmpeqb 64 + | 512 -> GeneralLifter.nop insLen ctxt (* FIXME: #197 *) + | _ -> buildPackedInstr ins insLen ctxt true 8 opPcmpeqb let vpcmpeqd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPcmpeqd 32 + buildPackedInstr ins insLen ctxt true 32 opPcmpeqd let vpcmpeqq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 SSELifter.opPcmpeqq 16 + buildPackedInstr ins insLen ctxt true 64 SSELifter.opPcmpeqq let vpcmpgtb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPcmpgtb 64 + buildPackedInstr ins insLen ctxt true 8 opPcmpgtb + +let vpinsrb ins insLen ctxt = + let ir = !*ctxt + ! + let amount = sel * 8L + let t = !+ir 64 + let expAmt = numI64 (amount % 64L) 64 + !!ir (t := ((AST.zext 64 src2) << expAmt) .& mask) + if amount < 64 then !!ir (dstA := (src1A .& (AST.not mask)) .| t) + else !!ir (dstB := (src1B .& (AST.not mask)) .| t) + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir + !>ir insLen + +let vperm2i128 ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src1, src2, imm) = getFourOprs ins + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let src1D, src1C, src1B, src1A = + transOprToExpr256 ir false ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ir false ins insLen ctxt src2 + let imm = getImmValue imm + let struct (tDstA, tDstB, tDstC, tDstD) = tmpVars4 ir 64 + !>> count) &&& 0b11L + let imm0 (* imm8[3] *) = (imm >>> 3) &&& 0b1L + let imm1 (* imm8[7] *) = (imm >>> 7) &&& 0b1L + let getSrc cond = + match cond with + | 0L -> src1A, src1B + | 1L -> src1C, src1D + | 2L -> src2A, src2B + | _ -> src2C, src2D + let src1, src2 = getSrc (cond 0) + !!ir (tDstA := src1) + !!ir (tDstB := src2) + let src1, src2 = getSrc (cond 4) + !!ir (tDstC := src1) + !!ir (tDstD := src2) + !!ir (dstA := if imm0 = 1L then AST.num0 64 else tDstA) + !!ir (dstB := if imm0 = 1L then AST.num0 64 else tDstB) + !!ir (dstC := if imm1 = 1L then AST.num0 64 else tDstC) + !!ir (dstD := if imm1 = 1L then AST.num0 64 else tDstD) + !>ir insLen + +let private getSrc cond dst e0 e1 e2 e3 e4 e5 e6 e7 ir = + !!ir (dst := AST.ite (cond == AST.num0 8) e0 + (AST.ite (cond == AST.num1 8) e1 + (AST.ite (cond == numI32 2 8) e2 + (AST.ite (cond == numI32 3 8) e3 + (AST.ite (cond == numI32 4 8) e4 + (AST.ite (cond == numI32 5 8) e5 + (AST.ite (cond == numI32 6 8) e6 e7))))))) + +let vpermd ins insLen ctxt = + let ir = !*ctxt + let struct (dst, src1, src2) = getThreeOprs ins + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let src1D, src1C, src1B, src1A = + transOprToExpr256 ir false ins insLen ctxt src1 + let src2D, src2C, src2B, src2A = + transOprToExpr256 ir false ins insLen ctxt src2 + let struct (tmp1A, tmp2A, tmp1B, tmp2B) = tmpVars4 ir 32 + let struct (tmp1C, tmp2C, tmp1D, tmp2D) = tmpVars4 ir 32 + let xthi operand = AST.xthi 32 operand + let xtlo operand = AST.xtlo 32 operand + ! + let cond src pos = + !!ir (tmp := AST.extract src 8 pos .& numI32 0b00000111 8) + cond src1A 0 + getSrc tmp (xtlo dstA) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1A 32 + getSrc tmp (xthi dstA) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1B 0 + getSrc tmp (xtlo dstB) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1B 32 + getSrc tmp (xthi dstB) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1C 0 + getSrc tmp (xtlo dstC) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1C 32 + getSrc tmp (xthi dstC) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1D 0 + getSrc tmp (xtlo dstD) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + cond src1D 32 + getSrc tmp (xthi dstD) tmp1A tmp2A tmp1B tmp2B tmp1C tmp2C tmp1D tmp2D ir + !>ir insLen + +let vpermq ins insLen ctxt = + let ir = !*ctxt + ! 1 oprSize src + let imm = getImmValue imm |> int + let result = Array.init 4 (fun i -> src[ (imm >>> (i * 2)) &&& 0b11 ]) + assignPackedInstr ir false ins insLen ctxt 1 oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen let vpinsrd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! let amount = sel * 32L - let t = !*ir 64 + let t = !+ir 64 let expAmt = numI64 (amount % 64L) 64 + !!ir (t := ((AST.zext 64 src2) << expAmt) .& mask) + if amount < 64 then !!ir (dstA := (src1A .& (AST.not mask)) .| t) + else !!ir (dstB := (src1B .& (AST.not mask)) .| t) + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir + !>ir insLen + +let vpinsrq ins insLen ctxt = + let ir = !*ctxt ! + let amount = sel * 64L + let t = !+ir 64 + let expAmt = numI64 (amount % 64L) 64 !!ir (t := ((AST.zext 64 src2) << expAmt) .& mask) - if amount < 64 then !!ir (dstA := (src1A .& (AST.not mask)) .& t) - else !!ir (dstB := (src1B .& (AST.not mask)) .& t) - fillZeroFromVLToMaxVL ctxt dst 128 512 ir + if amount < 64 then !!ir (dstA := (src1A .& (AST.not mask)) .| t) + else !!ir (dstB := (src1B .& (AST.not mask)) .| t) + fillZeroFromVLToMaxVL ctxt dst (getOperationSize ins) 512 ir !>ir insLen +let vpinsrw ins insLen ctxt = + let ir = !*ctxt + ! + let packNum = 64 / packSz + let struct (dst, src1, src2, imm8) = getFourOprs ins + let src1 = transOprToArr ir true ins insLen ctxt packSz packNum 128 src1 + let src2 = transOprToExpr ir false ins insLen ctxt src2 |> AST.xtlo packSz + let tmps = Array.init 8 (fun _ -> !+ir packSz) + let index = (getImmValue imm8 &&& 0b111) |> int + Array.iter2 (fun t e -> !!ir (t := e)) tmps src1 + !!ir (tmps[index] := src2) + assignPackedInstr ir false ins insLen ctxt packNum 128 dst tmps + fillZeroFromVLToMaxVL ctxt dst 128 512 ir + !>ir insLen + +let vpmaxsd ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 32 SSELifter.opPmaxs + let vpminub ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 SSELifter.opPminub 64 + buildPackedInstr ins insLen ctxt true 8 SSELifter.opPminu let vpminud ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 SSELifter.opPminud 32 + buildPackedInstr ins insLen ctxt true 32 SSELifter.opPminu + +let vpminsb ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 8 SSELifter.opPmins + +let vpminsd ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 32 SSELifter.opPmins + +let vpmovx ins insLen ctxt srcSz dstSz isSignExt = + let ir = !*ctxt + ! / dstSz + let struct (dst, src) = getTwoOprs ins + let ext = if isSignExt then AST.sext dstSz else AST.zext dstSz + let inline extSrc num src = + Array.init num (fun i -> AST.extract src srcSz (i * (int srcSz))) + match src, oprSize with + | OprMem (_, _, _, 128), 128 | OprReg _, 128 -> + let sNum = oprSize / dstSz + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + let result = Array.map ext (extSrc sNum srcA) + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + | OprMem (_, _, _, 128), 256 | OprReg _, 256 -> + let sNum = (oprSize / 2) / dstSz + let src = + let srcB, srcA = transOprToExpr128 ir false ins insLen ctxt src + if (dstSz / srcSz) = 2 then + Array.append (extSrc sNum srcA) (extSrc sNum srcB) + else extSrc (sNum * 2) srcA + let result = Array.map ext src + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + | OprMem (_, _, _, memSz), _ -> + let sNum = memSz / srcSz + let src = transOprToExpr ir false ins insLen ctxt src + let result = Array.map ext (extSrc sNum src) + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let vpmovd2m ins insLen ctxt = + let ir = !*ctxt + ! + let packNum = 64 / packSize + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr ir false ins insLen ctxt dst + let src = transOprToArr ir false ins insLen ctxt packSize packNum oprSize src + let tmp = !+ir 16 + !!ir (tmp := AST.num0 16) + let assignShf idx expr = + !!ir (tmp := tmp .| ((AST.zext 16 expr) << (numI32 idx 16))) + Array.map (fun e -> AST.xthi 1 e) src |> Array.iteri assignShf + !!ir (dst := AST.zext 64 tmp) + !>ir insLen + +let private opVpmulhuw _ = opPmul AST.xthi AST.zext 32 16 + +let vpmulhuw ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 16 opVpmulhuw let private opVpmuludq _ = let low32 expr = expr .& numI64 0xffffffffL 64 Array.map2 (fun e1 e2 -> low32 e1 .* low32 e2) let vpmuludq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opVpmuludq 16 + buildPackedInstr ins insLen ctxt true 64 opVpmuludq + +let private opVpmulld _ = opPmul AST.xtlo AST.sext 32 32 + +let vpmulld ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 32 opVpmulld let vpor ins insLen ctxt = match getOperationSize ins with - | 512 -> GeneralLifter.nop insLen - | _ -> buildPackedInstr ins insLen ctxt 64 opPor 8 + | 512 -> GeneralLifter.nop insLen ctxt + | _ -> buildPackedInstr ins insLen ctxt true 64 opPor let vpshufb ins insLen ctxt = - let struct (dst, src1, src2) = getThreeOprs ins - let oprSize = getOperationSize ins - let cnt = if oprSize = 128 then 16 else 32 - let ir = IRBuilder (2 * cnt) - let n0 = AST.num0 8 - let mask = numU32 0x0Fu 8 + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - let highTmps = Array.init 8 (fun _ -> !*ir 8) - let lowTmps = Array.init 8 (fun _ -> !*ir 8) - let struct (tSrc1, tSrc2) = tmpVars2 ir 64 - for i in 0 .. cnt - 1 do - !!ir (tSrc2 := if i < 8 then src2A else src2B) - let cond = AST.extract tSrc2 1 (((i * 8) % 64) + 7) - let idx = (AST.extract tSrc2 8 ((i * 8) % 64)) .& mask - let numShift = - ((AST.zext 64 idx) .* (numI32 8 64)) .% (numI32 64 64) - !!ir (tSrc1 := AST.ite (idx .< numI32 8 8) src1A src1B) - let src1 = AST.xtlo 8 (tSrc1 >> numShift) - if i < 8 then !!ir (lowTmps[i] := AST.ite cond n0 src1) - else !!ir (highTmps[i % 8] := AST.ite cond n0 src1) - done - !!ir (dstA := AST.concatArr lowTmps) - !!ir (dstB := AST.concatArr highTmps) - fillZeroHigh128 ctxt dst ir - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let src1D, src1C, src1B, src1A = transOprToExpr256 ins insLen ctxt src1 - let src2D, src2C, src2B, src2A = transOprToExpr256 ins insLen ctxt src2 - let tmpsA = Array.init 8 (fun _ -> !*ir 8) - let tmpsB = Array.init 8 (fun _ -> !*ir 8) - let tmpsC = Array.init 8 (fun _ -> !*ir 8) - let tmpsD = Array.init 8 (fun _ -> !*ir 8) - let struct (tSrc1, tSrc2) = tmpVars2 ir 64 - let src1 = [| src1A; src1B; src1C; src1D |] - let src2 = [| src2A; src2B; src2C; src2D |] - let n8 = numI32 8 8 - let n16 = numI32 16 8 - let n24 = numI32 24 8 - for i in 0 .. cnt - 1 do - !!ir (tSrc1 := src1[i / 8]) - !!ir (tSrc2 := src2[i / 8]) - let cond = AST.extract tSrc2 1 (((i * 8) % 64) + 7) - let idx = (AST.extract tSrc2 8 ((i * 8) % 64)) .& mask - let numShift = - ((AST.zext 64 idx) .* (numI32 8 64)) .% (numI32 64 64) - let src1 = - AST.ite (idx .< n8) src1A (AST.ite (idx .< n16) src1B - (AST.ite (idx .< n24) src1C src1D)) - !!ir (tSrc1 := src1) - let src1 = AST.xtlo 8 (tSrc1 >> numShift) - if i < 8 then !!ir (tmpsA[i] := AST.ite cond n0 src1) - elif i < 16 then !!ir (tmpsB[i % 8] := AST.ite cond n0 src1) - elif i < 24 then !!ir (tmpsC[i % 8] := AST.ite cond n0 src1) - else !!ir (tmpsD[i % 8] := AST.ite cond n0 src1) - done - !!ir (dstA := AST.concatArr tmpsA) - !!ir (dstB := AST.concatArr tmpsB) - !!ir (dstC := AST.concatArr tmpsC) - !!ir (dstD := AST.concatArr tmpsD) - | 512 -> - let kl, vl = 64, 512 - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = - transOprToExpr512 ins insLen ctxt src1 - let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = - transOprToExpr512 ins insLen ctxt src2 - let tmpsA = Array.init 8 (fun _ -> !*ir 8) - let tmpsB = Array.init 8 (fun _ -> !*ir 8) - let tmpsC = Array.init 8 (fun _ -> !*ir 8) - let tmpsD = Array.init 8 (fun _ -> !*ir 8) - let tmpsE = Array.init 8 (fun _ -> !*ir 8) - let tmpsF = Array.init 8 (fun _ -> !*ir 8) - let tmpsG = Array.init 8 (fun _ -> !*ir 8) - let tmpsH = Array.init 8 (fun _ -> !*ir 8) - let src1 = [| src1A; src1B; src1C; src1D; src1E; src1F; src1G; src1H |] - let src2 = [| src2A; src2B; src2C; src2D; src2E; src2F; src2G; src2H |] - let struct (tSrc1, tSrc2) = tmpVars2 ir 64 - let numF = numU32 0xFu 8 - let n0 = AST.num0 8 - let jmask = !*ir 8 - let ePrx = getEVEXPrx ins.VEXInfo - let k = !.ctxt (ePrx.AAA |> Disasm.getOpmaskRegister) - let cond1 idx = - let noWritemask = (* no masking *) - if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let lblNoMask = ir.NewSymbol "NoMasking" - let lblZero = ir.NewSymbol "Zeroing" - let lblL0 = ir.NewSymbol "L0" (* index & 0x80 *) - let lblL1 = ir.NewSymbol "L1" - let lblEnd = ir.NewSymbol "End" - let struct (index, cond2) = tmpVars2 ir 8 - let getTmpDst idx = - if idx < 8 then tmpsA[idx] - elif idx < 16 then tmpsB[idx % 8] - elif idx < 24 then tmpsC[idx % 8] - elif idx < 32 then tmpsD[idx % 8] - elif idx < 40 then tmpsE[idx % 8] - elif idx < 48 then tmpsF[idx % 8] - elif idx < 56 then tmpsG[idx % 8] - else tmpsG[idx % 8] - let n8 = numI32 8 8 - let n16 = numI32 16 8 - let n24 = numI32 24 8 - let n32 = numI32 32 8 - let n40 = numI32 40 8 - let n48 = numI32 48 8 - let n56 = numI32 56 8 - !!ir (jmask := numI32 ((kl - 1) &&& ~~~0xF) 8) - for i in 0 .. kl - 1 do - !!ir (tSrc2 := src2[i / 8]) - !!ir (AST.cjmp (cond1 i) (AST.name lblNoMask) (AST.name lblZero)) - !!ir (AST.lmark lblNoMask) - !!ir (index := AST.extract tSrc2 8 ((i * 8) % 64)) - !!ir (cond2 := index .& numI32 0x80 8) - !!ir (AST.cjmp cond2 (AST.name lblL0) (AST.name lblL1)) - !!ir (AST.lmark lblL0) - !!ir (getTmpDst i := n0) - !!ir (AST.jmp (AST.name lblEnd)) - !!ir (AST.lmark lblL1) - !!ir (index := (index .& numF) .+ (numI32 (i % 8) 8 .& jmask)) - let numShift = - ((AST.zext 64 index) .* (numI32 8 64)) .% (numI32 64 64) - let src1 = - AST.ite (index .< n8) src1A (AST.ite (index .< n16) src1B - (AST.ite (index .< n24) src1C (AST.ite (index .< n32) src1D - (AST.ite (index .< n40) src1E (AST.ite (index .< n48) src1E - (AST.ite (index .< n56) src1G src1H)))))) - !!ir (tSrc1 := src1) - let src1 = AST.xtlo 8 (tSrc1 >> numShift) - !!ir (getTmpDst i := src1) - !!ir (AST.jmp (AST.name lblEnd)) - !!ir (AST.lmark lblZero) - !!ir (getTmpDst i := n0) - !!ir (AST.lmark lblEnd) - done - !!ir (dstA := AST.concatArr tmpsA) - !!ir (dstB := AST.concatArr tmpsB) - !!ir (dstC := AST.concatArr tmpsC) - !!ir (dstD := AST.concatArr tmpsD) - !!ir (dstE := AST.concatArr tmpsE) - !!ir (dstF := AST.concatArr tmpsF) - !!ir (dstG := AST.concatArr tmpsG) - !!ir (dstH := AST.concatArr tmpsH) - | _ -> raise InvalidOperandSizeException + let oprSz = getOperationSize ins + let packSz = 8 + let packNum = 64 / packSz + let struct (dst, src1, src2) = getThreeOprs ins + let nPackSz = numI32 (int packSz) packSz + let n64 = numI32 64 packSz + let src1 = transOprToArr ir true ins insLen ctxt 64 1 oprSz src1 + let src2 = transOprToArr ir true ins insLen ctxt packSz packNum oprSz src2 + let mask = numI32 0xF packSz + let n0 = AST.num0 packSz + let n1 = AST.num1 1 + let inline getSrcByIdx i idx = + let shfAmt = (idx .& mask) .* nPackSz + let index = AST.zext 64 (shfAmt .% n64) + let idxA = (i / (128 / packSz)) * 2 + let idxB = idxA + 1 + ((AST.ite (shfAmt .< n64) src1[idxA] src1[idxB]) >> index) + |> AST.xtlo packSz + let inline shuffle i src2 = + AST.ite (AST.xthi 1 src2 == n1) n0 (getSrcByIdx i src2) + let inline shuffleOfEVEX ePrx k i dst src2 = + let cond = getVectorMoveCond ePrx k i + let shuff = AST.ite (AST.xthi 1 src2 == n1) n0 (getSrcByIdx i src2) + AST.ite cond shuff (maskWithEPrx ePrx dst packSz) + let result = + if haveEVEXPrx ins.VEXInfo then + let eDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSz dst + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + Array.mapi2 (shuffleOfEVEX ePrx k) eDst src2 + else Array.mapi shuffle src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir !>ir insLen let vpshufd ins insLen ctxt = - let struct (dst, src, ord) = getThreeOprs ins - let ord = getImmValue ord - let oprSize = getOperationSize ins - let cnt = RegType.toBitWidth oprSize / 32 - let ir = IRBuilder (2 * cnt) - let rShiftTo64 hiExpr lowExpr amount = - let rightAmt = numI64 (amount % 64L) 64 - let leftAmt = numI64 (64L - (amount % 64L)) 64 - if amount < 64L then - AST.xtlo 32 ((hiExpr << leftAmt) .| (lowExpr >> rightAmt)) - elif amount < 128 then AST.xtlo 32 (hiExpr >> rightAmt) - else AST.num0 32 - let amount idx = ((ord >>> (idx * 2)) &&& 0b11L) * 32L + let ir = !*ctxt ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - let struct (tSrcB, tSrcA) = tmpVars2 ir 64 - !!ir (tSrcA := srcA) - !!ir (tSrcB := srcB) - let src amtIdx = rShiftTo64 tSrcB tSrcA (amount amtIdx) - !!ir (dstA := AST.concat (src 1) (src 0)) - !!ir (dstB := AST.concat (src 3) (src 2)) - fillZeroHigh128 ctxt dst ir - | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src - let struct (tSrcD, tSrcC, tSrcB, tSrcA) = tmpVars4 ir 64 - !!ir (tSrcA := srcA) - !!ir (tSrcB := srcB) - !!ir (tSrcC := srcC) - !!ir (tSrcD := srcD) - let lowSrc amtIdx = rShiftTo64 tSrcB tSrcA (amount amtIdx) - let hiSrc amtIdx = rShiftTo64 tSrcD tSrcC (amount amtIdx) - !!ir (dstA := AST.concat (lowSrc 1) (lowSrc 0)) - !!ir (dstB := AST.concat (lowSrc 3) (lowSrc 2)) - !!ir (dstC := AST.concat (hiSrc 1) (hiSrc 0)) - !!ir (dstD := AST.concat (hiSrc 3) (hiSrc 2)) - fillZeroHigh256 ctxt dst ir - | 512 -> () (* FIXME: #196 *) - | _ -> raise InvalidOperandSizeException + let oprSize = getOperationSize ins + let packSize = 32 + let packNum = 64 / packSize + let allPackNum = oprSize / packSize + let struct (dst, src1, src2) = getThreeOprs ins + let eDst = transOprToArr ir false ins insLen ctxt packSize packNum oprSize dst + let src = transOprToArr ir false ins insLen ctxt packSize packNum oprSize src1 + let ord = getImmValue src2 |> int + let inline getIdx i = (i / 4 * 4) + ((ord >>> ((i &&& 0x3) * 2)) &&& 0x3) + let result = + if haveEVEXPrx ins.VEXInfo then + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + let src = + if (isMemOpr src1) && ePrx.B (* B *) = 1uy then + Array.init allPackNum (fun _ -> Array.head src) + else src + let src = Array.init allPackNum (fun i -> src[ getIdx i ]) + makeAssignWithMask ir ePrx k oprSize packSize eDst src false + else + let getIdx i = (i / 4 * 4) + ((ord >>> ((i &&& 0x3) * 2)) &&& 0x3) + Array.init allPackNum (fun i -> src[ getIdx i ]) + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen -let private opShiftVpackedDataLogical oprSize packSz shf src1 (src2: Expr []) = - let count = src2[0] |> AST.zext oprSize - let cond = AST.gt count (numI32 ((int packSz) - 1) oprSize) - let shifted expr = AST.extract (shf (AST.zext oprSize expr) count) packSz 0 +let private opShiftVpackedDataLogical packSz shf src1 src2 = + let count = src2 |> AST.zext 64 + let cond = AST.gt count (numI32 ((int packSz) - 1) 64) + let shifted expr = AST.extract (shf (AST.zext 64 expr) count) packSz 0 Array.map (fun e -> AST.ite cond (AST.num0 packSz) (shifted e)) src1 -let private opVpslld oprSize = opShiftVpackedDataLogical oprSize 32 (<<) +let private vpsll ins insLen ctxt packSz = + let ir = !*ctxt + ! / packSz + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt packSz packNum oprSize src1 + let src2 = + match src2 with + | OprImm _ -> + transOprToExpr ir false ins insLen ctxt src2 |> AST.xtlo packSz + | _ -> transOprToExpr128 ir false ins insLen ctxt src2 |> snd + let result = opShiftVpackedDataLogical packSz (<<) src1 src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen let vpslld ins insLen ctxt = match getOperationSize ins with - | 512 -> GeneralLifter.nop insLen - | _ -> buildPackedInstr ins insLen ctxt 32 opVpslld 16 - -let private opVpsllq oprSize = opShiftVpackedDataLogical oprSize 64 (<<) + | 512 -> GeneralLifter.nop insLen ctxt + | _ -> vpsll ins insLen ctxt 32 -let vpsllq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opVpsllq 16 +let vpsllq ins insLen ctxt = vpsll ins insLen ctxt 64 let vpslldq ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! 15L then 16L else cnt let amount = cnt * 8L let rightAmt = numI64 (64L - (amount % 64L)) 64 let leftAmt = numI64 (amount % 64L) 64 let oprSize = getOperationSize ins - ! 15L then 16L else cnt match oprSize with | 128 -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ir false ins insLen ctxt src let struct (tSrcB, tSrcA) = tmpVars2 ir 64 !!ir (tSrcA := srcA) !!ir (tSrcB := srcB) @@ -2175,10 +1674,9 @@ let vpslldq ins insLen ctxt = else !!ir (dstA := AST.num0 64) !!ir (dstB := AST.num0 64) - fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ir false ins insLen ctxt src let struct (tSrcD, tSrcC, tSrcB, tSrcA) = tmpVars4 ir 64 !!ir (tSrcA := srcA) !!ir (tSrcB := srcB) @@ -2187,36 +1685,88 @@ let vpslldq ins insLen ctxt = if amount < 64 then !!ir (dstA := tSrcA << leftAmt) !!ir (dstB := (tSrcB << leftAmt) .| (tSrcA >> rightAmt)) - !!ir (dstC := (tSrcC << leftAmt) .| (tSrcB >> rightAmt)) + !!ir (dstC := tSrcC << leftAmt) !!ir (dstD := (tSrcD << leftAmt) .| (tSrcC >> rightAmt)) elif amount < 128 then !!ir (dstA := AST.num0 64) !!ir (dstB := tSrcA << leftAmt) - !!ir (dstC := (tSrcB << leftAmt) .| (tSrcA >> rightAmt)) - !!ir (dstD := (tSrcC << leftAmt) .| (tSrcB >> rightAmt)) - elif amount < 192 then - !!ir (dstA := AST.num0 64) - !!ir (dstB := AST.num0 64) - !!ir (dstC := tSrcA << leftAmt) - !!ir (dstD := (tSrcB << leftAmt) .| (tSrcA >> rightAmt)) - elif amount < 256 then - !!ir (dstA := AST.num0 64) - !!ir (dstB := AST.num0 64) !!ir (dstC := AST.num0 64) - !!ir (dstD := tSrcA << leftAmt) + !!ir (dstD := tSrcC << leftAmt) else !!ir (dstA := AST.num0 64) !!ir (dstB := AST.num0 64) !!ir (dstC := AST.num0 64) !!ir (dstD := AST.num0 64) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen + +let private shiftPackedDataRight ins insLen ctxt packSize shf = + let ir = !*ctxt + ! / packSize + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir false ins insLen ctxt packSize packNum oprSz src1 + let src2 = + match src2 with + | OprImm _ -> transOprToExpr ir false ins insLen ctxt src2 + | _ -> transOprToExpr128 ir false ins insLen ctxt src2 |> snd + let struct (tCnt, max) = tmpVars2 ir 64 + let cnt = !+ir packSize + !!ir (max := numI32 (int packSize) 64) + !!ir (tCnt := AST.xtlo 64 src2) + !!ir (tCnt := AST.ite (tCnt .> max .- AST.num1 64) max tCnt) + !!ir (cnt := AST.xtlo packSize tCnt) + let result = Array.map (fun e -> shf e cnt) src1 + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir + !>ir insLen + +let vpsrad ins insLen ctxt = shiftPackedDataRight ins insLen ctxt 32 (?>>) +let vpsraw ins insLen ctxt = shiftPackedDataRight ins insLen ctxt 16 (?>>) + +let vpsravd ins insLen ctxt = + let ir = !*ctxt + ! + let packNum = 64 / packSize + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir false ins insLen ctxt packSize packNum oprSz src1 + let src2 = transOprToArr ir false ins insLen ctxt packSize packNum oprSz src2 + let struct (n0, n32, max) = tmpVars3 ir packSize + !!ir (n0 := AST.num0 packSize) + !!ir (n32 := numI32 32 packSize) + !!ir (max := numI32 0xFFFFFFFF packSize) + let fillSignBit e1 e2 = + AST.ite (e2 .< n32) (e1 ?>> e2) (AST.ite (AST.xthi 1 e1) max n0) + let result = Array.map2 fillSignBit src1 src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir !>ir insLen let vpsrlq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opVpsllq 16 + let ir = !*ctxt + ! + let packNum = 64 / packSz + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt packSz packNum oprSize src1 + let src2 = + match src2 with + | OprImm _ -> + transOprToExpr ir false ins insLen ctxt src2 |> AST.xtlo packSz + | _ -> transOprToExpr128 ir false ins insLen ctxt src2 |> snd + let result = opShiftVpackedDataLogical packSz (>>) src1 src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir + !>ir insLen let vpsrldq ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! 15L then 16L else cnt @@ -2224,36 +1774,20 @@ let vpsrldq ins insLen ctxt = let rightAmt = numI64 (amount % 64L) 64 let leftAmt = numI64 (64L - (amount % 64L)) 64 let oprSize = getOperationSize ins - ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ir false ins insLen ctxt src let struct (tSrcB, tSrcA) = tmpVars2 ir 64 !!ir (tSrcA := srcA) !!ir (tSrcB := srcB) - (* FIXME: refactoring *) - /// Case 1 let index = (int amount) / 64 let src = [| tSrcA; tSrcB; AST.num0 64; AST.num0 64 |] !!ir (dstA := (src[index + 1] << leftAmt) .| (src[index] >> rightAmt)) !!ir (dstB := src[index + 1] >> rightAmt) - (* - /// Case 2 - if amount < 64 then - !!ir (dstA := (srcB << leftAmt) .| (srcA >> rightAmt)) - !!ir (dstB := srcB >> rightAmt) - elif amount < 128 then - !!ir (dstA := srcB >> rightAmt) - !!ir (dstB := AST.num0 64) - else - !!ir (dstA := AST.num0 64) - !!ir (dstB := AST.num0 64) - *) - fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ir false ins insLen ctxt src let struct (tSrcD, tSrcC, tSrcB, tSrcA) = tmpVars4 ir 64 !!ir (tSrcA := srcA) !!ir (tSrcB := srcB) @@ -2261,47 +1795,44 @@ let vpsrldq ins insLen ctxt = !!ir (tSrcD := srcD) if amount < 64 then !!ir (dstA := (tSrcB << leftAmt) .| (tSrcA >> rightAmt)) - !!ir (dstB := (tSrcC << leftAmt) .| (tSrcB >> rightAmt)) + !!ir (dstB := tSrcB >> rightAmt) !!ir (dstC := (tSrcD << leftAmt) .| (tSrcC >> rightAmt)) !!ir (dstD := tSrcD >> rightAmt) elif amount < 128 then - !!ir (dstA := (tSrcC << leftAmt) .| (tSrcB >> rightAmt)) - !!ir (dstB := (tSrcD << leftAmt) .| (tSrcC >> rightAmt)) + !!ir (dstA := (tSrcB >> rightAmt)) + !!ir (dstB := AST.num0 64) !!ir (dstC := tSrcD >> rightAmt) !!ir (dstD := AST.num0 64) - elif amount < 192 then - !!ir (dstA := (tSrcD << leftAmt) .| (tSrcC >> rightAmt)) - !!ir (dstB := tSrcD >> rightAmt) - !!ir (dstC := AST.num0 64) - !!ir (dstD := AST.num0 64) else - !!ir (dstA := tSrcD >> rightAmt) + !!ir (dstA := AST.num0 64) !!ir (dstB := AST.num0 64) !!ir (dstC := AST.num0 64) !!ir (dstD := AST.num0 64) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir !>ir insLen -let private opVpsrld oprSize = opShiftVpackedDataLogical oprSize 32 (<<) - -let vpsrld ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opVpsrld 16 +let vpsrld ins insLen ctxt = shiftPackedDataRight ins insLen ctxt 32 (>>) +let vpsrlw ins insLen ctxt = shiftPackedDataRight ins insLen ctxt 16 (>>) let vpsubb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPsub 128 + buildPackedInstr ins insLen ctxt true 8 (opP (.-)) + +let vpsubd ins insLen ctxt = + buildPackedInstr ins insLen ctxt true 32 (opP (.-)) let vptest ins insLen ctxt = if getOperationSize ins = 128 then SSELifter.ptest ins insLen ctxt else - let ir = IRBuilder (16) + let ir = !*ctxt + ! let struct (t5, t6, t7, t8) = tmpVars4 ir 64 - !ir insLen let vpunpckhdq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPunpckHigh 16 + buildPackedInstr ins insLen ctxt true 32 opUnpackHighData let vpunpckhqdq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPunpckHigh 16 + buildPackedInstr ins insLen ctxt true 64 opUnpackHighData + +let vpunpckhwd ins insLen ctxt = unpackLowHighData ins insLen ctxt 16 true +let vpunpcklwd ins insLen ctxt = unpackLowHighData ins insLen ctxt 16 false let vpunpckldq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPunpckLow 16 + buildPackedInstr ins insLen ctxt true 32 opUnpackLowData let vpunpcklqdq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPunpckLow 16 + buildPackedInstr ins insLen ctxt true 64 opUnpackLowData let vpxor ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src1B, src1A = transOprToExpr128 ir false ins insLen ctxt src1 + let src2B, src2A = transOprToExpr128 ir false ins insLen ctxt src2 !!ir (dstB := src1B <+> src2B) !!ir (dstA := src1A <+> src2A) - fillZeroHigh128 ctxt dst ir | 256 -> - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst let src1D, src1C, src1B, src1A = - transOprToExpr256 ins insLen ctxt src1 + transOprToExpr256 ir false ins insLen ctxt src1 let src2D, src2C, src2B, src2A = - transOprToExpr256 ins insLen ctxt src2 + transOprToExpr256 ir false ins insLen ctxt src2 !!ir (dstD := src1D <+> src2D) !!ir (dstC := src1C <+> src2C) !!ir (dstB := src1B <+> src2B) !!ir (dstA := src1A <+> src2A) | _ -> raise InvalidOperandSizeException + fillZeroFromVLToMaxVL ctxt dst 128 512 ir !>ir insLen let vpxord ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = getThreeOprs ins - let oprSize = getOperationSize ins + let ir = !*ctxt ! Disasm.getOpmaskRegister) - let masking dst = - match ePrx.Z with - | Zeroing -> AST.num0 32 - | Merging -> dst - let cond idx = - (* no write mask *) - let noWritemask = if ePrx.AAA = 0uy then AST.num1 1 else AST.num0 1 - AST.extract k 1 idx .| noWritemask - let tmpDest = Array.init 2 (fun _ -> !*ir 32) - let evAssign dst s1 s2 src2A dstA idx = - for i in 0 .. 1 do - let s1 = AST.extract s1 32 (i * 32) - let s2 = AST.extract s2 32 (i * 32) - let dst = AST.extract dstA 32 0 - let tSrc = - match src2 with - | OprMem _ when ePrx.AAA (* B *) = 1uy -> - s1 <+> (AST.extract src2A 32 0) - | _ -> s1 <+> s2 - !!ir (tmpDest[i] := AST.ite (cond (idx + i)) tSrc (masking dst)) - AST.concatArr tmpDest - match oprSize with - | 128 -> - let kl, vl = 4, 128 - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - !!ir (dstA := evAssign dstA src1A src2A src2A dstA 0) - !!ir (dstB := evAssign dstB src1B src2B src2A dstA 2) - fillZeroHigh128 ctxt dst ir - | 256 -> - let kl, vl = 8, 256 - let dstD, dstC, dstB, dstA = transOprToExpr256 ins insLen ctxt dst - let src1D, src1C, src1B, src1A = - transOprToExpr256 ins insLen ctxt src1 - let src2D, src2C, src2B, src2A = - transOprToExpr256 ins insLen ctxt src2 - !!ir (dstA := evAssign dstA src1A src2A src2A dstA 0) - !!ir (dstB := evAssign dstB src1B src2B src2A dstA 2) - !!ir (dstC := evAssign dstC src1C src2B src2A dstA 4) - !!ir (dstD := evAssign dstD src1D src2B src2A dstA 6) - fillZeroHigh256 ctxt dst ir - | 512 -> - let kl, vl = 16, 512 - let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = - transOprToExpr512 ins insLen ctxt dst - let src1H, src1G, src1F, src1E, src1D, src1C, src1B, src1A = - transOprToExpr512 ins insLen ctxt src1 - let src2H, src2G, src2F, src2E, src2D, src2C, src2B, src2A = - transOprToExpr512 ins insLen ctxt src2 - !!ir (dstA := evAssign dstA src1A src2A src2A dstA 0) - !!ir (dstB := evAssign dstB src1B src2B src2A dstA 2) - !!ir (dstC := evAssign dstC src1C src2C src2A dstA 4) - !!ir (dstD := evAssign dstD src1D src2D src2A dstA 6) - !!ir (dstE := evAssign dstE src1E src2E src2A dstA 8) - !!ir (dstF := evAssign dstF src1F src2F src2A dstA 10) - !!ir (dstG := evAssign dstG src1G src2G src2A dstA 12) - !!ir (dstH := evAssign dstH src1H src2H src2A dstA 14) - | _ -> raise InvalidOperandSizeException + let oprSz = getOperationSize ins + let packSz = 32 + let packNum = 64 / packSz + let struct (dst, src1, src2) = getThreeOprs ins + let tDst = transOprToArr ir false ins insLen ctxt packSz packNum oprSz dst + let tSrc1 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src1 + let tSrc2 = transOprToArr ir false ins insLen ctxt packSz packNum oprSz src2 + let result = + if haveEVEXPrx ins.VEXInfo then + let isSrc2Mem = isMemOpr src2 + let ePrx = getEVEXPrx ins.VEXInfo + let k = !.ctxt (ePrx.AAA |> int |> Register.opmask) + makeAssignEVEX ir ePrx k oprSz packSz tDst tSrc1 tSrc2 (<+>) isSrc2Mem + else Array.map2 (<+>) tSrc1 tSrc2 + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir !>ir insLen let vzeroupper ins insLen ctxt = - let ir = IRBuilder (32) + let ir = !*ctxt ! !!ir (getPseudoRegVar ctxt R.YMM0 3 := n0) @@ -2464,40 +1954,40 @@ let vzeroupper ins insLen ctxt = !>ir insLen let vfmadd132sd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src2, src3) = getThreeOprs ins - let _dstB , dstA = transOprToExpr128 ins insLen ctxt dst - let src2 = transOprToExpr64 ins insLen ctxt src2 - let src3 = transOprToExpr64 ins insLen ctxt src3 - let tmp = !*ir 64 + let ir = !*ctxt ! !!ir (tmp := AST.fmul dstA src3) !!ir (dstA := AST.fadd tmp src2) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst 128 512 ir !>ir insLen let vfmadd213sd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src2, src3) = getThreeOprs ins - let _dstB , dstA = transOprToExpr128 ins insLen ctxt dst - let src2 = transOprToExpr64 ins insLen ctxt src2 - let src3 = transOprToExpr64 ins insLen ctxt src3 - let tmp = !*ir 64 + let ir = !*ctxt ! !!ir (tmp := AST.fmul dstA src2) !!ir (dstA := AST.fadd tmp src3) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst 128 512 ir !>ir insLen let vfmadd231sd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src2, src3) = getThreeOprs ins - let _dstB , dstA = transOprToExpr128 ins insLen ctxt dst - let src2 = transOprToExpr64 ins insLen ctxt src2 - let src3 = transOprToExpr64 ins insLen ctxt src3 - let tmp = !*ir 64 + let ir = !*ctxt ! !!ir (tmp := AST.fmul src2 src3) !!ir (dstA := AST.fadd dstA tmp) - fillZeroHigh128 ctxt dst ir + fillZeroFromVLToMaxVL ctxt dst 128 512 ir !>ir insLen diff --git a/src/FrontEnd/BinLifter/Intel/IntelDisasm.fs b/src/FrontEnd/BinLifter/Intel/IntelDisasm.fs index d65b14e5..b34a164f 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelDisasm.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelDisasm.fs @@ -22,11 +22,13 @@ SOFTWARE. *) -module internal B2R2.FrontEnd.BinLifter.Intel.Disasm +module B2R2.FrontEnd.BinLifter.Intel.Disasm open B2R2 open B2R2.FrontEnd.BinLifter +type Disasm = delegate of INameReadable * DisasmBuilder * InsInfo -> unit + let opCodeToString = function | Opcode.AAA -> "aaa" | Opcode.AAD -> "aad" @@ -289,6 +291,7 @@ let opCodeToString = function | Opcode.INSERTQ -> "insertq" | Opcode.INSW -> "insw" | Opcode.INT -> "int" + | Opcode.INT1 -> "int1" (* ICEBP *) | Opcode.INT3 -> "int3" | Opcode.INTO -> "into" | Opcode.INVD -> "invd" @@ -717,7 +720,8 @@ let opCodeToString = function | Opcode.TZCNT -> "tzcnt" | Opcode.UCOMISD -> "ucomisd" | Opcode.UCOMISS -> "ucomiss" - | Opcode.UD -> "ud" + | Opcode.UD0 -> "ud0" + | Opcode.UD1 -> "ud1" | Opcode.UD2 -> "ud2" | Opcode.UNPCKHPD -> "unpckhpd" | Opcode.UNPCKHPS -> "unpckhps" @@ -776,6 +780,7 @@ let opCodeToString = function | Opcode.VCVTPD2UDQ -> "vcvtpd2udq" | Opcode.VCVTPD2UQQ -> "vcvtpd2uqq" | Opcode.VCVTPH2PS -> "vcvtph2ps" + | Opcode.VCVTPS2DQ -> "vcvtps2dq" | Opcode.VCVTPS2PD -> "vcvtps2pd" | Opcode.VCVTPS2PH -> "vcvtps2ph" | Opcode.VCVTPS2QQ -> "vcvtps2qq" @@ -817,6 +822,8 @@ let opCodeToString = function | Opcode.VDIVSD -> "vdivsd" | Opcode.VDIVSS -> "vdivss" | Opcode.VDPBF16PS -> "vdpbf16ps" + | Opcode.VDPPD -> "vdppd" + | Opcode.VDPPS -> "vdpps" | Opcode.VERR -> "verr" | Opcode.VERW -> "verw" | Opcode.VEXP2PD -> "vexp2pd" @@ -852,6 +859,10 @@ let opCodeToString = function | Opcode.VFMADD231PS -> "vfmadd231ps" | Opcode.VFMADD231SD -> "vfmadd231sd" | Opcode.VFMADD231SS -> "vfmadd231ss" + | Opcode.VFMADDPD -> "vfmaddpd" + | Opcode.VFMADDPS -> "vfmaddps" + | Opcode.VFMADDSD -> "vfmaddsd" + | Opcode.VFMADDSS -> "vfmaddss" | Opcode.VFMADDSUB132PD -> "vfmaddsub132pd" | Opcode.VFMADDSUB132PS -> "vfmaddsub132ps" | Opcode.VFMADDSUB213PD -> "vfmaddsub213pd" @@ -941,6 +952,7 @@ let opCodeToString = function | Opcode.VINSERTI64X4 -> "vinserti64x4" | Opcode.VINSERTPS -> "vinsertps" | Opcode.VLDDQU -> "vlddqu" + | Opcode.VMASKMOVDQU -> "vmaskmovdqu" | Opcode.VMASKMOVPD -> "vmaskmovpd" | Opcode.VMASKMOVPS -> "vmaskmovps" | Opcode.VMAXPD -> "vmaxpd" @@ -976,6 +988,7 @@ let opCodeToString = function | Opcode.VMOVMSKPD -> "vmovmskpd" | Opcode.VMOVMSKPS -> "vmovmskps" | Opcode.VMOVNTDQ -> "vmovntdq" + | Opcode.VMOVNTDQA -> "vmovntdqa" | Opcode.VMOVNTPD -> "vmovntpd" | Opcode.VMOVNTPS -> "vmovntps" | Opcode.VMOVQ -> "vmovq" @@ -985,6 +998,7 @@ let opCodeToString = function | Opcode.VMOVSS -> "vmovss" | Opcode.VMOVUPD -> "vmovupd" | Opcode.VMOVUPS -> "vmovups" + | Opcode.VMPSADBW -> "vmpsadbw" | Opcode.VMPTRLD -> "vmptrld" | Opcode.VMPTRST -> "vmptrst" | Opcode.VMREAD -> "vmread" @@ -1100,6 +1114,7 @@ let opCodeToString = function | Opcode.VPEXPANDW -> "vpexpandw" | Opcode.VPEXTRB -> "vpextrb" | Opcode.VPEXTRD -> "vpextrd" + | Opcode.VPEXTRQ -> "vpextrq" | Opcode.VPEXTRW -> "vpextrw" | Opcode.VPGATHERDD -> "vpgatherdd" | Opcode.VPGATHERDQ -> "vpgatherdq" @@ -1120,6 +1135,7 @@ let opCodeToString = function | Opcode.VPLZCNTQ -> "vplzcntq" | Opcode.VPMADD52HUQ -> "vpmadd52huq" | Opcode.VPMADD52LUQ -> "vpmadd52luq" + | Opcode.VPMADDUBSW -> "vpmaddubsw" | Opcode.VPMADDWD -> "vpmaddwd" | Opcode.VPMASKMOVD -> "vpmaskmovd" | Opcode.VPMASKMOVQ -> "vpmaskmovq" @@ -1354,6 +1370,8 @@ let opCodeToString = function | Opcode.VSUBPS -> "vsubps" | Opcode.VSUBSD -> "vsubsd" | Opcode.VSUBSS -> "vsubss" + | Opcode.VTESTPD -> "vtestpd" + | Opcode.VTESTPS -> "vtestps" | Opcode.VUCOMISD -> "vucomisd" | Opcode.VUCOMISS -> "vucomiss" | Opcode.VUNPCKHPD -> "vunpckhpd" @@ -1399,26 +1417,35 @@ let opCodeToString = function | Opcode.XTEST -> "xtest" | _ -> raise InvalidOpcodeException -let inline private iToHexStr (i: int64) (builder: DisasmBuilder<_>) = - builder.Accumulate AsmWordKind.Value (String.i64ToHex i) +let inline private iToHexStr (i: int64) (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value (HexString.ofInt64 i) + +let inline private uToHexStr (i: uint64) (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 i) + +let inline private getMask sz = + match sz with + | 8 -> 0xFFL + | 16 -> 0xFFFFL + | 32 -> 0xFFFFFFFFL + | _ -> 0xFFFFFFFFFFFFFFFFL -let inline private uToHexStr (i: uint64) (builder: DisasmBuilder<_>) = - builder.Accumulate AsmWordKind.Value (String.u64ToHex i) +let inline private buildPref (prefs: Prefix) (builder: DisasmBuilder) = + if prefs = Prefix.PrxNone then () + elif (prefs &&& Prefix.PrxLOCK) <> Prefix.PrxNone then + builder.Accumulate AsmWordKind.String "lock " + elif (prefs &&& Prefix.PrxREPNZ) <> Prefix.PrxNone then + builder.Accumulate AsmWordKind.String "repnz " + elif (prefs &&& Prefix.PrxREPZ) <> Prefix.PrxNone then + builder.Accumulate AsmWordKind.String "repz " + elif (prefs &&& Prefix.PrxBND) <> Prefix.PrxNone then + builder.Accumulate AsmWordKind.String "bnd " + else () -let private ptrDirectiveString isFar = function - | 8 -> "byte ptr" - | 16 -> "word ptr" - | 32 -> if isFar then "word far ptr" else "dword ptr" - | 48 -> "dword far ptr" - | 64 -> "qword ptr" - | 80 -> if isFar then "qword far ptr" else "tword ptr" - | 128 -> "xmmword ptr" - | 256 -> "ymmword ptr" - | 512 -> "zmmword ptr" - | 224 | 864 -> "" (* x87 FPU state *) - | _ -> Utils.impossible () +let inline private buildOpcode opcode (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) -let dispToString showSign (disp: Disp) (builder: DisasmBuilder<_>) = +let private buildDisplacement showSign (disp: Disp) (builder: DisasmBuilder) = let mask = WordSize.toRegType builder.WordSize |> RegType.getMask |> uint64 if showSign && disp < 0L then builder.Accumulate AsmWordKind.String "-" @@ -1429,59 +1456,16 @@ let dispToString showSign (disp: Disp) (builder: DisasmBuilder<_>) = else uToHexStr (uint64 disp &&& mask) builder -let inline private memDispToStr showSign disp builder = - match disp with - | None -> () - | Some d -> dispToString showSign d builder - -let inline scaleToString (scale: Scale) (builder: DisasmBuilder<_>) = - if scale = Scale.X1 then () - else - builder.Accumulate AsmWordKind.String "*" - builder.Accumulate AsmWordKind.Value ((int scale).ToString()) - -let private memScaleDispToStr emptyBase si d builder = - match si with - | None -> memDispToStr (not emptyBase) d builder - | Some (i, scale) -> - if emptyBase then () else builder.Accumulate AsmWordKind.String "+" - builder.Accumulate AsmWordKind.Variable (Register.toString i) - scaleToString scale builder - memDispToStr true d builder - -let private memAddrToStr b si disp builder = - match b with - | None -> memScaleDispToStr true si disp builder - | Some b -> - builder.Accumulate AsmWordKind.Variable (Register.toString b) - memScaleDispToStr false si disp builder - -let inline isFar (ins: InsInfo) = - match ins.Opcode with - | Opcode.JMPFar | Opcode.CALLFar -> true - | _ -> false - -let mToString (ins: InsInfo) (builder: DisasmBuilder<_>) b si d oprSz = - let ptrDirective = ptrDirectiveString (isFar ins) oprSz - match Helper.getSegment ins.Prefixes with - | None -> - builder.Accumulate AsmWordKind.String ptrDirective - builder.Accumulate AsmWordKind.String (" [") - memAddrToStr b si d builder - builder.Accumulate AsmWordKind.String "]" - | Some seg -> - builder.Accumulate AsmWordKind.String ptrDirective - builder.Accumulate AsmWordKind.String (" [") - builder.Accumulate AsmWordKind.Variable (Register.toString seg) - builder.Accumulate AsmWordKind.String ":" - memAddrToStr b si d builder - builder.Accumulate AsmWordKind.String "]" +let inline private buildAbsAddr selector (offset: Addr) builder = + uToHexStr (uint64 selector) builder + builder.Accumulate AsmWordKind.String ":" + uToHexStr offset builder -let commentWithSymbol (helper: DisasmHelper) targetAddr builder = - if (builder: DisasmBuilder<_>).ResolveSymbol then - match helper.FindFunctionSymbol (targetAddr) with +let private buildComment (reader: INameReadable) targetAddr builder = + if (builder: DisasmBuilder).ResolveSymbol then + match reader.TryFindFunctionName targetAddr with | Error _ -> - (builder: DisasmBuilder<_>).Accumulate AsmWordKind.String " ; " + (builder: DisasmBuilder).Accumulate AsmWordKind.String " ; " uToHexStr targetAddr builder | Ok "" -> () | Ok name -> @@ -1490,138 +1474,439 @@ let commentWithSymbol (helper: DisasmHelper) targetAddr builder = builder.Accumulate AsmWordKind.String ">" else () -let inline relToString offset hlp (builder: DisasmBuilder<_>) = +let inline private buildRelAddr offset reader (builder: DisasmBuilder) = if offset < 0L then builder.Accumulate AsmWordKind.String "-" else builder.Accumulate AsmWordKind.String "+" iToHexStr (abs offset) builder - commentWithSymbol hlp (builder.Address + uint64 offset) builder + buildComment reader (builder.Address + uint64 offset) builder -let inline absToString selector (offset: Addr) builder = - uToHexStr (uint64 selector) builder - builder.Accumulate AsmWordKind.String ":" - uToHexStr offset builder +/// Zeroing/Merging (EVEX.z) +let inline buildEVEXZ ev (builder: DisasmBuilder) = + if ev.Z = Zeroing then builder.Accumulate AsmWordKind.String "{z}" + else () -let getOpmaskRegister = function - | 0x0uy -> Register.K0 - | 0x1uy -> Register.K1 - | 0x2uy -> Register.K2 - | 0x3uy -> Register.K3 - | 0x4uy -> Register.K4 - | 0x5uy -> Register.K5 - | 0x6uy -> Register.K6 - | 0x7uy -> Register.K7 - | _ -> raise InvalidRegisterException +module private IntelSyntax = begin -/// Zeroing/Merging (EVEX.z) -let maskZtoString ev (builder: DisasmBuilder<_>) = - if ev.Z = Zeroing then () - else builder.Accumulate AsmWordKind.String "{z}" + let inline private memDispToStr showSign disp builder = + match disp with + | None -> () + | Some d -> buildDisplacement showSign d builder -/// Opmask register -let maskRegToString ePrx (builder: DisasmBuilder<_>) = - if ePrx.AAA = 0uy then () - else - builder.Accumulate AsmWordKind.String " {" - builder.Accumulate AsmWordKind.Variable - (getOpmaskRegister ePrx.AAA |> Register.toString) - builder.Accumulate AsmWordKind.String "}" + let inline scaleToString (scale: Scale) (builder: DisasmBuilder) = + if scale = Scale.X1 then () + else + builder.Accumulate AsmWordKind.String "*" + builder.Accumulate AsmWordKind.Value ((int scale).ToString()) -let buildMask (ins: InsInfo) builder = - match ins.VEXInfo with - | Some { EVEXPrx = Some ePrx }-> - maskRegToString ePrx builder - maskZtoString ePrx builder - | _ -> () + let private memScaleDispToStr emptyBase si d builder = + match si with + | None -> memDispToStr (not emptyBase) d builder + | Some (i, scale) -> + if emptyBase then () else builder.Accumulate AsmWordKind.String "+" + builder.Accumulate AsmWordKind.Variable (Register.toString i) + scaleToString scale builder + memDispToStr true d builder -let inline private getMask sz = - match sz with - | 8 -> 0xFFL - | 16 -> 0xFFFFL - | 32 -> 0xFFFFFFFFL - | _ -> 0xFFFFFFFFFFFFFFFFL + let private memAddrToStr b si disp builder = + match b with + | None -> memScaleDispToStr true si disp builder + | Some b -> + builder.Accumulate AsmWordKind.Variable (Register.toString b) + memScaleDispToStr false si disp builder -let oprToString ins hlp opr isFst (builder: DisasmBuilder<_>) = - match opr with - | OprReg reg -> - builder.Accumulate AsmWordKind.Variable (Register.toString reg) - if isFst then buildMask ins builder else () - | OprMem (b, si, disp, oprSz) -> - mToString ins builder b si disp oprSz - if isFst then buildMask ins builder else () - | OprImm (imm, _) -> iToHexStr (imm &&& getMask ins.MainOperationSize) builder - | OprDirAddr (Absolute (sel, offset, _)) -> absToString sel offset builder - | OprDirAddr (Relative (offset)) -> relToString offset hlp builder - | Label _ -> Utils.impossible () + let inline private isFar (ins: InsInfo) = + match ins.Opcode with + | Opcode.JMPFar | Opcode.CALLFar -> true + | _ -> false -let inline buildPref (prefs: Prefix) (builder: DisasmBuilder<_>) = - if prefs = Prefix.PrxNone then () - elif (prefs &&& Prefix.PrxLOCK) <> Prefix.PrxNone then - builder.Accumulate AsmWordKind.String "lock " - elif (prefs &&& Prefix.PrxREPNZ) <> Prefix.PrxNone then - builder.Accumulate AsmWordKind.String "repnz " - elif (prefs &&& Prefix.PrxREPZ) <> Prefix.PrxNone then - builder.Accumulate AsmWordKind.String "repz " - elif (prefs &&& Prefix.PrxBND) <> Prefix.PrxNone then - builder.Accumulate AsmWordKind.String "bnd " - else () + let private ptrDirectiveString isFar = function + | 8 -> "byte ptr" + | 16 -> "word ptr" + | 32 -> if isFar then "word far ptr" else "dword ptr" + | 48 -> "fword ptr" + | 64 -> "qword ptr" + | 80 -> if isFar then "qword far ptr" else "tbyte ptr" + | 128 -> "xmmword ptr" + | 256 -> "ymmword ptr" + | 512 -> "zmmword ptr" + | 224 | 864 -> "" (* x87 FPU state *) + | _ -> Utils.impossible () -let inline buildOpcode opcode (builder: DisasmBuilder<_>) = - builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) + let mToString (ins: InsInfo) (builder: DisasmBuilder) b si d oprSz = + let ptrDirective = ptrDirectiveString (isFar ins) oprSz + match Helper.getSegment ins.Prefixes with + | None -> + builder.Accumulate AsmWordKind.String ptrDirective + builder.Accumulate AsmWordKind.String (" [") + memAddrToStr b si d builder + builder.Accumulate AsmWordKind.String "]" + | Some seg -> + builder.Accumulate AsmWordKind.String ptrDirective + builder.Accumulate AsmWordKind.String (" [") + builder.Accumulate AsmWordKind.Variable (Register.toString seg) + builder.Accumulate AsmWordKind.String ":" + memAddrToStr b si d builder + builder.Accumulate AsmWordKind.String "]" + + /// Opmask register + let buildOpMask ePrx (builder: DisasmBuilder) = + if ePrx.AAA = 0uy then () + else + builder.Accumulate AsmWordKind.String "{" + builder.Accumulate AsmWordKind.Variable + (ePrx.AAA |> int |> Register.opmask |> Register.toString) + builder.Accumulate AsmWordKind.String "}" + + let buildMask (ins: InsInfo) builder = + match ins.VEXInfo with + | Some { EVEXPrx = Some ePrx }-> + buildOpMask ePrx builder + buildEVEXZ ePrx builder + | _ -> () + + let oprToString ins reader opr (builder: DisasmBuilder) = + match opr with + | OprReg reg -> + builder.Accumulate AsmWordKind.Variable (Register.toString reg) + | OprMem (b, si, disp, oprSz) -> + mToString ins builder b si disp oprSz + | OprImm (imm, _) -> + iToHexStr (imm &&& getMask ins.MainOperationSize) builder + | OprDirAddr (Absolute (sel, offset, _)) -> buildAbsAddr sel offset builder + | OprDirAddr (Relative (offset)) -> buildRelAddr offset reader builder + | Label _ -> Utils.impossible () + + let buildOprs (ins: InsInfo) reader (builder: DisasmBuilder) = + match ins.Operands with + | NoOperand -> () + | OneOperand (OprMem (Some Register.RIP, None, Some off, 64)) -> + builder.Accumulate AsmWordKind.String (" ") + mToString ins builder (Some Register.RIP) None (Some off) 64 + buildComment reader + (builder.Address + uint64 builder.InsLength + uint64 off) builder + | OneOperand opr -> + builder.Accumulate AsmWordKind.String " " + oprToString ins reader opr builder + | TwoOperands (OprMem (Some R.RIP, None, Some disp, sz), opr) -> + builder.Accumulate AsmWordKind.String " " + mToString ins builder (Some Register.RIP) None (Some disp) sz + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr builder + buildComment reader + (builder.Address + uint64 builder.InsLength + uint64 disp) builder + | TwoOperands (opr, OprMem (Some R.RIP, None, Some disp, sz)) -> + builder.Accumulate AsmWordKind.String " " + oprToString ins reader opr builder + builder.Accumulate AsmWordKind.String ", " + mToString ins builder (Some Register.RIP) None (Some disp) sz + buildComment reader + (builder.Address + uint64 builder.InsLength + uint64 disp) builder + | TwoOperands (opr1, opr2) -> + builder.Accumulate AsmWordKind.String " " + oprToString ins reader opr1 builder + buildMask ins builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr2 builder + | ThreeOperands (opr1, opr2, opr3) -> + builder.Accumulate AsmWordKind.String " " + oprToString ins reader opr1 builder + buildMask ins builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr2 builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr3 builder + | FourOperands (opr1, opr2, opr3, opr4) -> + builder.Accumulate AsmWordKind.String " " + oprToString ins reader opr1 builder + buildMask ins builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr2 builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr3 builder + builder.Accumulate AsmWordKind.String ", " + oprToString ins reader opr4 builder + + let disasm reader (builder: DisasmBuilder) ins = + if builder.ShowAddr then builder.AccumulateAddr () else () + buildPref (ins: InsInfo).Prefixes builder + buildOpcode ins.Opcode builder + buildOprs ins reader builder + +end + +module private ATTSyntax = begin + + let buildDisp disp showSign builder = + match disp with + | Some d -> buildDisplacement showSign d builder + | None -> () + + let buildScaledIndex si (builder: DisasmBuilder) = + match si with + | None -> () + | Some (i, Scale.X1) -> + builder.Accumulate AsmWordKind.String ", %" + builder.Accumulate AsmWordKind.Variable (Register.toString i) + | Some (i, scale) -> + builder.Accumulate AsmWordKind.String ", %" + builder.Accumulate AsmWordKind.Variable (Register.toString i) + builder.Accumulate AsmWordKind.String ", " + builder.Accumulate AsmWordKind.Value ((int scale).ToString()) + + let buildSeg seg (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.String "%" + builder.Accumulate AsmWordKind.Variable (Register.toString seg) + builder.Accumulate AsmWordKind.String ":" + + let buildBasedMemory b si d builder = + buildDisp d true builder + builder.Accumulate AsmWordKind.String "(%" + builder.Accumulate AsmWordKind.Variable (Register.toString b) + buildScaledIndex si builder + builder.Accumulate AsmWordKind.String ")" + + let buildNobaseMemory (i, s) d builder = + buildDisp d true builder + match s with + | Scale.X1 -> + builder.Accumulate AsmWordKind.String "(%" + builder.Accumulate AsmWordKind.Variable (Register.toString i) + | _ -> + builder.Accumulate AsmWordKind.String "(, %" + builder.Accumulate AsmWordKind.Variable (Register.toString i) + builder.Accumulate AsmWordKind.String ", " + builder.Accumulate AsmWordKind.Value ((int s).ToString()) + builder.Accumulate AsmWordKind.String ")" + + let buildMemOp (ins: InsInfo) (builder: DisasmBuilder) b si d oprSz isFst = + if ins.IsBranch () then + builder.Accumulate AsmWordKind.String " *" + elif isFst then + builder.Accumulate AsmWordKind.String " " + else + builder.Accumulate AsmWordKind.String ", " + match Helper.getSegment ins.Prefixes, b, si with + | None, Some b, _ -> + buildBasedMemory b si d builder + | None, None, None -> + buildDisp d false builder + | None, None, Some si -> + buildNobaseMemory si d builder + | Some seg, Some b, _ -> + buildSeg seg builder + buildBasedMemory b si d builder + | Some seg, None, _ -> + buildSeg seg builder + buildDisp d false builder + + let buildMask (ins: InsInfo) (builder: DisasmBuilder) = + match ins.VEXInfo with + | Some { EVEXPrx = Some ePrx }-> + if ePrx.AAA = 0uy then () + else + builder.Accumulate AsmWordKind.String "{%" + builder.Accumulate AsmWordKind.Variable + (ePrx.AAA |> int |> Register.opmask |> Register.toString) + builder.Accumulate AsmWordKind.String "}" + buildEVEXZ ePrx builder + | _ -> () + + let buildOpr (ins: InsInfo) reader isFst (builder: DisasmBuilder) opr = + match opr with + | OprReg reg -> + if isFst then + if ins.IsBranch () then builder.Accumulate AsmWordKind.String " *%" + else builder.Accumulate AsmWordKind.String " %" + else builder.Accumulate AsmWordKind.String ", %" + builder.Accumulate AsmWordKind.Variable (Register.toString reg) + | OprMem (b, si, disp, oprSz) -> + buildMemOp ins builder b si disp oprSz isFst + | OprImm (imm, _) -> + if isFst then builder.Accumulate AsmWordKind.String " $" + else builder.Accumulate AsmWordKind.String ", $" + iToHexStr (imm &&& getMask ins.MainOperationSize) builder + | OprDirAddr (Absolute (sel, offset, _)) -> + builder.Accumulate AsmWordKind.String " " + buildAbsAddr sel offset builder + | OprDirAddr (Relative (offset)) -> + builder.Accumulate AsmWordKind.String " " + buildRelAddr offset reader builder + | Label _ -> Utils.impossible () + + let addOpSuffix (builder: DisasmBuilder) = function + | 8 -> builder.Accumulate AsmWordKind.Mnemonic "b" + | 16 -> builder.Accumulate AsmWordKind.Mnemonic "w" + | 32 -> builder.Accumulate AsmWordKind.Mnemonic "l" + | 64 -> builder.Accumulate AsmWordKind.Mnemonic "q" + | 80 -> builder.Accumulate AsmWordKind.Mnemonic "t" + | _ -> () + + let buildOpSuffix operands builder = + match operands with + | OneOperand (OprMem (_, _, _, sz)) -> addOpSuffix builder sz + | TwoOperands (OprMem (_, _, _, sz), _) + | TwoOperands (_, OprMem (_, _, _, sz)) -> addOpSuffix builder sz + | ThreeOperands (OprMem (_, _, _, sz), _, _) + | ThreeOperands (_, OprMem (_, _, _, sz), _) + | ThreeOperands (_, _, OprMem (_, _, _, sz)) -> addOpSuffix builder sz + | FourOperands (OprMem (_, _, _, sz), _, _, _) + | FourOperands (_, OprMem (_, _, _, sz), _, _) + | FourOperands (_, _, OprMem (_, _, _, sz), _) + | FourOperands (_, _, _, OprMem (_, _, _, sz)) -> addOpSuffix builder sz + | _ -> () + + let buildSrcSizeSuffix operands builder = + match operands with + | TwoOperands (_, OprMem (_, _, _, sz)) -> addOpSuffix builder sz + | TwoOperands (_, OprReg dst) -> + Register.toRegType dst |> addOpSuffix builder + | _ -> Utils.impossible () + + let buildDstSizeSuffix operands builder = + match operands with + | TwoOperands (OprReg dst, _) -> + Register.toRegType dst |> addOpSuffix builder + | _ -> Utils.impossible () + + let buildOprs (ins: InsInfo) reader (builder: DisasmBuilder) = + match ins.Operands with + | NoOperand -> () + | OneOperand opr -> + buildOpr ins reader true builder opr + | TwoOperands (opr1, opr2) -> + buildOpr ins reader true builder opr2 + buildOpr ins reader false builder opr1 + buildMask ins builder + | ThreeOperands (opr1, opr2, opr3) -> + buildOpr ins reader true builder opr3 + buildOpr ins reader false builder opr2 + buildOpr ins reader false builder opr1 + buildMask ins builder + | FourOperands (opr1, opr2, opr3, opr4) -> + buildOpr ins reader true builder opr4 + buildOpr ins reader false builder opr3 + buildOpr ins reader false builder opr2 + buildOpr ins reader false builder opr1 + buildMask ins builder -let recomputeRIPRel disp oprSize builder = - let dir = ptrDirectiveString false oprSize - (builder: DisasmBuilder<_>).Accumulate AsmWordKind.String dir - builder.Accumulate AsmWordKind.String " [" - uToHexStr (builder.Address + uint64 disp + uint64 builder.InsLength) builder - builder.Accumulate AsmWordKind.String "]" + let disasm reader (builder: DisasmBuilder) ins = + if builder.ShowAddr then builder.AccumulateAddr () else () + buildPref (ins: InsInfo).Prefixes builder + match ins.Opcode with + | Opcode.MOVSX -> + builder.Accumulate AsmWordKind.Mnemonic "movs" + buildSrcSizeSuffix ins.Operands builder + buildDstSizeSuffix ins.Operands builder + | Opcode.MOVZX -> + builder.Accumulate AsmWordKind.Mnemonic "movz" + buildSrcSizeSuffix ins.Operands builder + buildDstSizeSuffix ins.Operands builder + | Opcode.MOVSXD -> + builder.Accumulate AsmWordKind.Mnemonic "movslq" + (* Below are the list of opcodes that should not be used with a suffix. *) + | Opcode.ADDSD + | Opcode.ADDSS + | Opcode.CMPSD + | Opcode.CMPSS + | Opcode.COMISD + | Opcode.COMISS + | Opcode.CVTDQ2PD + | Opcode.CVTPI2PS + | Opcode.CVTPS2PD + | Opcode.CVTPS2PI + | Opcode.CVTSD2SS + | Opcode.CVTSS2SD + | Opcode.CVTTPS2PI + | Opcode.CVTTSD2SI + | Opcode.CVTTSS2SI + | Opcode.DIVSD + | Opcode.DIVSS + | Opcode.FBLD + | Opcode.FBSTP + | Opcode.FCOMP + | Opcode.FCOM + | Opcode.FDIV + | Opcode.FDIVR + | Opcode.FIADD + | Opcode.FICOMP + | Opcode.FICOM + | Opcode.FIDIVR + | Opcode.FIDIV + | Opcode.FILD + | Opcode.FIMUL + | Opcode.FISTP + | Opcode.FISTTP + | Opcode.FISUBR + | Opcode.FISUB + | Opcode.FMUL + | Opcode.FST + | Opcode.FSUB + | Opcode.FSUBR + | Opcode.IRET + | Opcode.LAR + | Opcode.LDMXCSR + | Opcode.MAXSD + | Opcode.MAXSS + | Opcode.MINSD + | Opcode.MINSS + | Opcode.MOVD + | Opcode.MOVHPD + | Opcode.MOVHPS + | Opcode.MOVLPD + | Opcode.MOVLPS + | Opcode.MOVQ + | Opcode.MOVSD + | Opcode.MOVSS + | Opcode.MULSD + | Opcode.MULSS + | Opcode.PACKUSWB + | Opcode.PADDSW + | Opcode.PCMPEQB + | Opcode.PCMPGTD + | Opcode.PINSRW + | Opcode.PMAXSW + | Opcode.POR + | Opcode.PREFETCHNTA + | Opcode.PREFETCHT0 + | Opcode.PSADBW + | Opcode.PSLLD + | Opcode.PSUBSB + | Opcode.PXOR + | Opcode.SGDT + | Opcode.SIDT + | Opcode.SQRTSD + | Opcode.SQRTSS + | Opcode.STMXCSR + | Opcode.SUBSD + | Opcode.SUBSS + | Opcode.UCOMISD + | Opcode.UCOMISS + | Opcode.VFMSUB213SD + | Opcode.VFMSUB213PD + | Opcode.VFNMSUB231SD + | Opcode.VFNMSUB231PD + | Opcode.VMOVDDUP + | Opcode.VMOVD + | Opcode.VMOVQ + | Opcode.VPBROADCASTB + | Opcode.VPBROADCASTQ -> + buildOpcode ins.Opcode builder + (* Far jmp/call *) + | Opcode.JMPFar -> + builder.Accumulate AsmWordKind.Mnemonic "ljmp" + buildOpSuffix ins.Operands builder + | Opcode.CALLFar -> + builder.Accumulate AsmWordKind.Mnemonic "lcall" + buildOpSuffix ins.Operands builder + | opcode -> + buildOpcode opcode builder + buildOpSuffix ins.Operands builder + buildOprs ins reader builder -let buildOprs (ins: InsInfo) hlp (builder: DisasmBuilder<_>) = - match ins.Operands with - | NoOperand -> () - | OneOperand (OprMem (Some Register.RIP, None, Some off, 64)) -> - builder.Accumulate AsmWordKind.String (" ") - mToString ins builder (Some Register.RIP) None (Some off) 64 - commentWithSymbol hlp - (builder.Address + uint64 builder.InsLength + uint64 off) builder - | OneOperand opr -> - builder.Accumulate AsmWordKind.String " " - oprToString ins hlp opr true builder - | TwoOperands (OprMem (Some R.RIP, None, Some disp, sz), opr) -> - builder.Accumulate AsmWordKind.String " " - recomputeRIPRel disp sz builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr false builder - | TwoOperands (opr, OprMem (Some R.RIP, None, Some disp, sz)) -> - builder.Accumulate AsmWordKind.String " " - oprToString ins hlp opr true builder - builder.Accumulate AsmWordKind.String ", " - recomputeRIPRel disp sz builder - | TwoOperands (opr1, opr2) -> - builder.Accumulate AsmWordKind.String " " - oprToString ins hlp opr1 true builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr2 false builder - | ThreeOperands (opr1, opr2, opr3) -> - builder.Accumulate AsmWordKind.String " " - oprToString ins hlp opr1 true builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr2 false builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr3 false builder - | FourOperands (opr1, opr2, opr3, opr4) -> - builder.Accumulate AsmWordKind.String " " - oprToString ins hlp opr1 true builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr2 false builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr3 false builder - builder.Accumulate AsmWordKind.String ", " - oprToString ins hlp opr4 false builder +end -let disasm hlp ins (builder: DisasmBuilder<_>) = - if builder.ShowAddr then builder.AccumulateAddr () else () - buildPref (ins: InsInfo).Prefixes builder - buildOpcode ins.Opcode builder - buildOprs ins hlp builder +let mutable disasm = Disasm IntelSyntax.disasm -// vim: set tw=80 sts=2 sw=2: +let setDisassemblyFlavor = function + | DefaultSyntax -> disasm <- Disasm IntelSyntax.disasm + | ATTSyntax -> disasm <- Disasm ATTSyntax.disasm diff --git a/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs index f4fce5e8..de4ea5f7 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelGeneralLifter.fs @@ -36,8 +36,6 @@ open B2R2.FrontEnd.BinLifter.Intel.RegGroup open B2R2.FrontEnd.BinLifter.Intel.Helper open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils -open type BinOpType - #if !EMULATION let private undefCF = AST.undef 1 "CF is undefined." @@ -52,60 +50,6 @@ let private undefZF = AST.undef 1 "ZF is undefined." let private undefPF = AST.undef 1 "PF is undefined." #endif -let private buildAF ctxt e1 e2 r size = - let t1 = r <+> e1 - let t2 = t1 <+> e2 - let t3 = (AST.num1 size) << (numU32 4ul size) - let t4 = t2 .& t3 - !.ctxt R.AF := t4 == t3 - -let private buildPF ctxt r size cond ir = - let struct (t1, t2) = tmpVars2 ir size - let s2 = r <+> (r >> (AST.zext size (numU32 4ul 8))) - let s4 = s2 <+> (t1 >> (AST.zext size (numU32 2ul 8))) - let s5 = s4 <+> (t2 >> (AST.zext size (AST.num1 8))) - let pf = !.ctxt R.PF - let computedPF = AST.unop UnOpType.NOT (AST.xtlo 1 s5) - !!ir (t1 := s2) - !!ir (t2 := s4) - !!ir (match cond with - | None -> pf := computedPF - | Some cond -> pf := AST.ite cond pf computedPF) - -let private enumSZPFlags ctxt r size ir = - !!ir (!.ctxt R.SF := AST.xthi 1 r) - !!ir (!.ctxt R.ZF := r == (AST.num0 size)) - !?ir (buildPF ctxt r size None) - -let private enumASZPFlags ctxt e1 e2 r size ir = - !!ir (buildAF ctxt e1 e2 r size) - !?ir (enumSZPFlags ctxt r size) - -let private enumEFLAGS ctxt e1 e2 e3 size cf ofl ir = - !!ir (!.ctxt R.CF := cf) - !!ir (!.ctxt R.OF := ofl) - !!ir (buildAF ctxt e1 e2 e3 size) - !!ir (!.ctxt R.SF := AST.xthi 1 e3) - !!ir (!.ctxt R.ZF := e3 == (AST.num0 size)) - !?ir (buildPF ctxt e3 size None) - -/// CF on add. -let private cfOnAdd e1 r = AST.lt r e1 - -/// CF on sub. -let private cfOnSub e1 e2 = AST.lt e1 e2 - -/// OF on add. -let private ofOnAdd e1 e2 r = - let e1High = AST.xthi 1 e1 - let e2High = AST.xthi 1 e2 - let rHigh = AST.xthi 1 r - (e1High == e2High) .& (e1High <+> rHigh) - -/// OF on sub. -let private ofOnSub e1 e2 r = - AST.xthi 1 ((e1 <+> e2) .& (e1 <+> r)) - let private getInstrPtr ctxt = !.ctxt (if is64bit ctxt then R.RIP else R.EIP) @@ -121,15 +65,15 @@ let private getRegOfSize ctxt oprSize regGrp = let inline private getStackWidth wordSize oprSize = numI32 (RegType.toByteWidth oprSize) wordSize +/// Push the given expression to the stack, assuming that the expression does +/// not include stack pointer. let private auxPush oprSize ctxt expr ir = - let t = !*ir oprSize let sp = getStackPtr ctxt - !!ir (t := expr) !!ir (sp := sp .- (getStackWidth ctxt.WordBitSize oprSize)) - !!ir (AST.loadLE oprSize sp := t) + !!ir (AST.loadLE oprSize sp := expr) let private computePopSize oprSize = function - | Var (_, id, _, _) when isSegReg (Register.ofRegID id) -> 16 + | Var (_, id, _) when isSegReg (Register.ofRegID id) -> 16 | _ -> oprSize let private auxPop oprSize ctxt dst ir = @@ -147,24 +91,28 @@ let private maskOffset offset oprSize = let rec private isVar = function | Var _ | TempVar _ -> true - | Extract (e, _, _, _) -> isVar e.E + | Extract (e, _, _) -> isVar e.E | _ -> false let private calculateOffset offset oprSize = - let offset = AST.zext oprSize offset - match oprSize with - | 16 -> numU32 2u 16 .* (offset ./ numU32 16u 16), - offset .& numU32 15u 16 - | 32 -> numU32 4u 32 .* (offset ./ numU32 32u 32), - offset .& numU32 31u 32 - | 64 -> numU32 4u 64 .* (offset ./ numU32 32u 64), - offset .& numU32 31u 64 - | _ -> raise InvalidOperandSizeException + match offset.E with + | Num _ -> + numU32 0u oprSize , maskOffset offset oprSize + | _ -> + let offset = AST.zext oprSize offset + match oprSize with + | 16 -> numU32 2u 16 .* (offset ./ numU32 16u 16), + offset .& numU32 15u 16 + | 32 -> numU32 4u 32 .* (offset ./ numU32 32u 32), + offset .& numU32 31u 32 + | 64 -> numU32 4u 64 .* (offset ./ numU32 32u 64), + offset .& numU32 31u 64 + | _ -> raise InvalidOperandSizeException let private strRepeat ins insLen ctxt body cond (ir: IRBuilder) = - let lblExit = ir.NewSymbol "Exit" - let lblCont = ir.NewSymbol "Continue" - let lblNext = ir.NewSymbol "Next" + let lblExit = !%ir "Exit" + let lblCont = !%ir "Continue" + let lblNext = !%ir "Next" let n0 = AST.num0 (ctxt: TranslationContext).WordBitSize let cx = !.ctxt (if is64bit ctxt then R.RCX else R.ECX) let pc = getInstrPtr ctxt @@ -173,6 +121,10 @@ let private strRepeat ins insLen ctxt body cond (ir: IRBuilder) = !!ir (AST.lmark lblCont) !?ir (body ins ctxt) !!ir (cx := cx .- AST.num1 ctxt.WordBitSize) +#if EMULATION + !?ir (setCCOp ctxt) + ctxt.ConditionCodeOp <- ConditionCodeOp.TraceStart +#endif match cond with | None -> !!ir (AST.interjmp pc InterJmpKind.Base) | Some cond -> @@ -189,17 +141,20 @@ let aaa insLen ctxt = #if DEBUG assert32 ctxt #endif - let ir = IRBuilder (16) + let ir = !*ctxt let al = !.ctxt R.AL let af = !.ctxt R.AF let ax = !.ctxt R.AX let cf = !.ctxt R.CF let alAnd0f = al .& numI32 0x0f 8 let cond1 = AST.gt alAnd0f (numI32 9 8) - let cond2 = af == AST.b1 - let cond = !*ir 1 + let cond = !+ir 1 !) ax) !!ir (af := AST.ite cond AST.b1 AST.b0) !!ir (cf := AST.ite cond AST.b1 AST.b0) @@ -209,6 +164,8 @@ let aaa insLen ctxt = !!ir (!.ctxt R.SF := undefSF) !!ir (!.ctxt R.ZF := undefZF) !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen @@ -216,18 +173,21 @@ let aad ins insLen ctxt = #if DEBUG assert32 ctxt #endif - let imm8 = transOneOpr ins insLen ctxt |> AST.xtlo 8 + let ir = !*ctxt + ! AST.xtlo 8 let al = !.ctxt R.AL let ah = !.ctxt R.AH - let ir = IRBuilder (8) - ! al !!ir (al := (al .+ (ah .* imm8)) .& (numI32 0xff 8)) !!ir (ah := AST.num0 8) - !?ir (enumSZPFlags ctxt al 8) + !?ir (enumSZPFlags ctxt al 8 sf) #if !EMULATION !!ir (!.ctxt R.OF := undefOF) !!ir (!.ctxt R.AF := undefAF) !!ir (!.ctxt R.CF := undefCF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen @@ -235,18 +195,21 @@ let aam ins insLen ctxt = #if DEBUG assert32 ctxt #endif - let imm8 = transOneOpr ins insLen ctxt |> AST.xtlo 8 + let ir = !*ctxt + ! AST.xtlo 8 let al = !.ctxt R.AL let ah = !.ctxt R.AH - let ir = IRBuilder (8) - ! al !!ir (ah := al ./ imm8) !!ir (al := al .% imm8) - !?ir (enumSZPFlags ctxt al 8) + !?ir (enumSZPFlags ctxt al 8 sf) #if !EMULATION !!ir (!.ctxt R.OF := undefOF) !!ir (!.ctxt R.AF := undefAF) !!ir (!.ctxt R.CF := undefCF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen @@ -261,102 +224,253 @@ let aas insLen ctxt = let ah = !.ctxt R.AH let alAnd0f = al .& numI32 0x0f 8 let cond1 = AST.gt alAnd0f (numI32 9 8) - let cond2 = af == AST.b1 - let ir = IRBuilder (16) - let cond = !*ir 1 + let ir = !*ctxt + let cond = !+ir 1 !) ax) !!ir (ah := AST.ite cond (ah .- AST.num1 8) ah) !!ir (af := AST.ite cond AST.b1 AST.b0) !!ir (cf := AST.ite cond AST.b1 AST.b0) !!ir (al := alAnd0f) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let adc ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + !ir insLen let add ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (16) - let struct (t1, t2, t3) = tmpVars3 ir oprSize + let ir = !*ctxt ! + let dst = transOprToExpr ir false ins insLen ctxt o1 + if hasLock ins.Prefixes then !!ir (AST.sideEffect Lock) else () +#if !EMULATION + let struct (t1, t2) = tmpVars2 ir oprSize + !!ir (t1 := dst) + !!ir (t2 := t1 .+ t1) + !!ir (dstAssign oprSize dst t2) + let struct (ofl, sf) = osfOnAdd t1 t1 t2 ir + !?ir (enumEFLAGS ctxt t1 t1 t2 oprSize (cfOnAdd t1 t2) ofl sf) +#else + let t = !+ir oprSize + !!ir (t := dst) + !!ir (dstAssign oprSize dst (t .+ t)) + !?ir (setCCOperands2 ctxt t dst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDQ + | _ -> raise InvalidRegTypeException +#endif + | TwoOperands (o1, o2) -> + let dst = transOprToExpr ir true ins insLen ctxt o1 + let src = transOprToExpr ir false ins insLen ctxt o2 |> transReg ir true + if hasLock ins.Prefixes then !!ir (AST.sideEffect Lock) else () +#if !EMULATION + let isSrcConst = isConst src + let t1 = !+ir oprSize + let t2 = if isSrcConst then src else !+ir oprSize + let t3 = !+ir oprSize + !!ir (t1 := dst) + if isSrcConst then () else !!ir (t2 := src) + !!ir (t3 := t1 .+ t2) + !!ir (dstAssign oprSize dst t3) + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnAdd t1 t3) ofl sf) +#else + let src = + if isConst src then src + else + let t = !+ir oprSize + !!ir (t := src) + t + !!ir (dstAssign oprSize dst (dst .+ src)) + !?ir (setCCOperands2 ctxt src dst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDQ + | _ -> raise InvalidRegTypeException +#endif + | _ -> raise InvalidOperandException if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () !>ir insLen -let ``and`` ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt +let adox ins insLen ctxt = + let ir = !*ctxt + ! -> + let struct (t1, t2, t3) = tmpVars3 ir 64 + !!ir (t1 := AST.zext 64 dst) + !!ir (t2 := AST.zext 64 src) + !!ir (t3 := t1 .+ t2 .+ AST.zext 64 oF) + !!ir (dstAssign oprSize dst (AST.xtlo oprSize t3)) + !!ir (oF := AST.extract t3 1 32) + | 64 -> + let struct (t1a, t2a, t3a) = tmpVars3 ir 64 + let struct (t1b, t2b, t3b) = tmpVars3 ir 64 + let mask = !+ir 64 + !!ir (mask := numU64 0xFFFFFFFFUL 64) + !!ir (t1a := dst .& mask) + !!ir (t1b := (dst >> (numI32 32 64)) .& mask) + !!ir (t2a := src .& mask) + !!ir (t2b := (src >> (numI32 32 64)) .& mask) + !!ir (t3a := t1a .+ t2a .+ AST.zext 64 oF) + !!ir (t3b := t1b .+ t2b .+ (t3a >> (numI32 32 64))) + !!ir (dstAssign oprSize dst (dst .+ src .+ (AST.zext 64 oF))) + !!ir (oF := AST.extract t3b 1 32) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let ``and`` ins insLen ctxt = + let ir = !*ctxt ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICQ + | _ -> raise InvalidRegTypeException +#else + let sf = AST.xthi 1 dst !!ir (!.ctxt R.OF := AST.b0) !!ir (!.ctxt R.CF := AST.b0) -#if !EMULATION + !?ir (enumSZPFlags ctxt dst oprSize sf) !!ir (!.ctxt R.AF := undefAF) #endif - !?ir (enumSZPFlags ctxt t oprSize) if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () !>ir insLen let andn ins insLen ctxt = - let struct (dst, src1, src2) = transThreeOprs ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (16) - let t = !*ir oprSize + let ir = !*ctxt ! (int oprSize - 1)) !!ir (!.ctxt R.ZF := AST.eq dst (AST.num0 oprSize)) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let arpl ins insLen ctxt = #if DEBUG assert32 ctxt #endif - let ir = IRBuilder (8) - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! let mask = numI32 0xfffc 16 let zF = !.ctxt R.ZF - !) !!ir (t2 := src .& numI32 0x3 16) - !!ir (dst := AST.ite (AST.lt t1 t2) ((dst .& mask) .| t2) dst) - !!ir (zF := AST.lt t1 t2) + !!ir (dst := AST.ite (t1 .< t2) ((dst .& mask) .| t2) dst) + !!ir (zF := t1 .< t2) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif + !>ir insLen + +let bextr ins insLen ctxt = + let ir = !*ctxt + ! 0)) + !!ir (len := AST.zext oprSize (AST.extract src2 8 8)) + !!ir (mask := AST.not(numI32 0 oprSize) << len) + !!ir (tmp := AST.zext oprSize src1) + !!ir (tmp := (tmp >> start) .& AST.not(mask)) + !!ir (dstAssign oprSize dst tmp) + !!ir (zF := (dst == AST.num0 oprSize)) +#if !EMULATION + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif + !>ir insLen + +let blsi ins insLen ctxt = + let ir = !*ctxt + ! tmp) + !!ir (!.ctxt R.ZF := tmp == AST.num0 oprSize) + !!ir (!.ctxt R.CF := src != AST.num0 oprSize) + !!ir (dstAssign oprSize dst tmp) +#if !EMULATION + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let private bndmov64 ins insLen ctxt = - let struct (dst, src) = getTwoOprs ins - let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst - let src1, src2 = transOprToExpr128 ins insLen ctxt src - let ir = IRBuilder (4) + let ir = !*ctxt !ir insLen @@ -365,18 +479,18 @@ let private bndmov32Aux ins insLen ctxt ir = let struct (dst, src) = getTwoOprs ins match dst, src with | OprReg _, OprMem _ -> - let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst - let src = transOprToExpr ins insLen ctxt src + let dst1, dst2 = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src !!ir (dst1 := AST.xthi 32 src |> AST.zext 64) !!ir (dst2 := AST.xtlo 32 src |> AST.zext 64) | OprMem _, OprReg _ -> - let src1, src2 = transOprToExpr128 ins insLen ctxt src - let dst = transOprToExpr ins insLen ctxt dst + let src1, src2 = transOprToExpr128 ir false ins insLen ctxt src + let dst = transOprToExpr ir false ins insLen ctxt dst !!ir (dst := AST.concat (AST.xtlo 32 src1) (AST.xtlo 32 src2)) | _ -> raise InvalidOperandException let bndmov32 ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt !ir insLen @@ -386,19 +500,22 @@ let bndmov ins insLen ctxt = else bndmov32 ins insLen ctxt let bsf ins insLen ctxt = - let ir = IRBuilder (26) - let lblL0 = ir.NewSymbol "L0" - let lblL1 = ir.NewSymbol "L1" - let lblEnd = ir.NewSymbol "End" - let lblLoopCond = ir.NewSymbol "LoopCond" - let lblLE = ir.NewSymbol "LoopEnd" - let lblLoop = ir.NewSymbol "Loop" - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + !ir insLen let bsr ins insLen ctxt = - let ir = IRBuilder (26) - let lblL0 = ir.NewSymbol "L0" - let lblL1 = ir.NewSymbol "L1" - let lblEnd = ir.NewSymbol "End" - let lblLoopCond = ir.NewSymbol "LoopCond" - let lblLE = ir.NewSymbol "LoopEnd" - let lblLoop = ir.NewSymbol "Loop" - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + !ir insLen let bswap ins insLen ctxt = - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! int - let ir = IRBuilder (2 * cnt) - let t = !*ir oprSize - let tmps = Array.init cnt (fun _ -> !*ir 8) - ! !+ir 8) !!ir (t := dst) for i in 0 .. cnt - 1 do !!ir (tmps[i] := AST.extract t 8 (i * 8)) @@ -482,7 +606,7 @@ let bswap ins insLen ctxt = let private bit ins bitBase bitOffset oprSize = match bitBase.E with - | Load (e, t, expr, _) -> + | Load (e, t, expr) -> let effAddrSz = getEffAddrSz ins let addrOffset, bitOffset = calculateOffset bitOffset oprSize let addrOffset = AST.zext effAddrSz addrOffset @@ -492,40 +616,52 @@ let private bit ins bitBase bitOffset oprSize = else raise InvalidExprException let bt ins insLen ctxt = - let struct (bitBase, bitOffset) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (8) + let ir = !*ctxt !ir insLen let private setBit ins bitBase bitOffset oprSize setValue = match bitBase.E with - | Load (e, t, expr, _) -> + | Load (e, t, expr) -> let effAddrSz = getEffAddrSz ins let addrOffset, bitOffset = calculateOffset bitOffset oprSize let addrOffset = AST.zext effAddrSz addrOffset let mask = setValue << bitOffset + let bit = (AST.zext oprSize AST.b1) << bitOffset let loadMem = AST.load e t (expr .+ addrOffset) - loadMem := (loadMem .& (getMask oprSize .- mask)) .| mask - | _ -> if isVar bitBase.E - then let mask = setValue << maskOffset bitOffset oprSize - bitBase := (bitBase .& (getMask oprSize .- mask)) .| mask - else raise InvalidExprException + loadMem := (loadMem .& (getMask oprSize .- bit)) .| mask + | _ -> + if isVar bitBase.E then + let mask = setValue << maskOffset bitOffset oprSize + let bit = (AST.zext oprSize AST.b1) << maskOffset bitOffset oprSize + dstAssign oprSize bitBase ((bitBase .& (getMask oprSize .- bit)) .| mask) + else + raise InvalidExprException let bitTest ins insLen ctxt setValue = - let struct (bitBase, bitOffset) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + !ir insLen let btc ins insLen ctxt = - bitTest ins insLen ctxt (!.ctxt R.CF |> AST.not) + let ir = !*ctxt + ! AST.not) +#else + let setValue = AST.zext oprSize (getCFLazy ctxt ir |> AST.not) + !!ir (!.ctxt R.ZF := getZFLazy ctxt ir) +#endif + !!ir (!.ctxt R.CF := bit ins bitBase bitOffset oprSize) + !!ir (setBit ins bitBase bitOffset oprSize setValue) +#if !EMULATION + !!ir (!.ctxt R.OF := undefOF) + !!ir (!.ctxt R.SF := undefSF) + !!ir (!.ctxt R.AF := undefAF) + !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif + if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () + !>ir insLen let btr ins insLen ctxt = bitTest ins insLen ctxt AST.b0 @@ -546,17 +706,38 @@ let btr ins insLen ctxt = let bts ins insLen ctxt = bitTest ins insLen ctxt AST.b1 -let call ins insLen ctxt = - let pc = getInstrPtr ctxt +let bzhi ins insLen ctxt = + let ir = !*ctxt + ! src2 + let cond1 = n .< numI32 (RegType.toBitWidth oprSize) 8 + let cond2 = n .> numI32 ((RegType.toBitWidth oprSize) - 1) 8 + let tmp = AST.zext oprSize (numI32 (RegType.toBitWidth oprSize) 8 .- n) + let cf = !.ctxt R.CF + !!ir (dstAssign oprSize dst (AST.ite cond1 ((src1 << tmp) >> tmp) src1)) + !!ir (cf := AST.ite cond2 AST.b1 AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif + !>ir insLen + +let call ins insLen ctxt = + let ir = !*ctxt ! -> AST.xtlo 16 opr := AST.sext 16 (AST.xtlo 8 opr) - | 32 -> AST.xtlo 32 opr := AST.sext 32 (AST.xtlo 16 opr) - | 64 -> opr := AST.sext 64 (AST.xtlo 32 opr) - | _ -> raise InvalidOperandSizeException) + let oprSize = getOperationSize ins + let src = AST.sext oprSize (AST.xtlo (oprSize / 2) opr) + !!ir (dstAssign oprSize (AST.xtlo oprSize opr) src) !>ir insLen let clearFlag insLen ctxt flagReg = - let ir = IRBuilder (4) + let ir = !*ctxt !ir insLen let cmc ins insLen ctxt = let cf = !.ctxt R.CF - let ir = IRBuilder (8) + let ir = !*ctxt !ir insLen @@ -616,24 +803,101 @@ let private getCondOfCMov (ins: IntelInternalInstruction) ctxt = (!.ctxt R.SF == !.ctxt R.OF) | _ -> raise InvalidOpcodeException +#if EMULATION +let private getCondOfCMovLazy (ins: IntelInternalInstruction) ctxt ir = + match ins.Opcode with + | Opcode.CMOVO -> getOFLazy ctxt ir + | Opcode.CMOVNO -> getOFLazy ctxt ir |> AST.not + | Opcode.CMOVB -> getCFLazy ctxt ir + | Opcode.CMOVAE -> getCFLazy ctxt ir |> AST.not + | Opcode.CMOVZ -> getZFLazy ctxt ir + | Opcode.CMOVNZ -> getZFLazy ctxt ir |> AST.not + | Opcode.CMOVBE -> + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src2 = getCCSrc1 ctxt regType + let src1 = getCCDst ctxt regType .+ src2 + src1 .<= src2 + | _ -> (getCFLazy ctxt ir) .| (getZFLazy ctxt ir) + | Opcode.CMOVA -> (getCFLazy ctxt ir .| getZFLazy ctxt ir) |> AST.not + | Opcode.CMOVS -> getSFLazy ctxt ir + | Opcode.CMOVNS -> getSFLazy ctxt ir |> AST.not + | Opcode.CMOVP -> getPFLazy ctxt ir + | Opcode.CMOVNP -> getPFLazy ctxt ir |> AST.not + | Opcode.CMOVL -> + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src2 = getCCSrc1 ctxt regType + let src1 = getCCDst ctxt regType .+ src2 + src1 ?< src2 + | _ -> getOFLazy ctxt ir != getSFLazy ctxt ir + | Opcode.CMOVGE -> getOFLazy ctxt ir == getSFLazy ctxt ir + | Opcode.CMOVLE -> + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src2 = getCCSrc1 ctxt regType + let src1 = getCCDst ctxt regType .+ src2 + src1 ?<= src2 + | _ -> (getOFLazy ctxt ir != getSFLazy ctxt ir) .| (getZFLazy ctxt ir) + | Opcode.CMOVG -> + (getOFLazy ctxt ir == getSFLazy ctxt ir) .& (getZFLazy ctxt ir |> AST.not) + | _ -> raise InvalidOpcodeException +#endif + let cmovcc ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (4) + let ir = !*ctxt !ir insLen let cmp ins insLen ctxt = - let oprSize = getOperationSize ins - let struct (src1, src2) = transTwoOprs ins insLen ctxt - let ir = IRBuilder (16) - let struct (t1, t2, t3) = tmpVars3 ir oprSize + let ir = !*ctxt ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBQ + | _ -> raise InvalidRegTypeException +#else + let isRhsConst = isConst src2 + let t1 = !+ir oprSize + let t2 = if isRhsConst then AST.sext oprSize src2 else !+ir oprSize + let t3 = !+ir oprSize !!ir (t1 := src1) - !!ir (t2 := AST.sext oprSize src2) + if isRhsConst then () else !!ir (t2 := AST.sext oprSize src2) !!ir (t3 := t1 .- t2) - !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnSub t1 t2) (ofOnSub t1 t2 t3)) + let sf = AST.xthi 1 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnSub t1 t2) (ofOnSub t1 t2 t3) sf) +#endif !>ir insLen let private cmpsBody ins ctxt ir = @@ -645,17 +909,21 @@ let private cmpsBody ins ctxt ir = let src2 = AST.loadLE oprSize di let struct (t1, t2, t3) = tmpVars3 ir oprSize let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + let sf = AST.xthi 1 t3 !!ir (t1 := src1) !!ir (t2 := src2) !!ir (t3 := t1 .- t2) !!ir (si := AST.ite df (si .- amount) (si .+ amount)) !!ir (di := AST.ite df (di .- amount) (di .+ amount)) - !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnSub t1 t2) (ofOnSub t1 t2 t3)) + !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnSub t1 t2) (ofOnSub t1 t2 t3) sf) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif let cmps (ins: InsInfo) insLen ctxt = let pref = ins.Prefixes let zf = !.ctxt R.ZF - let ir = IRBuilder (32) + let ir = !*ctxt !ir insLen let cmpxchg ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (32) + let ir = !*ctxt ! - let lblEq = ir.NewSymbol "Equal" - let lblNeq = ir.NewSymbol "NotEqual" - let lblEnd = ir.NewSymbol "End" + let tAcc = !+ir oprSize + let cond = !+ir 1 + let lblEq = !%ir "Equal" + let lblNeq = !%ir "NotEqual" + let lblEnd = !%ir "End" !!ir (t := dst) - !!ir (r := acc .- t) - !!ir (cond := acc == t) + !!ir (tAcc := acc) + !!ir (r := tAcc .- t) + !!ir (cond := tAcc == t) !!ir (AST.cjmp cond (AST.name lblEq) (AST.name lblNeq)) !!ir (AST.lmark lblEq) !!ir (!.ctxt R.ZF := AST.b1) @@ -689,43 +959,46 @@ let cmpxchg ins insLen ctxt = !!ir (!.ctxt R.ZF := AST.b0) !!ir (dstAssign oprSize acc t) !!ir (AST.lmark lblEnd) - !!ir (!.ctxt R.OF := ofOnSub acc t r) + !!ir (!.ctxt R.OF := ofOnSub tAcc t r) !!ir (!.ctxt R.SF := AST.xthi 1 r) - !!ir (buildAF ctxt acc t r oprSize) + !!ir (buildAF ctxt tAcc t r oprSize) !?ir (buildPF ctxt r oprSize None) - !!ir (!.ctxt R.CF := AST.lt (acc .+ t) acc) + !!ir (!.ctxt R.CF := cfOnSub tAcc t) if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let compareExchangeBytes ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let oprSize = getOperationSize ins let zf = !.ctxt R.ZF - let cond = !*ir 1 + let cond = !+ir 1 ! -> - let dst = transOneOpr ins insLen ctxt - let edx = getRegOfSize ctxt 32 grpEDX - let eax = getRegOfSize ctxt 32 grpEAX - let ecx = getRegOfSize ctxt 32 grpECX - let ebx = getRegOfSize ctxt 32 grpEBX - let t = !*ir oprSize + let dst = transOneOpr ir ins insLen ctxt + let eax = !.ctxt R.EAX + let ecx = !.ctxt R.ECX + let edx = !.ctxt R.EDX + let ebx = !.ctxt R.EBX + let t = !+ir oprSize !!ir (t := dst) !!ir (cond := AST.concat edx eax == t) !!ir (zf := cond) - !!ir (eax := AST.ite cond eax (AST.extract t 32 0)) - !!ir (edx := AST.ite cond edx (AST.extract t 32 32)) + !!ir (dstAssign 32 eax (AST.ite cond eax (AST.xtlo 32 t))) + !!ir (dstAssign 32 edx (AST.ite cond edx (AST.xthi 32 t))) !!ir (dst := AST.ite cond (AST.concat ecx ebx) t) | 128 -> let dstB, dstA = match ins.Operands with - | OneOperand opr -> transOprToExpr128 ins insLen ctxt opr + | OneOperand opr -> transOprToExpr128 ir false ins insLen ctxt opr | _ -> raise InvalidOperandException - let rdx = getRegOfSize ctxt 64 grpEDX - let rax = getRegOfSize ctxt 64 grpEAX - let rcx = getRegOfSize ctxt 64 grpECX - let rbx = getRegOfSize ctxt 64 grpEBX + let rax = !.ctxt R.RAX + let rcx = !.ctxt R.RCX + let rdx = !.ctxt R.RDX + let rbx = !.ctxt R.RBX !!ir (cond := (dstB == rdx) .& (dstA == rax)) !!ir (zf := cond) !!ir (rax := AST.ite cond rax dstA) @@ -736,23 +1009,23 @@ let compareExchangeBytes ins insLen ctxt = !>ir insLen let convWDQ ins insLen (ctxt: TranslationContext) = - let ir = IRBuilder (8) + let ir = !*ctxt let oprSize = getOperationSize ins !, _ -> - let t = !*ir 32 + let t = !+ir 32 let ax = !.ctxt R.AX let dx = !.ctxt R.DX !!ir (t := AST.sext 32 ax) !!ir (dx := AST.xthi 16 t) !!ir (ax := AST.xtlo 16 t) | 32, _ -> - let t = !*ir 64 + let t = !+ir 64 let eax = !.ctxt R.EAX let edx = !.ctxt R.EDX !!ir (t := AST.sext 64 eax) - !!ir (edx := AST.xthi 32 t) + !!ir (dstAssign oprSize edx (AST.xthi 32 t)) !!ir (eax := AST.xtlo 32 t) | 64, 64 -> let rdx = !.ctxt R.RDX @@ -766,33 +1039,43 @@ let daa insLen ctxt = #if DEBUG assert32 ctxt #endif - let ir = IRBuilder (16) + let ir = !*ctxt let al = !.ctxt R.AL let cf = !.ctxt R.CF let af = !.ctxt R.AF - let oldAl = !*ir 8 - let oldCf = !*ir 1 + let oldAl = !+ir 8 + let oldCf = !+ir 1 let alAnd0f = al .& numI32 0x0f 8 let subCond1 = AST.gt alAnd0f (numI32 9 8) - let subCond2 = af == AST.b1 - let cond1 = !*ir 1 + let cond1 = !+ir 1 let subCond3 = AST.gt oldAl (numI32 0x99 8) let subCond4 = oldCf == AST.b1 - let cond2 = !*ir 1 + let cond2 = !+ir 1 + let sf = AST.xthi 1 al !) al) !!ir (cf := AST.ite cond1 oldCf cf) !!ir (af := cond1) !!ir (cond2 := subCond3 .| subCond4) !!ir (al := AST.ite cond2 (al .+ numI32 0x60 8) al) !!ir (cf := cond2) - !?ir (enumSZPFlags ctxt al 8) + !?ir (enumSZPFlags ctxt al 8 sf) #if !EMULATION !!ir (!.ctxt R.OF := undefOF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen @@ -800,64 +1083,139 @@ let das insLen ctxt = #if DEBUG assert32 ctxt #endif - let ir = IRBuilder (16) + let ir = !*ctxt let al = !.ctxt R.AL let cf = !.ctxt R.CF let af = !.ctxt R.AF - let oldAl = !*ir 8 - let oldCf = !*ir 1 + let oldAl = !+ir 8 + let oldCf = !+ir 1 let alAnd0f = al .& numI32 0x0f 8 let subCond1 = AST.gt alAnd0f (numI32 9 8) let subCond2 = af == AST.b1 - let cond1 = !*ir 1 + let cond1 = !+ir 1 let subCond3 = AST.gt oldAl (numI32 0x99 8) let subCond4 = oldCf == AST.b1 - let cond2 = !*ir 1 + let cond2 = !+ir 1 + let sf = AST.xthi 1 al !) al) !!ir (cf := AST.ite cond1 oldCf cf) !!ir (af := cond1) !!ir (cond2 := subCond3 .| subCond4) !!ir (al := AST.ite cond2 (al .- numI32 0x60 8) al) !!ir (cf := cond2) - !?ir (enumSZPFlags ctxt al 8) + !?ir (enumSZPFlags ctxt al 8 sf) #if !EMULATION !!ir (!.ctxt R.OF := undefOF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen let dec ins insLen ctxt = - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! t3 if hasLock ins.Prefixes then !!ir (AST.sideEffect Lock) else () !!ir (t1 := dst) !!ir (t2 := AST.num1 oprSize) !!ir (t3 := (t1 .- t2)) !!ir (dstAssign oprSize dst t3) !!ir (!.ctxt R.OF := ofOnSub t1 t2 t3) - !?ir (enumASZPFlags ctxt t1 t2 t3 oprSize) + !?ir (enumASZPFlags ctxt t1 t2 t3 oprSize sf) if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () +#if EMULATION + !!ir (!.ctxt R.CF := getCFLazy ctxt ir) + !?ir (setCCOperands2 ctxt t2 t3) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.DECB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.DECW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.DECD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.DECQ + | _ -> raise InvalidRegTypeException +#endif !>ir insLen +let private mul64Bit src1 src2 ir = + let struct (hiSrc1, loSrc1, hiSrc2, loSrc2) = tmpVars4 ir 64 + let struct (tSrc1, tSrc2) = tmpVars2 ir 64 + let struct (tHigh, tLow) = tmpVars2 ir 64 + let struct (pMid, pLow) = tmpVars2 ir 64 + let struct (hi1Lo2, lo1Hi2) = tmpVars2 ir 64 + let n32 = numI32 32 64 + let mask = numI64 0xFFFFFFFFL 64 + !!ir (tSrc1 := src1) + !!ir (tSrc2 := src2) + !!ir (hiSrc1 := (tSrc1 >> n32) .& mask) (* SRC1[63:32] *) + !!ir (loSrc1 := tSrc1 .& mask) (* SRC1[31:0] *) + !!ir (hiSrc2 := (tSrc2 >> n32) .& mask) (* SRC2[63:32] *) + !!ir (loSrc2 := tSrc2 .& mask) (* SRC2[31:0] *) + let pHigh = hiSrc1 .* hiSrc2 + !!ir (hi1Lo2 := hiSrc1 .* loSrc2) + !!ir (lo1Hi2 := loSrc1 .* hiSrc2) + !!ir (pMid := hi1Lo2 .+ lo1Hi2) + !!ir (pLow := loSrc1 .* loSrc2) + let high = pHigh .+ ((pMid .+ (pLow >> n32)) >> n32) + let low = pLow .+ ((pMid .& mask) << n32) + let isOverflow = hi1Lo2 .> numI64 0xffffffff_ffffffffL 64 .- lo1Hi2 + !!ir (tHigh := + high .+ AST.ite isOverflow (numI64 0x100000000L 64) (AST.num0 64)) + !!ir (tLow := low) + struct (tHigh, tLow) + +let private helperRemSub remHi remLo srcHi srcLo ir = + let t = !+ir 1 + !!ir (t := remLo .< srcLo) + !!ir (remLo := remLo .- srcLo) + !!ir (remHi := remHi .- srcHi) + !!ir (remHi := remHi .- AST.ite t (AST.num1 64) (AST.num0 64)) + +let helperRemAdd remHi remLo srcHi srcLo remMsb ir = + let r = !+ir 64 + let t = !+ir 1 + let cond = r .< remLo + !!ir (r := remLo .+ srcLo) + !!ir (t := cond) + !!ir (remLo := AST.ite remMsb r remLo) + let toAdd = AST.ite t (AST.num1 64) (AST.num0 64) + !!ir (remHi := AST.ite remMsb (remHi .+ srcHi .+ toAdd) remHi) + let divideWithoutConcat opcode oprSize divisor lblAssign lblErr ctxt ir = - let rdx, rax = !.ctxt R.RDX, !.ctxt R.RAX let struct (trdx, trax, tdivisor) = tmpVars3 ir oprSize - let updateSign = !*ir 1 - let lblComputable = (ir: IRBuilder).NewSymbol "Computable" - let lblEasy = (ir: IRBuilder).NewSymbol "Easy" - let lblHard = (ir: IRBuilder).NewSymbol "Hard" + let rdx, rax = !.ctxt R.RDX, !.ctxt R.RAX + let struct (lz, y, t, nrmDvsr) = tmpVars4 ir oprSize + let struct (remHi, remLo) = tmpVars2 ir oprSize + let struct (qh, ql, q) = tmpVars3 ir oprSize + let remMsb = !+ir 1 + let n32 = numI32 32 64 + let zero = AST.num0 64 + let one = AST.num1 64 + let numF = numI64 0xffffffff oprSize + let struct (nrmDvsrShl32, nrmDvsrShr32) = tmpVars2 ir oprSize + let condGE = (remHi >> n32) .>= nrmDvsrShr32 + let updateSign = !+ir 1 + let lblComputable = !%ir "Computable" + let lblEasy = !%ir "Easy" + let lblHard = !%ir "Hard" let isEasy = trdx == AST.num0 oprSize - let errChk = AST.gt tdivisor trdx - let quotient = !*ir oprSize - let remainder = !*ir oprSize - let bignum = numI64 0x8000000000000000L oprSize + let errChk = AST.gt divisor trdx + let quotient = !+ir oprSize + let remainder = !+ir oprSize match opcode with | Opcode.DIV -> !!ir (trdx := rdx) @@ -869,6 +1227,8 @@ let divideWithoutConcat opcode oprSize divisor lblAssign lblErr ctxt ir = !!ir (divisorIsNeg := (AST.xthi 1 divisor == AST.b1)) !!ir (trdx := AST.ite dividendIsNeg (AST.not rdx) rdx) !!ir (trax := AST.ite dividendIsNeg (AST.not rax .+ numI32 1 oprSize) rax) + let carry = AST.ite (AST.``and`` dividendIsNeg (AST.eq trax zero)) one zero + !!ir (trdx := trdx .+ carry) !!ir (tdivisor := AST.ite divisorIsNeg (AST.neg divisor) divisor) !!ir (updateSign := dividendIsNeg <+> divisorIsNeg) | _ -> raise InvalidOpcodeException @@ -880,16 +1240,79 @@ let divideWithoutConcat opcode oprSize divisor lblAssign lblErr ctxt ir = !!ir (remainder := trax .% tdivisor) !!ir (AST.jmp (AST.name lblAssign)) !!ir (AST.lmark lblHard) - !!ir (quotient := (bignum ./ (tdivisor ./ trdx)) .+ (trax ./ tdivisor)) - !!ir (remainder := trax .- (quotient .* tdivisor)) + (* normalize divisor; adjust dividend + accordingly (initial partial remainder) *) + let z = !+ir 1 + !!ir (lz := (numI64 64L oprSize)) + !!ir (t := tdivisor) + !!ir (y := (t >> (numI64 32 oprSize))) + !!ir (z := y != zero) + !!ir (lz := (AST.ite z (lz .- numI64 32 oprSize) lz)) + !!ir (t := (AST.ite z y t)) + !!ir (y := (t >> (numI64 16 oprSize))) + !!ir (z := y != zero) + !!ir (lz := (AST.ite z (lz .- numI64 16 oprSize) lz)) + !!ir (t := (AST.ite z y t)) + !!ir (y := (t >> (numI64 8 oprSize))) + !!ir (z := y != zero) + !!ir (lz := (AST.ite z (lz .- numI64 8 oprSize) lz)) + !!ir (t := (AST.ite z y t)) + !!ir (y := (t >> (numI64 4 oprSize))) + !!ir (z := y != zero) + !!ir (lz := (AST.ite z (lz .- numI64 4 oprSize) lz)) + !!ir (t := (AST.ite z y t)) + !!ir (y := (t >> (numI64 2 oprSize))) + !!ir (z := y != zero) + !!ir (lz := (AST.ite z (lz .- numI64 2 oprSize) lz)) + !!ir (t := (AST.ite z y t)) + !!ir (y := (t >> (numI64 1 oprSize))) + !!ir (z := y != zero) + !!ir (lz := (AST.ite z (lz .- numI64 2 oprSize) (lz .- t))) + !!ir (nrmDvsr := tdivisor << lz) + !!ir (nrmDvsrShl32 := nrmDvsr << n32) + !!ir (nrmDvsrShr32 := nrmDvsr >> n32) + !!ir (t := AST.ite (lz != zero) (trax >> ((numI64 64 oprSize) .- lz)) zero) + !!ir (remHi := (trdx << lz) .| t) + !!ir (remLo := trax << lz) + !!ir (qh := AST.ite condGE numF (remHi ./ nrmDvsrShr32)) + (* compute remainder; correct quotient "digit" if remainder negative *) + let struct (prodHi, prodLo) = mul64Bit (qh << n32) nrmDvsr ir + helperRemSub remHi remLo prodHi prodLo ir + !!ir (remMsb := (AST.xthi 1 remHi)) + !!ir (qh := (AST.ite remMsb (qh .- one) (qh))) + helperRemAdd remHi remLo nrmDvsrShr32 (nrmDvsrShl32) remMsb ir + !!ir (remMsb := (AST.xthi 1 remHi)) + !!ir (qh := (AST.ite remMsb (qh .- one) (qh))) + helperRemAdd remHi remLo nrmDvsrShr32 (nrmDvsrShl32) remMsb ir + !!ir (remHi := (remHi << n32) .| (remLo >> n32)) + !!ir (remLo := (remLo << n32)) + (* compute least significant quotient "digit"; + TAOCP: may be off by 0, +1, +2 *) + !!ir (ql := AST.ite condGE numF (remHi ./ nrmDvsrShr32)) + !!ir (q := (qh << n32) .+ ql) + (* compute remainder; correct quotient "digit" if remainder negative *) + let struct (prodHi, prodLo) = mul64Bit q tdivisor ir + !!ir (remLo := trax) + !!ir (remHi := trdx) + helperRemSub remHi remLo prodHi prodLo ir + !!ir (remMsb := (AST.xthi 1 remHi)) + !!ir (q := (AST.ite remMsb (q .- one) q)) + helperRemAdd remHi remLo zero tdivisor remMsb ir + !!ir (remMsb := (AST.xthi 1 remHi)) + !!ir (q := (AST.ite remMsb (q .- one) q)) + let struct (prodHi, prodLo) = mul64Bit q tdivisor ir + helperRemSub trdx trax prodHi prodLo ir + !!ir (quotient := q) + !!ir (remainder := trax) !!ir (AST.lmark lblAssign) match opcode with | Opcode.DIV -> !!ir (dstAssign oprSize rax quotient) !!ir (dstAssign oprSize rdx remainder) | Opcode.IDIV -> + let isDividendNeg = AST.xthi 1 rdx == AST.b1 !!ir (rax := (AST.ite updateSign (AST.neg quotient) quotient)) - !!ir (rdx := (AST.ite updateSign (AST.neg remainder) remainder)) + !!ir (rdx := (AST.ite isDividendNeg (AST.neg remainder) remainder)) | _ -> raise InvalidOpcodeException let private getDividend ctxt = function @@ -906,16 +1329,16 @@ let private checkQuotientIDIV oprSize sz lblAssign lblErr q = let amount = numI32 (RegType.toBitWidth oprSize - 1) oprSize let mask = AST.num1 oprSize << amount let msb = AST.xthi 1 q - let negRes = AST.lt q (AST.zext sz mask) - let posRes = AST.gt q (AST.zext sz (mask .- (AST.num1 oprSize))) + let negRes = q .< (AST.zext sz mask) + let posRes = q .> (AST.zext sz (mask .- (AST.num1 oprSize))) let cond = AST.ite (msb == AST.b1) negRes posRes AST.cjmp cond (AST.name lblErr) (AST.name lblAssign) let divideWithConcat opcode oprSize divisor lblAssign lblErr ctxt ir = let dividend = getDividend ctxt oprSize let sz = TypeCheck.typeOf dividend - let quotient = !*ir sz - let remainder = !*ir sz + let quotient = !+ir sz + let remainder = !+ir sz match opcode with | Opcode.DIV -> let divisor = AST.zext sz divisor @@ -941,13 +1364,13 @@ let divideWithConcat opcode oprSize divisor lblAssign lblErr ctxt ir = | _ -> raise InvalidOperandSizeException let div ins insLen ctxt = - let ir = IRBuilder (16) - let lblAssign = ir.NewSymbol "Assign" - let lblChk = ir.NewSymbol "Check" - let lblErr = ir.NewSymbol "DivErr" - let divisor = transOneOpr ins insLen ctxt - let oprSize = getOperationSize ins + let ir = !*ctxt !ir insLen let enter ins insLen ctxt = let oSz = getOperationSize ins - let ir = IRBuilder (16) - let struct (imm16, imm8) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! then numI32 8 bitSize else numI32 4 bitSize - !ir insLen @@ -1010,7 +1438,12 @@ let private imul64Bit src1 src2 ir = let struct (hiSrc1, loSrc1, hiSrc2, loSrc2) = tmpVars4 ir 64 let struct (tSrc1, tSrc2) = tmpVars2 ir 64 let struct (tHigh, tLow) = tmpVars2 ir 64 + let struct (pHigh, pMid, pLow) = tmpVars3 ir 64 + let struct (pMid1, pMid2) = tmpVars2 ir 64 + let struct (high, low) = tmpVars2 ir 64 let n32 = numI32 32 64 + let zero = numI32 0 64 + let one = numI32 1 64 let mask = numI64 0xFFFFFFFFL 64 let struct (src1IsNeg, src2IsNeg, isSign) = tmpVars3 ir 1 !!ir (src1IsNeg := AST.xthi 1 src1) @@ -1021,39 +1454,42 @@ let private imul64Bit src1 src2 ir = !!ir (loSrc1 := tSrc1 .& mask) (* SRC1[31:0] *) !!ir (hiSrc2 := (tSrc2 >> n32) .& mask) (* SRC2[63:32] *) !!ir (loSrc2 := tSrc2 .& mask) (* SRC2[31:0] *) - let pHigh = hiSrc1 .* hiSrc1 - let pMid = (hiSrc1 .* loSrc2) .+ (loSrc1 .* hiSrc2) - let pLow = (loSrc1 .* loSrc2) - let high = pHigh .+ ((pMid .+ (pLow >> n32)) >> n32) - let low = pLow .+ ((pMid .& mask) << n32) - !!ir (isSign := src1IsNeg <+> src2IsNeg) + !!ir (pHigh := hiSrc1 .* hiSrc2) + !!ir (pMid1 := hiSrc1 .* loSrc2) + !!ir (pMid2 := loSrc1 .* hiSrc2) + !!ir (pMid := pMid1 .+ pMid2) + !!ir (pLow := loSrc1 .* loSrc2) + let isOverflow = + pMid1 .> numI64 0xffffffff_ffffffffL 64 .- pMid2 + let c = AST.ite isOverflow (numI64 0x100000000L 64) (AST.num0 64) + !!ir (high := pHigh .+ ((pMid .+ (pLow >> n32)) >> n32) .+ c) + !!ir (low := pLow .+ ((pMid .& mask) << n32)) + !!ir (isSign := src1IsNeg <+> src2IsNeg) // T11 !!ir (tHigh := AST.ite isSign (AST.not high) high) !!ir (tLow := AST.ite isSign (AST.neg low) low) + let carry = AST.ite (AST.``and`` isSign (AST.eq tLow zero)) one zero + !!ir (tHigh := tHigh .+ carry) struct (tHigh, tLow) let private oneOperandImul ctxt oprSize src ir = - let sF = !.ctxt R.SF - let shiftNum = RegType.toBitWidth oprSize match oprSize with | 8 -> - let mulSize = RegType.double oprSize - let t = !*ir mulSize + let mulSize = oprSize * 2 + let t = !+ir mulSize let cond = AST.sext mulSize (AST.xtlo oprSize t) == t !!ir (t := AST.sext mulSize (!.ctxt R.AL) .* AST.sext mulSize src) !!ir (dstAssign oprSize (!.ctxt R.AX) t) - !!ir (sF := AST.extract t 1 (shiftNum - 1)) !!ir (!.ctxt R.CF := cond == AST.b0) !!ir (!.ctxt R.OF := cond == AST.b0) | 16 | 32 -> - let mulSize = RegType.double oprSize - let t = !*ir mulSize + let mulSize = oprSize * 2 + let t = !+ir mulSize let cond = AST.sext mulSize (AST.xtlo oprSize t) == t let r1 = getRegOfSize ctxt oprSize grpEDX let r2 = getRegOfSize ctxt oprSize grpEAX !!ir (t := AST.sext mulSize r2 .* AST.sext mulSize src) !!ir (dstAssign oprSize r1 (AST.xthi oprSize t)) !!ir (dstAssign oprSize r2 (AST.xtlo oprSize t)) - !!ir (sF := AST.extract t 1 (shiftNum - 1)) !!ir (!.ctxt R.CF := cond == AST.b0) !!ir (!.ctxt R.OF := cond == AST.b0) | 64 -> @@ -1064,9 +1500,8 @@ let private oneOperandImul ctxt oprSize src ir = !!ir (dstAssign oprSize r2 low) let num0 = AST.num0 64 let numF = numI64 0xFFFFFFFFFFFFFFFFL 64 - let cond = !*ir 1 + let cond = !+ir 1 !!ir (cond := AST.ite (AST.xthi 1 low) (high == numF) (high == num0)) - !!ir (sF := AST.extract high 1 (shiftNum - 1)) !!ir (!.ctxt R.CF := cond == AST.b0) !!ir (!.ctxt R.OF := cond == AST.b0) | _ -> raise InvalidOperandSizeException @@ -1074,12 +1509,11 @@ let private oneOperandImul ctxt oprSize src ir = let private operandsImul ctxt oprSize dst src1 src2 ir = match oprSize with | 8 | 16 | 32 -> - let doubleWidth = RegType.double oprSize - let t = !*ir doubleWidth + let doubleWidth = oprSize * 2 + let t = !+ir doubleWidth let cond = (AST.sext doubleWidth dst) != t !!ir (t := AST.sext doubleWidth src1 .* AST.sext doubleWidth src2) !!ir (dstAssign oprSize dst (AST.xtlo oprSize t)) - !!ir (!.ctxt R.SF := AST.xthi 1 dst) !!ir (!.ctxt R.CF := cond) !!ir (!.ctxt R.OF := cond) | 64 -> @@ -1087,9 +1521,8 @@ let private operandsImul ctxt oprSize dst src1 src2 ir = !!ir (dstAssign oprSize dst low) let num0 = AST.num0 64 let numF = numI64 0xFFFFFFFFFFFFFFFFL 64 - let cond = !*ir 1 + let cond = !+ir 1 !!ir (cond := AST.ite (AST.xthi 1 low) (high != numF) (high != num0)) - !!ir (!.ctxt R.SF := AST.xthi 1 dst) !!ir (!.ctxt R.CF := cond) !!ir (!.ctxt R.OF := cond) | _ -> raise InvalidOperandSizeException @@ -1098,44 +1531,58 @@ let private buildMulBody ins insLen ctxt ir = let oprSize = getOperationSize ins match ins.Operands with | OneOperand op -> - let src = transOprToExpr ins insLen ctxt op + let src = transOprToExpr ir false ins insLen ctxt op oneOperandImul ctxt oprSize src ir | TwoOperands (o1, o2) -> - let dst = transOprToExpr ins insLen ctxt o1 - let src = transOprToExpr ins insLen ctxt o2 + let dst = transOprToExpr ir false ins insLen ctxt o1 + let src = transOprToExpr ir false ins insLen ctxt o2 operandsImul ctxt oprSize dst dst src ir | ThreeOperands (o1, o2, o3) -> - let dst = transOprToExpr ins insLen ctxt o1 - let src1 = transOprToExpr ins insLen ctxt o2 - let src2 = transOprToExpr ins insLen ctxt o3 + let dst = transOprToExpr ir false ins insLen ctxt o1 + let src1 = transOprToExpr ir false ins insLen ctxt o2 + let src2 = transOprToExpr ir false ins insLen ctxt o3 operandsImul ctxt oprSize dst src1 src2 ir | _ -> raise InvalidOperandException let imul ins insLen ctxt = - let ir = IRBuilder (24) + let ir = !*ctxt !ir insLen let inc ins insLen ctxt = - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.INCB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.INCW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.INCD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.INCQ + | _ -> raise InvalidRegTypeException +#endif !>ir insLen let private insBody ins ctxt ir = @@ -1148,7 +1595,7 @@ let private insBody ins ctxt ir = !!ir (di := AST.ite df (di .- amount) (di .+ amount)) let insinstr (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt !ir insLen let interrupt ins insLen ctxt = - match transOneOpr ins insLen ctxt with - | { E = Num n } -> Interrupt (BitVector.toInt32 n) |> sideEffects insLen + let ir = !*ctxt + match transOneOpr ir ins insLen ctxt with + | { E = Num n } -> Interrupt (BitVector.ToInt32 n) |> sideEffects ctxt insLen | _ -> raise InvalidOperandException let private getCondOfJcc (ins: IntelInternalInstruction) @@ -1194,35 +1642,148 @@ let private getCondOfJcc (ins: IntelInternalInstruction) | Opcode.JRCXZ -> (!.ctxt R.RCX) == (AST.num0 ctxt.WordBitSize) | _ -> raise InvalidOpcodeException +#if EMULATION +let private getCondOfJccLazy (ins: IntelInternalInstruction) + (ctxt: TranslationContext) + (ir: IRBuilder) = +#if DEBUG + if ctxt.WordBitSize = 64 && (getOperationSize ins) = 16 then + Utils.impossible () + else () +#endif + match ins.Opcode with + | Opcode.JO -> getOFLazy ctxt ir + | Opcode.JNO -> getOFLazy ctxt ir |> AST.not + | Opcode.JB -> getCFLazy ctxt ir + | Opcode.JNB -> getCFLazy ctxt ir |> AST.not + | Opcode.JZ -> getZFLazy ctxt ir + | Opcode.JNZ -> getZFLazy ctxt ir |> AST.not + | Opcode.JBE -> + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src2 = getCCSrc1 ctxt regType + let src1 = getCCDst ctxt regType .+ src2 + src1 .<= src2 + | _ -> (getCFLazy ctxt ir) .| (getZFLazy ctxt ir) + | Opcode.JA -> (getCFLazy ctxt ir .| getZFLazy ctxt ir) |> AST.not + | Opcode.JS -> getSFLazy ctxt ir + | Opcode.JNS -> getSFLazy ctxt ir |> AST.not + | Opcode.JP -> getPFLazy ctxt ir + | Opcode.JNP -> getPFLazy ctxt ir |> AST.not + | Opcode.JL -> + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src2 = getCCSrc1 ctxt regType + let src1 = getCCDst ctxt regType .+ src2 + src1 ?< src2 + | _ -> getOFLazy ctxt ir != getSFLazy ctxt ir + | Opcode.JNL -> getOFLazy ctxt ir == getSFLazy ctxt ir + | Opcode.JLE -> + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src2 = getCCSrc1 ctxt regType + let src1 = getCCDst ctxt regType .+ src2 + src1 ?<= src2 + | _ -> (getOFLazy ctxt ir != getSFLazy ctxt ir) .| (getZFLazy ctxt ir) + | Opcode.JG -> + (getOFLazy ctxt ir == getSFLazy ctxt ir) .& (getZFLazy ctxt ir |> AST.not) + | Opcode.JCXZ -> !.ctxt R.CX == AST.num0 ctxt.WordBitSize + | Opcode.JECXZ -> + let sz = ctxt.WordBitSize + (AST.cast CastKind.ZeroExt sz (!.ctxt R.ECX)) == (AST.num0 sz) + | Opcode.JRCXZ -> (!.ctxt R.RCX) == (AST.num0 ctxt.WordBitSize) + | _ -> raise InvalidOpcodeException +#endif + let jcc ins insLen ctxt = - let pc = getInstrPtr ctxt - let jmpTarget = pc .+ transOneOpr ins insLen ctxt + let ir = !*ctxt + !ir insLen let jmp ins insLen ctxt = - let pc = getInstrPtr ctxt - let struct (target, _) = transJumpTargetOpr ins pc insLen ctxt - let ir = IRBuilder (4) + let ir = !*ctxt !ir insLen let private convertSrc = function - | Load (_, _, expr, _) -> expr + | Load (_, _, expr) -> expr | _ -> Utils.impossible () +let lahf _ insLen ctxt = + let ir = !*ctxt + let t = !+ir 8 + ! (!.ctxt R.CF) + let pf = AST.zext 8 (!.ctxt R.PF) + let af = AST.zext 8 (!.ctxt R.AF) + let zf = AST.zext 8 (!.ctxt R.ZF) + let sf = AST.zext 8 (!.ctxt R.SF) +#endif + let cf = AST.zext 8 (!.ctxt R.CF) + let pf = AST.zext 8 (!.ctxt R.PF) + let af = AST.zext 8 (!.ctxt R.AF) + let zf = AST.zext 8 (!.ctxt R.ZF) + let sf = AST.zext 8 (!.ctxt R.SF) + !!ir (t := numI32 2 8) + !!ir (t := t .| cf) + !!ir (t := t .| (pf << numI32 2 8)) + !!ir (t := t .| (af << numI32 4 8)) + !!ir (t := t .| (zf << numI32 6 8)) + !!ir (t := t .| (sf << numI32 7 8)) + !!ir (ah := t) + !>ir insLen + let lea ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + !, 16 | 32, 32 | 64, 64 -> @@ -1231,13 +1792,14 @@ let lea ins insLen ctxt = dstAssign oprSize dst (AST.xtlo 16 src) | 32, 16 -> dstAssign oprSize dst (AST.zext 32 src) | 32, 64 -> dstAssign oprSize dst (AST.xtlo 32 src) + | 64, 32 -> dstAssign oprSize dst (AST.zext 64 src) | _ -> raise InvalidOperandSizeException) !>ir insLen let leave _ins insLen ctxt = let sp = getStackPtr ctxt let bp = getBasePtr ctxt - let ir = IRBuilder (8) + let ir = !*ctxt !ir insLen let loop ins insLen ctxt = - let ir = IRBuilder (8) - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! then !.ctxt R.ECX, 32 elif addrSize = 64 then !.ctxt R.RCX, 64 else !.ctxt R.CX, 16 +#if EMULATION + let zf = getZFLazy ctxt ir +#else let zf = !.ctxt R.ZF - ! raise InvalidOpcodeException let fallThrough = pc .+ numInsLen insLen ctxt let jumpTarget = if addrSize = 16 then pc .& numI32 0xFFFF 32 - else pc .+ AST.sext addrSize dst + else pc .+ AST.sext ctxt.WordBitSize dst !!ir (AST.intercjmp branchCond jumpTarget fallThrough) !>ir insLen let lzcnt ins insLen ctxt = - let ir = IRBuilder (16) - let lblLoop = ir.NewSymbol "Loop" - let lblExit = ir.NewSymbol "Exit" - let lblLoopCond = ir.NewSymbol "LoopCond" - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt let oprSize = getOperationSize ins - let n = AST.num0 oprSize + let struct (dst, src) = transTwoOprs ir true ins insLen ctxt ! (src >> temp)) == AST.b0) - !!ir (AST.cjmp cond1 (AST.name lblLoop) (AST.name lblExit)) - !!ir (AST.lmark lblLoop) - !!ir (temp := temp .- AST.num1 oprSize) - !!ir (dst := dst .+ AST.num1 oprSize) - !!ir (AST.jmp (AST.name lblLoopCond)) - !!ir (AST.lmark lblExit) + let x = !+ir oprSize + let n = AST.num0 oprSize + match oprSize with + | 16 -> + let mask1 = numI32 0x5555 16 + let mask2 = numI32 0x3333 16 + let mask3 = numI32 0x0f0f 16 + !!ir (x := src) + !!ir (x := x .| (x >> numI32 1 16)) + !!ir (x := x .| (x >> numI32 2 16)) + !!ir (x := x .| (x >> numI32 4 16)) + !!ir (x := x .| (x >> numI32 8 16)) + !!ir (x := x .- ((x >> numI32 1 16) .& mask1)) + !!ir (x := ((x >> numI32 2 16) .& mask2) .+ (x .& mask2)) + !!ir (x := ((x >> numI32 4 16) .+ x) .& mask3) + !!ir (x := x .+ (x >> numI32 8 16)) + !!ir (dstAssign oprSize dst (numI32 16 16 .- (x .& numI32 31 16))) + | 32 -> + let mask1 = numI32 0x55555555 32 + let mask2 = numI32 0x33333333 32 + let mask3 = numI32 0x0f0f0f0f 32 + !!ir (x := src) + !!ir (x := x .| (x >> numI32 1 32)) + !!ir (x := x .| (x >> numI32 2 32)) + !!ir (x := x .| (x >> numI32 4 32)) + !!ir (x := x .| (x >> numI32 8 32)) + !!ir (x := x .| (x >> numI32 16 32)) + !!ir (x := x .- ((x >> numI32 1 32) .& mask1)) + !!ir (x := ((x >> numI32 2 32) .& mask2) .+ (x .& mask2)) + !!ir (x := ((x >> numI32 4 32) .+ x) .& mask3) + !!ir (x := x .+ (x >> numI32 8 32)) + !!ir (x := x .+ (x >> numI32 16 32)) + !!ir (dstAssign oprSize dst (numI32 32 32 .- (x .& numI32 63 32))) + | 64 -> + let mask1 = numU64 0x5555555555555555UL 64 + let mask2 = numU64 0x3333333333333333UL 64 + let mask3 = numU64 0x0f0f0f0f0f0f0f0fUL 64 + !!ir (x := src) + !!ir (x := x .| (x >> numI32 1 64)) + !!ir (x := x .| (x >> numI32 2 64)) + !!ir (x := x .| (x >> numI32 4 64)) + !!ir (x := x .| (x >> numI32 8 64)) + !!ir (x := x .| (x >> numI32 16 64)) + !!ir (x := x .| (x >> numI32 32 64)) + !!ir (x := x .- ((x >> numI32 1 64) .& mask1)) + !!ir (x := ((x >> numI32 2 64) .& mask2) .+ (x .& mask2)) + !!ir (x := ((x >> numI32 4 64) .+ x) .& mask3) + !!ir (x := x .+ (x >> numI32 8 64)) + !!ir (x := x .+ (x >> numI32 16 64)) + !!ir (x := x .+ (x >> numI32 32 64)) + !!ir (dstAssign oprSize dst (numI32 64 64 .- (x .& numI32 127 64))) + | _ -> raise InvalidOperandSizeException let oprSize = numI32 (RegType.toBitWidth oprSize) oprSize !!ir (!.ctxt R.CF := dst == oprSize) !!ir (!.ctxt R.ZF := dst == n) @@ -1313,25 +1916,27 @@ let lzcnt ins insLen ctxt = !!ir (!.ctxt R.SF := undefSF) !!ir (!.ctxt R.PF := undefPF) !!ir (!.ctxt R.AF := undefAF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen let mov ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins + let ir = !*ctxt !ir insLen let movbe ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! int - let ir = IRBuilder (2 * cnt) - let t = !*ir oprSize - let tmps = Array.init cnt (fun _ -> !*ir 8) - ! !+ir 8) !!ir (t := src) for i in 0 .. cnt - 1 do !!ir (tmps[i] := AST.extract t 8 (i * 8)) @@ -1350,42 +1955,40 @@ let private movsBody ins ctxt ir = !!ir (di := AST.ite df (di .- amount) (di .+ amount)) let movs (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt !ir insLen let movsx ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins + let ir = !*ctxt !ir insLen let movzx ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins + let ir = !*ctxt !ir insLen let mul ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let oprSize = getOperationSize ins ! -> - let dblWidth = RegType.double oprSize + let dblWidth = oprSize * 2 let src1 = AST.zext dblWidth (getRegOfSize ctxt oprSize grpEAX) - let src2 = AST.zext dblWidth (transOneOpr ins insLen ctxt) - let t = !*ir dblWidth + let src2 = AST.zext dblWidth (transOneOpr ir ins insLen ctxt) + let t = !+ir dblWidth !!ir (t := src1 .* src2) - let cond = !*ir 1 + let cond = !+ir 1 !!ir (!.ctxt R.AX := t) !!ir (cond := AST.xthi oprSize t != (AST.num0 oprSize)) !!ir (!.ctxt R.CF := cond) @@ -1395,16 +1998,20 @@ let mul ins insLen ctxt = !!ir (!.ctxt R.ZF := undefZF) !!ir (!.ctxt R.AF := undefAF) !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif | 16 | 32 -> - let dblWidth = RegType.double oprSize - let src1 = AST.zext dblWidth (getRegOfSize ctxt oprSize grpEAX) - let src2 = AST.zext dblWidth (transOneOpr ins insLen ctxt) - let t = !*ir dblWidth + let dblWidth = oprSize * 2 + let edx = getRegOfSize ctxt oprSize grpEDX + let eax = getRegOfSize ctxt oprSize grpEAX + let src1 = AST.zext dblWidth eax + let src2 = AST.zext dblWidth (transOneOpr ir ins insLen ctxt) + let t = !+ir dblWidth !!ir (t := src1 .* src2) - let cond = !*ir 1 - !!ir (getRegOfSize ctxt oprSize grpEDX := AST.xthi oprSize t) - !!ir (getRegOfSize ctxt oprSize grpEAX := AST.xtlo oprSize t) + let cond = !+ir 1 + !!ir (dstAssign oprSize edx (AST.xthi oprSize t)) + !!ir (dstAssign oprSize eax (AST.xtlo oprSize t)) !!ir (cond := AST.xthi oprSize t != (AST.num0 oprSize)) !!ir (!.ctxt R.CF := cond) !!ir (!.ctxt R.OF := cond) @@ -1413,11 +2020,13 @@ let mul ins insLen ctxt = !!ir (!.ctxt R.ZF := undefZF) !!ir (!.ctxt R.AF := undefAF) !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif | 64 -> let rax = getRegOfSize ctxt oprSize grpEAX let rdx = getRegOfSize ctxt oprSize grpEDX - let src = transOneOpr ins insLen ctxt + let src = transOneOpr ir ins insLen ctxt let struct (hiRAX, loRAX, hiSrc, loSrc) = tmpVars4 ir 64 let struct (tHigh, tLow) = tmpVars2 ir 64 let n32 = numI32 32 64 @@ -1431,11 +2040,14 @@ let mul ins insLen ctxt = let pLow = (loRAX .* loSrc) let high = pHigh .+ ((pMid .+ (pLow >> n32)) >> n32) let low = pLow .+ ((pMid .& mask) << n32) - !!ir (tHigh := high) + let isOverflow = + hiRAX .* loSrc .> numI64 0xffffffff_ffffffffL 64 .- loRAX .* hiSrc + !!ir (tHigh := + high .+ AST.ite isOverflow (numI64 0x100000000L 64) (AST.num0 64)) !!ir (tLow := low) !!ir (dstAssign oprSize rdx tHigh) !!ir (dstAssign oprSize rax tLow) - let cond = !*ir 1 + let cond = !+ir 1 !!ir (cond := tHigh != (AST.num0 oprSize)) !!ir (!.ctxt R.CF := cond) !!ir (!.ctxt R.OF := cond) @@ -1444,52 +2056,112 @@ let mul ins insLen ctxt = !!ir (!.ctxt R.ZF := undefZF) !!ir (!.ctxt R.AF := undefAF) !!ir (!.ctxt R.PF := undefPF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif | _ -> raise InvalidOperandSizeException !>ir insLen -let neg ins insLen ctxt = - let ir = IRBuilder (16) - let dst = transOneOpr ins insLen ctxt +let mulx ins insLen ctxt = + let ir = !*ctxt let oprSize = getOperationSize ins - let t = !*ir oprSize - let oFCond = t == (AST.num1 oprSize << (numU32 31u oprSize) ) ! -> + let struct (dst1, dst2, src) = transThreeOprs ir false ins insLen ctxt + let dblWidth = oprSize * 2 + let src1 = AST.zext dblWidth (getRegOfSize ctxt oprSize grpEDX) + let src2 = AST.zext dblWidth src + let t = !+ir dblWidth + !!ir (t := src1 .* src2) + !!ir (dstAssign oprSize dst2 (AST.xtlo 32 t)) + !!ir (dstAssign oprSize dst1 (AST.xthi 32 t)) + | 64 -> + let struct (dst1, dst2, src) = transThreeOprs ir false ins insLen ctxt + let src1 = getRegOfSize ctxt oprSize grpEDX + let struct (hiSrc1, loSrc1, hiSrc, loSrc) = tmpVars4 ir 64 + let struct (tHigh, tLow) = tmpVars2 ir 64 + let n32 = numI32 32 64 + let mask = numI64 0xFFFFFFFFL 64 + !!ir (hiSrc1 := (src1 >> n32) .& mask) (* SRC1[63:32] *) + !!ir (loSrc1 := src1 .& mask) (* SRC1[31:0] *) + !!ir (hiSrc := (src >> n32) .& mask) (* SRC[63:32] *) + !!ir (loSrc := src .& mask) (* SRC[31:0] *) + let pHigh = hiSrc1 .* hiSrc + let pMid = (hiSrc1 .* loSrc) .+ (loSrc1 .* hiSrc) + let pLow = (loSrc1 .* loSrc) + let high = pHigh .+ ((pMid .+ (pLow >> n32)) >> n32) + let low = pLow .+ ((pMid .& mask) << n32) + let isOverflow = + hiSrc1 .* loSrc .> numI64 0xffffffff_ffffffffL 64 .- loSrc1 .* hiSrc + !!ir (tHigh := + high .+ AST.ite isOverflow (numI64 0x100000000L 64) (AST.num0 64)) + !!ir (tLow := low) + !!ir (dstAssign oprSize dst1 tHigh) + !!ir (dstAssign oprSize dst2 tLow) + | _ -> raise InvalidOperandSizeException + !>ir insLen + +let neg ins insLen ctxt = + let ir = !*ctxt + ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBQ + | _ -> raise InvalidRegTypeException +#else + let sf = AST.xthi 1 dst + let cf = cfOnSub zero t + let ofl = ofOnSub zero t dst + !?ir (enumEFLAGS ctxt zero t dst oprSize cf ofl sf) +#endif !>ir insLen -let nop insLen = - let ir = IRBuilder (4) +let nop insLen ctxt = + let ir = !*ctxt !ir insLen let not ins insLen ctxt = - let ir = IRBuilder (4) - let dst = transOneOpr ins insLen ctxt - let oprSize = getOperationSize ins + let ir = !*ctxt !ir insLen let logOr ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let t = !*ir oprSize + let ir = !*ctxt ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICQ + | _ -> raise InvalidRegTypeException +#else + let sf = AST.xthi 1 dst !!ir (!.ctxt R.CF := AST.b0) !!ir (!.ctxt R.OF := AST.b0) -#if !EMULATION + !?ir (enumSZPFlags ctxt dst oprSize sf) !!ir (!.ctxt R.AF := undefAF) #endif - !?ir (enumSZPFlags ctxt t oprSize) if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () !>ir insLen @@ -1512,7 +2184,7 @@ let private outsBody ins ctxt ir = | _ -> raise InvalidOperandSizeException let outs (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt !ir insLen -let pop ins insLen ctxt = - let dst = transOneOpr ins insLen ctxt +let pdep ins insLen ctxt = + let ir = !*ctxt + ! + let k = !+ir oprSize + !!ir (temp := src1) + !!ir (mask := src2) + !!ir (dest := AST.num0 oprSize) + !!ir (k := AST.num0 oprSize) + for i in 0 .. (int oprSize) - 1 do + !!ir (cond := AST.extract mask 1 i) + let tempk = (temp >> k) |> AST.xtlo 1 + !!ir (AST.extract dest 1 i := AST.ite cond tempk AST.b0) + !!ir (k := AST.ite cond (k .+ AST.num1 oprSize) k) + done + !!ir (dstAssign oprSize dst dest) + !>ir insLen + +let pext ins insLen ctxt = + let ir = !*ctxt ! + !!ir (t := AST.num0 oSz) + !!ir (k := AST.num0 oSz) + for i in 0 .. (int oSz) - 1 do + !!ir (cond := AST.extract mask 1 i) + let extSrc = AST.zext oSz (AST.extract src 1 i) + !!ir (t := t .| (AST.ite cond (extSrc << k) t)) + !!ir (k := k .+ (AST.zext oSz cond)) + done + !!ir (dstAssign oSz dst t) + !>ir insLen + +let pop ins insLen ctxt = + let ir = !*ctxt + !ir insLen @@ -1537,7 +2248,7 @@ let popa insLen ctxt oprSize = let dx = if oprSize = 32 then R.EDX else R.DX let cx = if oprSize = 32 then R.ECX else R.CX let ax = if oprSize = 32 then R.EAX else R.AX - let ir = IRBuilder (16) + let ir = !*ctxt !ir insLen let popcnt ins insLen ctxt = - let ir = IRBuilder (16) - let lblLoop = ir.NewSymbol "Loop" - let lblExit = ir.NewSymbol "Exit" - let lblLoopCond = ir.NewSymbol "LoopCond" - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! (src >> i)) == AST.b1 !!ir (count := AST.ite cond (count .+ AST.num1 oprSize) count) @@ -1577,12 +2288,15 @@ let popcnt ins insLen ctxt = !!ir (!.ctxt R.AF := AST.b0) !!ir (!.ctxt R.CF := AST.b0) !!ir (!.ctxt R.PF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let popf ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let oprSize = getOperationSize ins - let t = !*ir oprSize + let t = !+ir oprSize ! 11) @@ -1594,26 +2308,34 @@ let popf ins insLen ctxt = !!ir (!.ctxt R.AF := AST.extract t 1 4) !!ir (!.ctxt R.PF := AST.extract t 1 2) !!ir (!.ctxt R.CF := AST.xtlo 1 t) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let inline private padPushExpr oprSize opr = match opr.E with - | Var (_, s, _, _) -> + | Var (_, s, _) -> if isSegReg <| Register.ofRegID s then AST.zext oprSize opr else opr | Num (_) -> AST.sext oprSize opr | _ -> opr let push ins insLen ctxt = - let src = transOneOpr ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (8) + let ir = !*ctxt !ir insLen let pusha ins insLen ctxt oprSize = - let ir = IRBuilder (16) - let t = !*ir oprSize + let ir = !*ctxt + let t = !+ir oprSize let sp = if oprSize = 32 then R.ESP else R.SP let ax = if oprSize = 32 then R.EAX else R.AX let cx = if oprSize = 32 then R.ECX else R.CX @@ -1635,9 +2357,22 @@ let pusha ins insLen ctxt oprSize = !>ir insLen let pushf ins insLen ctxt = + let ir = !*ctxt let oprSize = getOperationSize ins let e = AST.zext oprSize <| !.ctxt R.CF (* We only consider 9 flags (we ignore system flags). *) + ! -> e .& (numI32 0xfcffff 32) | 64 -> e .& (numI32 0xfcffff 64) | _ -> raise InvalidOperandSizeException - let ir = IRBuilder (8) - !ir insLen let rcl ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, count) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! let count = AST.zext oprSize count + let tmpCnt = !+ir oprSize let cnt = match oprSize with | 8 -> (count .& numI32 0x1f oprSize) .% numI32 9 oprSize @@ -1672,27 +2406,45 @@ let rcl ins insLen ctxt = | 32 -> count .& numI32 0x1f oprSize | 64 -> count .& numI32 0x3f oprSize | _ -> raise InvalidOperandSizeException - let cond = count == AST.num1 oprSize - !> (size .- tmpCount))) - !!ir (cF := AST.xthi 1 dst) + !!ir (tmpCnt := cnt) + let cond1 = tmpCnt != AST.num0 oprSize + let cntMask = numI32 (if oprSize = 64 then 0x3F else 0x1F) oprSize + let cond2 = (count .& cntMask) == AST.num1 oprSize +#if EMULATION + !!ir (cF := getCFLazy ctxt ir) +#endif + let lblRotate = !%ir "Rotate" + let lblZero = !%ir "Zero" + let lblExit = !%ir "Exit" + !!ir (AST.cjmp cond1 (AST.name lblRotate) (AST.name lblZero)) + !!ir (AST.lmark lblRotate) + !!ir (tmpCF := AST.xthi 1 dst) + let r = (dst << AST.num1 oprSize) .+ (AST.zext oprSize cF) + !!ir (dstAssign oprSize dst r) + !!ir (cF := tmpCF) + !!ir (tmpCnt := tmpCnt .- AST.num1 oprSize) + !!ir (AST.cjmp cond1 (AST.name lblRotate) (AST.name lblExit)) + !!ir (AST.lmark lblZero) + !!ir (dstAssign oprSize dst dst) + !!ir (AST.lmark lblExit) #if !EMULATION - !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) undefOF) + !!ir (oF := AST.ite cond2 (AST.xthi 1 dst <+> cF) undefOF) #else - !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) oF) + !!ir (oF := AST.ite cond2 (AST.xthi 1 dst <+> cF) (getOFLazy ctxt ir)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen let rcr ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, count) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! let count = AST.zext oprSize count + let tmpCnt = !+ir oprSize let cnt = match oprSize with | 8 -> (count .& numI32 0x1f oprSize) .% numI32 9 oprSize @@ -1700,22 +2452,40 @@ let rcr ins insLen ctxt = | 32 -> count .& numI32 0x1f oprSize | 64 -> count .& numI32 0x3f oprSize | _ -> raise InvalidOperandSizeException - let cond = count == AST.num1 oprSize - ! then 0x3F else 0x1F) oprSize + let cond2 = (count .& cntMask) == AST.num1 oprSize +#if EMULATION + !!ir (cF := getCFLazy ctxt ir) +#endif + !!ir (tmpOF := AST.xthi 1 dst <+> cF) + let lblRotate = !%ir "Rotate" + let lblZero = !%ir "Zero" + let lblExit = !%ir "Exit" + !!ir (AST.cjmp cond1 (AST.name lblRotate) (AST.name lblZero)) + !!ir (AST.lmark lblRotate) + !!ir (tmpCF := AST.xtlo 1 dst) + let extCF = (AST.zext oprSize cF) << (numI32 (int oprSize - 1) oprSize) + !!ir (dstAssign oprSize dst ((dst >> AST.num1 oprSize) .+ extCF)) + !!ir (cF := tmpCF) + !!ir (tmpCnt := tmpCnt .- AST.num1 oprSize) + !!ir (AST.cjmp cond1 (AST.name lblRotate) (AST.name lblExit)) + !!ir (AST.lmark lblZero) + !!ir (dstAssign oprSize dst dst) + !!ir (AST.lmark lblExit) #if !EMULATION - !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) undefOF) + !!ir (oF := AST.ite cond2 tmpOF undefOF) #else - !!ir (oF := AST.ite cond (AST.xthi 1 dst <+> cF) oF) + !!ir (oF := AST.ite cond2 tmpOF (getOFLazy ctxt ir)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif - !!ir (dst := (dst >> tmpCount) .| (dst << (size .- tmpCount))) - !!ir (cF := AST.xthi 1 dst) !>ir insLen let rdpkru ins insLen ctxt = - let ir = IRBuilder (8) - let lblSucc = ir.NewSymbol "Succ" - let lblErr = ir.NewSymbol "Err" + let ir = !*ctxt + let lblSucc = !%ir "Succ" + let lblErr = !%ir "Err" let oprSize = getOperationSize ins let ecx = !.ctxt R.ECX let eax = getRegOfSize ctxt ctxt.WordBitSize grpEAX @@ -1730,46 +2500,56 @@ let rdpkru ins insLen ctxt = !>ir insLen let retWithImm ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + !ir insLen let ret ins insLen ctxt = - let ir = IRBuilder (6) + let ir = !*ctxt let oprSize = getOperationSize ins - let t = !*ir oprSize + let t = !+ir oprSize !ir insLen let rotate ins insLen ctxt lfn hfn cfFn ofFn = - let ir = IRBuilder (8) - let struct (dst, count) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! dst)) #if !EMULATION !!ir (oF := AST.ite cond2 (ofFn dst cF) undefOF) #else !!ir (oF := AST.ite cond2 (ofFn dst cF) oF) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen @@ -1778,25 +2558,29 @@ let rol ins insLen ctxt = rotate ins insLen ctxt (<<) (>>) AST.xtlo ofFn let ror ins insLen ctxt = + let oprSize = getOperationSize ins let ofFn dst _cF = - AST.xthi 1 dst <+> AST.extract dst 1 1 + AST.xthi 1 dst <+> AST.extract dst 1 ((int oprSize - 1) - 1) rotate ins insLen ctxt (>>) (<<) AST.xthi ofFn let rorx ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src, imm) = transThreeOprs ins insLen ctxt + let ir = !*ctxt + ! then !!ir (y := imm .& (numI32 0x1F oprSize)) - !!ir (dst := (src >> y) .| (src << (numI32 32 oprSize .- y))) + !!ir (dstAssign oprSize dst + ((src >> y) .| (src << (numI32 32 oprSize .- y)))) else (* OperandSize = 64 *) !!ir (y := imm .& (numI32 0x3F oprSize)) - !!ir (dst := (src >> y) .| (src << (numI32 64 oprSize .- y))) + !!ir (dstAssign oprSize dst + ((src >> y) .| (src << (numI32 64 oprSize .- y)))) !>ir insLen let sahf ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let ah = !.ctxt R.AH ! ah) @@ -1804,110 +2588,149 @@ let sahf ins insLen ctxt = !!ir (!.ctxt R.AF := AST.extract ah 1 4) !!ir (!.ctxt R.ZF := AST.extract ah 1 6) !!ir (!.ctxt R.SF := AST.extract ah 1 7) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let shift ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! - let prevLBit = AST.xtlo 1 (tDst ?>> tCnt) - !!ir (dst := dst ?>> cnt) - !!ir (tCnt := cnt .- n1) - !!ir (cF := AST.ite cond2 cF prevLBit) -#if !EMULATION - !!ir (oF := AST.ite cond1 AST.b0 (AST.ite cond2 oF undefOF)) -#else - !!ir (oF := AST.ite cond1 AST.b0 oF) #endif + match ins.Opcode with | Opcode.SHL -> - let prevHBit = AST.xthi 1 (tDst << tCnt) +#if EMULATION + !!ir (tDst := dst << cnt) + !?ir (setCCOperands3 ctxt dst cnt tDst) + !!ir (dstAssign oprSize dst tDst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHLB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHLW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHLD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHLQ + | _ -> raise InvalidRegTypeException +#else + !!ir (dstAssign oprSize dst (tDst << cnt)) + if isCntConst then () else !!ir (tCnt := cnt .- n1) + !!ir (cF := AST.ite cond2 cF (AST.xthi 1 (tDst << tCnt))) let of1 = AST.xthi 1 dst <+> cF - !!ir (dstAssign oprSize dst (dst << cnt)) - !!ir (tCnt := cnt .- n1) - !!ir (cF := AST.ite cond2 cF prevHBit) -#if !EMULATION !!ir (oF := AST.ite cond1 of1 (AST.ite cond2 oF undefOF)) -#else - !!ir (oF := AST.ite cond1 of1 oF) #endif | Opcode.SHR -> - let prevLBit = AST.xtlo 1 (tDst ?>> tCnt) - !!ir (dstAssign oprSize dst (dst >> cnt)) - !!ir (tCnt := cnt .- n1) - !!ir (cF := AST.ite cond2 cF prevLBit) -#if !EMULATION - !!ir - (oF := AST.ite cond1 (AST.xthi 1 tDst) (AST.ite cond2 oF undefOF)) +#if EMULATION + !!ir (tDst := dst >> cnt) + !?ir (setCCOperands3 ctxt dst cnt tDst) + !!ir (dstAssign oprSize dst tDst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHRB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHRW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHRD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SHRQ + | _ -> raise InvalidRegTypeException #else - !!ir (oF := AST.ite cond1 (AST.xthi 1 tDst) oF) + !!ir (dstAssign oprSize dst (tDst >> cnt)) + if isCntConst then () else !!ir (tCnt := cnt .- n1) + !!ir (cF := AST.ite cond2 cF (AST.xtlo 1 (tDst >> tCnt))) + !!ir (oF := AST.ite cond1 (AST.xthi 1 tDst) (AST.ite cond2 oF undefOF)) +#endif + | Opcode.SAR -> +#if EMULATION + !!ir (tDst := dst ?>> cnt) + !?ir (setCCOperands3 ctxt dst cnt tDst) + !!ir (dstAssign oprSize dst tDst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SARB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SARW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SARD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SARQ + | _ -> raise InvalidRegTypeException +#else + !!ir (dstAssign oprSize dst (tDst ?>> cnt)) + if isCntConst then () else !!ir (tCnt := cnt .- n1) + !!ir (cF := AST.ite cond2 cF (AST.xtlo 1 (tDst ?>> tCnt))) + !!ir (oF := AST.ite cond1 AST.b0 (AST.ite cond2 oF undefOF)) #endif | _ -> raise InvalidOpcodeException +#if !EMULATION + let aF = !.ctxt R.AF + !!ir (aF := AST.ite cond2 aF undefAF) !!ir (sF := AST.ite cond2 sF (AST.xthi 1 dst)) !?ir (buildPF ctxt dst oprSize (Some cond2)) !!ir (zF := AST.ite cond2 zF (dst == n0)) -#if !EMULATION - !!ir (aF := AST.ite cond2 aF undefAF) #endif !>ir insLen + let sbb ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt + ! t4 !!ir (t1 := dst) !!ir (t2 := AST.sext oprSize src) +#if EMULATION + !!ir (t3 := t2 .+ AST.zext oprSize (getCFLazy ctxt ir)) +#else !!ir (t3 := t2 .+ AST.zext oprSize cf) +#endif !!ir (t4 := t1 .- t3) !!ir (dstAssign oprSize dst t4) - !!ir (cf := (AST.lt t1 t3) .| (AST.lt t3 t2)) + !!ir (cf := (t1 .< t3) .| (t3 .< t2)) !!ir (!.ctxt R.OF := ofOnSub t1 t2 t4) - !?ir (enumASZPFlags ctxt t1 t2 t4 oprSize) + !?ir (enumASZPFlags ctxt t1 t2 t4 oprSize sf) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let private scasBody ins ctxt ir = let oprSize = getOperationSize ins - let t = !*ir oprSize + let t = !+ir oprSize let df = !.ctxt R.DF let x = getRegOfSize ctxt oprSize grpEAX let di = !.ctxt (if is64bit ctxt then R.RDI else R.EDI) - let tSrc = !*ir oprSize + let tSrc = !+ir oprSize let amount = numI32 (RegType.toByteWidth oprSize) ctxt.WordBitSize + let sf = AST.xthi 1 t !!ir (tSrc := AST.loadLE oprSize di) !!ir (t := x .- tSrc) - !?ir (enumEFLAGS ctxt x tSrc t oprSize (cfOnSub x tSrc) (ofOnSub x tSrc t)) + !?ir (enumEFLAGS ctxt x tSrc t oprSize (cfOnSub x tSrc) (ofOnSub x tSrc t) sf) !!ir (di := AST.ite df (di .- amount) (di .+ amount)) let scas (ins: InsInfo) insLen ctxt = let pref = ins.Prefixes let zfCond n = Some (!.ctxt R.ZF == n) - let ir = IRBuilder (32) + let ir = !*ctxt !ir insLen let private getCondOfSet (ins: IntelInternalInstruction) ctxt = @@ -1932,47 +2755,80 @@ let private getCondOfSet (ins: IntelInternalInstruction) ctxt = (!.ctxt R.SF == !.ctxt R.OF) | _ -> raise InvalidOpcodeException +#if EMULATION +let private getCondOfSetLazy (ins: IntelInternalInstruction) ctxt ir = + match ins.Opcode with + | Opcode.SETO -> getOFLazy ctxt ir + | Opcode.SETNO -> getOFLazy ctxt ir |> AST.not + | Opcode.SETB -> getCFLazy ctxt ir + | Opcode.SETNB -> getCFLazy ctxt ir |> AST.not + | Opcode.SETZ -> getZFLazy ctxt ir + | Opcode.SETNZ -> getZFLazy ctxt ir |> AST.not + | Opcode.SETBE -> (getCFLazy ctxt ir) .| (getZFLazy ctxt ir) + | Opcode.SETA -> (getCFLazy ctxt ir .| getZFLazy ctxt ir) |> AST.not + | Opcode.SETS -> getSFLazy ctxt ir + | Opcode.SETNS -> getSFLazy ctxt ir |> AST.not + | Opcode.SETP -> getPFLazy ctxt ir + | Opcode.SETNP -> getPFLazy ctxt ir |> AST.not + | Opcode.SETL -> getSFLazy ctxt ir != getOFLazy ctxt ir + | Opcode.SETNL -> getSFLazy ctxt ir == getOFLazy ctxt ir + | Opcode.SETLE -> (getZFLazy ctxt ir) .| + (getSFLazy ctxt ir != getOFLazy ctxt ir) + | Opcode.SETG -> (getZFLazy ctxt ir |> AST.not) .& + (getSFLazy ctxt ir == getOFLazy ctxt ir) + | _ -> raise InvalidOpcodeException +#endif + let setcc ins insLen ctxt = - let ir = IRBuilder (4) - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! AST.zext oprSize +#else let cond = getCondOfSet ins ctxt |> AST.zext oprSize - !ir insLen let inline shiftDblPrec ins insLen ctxt fnDst fnSrc isShl = - let ir = IRBuilder (16) - let struct (dst, src, cnt) = transThreeOprs ins insLen ctxt - let oprSize = getOperationSize ins - let orig = !*ir oprSize - let c = !*ir oprSize - let cond1 = c == AST.num0 oprSize - let cond2 = c == AST.num1 oprSize + let ir = !*ctxt + ! (orig >> (maxSz .- c))) - else - cF := AST.ite cond1 cF (AST.xtlo 1 (orig >> (c .- AST.num1 oprSize))) - ) + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let cond1 = count == AST.num0 oprSz + let cond2 = count == AST.num1 oprSz + !!ir (org := dst) + !!ir (size := exprOprSz) + let wordSize = numI32 (if hasREXW ins.REXPrefix then 64 else 32) oprSz + !!ir (count := (AST.zext oprSz cnt .% wordSize)) + !!ir (tDst := dst) + !!ir (tSrc := src) + !!ir (tDst := fnDst tDst count) + !!ir (tSrc := fnSrc tSrc (size .- count)) + !!ir (dstAssign oprSz dst (AST.ite cond1 org (tDst .| tSrc))) + let amount = if isShl then size .- count else count .- AST.num1 oprSz + !!ir (cF := AST.ite cond1 cF (AST.xtlo 1 (org >> amount))) + let overflow = AST.xthi 1 (org <+> dst) #if !EMULATION - !!ir (oF := AST.ite cond1 oF - (AST.ite cond2 (AST.xthi 1 (orig <+> dst)) undefOF)) + let aF = !.ctxt R.AF + !!ir (oF := AST.ite cond1 oF (AST.ite cond2 overflow undefOF)) !!ir (aF := AST.ite cond1 aF undefAF) #else - !!ir (oF := AST.ite cond1 oF - (AST.ite cond2 (AST.xthi 1 (orig <+> dst)) oF)) + !!ir (oF := AST.ite cond1 oF (AST.ite cond2 overflow oF)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif - !?ir (enumSZPFlags ctxt dst oprSize) + !!ir (sf := AST.ite cond1 sf (AST.xthi 1 dst)) + !!ir (zf := AST.ite cond1 zf (dst == (AST.num0 oprSz))) + !?ir (buildPF ctxt dst oprSz (Some cond1)) !>ir insLen let shld ins insLen ctxt = @@ -1981,23 +2837,29 @@ let shld ins insLen ctxt = let shrd ins insLen ctxt = shiftDblPrec ins insLen ctxt (>>) (<<) false -let shlx ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src1, src2) = transThreeOprs ins insLen ctxt +let private shiftWithoutFlags ins insLen ctxt opFn = + let ir = !*ctxt + ! dst := AST.xthi 1 temp) - !!ir (dst := dst << count) + !!ir (dstAssign oprSize dst (opFn src1 count)) !>ir insLen +let sarx ins insLen ctxt = shiftWithoutFlags ins insLen ctxt (?>>) + +let shlx ins insLen ctxt = shiftWithoutFlags ins insLen ctxt (<<) + +let shrx ins insLen ctxt = shiftWithoutFlags ins insLen ctxt (>>) + let setFlag insLen ctxt flag = - let ir = IRBuilder (4) + let ir = !*ctxt !ir insLen let stc insLen ctxt = setFlag insLen ctxt R.CF @@ -2016,7 +2878,7 @@ let private stosBody ins ctxt ir = !!ir (di := AST.ite df (di .- amount) (di .+ amount)) let stos (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt !ir insLen let sub ins insLen ctxt = - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let ir = IRBuilder (16) - let struct (t1, t2, t3) = tmpVars3 ir oprSize + let ir = !*ctxt ! t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnSub t1 t2) (ofOnSub t1 t2 t3) sf) +#else + let src = + if isConst src then src + else + let t = !+ir oprSize + !!ir (t := src) + t + !!ir (dstAssign oprSize dst (dst .- src)) + !?ir (setCCOperands2 ctxt src dst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.SUBQ + | _ -> raise InvalidRegTypeException +#endif if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () !>ir insLen let test ins insLen ctxt = - let ir = IRBuilder (16) - let struct (src1, src2) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let t = !*ir oprSize + let ir = !*ctxt ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICQ + | _ -> raise InvalidRegTypeException +#else + let t = !+ir oprSize + !!ir (t := r) !!ir (!.ctxt R.SF := AST.xthi 1 t) !!ir (!.ctxt R.ZF := t == (AST.num0 oprSize)) !?ir (buildPF ctxt t oprSize None) !!ir (!.ctxt R.CF := AST.b0) !!ir (!.ctxt R.OF := AST.b0) -#if !EMULATION !!ir (!.ctxt R.AF := undefAF) #endif !>ir insLen let tzcnt ins insLen ctxt = - let ir = IRBuilder (16) - let lblLoop = ir.NewSymbol "Loop" - let lblExit = ir.NewSymbol "Exit" - let lblLoopCond = ir.NewSymbol "LoopCond" - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt let oprSize = getOperationSize ins - let max = numI32 (RegType.toBitWidth oprSize) oprSize + let struct (dst, src) = transTwoOprs ir true ins insLen ctxt ! (src >> t1) == AST.b0) - !!ir (AST.cjmp cond (AST.name lblLoop) (AST.name lblExit)) - !!ir (AST.lmark lblLoop) - !!ir (t1 := t1 .+ AST.num1 oprSize) - !!ir (AST.jmp (AST.name lblLoopCond)) - !!ir (AST.lmark lblExit) - !!ir (dstAssign oprSize dst t1) + let lblCnt = !%ir "Count" + let lblZero = !%ir "Zero" + let lblEnd = !%ir "End" + let z = AST.num0 oprSize + let max = numI32 (RegType.toBitWidth oprSize) oprSize + let struct (t1, t2, res) = tmpVars3 ir oprSize + !!ir (t1 := src) + !!ir (AST.cjmp (t1 == z) (AST.name lblZero) (AST.name lblCnt)) + !!ir (AST.lmark lblZero) + !!ir (dstAssign oprSize dst max) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblCnt) + !!ir (res := z) + !!ir (t1 := t1 .& (t1 .* numI32 0xFFFFFFFF oprSize)) + match oprSize with + | 16 -> + !!ir (t2 := t1 >> numI32 8 16) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 8 16) res) + !!ir (t2 := t1 >> numI32 4 16) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 4 16) res) + | 32 -> + !!ir (t2 := t1 >> numI32 16 32) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 16 32) res) + !!ir (t2 := t1 >> numI32 8 32) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 8 32) res) + !!ir (t2 := t1 >> numI32 4 32) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 4 32) res) + | 64 -> + !!ir (t2 := t1 >> numI32 32 64) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 32 64) res) + !!ir (t2 := t1 >> numI32 16 64) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 16 64) res) + !!ir (t2 := t1 >> numI32 8 64) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 8 64) res) + !!ir (t2 := t1 >> numI32 4 64) + !!ir (t1 := AST.ite (t2 != z) t2 t1) + !!ir (res := AST.ite (t2 != z) (res .+ numI32 4 64) res) + | _ -> raise InvalidOperandSizeException + let v = (res .+ ((t1 >> numI32 1 oprSize) .- (t1 >> numI32 3 oprSize))) + !!ir (dstAssign oprSize dst v) + !!ir (AST.lmark lblEnd) !!ir (!.ctxt R.CF := dst == max) - !!ir (!.ctxt R.ZF := dst == AST.num0 oprSize) + !!ir (!.ctxt R.ZF := dst == z) #if !EMULATION !!ir (!.ctxt R.OF := undefOF) !!ir (!.ctxt R.SF := undefSF) !!ir (!.ctxt R.PF := undefPF) !!ir (!.ctxt R.AF := undefAF) +#else + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags #endif !>ir insLen let wrfsbase ins insLen ctxt = - let ir = IRBuilder (4) - let src = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let wrgsbase ins insLen ctxt = - let ir = IRBuilder (4) - let src = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let wrpkru ins insLen ctxt = - let ir = IRBuilder (8) - let lblSucc = ir.NewSymbol "Succ" - let lblErr = ir.NewSymbol "Err" + let ir = !*ctxt + let lblSucc = !%ir "Succ" + let lblErr = !%ir "Err" let oprSize = getOperationSize ins let ecxIsZero = !.ctxt R.ECX == AST.num0 oprSize let edxIsZero = !.ctxt R.EDX == AST.num0 oprSize @@ -2116,33 +3045,48 @@ let wrpkru ins insLen ctxt = !>ir insLen let xadd ins insLen ctxt = - let ir = IRBuilder (16) - let struct (d, s) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let t = !*ir oprSize + let ir = !*ctxt ! -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.ADDQ + | _ -> raise InvalidRegTypeException +#else + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 oprSize (cfOnAdd t1 t3) ofl sf) +#endif if hasLock ins.Prefixes then !!ir (AST.sideEffect Unlock) else () !>ir insLen let xchg ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = transTwoOprs ins insLen ctxt + let ir = !*ctxt ! src then - let oprSize = getOperationSize ins - let t = !*ir oprSize + let t = !+ir oprSize !!ir (t := dst) !!ir (dstAssign oprSize dst src) !!ir (dstAssign oprSize src t) + else + !!ir (dstAssign oprSize dst src) !>ir insLen let xlatb ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt let addressSize = getEffAddrSz ins let al = AST.zext addressSize (!.ctxt R.AL) let bx = getRegOfSize ctxt addressSize grpEBX @@ -2151,18 +3095,44 @@ let xlatb ins insLen ctxt = !>ir insLen let xor ins insLen ctxt = - let ir = IRBuilder (16) - let struct (dst, src) = transTwoOprs ins insLen ctxt - let oprSize = getOperationSize ins - let r = !*ir oprSize + let ir = !*ctxt ! AST.sext oprSize src) - !!ir (dstAssign oprSize dst r) - !!ir (!.ctxt R.OF := AST.b0) - !!ir (!.ctxt R.CF := AST.b0) - !!ir (!.ctxt R.SF := AST.xthi 1 r) - !!ir (!.ctxt R.ZF := r == (AST.num0 oprSize)) - !?ir (buildPF ctxt r oprSize None) + let oprSize = getOperationSize ins + match ins.Operands with + | TwoOperands (o1, o2) when o1 = o2 -> + let dst = transOprToExpr ir false ins insLen ctxt o1 + let r = AST.num0 oprSize + !!ir (dstAssign oprSize dst r) +#if EMULATION + !?ir (setCCDst ctxt r) + ctxt.ConditionCodeOp <- ConditionCodeOp.XORXX +#else + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.CF := AST.b0) + !!ir (!.ctxt R.SF := AST.b0) + !!ir (!.ctxt R.ZF := AST.b1) + !!ir (!.ctxt R.PF := AST.b1) +#endif + | TwoOperands (o1, o2) -> + let dst = transOprToExpr ir false ins insLen ctxt o1 + let src = transOprToExpr ir false ins insLen ctxt o2 |> transReg ir true + !!ir (dstAssign oprSize dst (dst <+> src)) +#if EMULATION + !?ir (setCCDst ctxt dst) + match oprSize with + | 8 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICB + | 16 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICW + | 32 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICD + | 64 -> ctxt.ConditionCodeOp <- ConditionCodeOp.LOGICQ + | _ -> raise InvalidRegTypeException +#else + !!ir (!.ctxt R.OF := AST.b0) + !!ir (!.ctxt R.CF := AST.b0) + !!ir (!.ctxt R.SF := AST.xthi 1 dst) + !!ir (!.ctxt R.ZF := dst == (AST.num0 oprSize)) + !?ir (buildPF ctxt dst oprSize None) +#endif + | _ -> raise InvalidOperandException #if !EMULATION !!ir (!.ctxt R.AF := undefAF) #endif diff --git a/src/FrontEnd/BinLifter/Intel/IntelHelper.fs b/src/FrontEnd/BinLifter/Intel/IntelHelper.fs index 31d8c90d..336ce71e 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelHelper.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelHelper.fs @@ -40,7 +40,7 @@ and [] InsSizeComputer () = abstract Render: ReadHelper -> SzCond -> unit and ReadHelper (addr, cpos, pref, rex, vex, wordSz, ops, szs) = - let reader = BinReader.binReaderLE + let reader = BinReader.Init Endian.Little let mutable addr: Addr = addr let mutable cpos: int = cpos (* current position *) let mutable pref: Prefix = pref @@ -121,13 +121,6 @@ and ReadHelper (addr, cpos, pref, rex, vex, wordSz, ops, szs) = member inline __.ParsedLen () = cpos - member inline __.GetInsID (span: ByteSpan) = - let len = cpos - let bs = reader.ReadBytes (span, 0, len) - let chars: char [] = Array.zeroCreate (len * sizeof) - Buffer.BlockCopy (bs, 0, chars, 0, bs.Length) - String chars - let inline hasREXW rexPref = rexPref &&& REXPrefix.REXW = REXPrefix.REXW let inline hasREXR rexPref = rexPref &&& REXPrefix.REXR = REXPrefix.REXR @@ -168,12 +161,20 @@ let inline isReg101 span (rhlp: ReadHelper) = getReg (rhlp.PeekByte span) = 5 let inline isReg110 span (rhlp: ReadHelper) = getReg (rhlp.PeekByte span) = 6 +let inline isReg111 span (rhlp: ReadHelper) = getReg (rhlp.PeekByte span) = 7 + /// Filter out segment-related prefixes. let [] ClearSegMask: Prefix = EnumOfValue 0xFC0F /// Filter out PrxREPNZ(0x2), PrxREPZ(0x8), and PrxOPSIZE(0x400). let [] ClearVEXPrefMask: Prefix = EnumOfValue 0xFBF5 +/// Filter out PrxREPZ(0x8) +let [] ClearREPZPrefMask: Prefix = EnumOfValue 0xFFF7 + +/// Filter out REXW(0x8) +let [] ClearREXWPrefMask: REXPrefix = EnumOfValue 0xFFF7 + /// Filter out group 1 prefixes. let [] ClearGrp1PrefMask: Prefix = EnumOfValue 0xFFF0 @@ -1112,6 +1113,42 @@ type SzY () = rhlp.RegSize <- effOprSz rhlp.OperationSize <- effOprSz +/// KnKm MKn +type SzQQb () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 8 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- 8 + +/// KnKm MKn +type SzQQd () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 32 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- 32 + +/// KnKm MKn +type SzQQw () = + inherit InsSizeComputer () + override __.Render rhlp szCond = + let effAddrSz = getEffAddrSize rhlp + let effOprSz = getEffOprSize rhlp szCond + rhlp.MemEffOprSize <- 16 + rhlp.MemEffAddrSize <- effAddrSz + rhlp.MemEffRegSize <- effOprSz + rhlp.RegSize <- effOprSz + rhlp.OperationSize <- 16 + type SizeKind = | Byte = 0 | Word = 1 @@ -1186,5 +1223,8 @@ type SizeKind = | Qq = 70 | DqwdX = 71 | Y = 72 + | QQb = 73 + | QQd = 74 + | QQw = 75 // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelInstruction.fs b/src/FrontEnd/BinLifter/Intel/IntelInstruction.fs index ce7250b9..ac0beb4f 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelInstruction.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelInstruction.fs @@ -27,9 +27,6 @@ namespace B2R2.FrontEnd.BinLifter.Intel open B2R2 open B2R2.FrontEnd.BinLifter -module private Dummy = - let helper = DisasmHelper () - /// The internal representation for an Intel instruction used by our /// disassembler and lifter. type IntelInstruction @@ -63,13 +60,12 @@ type IntelInstruction | _ -> false override __.IsCJmpOnTrue () = - __.IsCondBranch () - && match opcode with - | Opcode.JA | Opcode.JB | Opcode.JBE | Opcode.JCXZ | Opcode.JECXZ - | Opcode.JG | Opcode.JL | Opcode.JLE | Opcode.JO | Opcode.JP - | Opcode.JRCXZ | Opcode.JS | Opcode.JZ | Opcode.LOOP | Opcode.LOOPE -> - true - | _ -> false + match opcode with + | Opcode.JA | Opcode.JB | Opcode.JBE | Opcode.JCXZ | Opcode.JECXZ + | Opcode.JG | Opcode.JL | Opcode.JLE | Opcode.JO | Opcode.JP + | Opcode.JRCXZ | Opcode.JS | Opcode.JZ | Opcode.LOOP | Opcode.LOOPE -> + true + | _ -> false override __.IsCall () = match opcode with @@ -139,20 +135,19 @@ type IntelInstruction | _ -> false member private __.AddBranchTargetIfExist addrs = - match __.DirectBranchTarget () |> Utils.tupleToOpt with + match __.DirectBranchTarget () |> Utils.tupleResultToOpt with | None -> addrs | Some target -> - Seq.singleton (target, ArchOperationMode.NoMode) |> Seq.append addrs + [| (target, ArchOperationMode.NoMode) |] |> Array.append addrs override __.GetNextInstrAddrs () = - let acc = - Seq.singleton (__.Address + uint64 __.Length, ArchOperationMode.NoMode) + let acc = [| (__.Address + uint64 __.Length, ArchOperationMode.NoMode) |] if __.IsCall () then acc |> __.AddBranchTargetIfExist elif __.IsDirectBranch () || __.IsIndirectBranch () then if __.IsCondBranch () then acc |> __.AddBranchTargetIfExist - else __.AddBranchTargetIfExist Seq.empty - elif opcode = Opcode.HLT then Seq.empty - elif opcode = Opcode.UD2 then Seq.empty + else __.AddBranchTargetIfExist [||] + elif opcode = Opcode.HLT then [||] + elif opcode = Opcode.UD2 then [||] else acc override __.InterruptNum (num: byref) = @@ -173,20 +168,21 @@ type IntelInstruction override __.TranslateToList ctxt = Lifter.translate __ len ctxt - override __.Disasm (showAddr, resolveSymb, disasmHelper) = + override __.Disasm (showAddr, nameReader) = + let resolveSymb = not (isNull nameReader) let builder = DisasmStringBuilder (showAddr, resolveSymb, wordSz, addr, len) - Disasm.disasm disasmHelper __ builder - builder.Finalize () + Disasm.disasm.Invoke (nameReader, builder, __) + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, wordSz, addr, len) - Disasm.disasm Dummy.helper __ builder - builder.Finalize () + Disasm.disasm.Invoke (null, builder, __) + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, wordSz, addr, len, 8) - Disasm.disasm Dummy.helper __ builder - builder.Finalize () + Disasm.disasm.Invoke (null, builder, __) + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/Intel/IntelLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelLifter.fs index 4ae7e808..405e9175 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelLifter.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelLifter.fs @@ -38,11 +38,14 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.AAS -> GeneralLifter.aas insLen ctxt | OP.ADC -> GeneralLifter.adc ins insLen ctxt | OP.ADD -> GeneralLifter.add ins insLen ctxt + | OP.ADOX-> GeneralLifter.adox ins insLen ctxt | OP.AND -> GeneralLifter.``and`` ins insLen ctxt | OP.ANDN -> GeneralLifter.andn ins insLen ctxt | OP.ARPL -> GeneralLifter.arpl ins insLen ctxt + | OP.BEXTR -> GeneralLifter.bextr ins insLen ctxt + | OP.BLSI -> GeneralLifter.blsi ins insLen ctxt | OP.BNDMOV -> GeneralLifter.bndmov ins insLen ctxt - | OP.BOUND -> GeneralLifter.nop insLen + | OP.BOUND -> GeneralLifter.nop insLen ctxt | OP.BSF -> GeneralLifter.bsf ins insLen ctxt | OP.BSR -> GeneralLifter.bsr ins insLen ctxt | OP.BSWAP -> GeneralLifter.bswap ins insLen ctxt @@ -50,15 +53,16 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.BTC -> GeneralLifter.btc ins insLen ctxt | OP.BTR -> GeneralLifter.btr ins insLen ctxt | OP.BTS -> GeneralLifter.bts ins insLen ctxt + | OP.BZHI -> GeneralLifter.bzhi ins insLen ctxt | OP.CALLNear -> GeneralLifter.call ins insLen ctxt - | OP.CALLFar -> LiftingUtils.sideEffects insLen UnsupportedFAR + | OP.CALLFar -> LiftingUtils.sideEffects ctxt insLen UnsupportedFAR | OP.CBW | OP.CWDE | OP.CDQE -> GeneralLifter.convBWQ ins insLen ctxt | OP.CLC -> GeneralLifter.clearFlag insLen ctxt R.CF | OP.CLD -> GeneralLifter.clearFlag insLen ctxt R.DF | OP.CLI -> GeneralLifter.clearFlag insLen ctxt R.IF - | OP.CLRSSBSY -> GeneralLifter.nop insLen - | OP.CLTS -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.CLRSSBSY -> GeneralLifter.nop insLen ctxt + | OP.CLTS -> LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr | OP.CMC -> GeneralLifter.cmc ins insLen ctxt | OP.CMOVO | OP.CMOVNO | OP.CMOVB | OP.CMOVAE | OP.CMOVZ | OP.CMOVNZ | OP.CMOVBE | OP.CMOVA @@ -71,31 +75,31 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.CMPXCHG -> GeneralLifter.cmpxchg ins insLen ctxt | OP.CMPXCHG8B | OP.CMPXCHG16B -> GeneralLifter.compareExchangeBytes ins insLen ctxt - | OP.CPUID -> LiftingUtils.sideEffects insLen ProcessorID - | OP.CRC32 -> GeneralLifter.nop insLen + | OP.CPUID -> LiftingUtils.sideEffects ctxt insLen ProcessorID + | OP.CRC32 -> GeneralLifter.nop insLen ctxt | OP.CWD | OP.CDQ | OP.CQO -> GeneralLifter.convWDQ ins insLen ctxt | OP.DAA -> GeneralLifter.daa insLen ctxt | OP.DAS -> GeneralLifter.das insLen ctxt | OP.DEC -> GeneralLifter.dec ins insLen ctxt | OP.DIV | OP.IDIV -> GeneralLifter.div ins insLen ctxt - | OP.ENDBR32 | OP.ENDBR64 -> GeneralLifter.nop insLen + | OP.ENDBR32 | OP.ENDBR64 -> GeneralLifter.nop insLen ctxt | OP.ENTER -> GeneralLifter.enter ins insLen ctxt - | OP.HLT -> LiftingUtils.sideEffects insLen Delay + | OP.HLT -> LiftingUtils.sideEffects ctxt insLen Delay | OP.IMUL -> GeneralLifter.imul ins insLen ctxt | OP.INC -> GeneralLifter.inc ins insLen ctxt - | OP.INCSSPD | OP.INCSSPQ -> GeneralLifter.nop insLen + | OP.INCSSPD | OP.INCSSPQ -> GeneralLifter.nop insLen ctxt | OP.INSB | OP.INSW | OP.INSD -> GeneralLifter.insinstr ins insLen ctxt | OP.INT | OP.INTO -> GeneralLifter.interrupt ins insLen ctxt - | OP.INT3 -> LiftingUtils.sideEffects insLen Breakpoint + | OP.INT3 -> LiftingUtils.sideEffects ctxt insLen Breakpoint | OP.JMPFar | OP.JMPNear -> GeneralLifter.jmp ins insLen ctxt | OP.JO | OP.JNO | OP.JB | OP.JNB | OP.JZ | OP.JNZ | OP.JBE | OP.JA | OP.JS | OP.JNS | OP.JP | OP.JNP | OP.JL | OP.JNL | OP.JLE | OP.JG | OP.JECXZ | OP.JRCXZ -> GeneralLifter.jcc ins insLen ctxt - | OP.LAHF -> LiftingUtils.sideEffects insLen ProcessorID + | OP.LAHF -> GeneralLifter.lahf ins insLen ctxt | OP.LEA -> GeneralLifter.lea ins insLen ctxt | OP.LEAVE -> GeneralLifter.leave ins insLen ctxt | OP.LODSB | OP.LODSW | OP.LODSD | OP.LODSQ -> @@ -104,7 +108,7 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = GeneralLifter.loop ins insLen ctxt | OP.LZCNT -> GeneralLifter.lzcnt ins insLen ctxt | OP.LDS | OP.LES | OP.LFS | OP.LGS | OP.LSS -> - LiftingUtils.sideEffects insLen UnsupportedFAR + LiftingUtils.sideEffects ctxt insLen UnsupportedFAR | OP.MOV -> GeneralLifter.mov ins insLen ctxt | OP.MOVBE -> GeneralLifter.movbe ins insLen ctxt | OP.MOVSB | OP.MOVSW | OP.MOVSQ -> @@ -112,12 +116,15 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.MOVSX | OP.MOVSXD -> GeneralLifter.movsx ins insLen ctxt | OP.MOVZX -> GeneralLifter.movzx ins insLen ctxt | OP.MUL -> GeneralLifter.mul ins insLen ctxt + | OP.MULX -> GeneralLifter.mulx ins insLen ctxt | OP.NEG -> GeneralLifter.neg ins insLen ctxt - | OP.NOP -> GeneralLifter.nop insLen + | OP.NOP -> GeneralLifter.nop insLen ctxt | OP.NOT -> GeneralLifter.not ins insLen ctxt | OP.OR -> GeneralLifter.logOr ins insLen ctxt | OP.OUTSB | OP.OUTSW | OP.OUTSD -> GeneralLifter.outs ins insLen ctxt + | OP.PDEP -> GeneralLifter.pdep ins insLen ctxt + | OP.PEXT -> GeneralLifter.pext ins insLen ctxt | OP.POP -> GeneralLifter.pop ins insLen ctxt | OP.POPA -> GeneralLifter.popa insLen ctxt 16 | OP.POPAD -> GeneralLifter.popa insLen ctxt 32 @@ -132,25 +139,25 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.RCL -> GeneralLifter.rcl ins insLen ctxt | OP.RCR -> GeneralLifter.rcr ins insLen ctxt | OP.RDMSR | OP.RSM -> - LiftingUtils.sideEffects insLen UnsupportedExtension + LiftingUtils.sideEffects ctxt insLen UnsupportedExtension | OP.RDPKRU -> GeneralLifter.rdpkru ins insLen ctxt - | OP.RDPMC -> LiftingUtils.sideEffects insLen UnsupportedExtension - | OP.RDRAND -> LiftingUtils.sideEffects insLen UnsupportedExtension - | OP.RDSSPD | OP.RDSSPQ -> GeneralLifter.nop insLen - | OP.RDTSC -> LiftingUtils.sideEffects insLen ClockCounter - | OP.RDTSCP -> LiftingUtils.sideEffects insLen ClockCounter + | OP.RDPMC -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension + | OP.RDRAND -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension + | OP.RDSSPD | OP.RDSSPQ -> GeneralLifter.nop insLen ctxt + | OP.RDTSC -> LiftingUtils.sideEffects ctxt insLen ClockCounter + | OP.RDTSCP -> LiftingUtils.sideEffects ctxt insLen ClockCounter | OP.RETNear -> GeneralLifter.ret ins insLen ctxt | OP.RETNearImm -> GeneralLifter.retWithImm ins insLen ctxt - | OP.RETFar -> LiftingUtils.sideEffects insLen UnsupportedFAR - | OP.RETFarImm -> LiftingUtils.sideEffects insLen UnsupportedFAR + | OP.RETFar -> LiftingUtils.sideEffects ctxt insLen UnsupportedFAR + | OP.RETFarImm -> LiftingUtils.sideEffects ctxt insLen UnsupportedFAR | OP.ROL -> GeneralLifter.rol ins insLen ctxt | OP.ROR -> GeneralLifter.ror ins insLen ctxt | OP.RORX -> GeneralLifter.rorx ins insLen ctxt - | OP.RSTORSSP -> GeneralLifter.nop insLen + | OP.RSTORSSP -> GeneralLifter.nop insLen ctxt | OP.SAHF -> GeneralLifter.sahf ins insLen ctxt | OP.SAR | OP.SHR | OP.SHL -> GeneralLifter.shift ins insLen ctxt - | OP.SAVEPREVSSP -> GeneralLifter.nop insLen + | OP.SAVEPREVSSP -> GeneralLifter.nop insLen ctxt | OP.SBB -> GeneralLifter.sbb ins insLen ctxt | OP.SCASB | OP.SCASW | OP.SCASD | OP.SCASQ -> GeneralLifter.scas ins insLen ctxt @@ -159,9 +166,11 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.SETS | OP.SETNS | OP.SETP | OP.SETNP | OP.SETL | OP.SETNL | OP.SETLE | OP.SETG -> GeneralLifter.setcc ins insLen ctxt - | OP.SETSSBSY -> GeneralLifter.nop insLen + | OP.SETSSBSY -> GeneralLifter.nop insLen ctxt | OP.SHLD -> GeneralLifter.shld ins insLen ctxt + | OP.SARX -> GeneralLifter.sarx ins insLen ctxt | OP.SHLX -> GeneralLifter.shlx ins insLen ctxt + | OP.SHRX -> GeneralLifter.shrx ins insLen ctxt | OP.SHRD -> GeneralLifter.shrd ins insLen ctxt | OP.STC -> GeneralLifter.stc insLen ctxt | OP.STD -> GeneralLifter.std insLen ctxt @@ -169,36 +178,36 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.STOSB | OP.STOSW | OP.STOSD | OP.STOSQ -> GeneralLifter.stos ins insLen ctxt | OP.SUB -> GeneralLifter.sub ins insLen ctxt - | OP.SYSCALL | OP.SYSENTER -> LiftingUtils.sideEffects insLen SysCall + | OP.SYSCALL | OP.SYSENTER -> LiftingUtils.sideEffects ctxt insLen SysCall | OP.SYSEXIT | OP.SYSRET -> - LiftingUtils.sideEffects insLen UnsupportedPrivInstr + LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr | OP.TEST -> GeneralLifter.test ins insLen ctxt | OP.TZCNT -> GeneralLifter.tzcnt ins insLen ctxt - | OP.UD2 -> LiftingUtils.sideEffects insLen UndefinedInstr - | OP.WBINVD -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.UD2 -> LiftingUtils.sideEffects ctxt insLen UndefinedInstr + | OP.WBINVD -> LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr | OP.WRFSBASE -> GeneralLifter.wrfsbase ins insLen ctxt | OP.WRGSBASE -> GeneralLifter.wrgsbase ins insLen ctxt | OP.WRPKRU -> GeneralLifter.wrpkru ins insLen ctxt - | OP.WRMSR -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr - | OP.WRSSD | OP.WRSSQ -> GeneralLifter.nop insLen - | OP.WRUSSD | OP.WRUSSQ -> GeneralLifter.nop insLen - | OP.XABORT -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.WRMSR -> LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr + | OP.WRSSD | OP.WRSSQ -> GeneralLifter.nop insLen ctxt + | OP.WRUSSD | OP.WRUSSQ -> GeneralLifter.nop insLen ctxt + | OP.XABORT -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension | OP.XADD -> GeneralLifter.xadd ins insLen ctxt - | OP.XBEGIN -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XBEGIN -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension | OP.XCHG -> GeneralLifter.xchg ins insLen ctxt - | OP.XEND -> LiftingUtils.sideEffects insLen UnsupportedExtension - | OP.XGETBV -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.XEND -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension + | OP.XGETBV -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension | OP.XLATB -> GeneralLifter.xlatb ins insLen ctxt | OP.XOR -> GeneralLifter.xor ins insLen ctxt | OP.XRSTOR | OP.XRSTORS | OP.XSAVE | OP.XSAVEC | OP.XSAVEC64 | OP.XSAVEOPT | OP.XSAVES | OP.XSAVES64 -> - LiftingUtils.sideEffects insLen UnsupportedExtension - | OP.XTEST -> LiftingUtils.sideEffects insLen UnsupportedExtension + LiftingUtils.sideEffects ctxt insLen UnsupportedExtension + | OP.XTEST -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension | OP.IN | OP.INVD | OP.INVLPG | OP.IRET | OP.IRETQ | OP.IRETW | OP.IRETD | OP.LAR | OP.LGDT | OP.LIDT | OP.LLDT | OP.LMSW | OP.LSL | OP.LTR | OP.OUT | OP.SGDT | OP.SIDT | OP.SLDT | OP.SMSW | OP.STR | OP.VERR -> - LiftingUtils.sideEffects insLen UnsupportedPrivInstr + LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr | OP.MOVD -> MMXLifter.movd ins insLen ctxt | OP.MOVQ -> MMXLifter.movq ins insLen ctxt | OP.PACKSSDW -> MMXLifter.packssdw ins insLen ctxt @@ -217,6 +226,9 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.PADDSW -> MMXLifter.paddsw ins insLen ctxt | OP.PADDUSB -> MMXLifter.paddusb ins insLen ctxt | OP.PADDUSW -> MMXLifter.paddusw ins insLen ctxt + | OP.PHADDD -> MMXLifter.phaddd ins insLen ctxt + | OP.PHADDW -> MMXLifter.phaddw ins insLen ctxt + | OP.PHADDSW -> MMXLifter.phaddsw ins insLen ctxt | OP.PSUBB -> MMXLifter.psubb ins insLen ctxt | OP.PSUBW -> MMXLifter.psubw ins insLen ctxt | OP.PSUBD -> MMXLifter.psubd ins insLen ctxt @@ -224,8 +236,12 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.PSUBSW -> MMXLifter.psubsw ins insLen ctxt | OP.PSUBUSB -> MMXLifter.psubusb ins insLen ctxt | OP.PSUBUSW -> MMXLifter.psubusw ins insLen ctxt + | OP.PHSUBD -> MMXLifter.phsubd ins insLen ctxt + | OP.PHSUBW -> MMXLifter.phsubw ins insLen ctxt + | OP.PHSUBSW -> MMXLifter.phsubsw ins insLen ctxt | OP.PMULHW -> MMXLifter.pmulhw ins insLen ctxt | OP.PMULLW -> MMXLifter.pmullw ins insLen ctxt + | OP.PMULLD -> SSELifter.pmulld ins insLen ctxt | OP.PMADDWD -> MMXLifter.pmaddwd ins insLen ctxt | OP.PCMPEQB -> MMXLifter.pcmpeqb ins insLen ctxt | OP.PCMPEQW -> MMXLifter.pcmpeqw ins insLen ctxt @@ -246,6 +262,8 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.PSRAW -> MMXLifter.psraw ins insLen ctxt | OP.PSRAD -> MMXLifter.psrad ins insLen ctxt | OP.EMMS -> MMXLifter.emms ins insLen ctxt + | OP.ADDSUBPD -> SSELifter.addsubpd ins insLen ctxt + | OP.ADDSUBPS -> SSELifter.addsubps ins insLen ctxt | OP.MOVAPS -> SSELifter.movaps ins insLen ctxt | OP.MOVAPD -> SSELifter.movapd ins insLen ctxt (* SSE2 *) | OP.MOVUPS -> SSELifter.movups ins insLen ctxt @@ -312,13 +330,17 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.ORPD -> SSELifter.orpd ins insLen ctxt (* SSE2 *) | OP.XORPS -> SSELifter.xorps ins insLen ctxt | OP.XORPD -> SSELifter.xorpd ins insLen ctxt (* SSE2 *) - | OP.XSETBV -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.XSETBV -> LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr | OP.SHUFPS -> SSELifter.shufps ins insLen ctxt | OP.SHUFPD -> SSELifter.shufpd ins insLen ctxt (* SSE2 *) | OP.UNPCKHPS -> SSELifter.unpckhps ins insLen ctxt | OP.UNPCKHPD -> SSELifter.unpckhpd ins insLen ctxt (* SSE2 *) | OP.UNPCKLPS -> SSELifter.unpcklps ins insLen ctxt | OP.UNPCKLPD -> SSELifter.unpcklpd ins insLen ctxt (* SSE2 *) + | OP.BLENDPD -> SSELifter.blendpd ins insLen ctxt + | OP.BLENDPS -> SSELifter.blendps ins insLen ctxt + | OP.BLENDVPD -> SSELifter.blendvpd ins insLen ctxt + | OP.BLENDVPS -> SSELifter.blendvps ins insLen ctxt | OP.CVTPI2PS -> SSELifter.cvtpi2ps ins insLen ctxt | OP.CVTPI2PD -> SSELifter.cvtpi2pd ins insLen ctxt (* SSE2 *) | OP.CVTSI2SS -> SSELifter.cvtsi2ss ins insLen ctxt @@ -345,20 +367,44 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = SSELifter.cvtss2si ins insLen ctxt false | OP.CVTTSD2SI | OP.VCVTTSD2SI -> (* SSE2 *) SSELifter.cvtsd2si ins insLen ctxt false + | OP.EXTRACTPS -> SSELifter.extractps ins insLen ctxt | OP.LDMXCSR -> SSELifter.ldmxcsr ins insLen ctxt | OP.STMXCSR -> SSELifter.stmxcsr ins insLen ctxt + | OP.PACKUSDW -> SSELifter.packusdw ins insLen ctxt | OP.PAVGB -> SSELifter.pavgb ins insLen ctxt | OP.PAVGW -> SSELifter.pavgw ins insLen ctxt + | OP.PBLENDVB -> SSELifter.pblendvb ins insLen ctxt + | OP.PBLENDW -> SSELifter.pblendw ins insLen ctxt + | OP.PEXTRB -> SSELifter.pextrb ins insLen ctxt + | OP.PEXTRD -> SSELifter.pextrd ins insLen ctxt + | OP.PEXTRQ -> SSELifter.pextrq ins insLen ctxt | OP.PEXTRW -> SSELifter.pextrw ins insLen ctxt | OP.PINSRW -> SSELifter.pinsrw ins insLen ctxt | OP.PMAXUB -> SSELifter.pmaxub ins insLen ctxt + | OP.PMAXUD -> SSELifter.pmaxud ins insLen ctxt + | OP.PMAXUW -> SSELifter.pmaxuw ins insLen ctxt + | OP.PMAXSB -> SSELifter.pmaxsb ins insLen ctxt + | OP.PMAXSD -> SSELifter.pmaxsd ins insLen ctxt | OP.PMAXSW -> SSELifter.pmaxsw ins insLen ctxt - | OP.PMAXSB -> SSELifter.pmaxsb ins insLen ctxt (* SSE4 *) | OP.PMINUB -> SSELifter.pminub ins insLen ctxt + | OP.PMINUD -> SSELifter.pminud ins insLen ctxt + | OP.PMINUW -> SSELifter.pminuw ins insLen ctxt + | OP.PMINSB -> SSELifter.pminsb ins insLen ctxt + | OP.PMINSD -> SSELifter.pminsd ins insLen ctxt | OP.PMINSW -> SSELifter.pminsw ins insLen ctxt - | OP.PMINUD -> SSELifter.pminud ins insLen ctxt (* SSE4 *) - | OP.PMINSB -> SSELifter.pminsb ins insLen ctxt (* SSE4 *) | OP.PMOVMSKB -> SSELifter.pmovmskb ins insLen ctxt + | OP.PMOVSXBW -> SSELifter.pmovbw ins insLen ctxt 8 true (* SSE4 *) + | OP.PMOVSXBD -> SSELifter.pmovbd ins insLen ctxt 8 true (* SSE4 *) + | OP.PMOVSXBQ -> SSELifter.pmovbq ins insLen ctxt 8 true (* SSE4 *) + | OP.PMOVSXWD -> SSELifter.pmovbw ins insLen ctxt 16 true (* SSE4 *) + | OP.PMOVSXWQ -> SSELifter.pmovbd ins insLen ctxt 16 true (* SSE4 *) + | OP.PMOVSXDQ -> SSELifter.pmovbw ins insLen ctxt 32 true (* SSE4 *) + | OP.PMOVZXBW -> SSELifter.pmovbw ins insLen ctxt 8 false (* SSE4 *) + | OP.PMOVZXBD -> SSELifter.pmovbd ins insLen ctxt 8 false (* SSE4 *) + | OP.PMOVZXBQ -> SSELifter.pmovbq ins insLen ctxt 8 false (* SSE4 *) + | OP.PMOVZXWD -> SSELifter.pmovbw ins insLen ctxt 16 false (* SSE4 *) + | OP.PMOVZXWQ -> SSELifter.pmovbd ins insLen ctxt 16 false (* SSE4 *) + | OP.PMOVZXDQ -> SSELifter.pmovbw ins insLen ctxt 32 false (* SSE4 *) | OP.PMULHUW -> SSELifter.pmulhuw ins insLen ctxt | OP.PSADBW -> SSELifter.psadbw ins insLen ctxt | OP.PSHUFW -> SSELifter.pshufw ins insLen ctxt @@ -381,15 +427,19 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.MOVNTPS -> SSELifter.movntps ins insLen ctxt | OP.PREFETCHNTA | OP.PREFETCHT0 | OP.PREFETCHT1 - | OP.PREFETCHW | OP.PREFETCHT2 -> GeneralLifter.nop insLen - | OP.SFENCE -> LiftingUtils.sideEffects insLen Fence - | OP.CLFLUSH -> GeneralLifter.nop insLen (* SSE2 *) - | OP.LFENCE -> LiftingUtils.sideEffects insLen Fence (* SSE2 *) - | OP.MFENCE -> LiftingUtils.sideEffects insLen Fence (* SSE2 *) - | OP.PAUSE -> LiftingUtils.sideEffects insLen Delay (* SSE2 *) + | OP.PREFETCHW | OP.PREFETCHT2 -> GeneralLifter.nop insLen ctxt + | OP.SFENCE -> LiftingUtils.sideEffects ctxt insLen Fence + | OP.CLFLUSH -> GeneralLifter.nop insLen ctxt (* SSE2 *) + | OP.LFENCE -> LiftingUtils.sideEffects ctxt insLen Fence (* SSE2 *) + | OP.MFENCE -> LiftingUtils.sideEffects ctxt insLen Fence (* SSE2 *) + | OP.PAUSE -> LiftingUtils.sideEffects ctxt insLen Delay (* SSE2 *) | OP.MOVNTPD -> SSELifter.movntpd ins insLen ctxt (* SSE2 *) | OP.MOVNTDQ -> SSELifter.movntdq ins insLen ctxt (* SSE2 *) | OP.MOVNTI -> SSELifter.movnti ins insLen ctxt (* SSE2 *) + | OP.HADDPD -> SSELifter.haddpd ins insLen ctxt (* SSE3 *) + | OP.HADDPS -> SSELifter.haddps ins insLen ctxt (* SSE3 *) + | OP.HSUBPD -> SSELifter.hsubpd ins insLen ctxt (* SSE3 *) + | OP.HSUBPS -> SSELifter.hsubps ins insLen ctxt (* SSE3 *) | OP.LDDQU -> SSELifter.lddqu ins insLen ctxt (* SSE3 *) | OP.MOVSHDUP -> SSELifter.movshdup ins insLen ctxt (* SSE3 *) | OP.MOVSLDUP -> SSELifter.movsldup ins insLen ctxt (* SSE3 *) @@ -397,6 +447,9 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.PALIGNR -> SSELifter.palignr ins insLen ctxt (* SSE3 *) | OP.ROUNDSD -> SSELifter.roundsd ins insLen ctxt (* SSE4 *) | OP.PINSRB -> SSELifter.pinsrb ins insLen ctxt (* SSE4 *) + | OP.PSIGNB -> SSELifter.psign ins insLen ctxt 8 (* SSE3 *) + | OP.PSIGNW -> SSELifter.psign ins insLen ctxt 16 (* SSE3 *) + | OP.PSIGND -> SSELifter.psign ins insLen ctxt 32 (* SSE3 *) | OP.PTEST -> SSELifter.ptest ins insLen ctxt (* SSE4 *) | OP.PCMPEQQ -> SSELifter.pcmpeqq ins insLen ctxt (* SSE4 *) | OP.PCMPESTRI | OP.PCMPESTRM | OP.PCMPISTRI | OP.PCMPISTRM -> @@ -409,6 +462,8 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.VADDPD -> AVXLifter.vaddpd ins insLen ctxt | OP.VADDSS -> AVXLifter.vaddss ins insLen ctxt | OP.VADDSD -> AVXLifter.vaddsd ins insLen ctxt + | OP.VBLENDVPD -> AVXLifter.vblendvpd ins insLen ctxt + | OP.VBLENDVPS -> AVXLifter.vblendvps ins insLen ctxt | OP.VSUBPS -> AVXLifter.vsubps ins insLen ctxt | OP.VSUBPD -> AVXLifter.vsubpd ins insLen ctxt | OP.VSUBSS -> AVXLifter.vsubss ins insLen ctxt @@ -427,8 +482,8 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.VCVTSS2SD -> AVXLifter.vcvtss2sd ins insLen ctxt | OP.VMOVD -> AVXLifter.vmovd ins insLen ctxt | OP.VMOVQ -> AVXLifter.vmovq ins insLen ctxt - | OP.VMOVAPS -> AVXLifter.vmovdqu ins insLen ctxt - | OP.VMOVAPD -> AVXLifter.vmovdqu ins insLen ctxt + | OP.VMOVAPS -> AVXLifter.vmovaps ins insLen ctxt + | OP.VMOVAPD -> AVXLifter.vmovapd ins insLen ctxt | OP.VMOVDQU -> AVXLifter.vmovdqu ins insLen ctxt | OP.VMOVDQU16 -> AVXLifter.vmovdqu16 ins insLen ctxt | OP.VMOVDQU64 -> AVXLifter.vmovdqu64 ins insLen ctxt @@ -468,16 +523,26 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.VBROADCASTI128 -> AVXLifter.vbroadcasti128 ins insLen ctxt | OP.VBROADCASTSS -> AVXLifter.vbroadcastss ins insLen ctxt | OP.VEXTRACTF32X8 -> AVXLifter.vextracti32x8 ins insLen ctxt + | OP.VEXTRACTI128 -> AVXLifter.vextracti128 ins insLen ctxt | OP.VEXTRACTI64X4 -> AVXLifter.vextracti64x4 ins insLen ctxt + | OP.VEXTRACTPS -> SSELifter.extractps ins insLen ctxt | OP.VINSERTI128 -> AVXLifter.vinserti128 ins insLen ctxt - | OP.VMPTRLD -> LiftingUtils.sideEffects insLen UnsupportedExtension + | OP.VMPTRLD -> LiftingUtils.sideEffects ctxt insLen UnsupportedExtension | OP.VPADDB -> AVXLifter.vpaddb ins insLen ctxt | OP.VPADDD -> AVXLifter.vpaddd ins insLen ctxt | OP.VPADDQ -> AVXLifter.vpaddq ins insLen ctxt | OP.VPALIGNR -> AVXLifter.vpalignr ins insLen ctxt | OP.VPAND -> AVXLifter.vpand ins insLen ctxt | OP.VPANDN -> AVXLifter.vpandn ins insLen ctxt + | OP.VPBLENDD -> AVXLifter.vpblendd ins insLen ctxt + | OP.VPBLENDW -> AVXLifter.vpblendw ins insLen ctxt + | OP.VPBLENDVB -> AVXLifter.vpblendvb ins insLen ctxt + | OP.VPACKUSDW -> AVXLifter.vpackusdw ins insLen ctxt + | OP.VPACKUSWB -> AVXLifter.vpackuswb ins insLen ctxt + | OP.VPAVGB -> AVXLifter.vpavgb ins insLen ctxt + | OP.VPAVGW -> AVXLifter.vpavgw ins insLen ctxt | OP.VPBROADCASTB -> AVXLifter.vpbroadcastb ins insLen ctxt + | OP.VPBROADCASTW -> AVXLifter.vpbroadcastw ins insLen ctxt | OP.VPBROADCASTD -> AVXLifter.vpbroadcastd ins insLen ctxt | OP.VPCMPEQB -> AVXLifter.vpcmpeqb ins insLen ctxt | OP.VPCMPEQD -> AVXLifter.vpcmpeqd ins insLen ctxt @@ -485,31 +550,63 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.VPCMPESTRI | OP.VPCMPESTRM | OP.VPCMPISTRI | OP.VPCMPISTRM -> SSELifter.pcmpstr ins insLen ctxt | OP.VPCMPGTB -> AVXLifter.vpcmpgtb ins insLen ctxt + | OP.VPERM2I128 -> AVXLifter.vperm2i128 ins insLen ctxt + | OP.VPERMD -> AVXLifter.vpermd ins insLen ctxt + | OP.VPERMQ -> AVXLifter.vpermq ins insLen ctxt + | OP.VPEXTRD -> SSELifter.pextrd ins insLen ctxt + | OP.VPEXTRB -> SSELifter.pextrb ins insLen ctxt + | OP.VPINSRB -> AVXLifter.vpinsrb ins insLen ctxt | OP.VPINSRD -> AVXLifter.vpinsrd ins insLen ctxt + | OP.VPMINSB -> AVXLifter.vpminsb ins insLen ctxt + | OP.VPMINSD -> AVXLifter.vpminsd ins insLen ctxt | OP.VPMINUB -> AVXLifter.vpminub ins insLen ctxt | OP.VPMINUD -> AVXLifter.vpminud ins insLen ctxt + | OP.VPMOVSXBW -> AVXLifter.vpmovx ins insLen ctxt 8 16 true + | OP.VPMOVSXBD -> AVXLifter.vpmovx ins insLen ctxt 8 32 true + | OP.VPMOVSXBQ -> AVXLifter.vpmovx ins insLen ctxt 8 64 true + | OP.VPMOVSXWD -> AVXLifter.vpmovx ins insLen ctxt 16 32 true + | OP.VPMOVSXWQ -> AVXLifter.vpmovx ins insLen ctxt 16 64 true + | OP.VPMOVSXDQ -> AVXLifter.vpmovx ins insLen ctxt 32 64 true + | OP.VPMOVZXBW -> AVXLifter.vpmovx ins insLen ctxt 8 16 false + | OP.VPMOVZXBD -> AVXLifter.vpmovx ins insLen ctxt 8 32 false + | OP.VPMOVZXBQ -> AVXLifter.vpmovx ins insLen ctxt 8 64 false + | OP.VPMOVZXWD -> AVXLifter.vpmovx ins insLen ctxt 16 32 false + | OP.VPMOVZXWQ -> AVXLifter.vpmovx ins insLen ctxt 16 64 false + | OP.VPMOVZXDQ -> AVXLifter.vpmovx ins insLen ctxt 32 64 false + | OP.VPMOVD2M -> AVXLifter.vpmovd2m ins insLen ctxt | OP.VPMOVMSKB -> SSELifter.pmovmskb ins insLen ctxt + | OP.VPMULLD -> AVXLifter.vpmulld ins insLen ctxt | OP.VPMULUDQ -> AVXLifter.vpmuludq ins insLen ctxt + | OP.VPMULHUW -> AVXLifter.vpmulhuw ins insLen ctxt + | OP.VPMULLW -> AVXLifter.vpmullw ins insLen ctxt | OP.VPOR -> AVXLifter.vpor ins insLen ctxt + | OP.VPINSRW -> AVXLifter.vpinsrw ins insLen ctxt | OP.VPSHUFB -> AVXLifter.vpshufb ins insLen ctxt | OP.VPSHUFD -> AVXLifter.vpshufd ins insLen ctxt | OP.VPSLLD -> AVXLifter.vpslld ins insLen ctxt | OP.VPSLLDQ -> AVXLifter.vpslldq ins insLen ctxt | OP.VPSLLQ -> AVXLifter.vpsllq ins insLen ctxt + | OP.VPSRAD -> AVXLifter.vpsrad ins insLen ctxt + | OP.VPSRAW -> AVXLifter.vpsraw ins insLen ctxt + | OP.VPSRAVD -> AVXLifter.vpsravd ins insLen ctxt | OP.VPSRLD -> AVXLifter.vpsrld ins insLen ctxt + | OP.VPSRLW -> AVXLifter.vpsrlw ins insLen ctxt | OP.VPSRLDQ -> AVXLifter.vpsrldq ins insLen ctxt | OP.VPSRLQ -> AVXLifter.vpsrlq ins insLen ctxt | OP.VPSUBB -> AVXLifter.vpsubb ins insLen ctxt + | OP.VPSUBD -> AVXLifter.vpsubd ins insLen ctxt | OP.VPTEST -> AVXLifter.vptest ins insLen ctxt | OP.VPUNPCKHDQ -> AVXLifter.vpunpckhdq ins insLen ctxt | OP.VPUNPCKHQDQ -> AVXLifter.vpunpckhqdq ins insLen ctxt + | OP.VPUNPCKHWD -> AVXLifter.vpunpckhwd ins insLen ctxt | OP.VPUNPCKLDQ -> AVXLifter.vpunpckldq ins insLen ctxt | OP.VPUNPCKLQDQ -> AVXLifter.vpunpcklqdq ins insLen ctxt + | OP.VPUNPCKLWD -> AVXLifter.vpunpcklwd ins insLen ctxt | OP.VPXOR -> AVXLifter.vpxor ins insLen ctxt | OP.VPXORD -> AVXLifter.vpxord ins insLen ctxt | OP.VZEROUPPER -> AVXLifter.vzeroupper ins insLen ctxt | OP.VEXTRACTI32X8 -> AVXLifter.vextracti32x8 ins insLen ctxt - | OP.VERW -> LiftingUtils.sideEffects insLen UnsupportedPrivInstr + | OP.VERW -> LiftingUtils.sideEffects ctxt insLen UnsupportedPrivInstr | OP.VFMADD132SD -> AVXLifter.vfmadd132sd ins insLen ctxt | OP.VFMADD213SD -> AVXLifter.vfmadd213sd ins insLen ctxt | OP.VFMADD231SD -> AVXLifter.vfmadd231sd ins insLen ctxt @@ -547,7 +644,7 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = | OP.FDIVP -> X87Lifter.fpudiv ins insLen ctxt true | OP.FIDIV -> X87Lifter.fidiv ins insLen ctxt | OP.FDIVR -> X87Lifter.fdivr ins insLen ctxt false - | OP.FDIVRP -> X87Lifter.fdivr ins insLen ctxt true + | OP.FDIVRP -> X87Lifter.fdivr ins insLen ctxt true | OP.FIDIVR -> X87Lifter.fidivr ins insLen ctxt | OP.FPREM -> X87Lifter.fprem ins insLen ctxt false | OP.FPREM1 -> X87Lifter.fprem ins insLen ctxt true @@ -609,7 +706,7 @@ let translate (ins: IntelInternalInstruction) insLen ctxt = eprintfn "%A" o eprintfn "%A" ins #endif - LiftingUtils.sideEffects insLen UnsupportedExtension + LiftingUtils.sideEffects ctxt insLen UnsupportedExtension // raise <| NotImplementedIRException (Disasm.opCodeToString o) // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs b/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs index f095f242..151da6d8 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelLiftingUtils.fs @@ -67,16 +67,39 @@ let inline getImmValue imm = | OprImm (imm, _) -> imm | _ -> raise InvalidOperandException +let inline isConst (e: Expr) = + match e.E with + | Num _ -> true + | _ -> false + let private getMemExpr128 expr = match expr.E with - | Load (e, 128, expr, _) -> + | Load (e, 128, { E = BinOp (BinOpType.ADD, _, b, { E = Num n }) }) + | Load (e, 128, { E = BinOp (BinOpType.ADD, _, { E = Num n }, b) }) + -> + let off1 = AST.num n + let off2 = BitVector.Add (n, BitVector.OfInt32 8 n.Length) |> AST.num + AST.load e 64 (b .+ off2), + AST.load e 64 (b .+ off1) + | Load (e, 128, expr) -> AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)), AST.load e 64 expr | _ -> raise InvalidOperandException let private getMemExpr256 expr = match expr.E with - | Load (e, 256, expr, _) -> + | Load (e, 256, { E = BinOp (BinOpType.ADD, _, b, { E = Num n }) }) + | Load (e, 256, { E = BinOp (BinOpType.ADD, _, { E = Num n }, b) }) + -> + let off1 = AST.num n + let off2 = BitVector.Add (n, BitVector.OfInt32 8 n.Length) |> AST.num + let off3 = BitVector.Add (n, BitVector.OfInt32 16 n.Length) |> AST.num + let off4 = BitVector.Add (n, BitVector.OfInt32 24 n.Length) |> AST.num + AST.load e 64 (b .+ off4), + AST.load e 64 (b .+ off3), + AST.load e 64 (b .+ off2), + AST.load e 64 (b .+ off1) + | Load (e, 256, expr) -> AST.load e 64 (expr .+ numI32 24 (TypeCheck.typeOf expr)), AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)), AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)), @@ -85,7 +108,26 @@ let private getMemExpr256 expr = let private getMemExpr512 expr = match expr.E with - | Load (e, 512, expr, _) -> + | Load (e, 512, { E = BinOp (BinOpType.ADD, _, b, { E = Num n }) }) + | Load (e, 512, { E = BinOp (BinOpType.ADD, _, { E = Num n }, b) }) + -> + let off1 = AST.num n + let off2 = BitVector.Add (n, BitVector.OfInt32 8 n.Length) |> AST.num + let off3 = BitVector.Add (n, BitVector.OfInt32 16 n.Length) |> AST.num + let off4 = BitVector.Add (n, BitVector.OfInt32 24 n.Length) |> AST.num + let off5 = BitVector.Add (n, BitVector.OfInt32 32 n.Length) |> AST.num + let off6 = BitVector.Add (n, BitVector.OfInt32 40 n.Length) |> AST.num + let off7 = BitVector.Add (n, BitVector.OfInt32 48 n.Length) |> AST.num + let off8 = BitVector.Add (n, BitVector.OfInt32 56 n.Length) |> AST.num + AST.load e 64 (b .+ off8), + AST.load e 64 (b .+ off7), + AST.load e 64 (b .+ off6), + AST.load e 64 (b .+ off5), + AST.load e 64 (b .+ off4), + AST.load e 64 (b .+ off3), + AST.load e 64 (b .+ off2), + AST.load e 64 (b .+ off1) + | Load (e, 512, expr) -> AST.load e 64 (expr .+ numI32 56 (TypeCheck.typeOf expr)), AST.load e 64 (expr .+ numI32 48 (TypeCheck.typeOf expr)), AST.load e 64 (expr .+ numI32 40 (TypeCheck.typeOf expr)), @@ -98,15 +140,15 @@ let private getMemExpr512 expr = let private getMemExprs expr = match expr.E with - | Load (e, 128, expr, _) -> + | Load (e, 128, expr) -> [ AST.load e 64 expr AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)) ] - | Load (e, 256, expr, _) -> + | Load (e, 256, expr) -> [ AST.load e 64 expr AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)) AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)) AST.load e 64 (expr .+ numI32 24 (TypeCheck.typeOf expr)) ] - | Load (e, 512, expr, _) -> + | Load (e, 512, expr) -> [ AST.load e 64 expr AST.load e 64 (expr .+ numI32 8 (TypeCheck.typeOf expr)) AST.load e 64 (expr .+ numI32 16 (TypeCheck.typeOf expr)) @@ -150,6 +192,10 @@ let isSegReg = function | Register.GS -> true | _ -> false +let isMemOpr = function + | OprMem _ -> true + | _ -> false + let private segRegToBase = function | R.CS -> R.CSBase | R.DS -> R.DSBase @@ -173,103 +219,131 @@ let private numOfAddrSz (ins: InsInfo) (ctxt: TranslationContext) n = numI64 n sz let inline private sIdx ins ctxt (r, s: Scale) = - (!.ctxt r) .* (numOfAddrSz ins ctxt (int64 s)) - -let private transMem ins insLen ctxt b index disp oprSize = - match b, index, (disp: Disp option) with - | None, None, Some d -> - numOfAddrSz ins ctxt d - |> ldMem ins ctxt oprSize - | None, Some i, Some d -> - (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) - |> ldMem ins ctxt oprSize - | Some b, None, None -> - !.ctxt b - |> ldMem ins ctxt oprSize - | Some R.RIP, None, Some d -> (* RIP-relative addressing *) - !.ctxt R.RIP .+ numOfAddrSz ins ctxt (d + int64 (insLen: uint32)) - |> ldMem ins ctxt oprSize - | Some b, None, Some d -> - !.ctxt b .+ (numOfAddrSz ins ctxt d) - |> ldMem ins ctxt oprSize - | Some b, Some i, None -> - !.ctxt b .+ (sIdx ins ctxt i) - |> ldMem ins ctxt oprSize - | Some b, Some i, Some d -> - !.ctxt b .+ (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) - |> ldMem ins ctxt oprSize - | _, _, _ -> raise InvalidOperandException - -let transOprToExpr ins insLen ctxt = function + match s with + | Scale.X1 -> !.ctxt r + | Scale.X2 -> !.ctxt r << numOfAddrSz ins ctxt 1 + | Scale.X4 -> !.ctxt r << numOfAddrSz ins ctxt 2 + | Scale.X8 -> !.ctxt r << numOfAddrSz ins ctxt 3 + | _ -> Utils.impossible () + +let private transMem ir useTmpVar ins insLen ctxt b index disp oprSize = + let address = + match b, index, (disp: Disp option) with + | None, None, Some d -> + numOfAddrSz ins ctxt d + | None, Some i, Some d -> + let e = (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) + if not useTmpVar then e + else + let tAddress = !+ir (ctxt: TranslationContext).WordBitSize + !!ir (tAddress := e) + tAddress + | Some b, None, None -> + !.ctxt b + | Some R.RIP, None, Some d -> (* RIP-relative addressing *) + let pc = +#if EMULATION + numOfAddrSz ins ctxt (int64 (ins: InsInfo).Address) +#else + !.ctxt R.RIP +#endif + let e = pc .+ numOfAddrSz ins ctxt (d + int64 (insLen: uint32)) + if not useTmpVar then e + else + let tAddress = !+ir (ctxt: TranslationContext).WordBitSize + !!ir (tAddress := e) + tAddress + | Some b, None, Some d -> + let e = !.ctxt b .+ (numOfAddrSz ins ctxt d) + if not useTmpVar then e + else + let tAddress = !+ir (ctxt: TranslationContext).WordBitSize + !!ir (tAddress := e) + tAddress + | Some b, Some i, None -> + let e = !.ctxt b .+ (sIdx ins ctxt i) + if not useTmpVar then e + else + let tAddress = !+ir (ctxt: TranslationContext).WordBitSize + !!ir (tAddress := e) + tAddress + | Some b, Some i, Some d -> + let e = !.ctxt b .+ (sIdx ins ctxt i) .+ (numOfAddrSz ins ctxt d) + if not useTmpVar then e + else + let tAddress = !+ir (ctxt: TranslationContext).WordBitSize + !!ir (tAddress := e) + tAddress + | _, _, _ -> raise InvalidOperandException + ldMem ins ctxt oprSize address + +let transOprToExpr ir useTmpVar ins insLen ctxt = function | OprReg reg -> !.ctxt reg | OprMem (b, index, disp, oprSize) -> - transMem ins insLen ctxt b index disp oprSize + transMem ir useTmpVar ins insLen ctxt b index disp oprSize | OprImm (imm, _) -> numI64 imm (getOperationSize ins) | OprDirAddr (Relative offset) -> numI64 offset ctxt.WordBitSize | OprDirAddr (Absolute (_, addr, _)) -> numU64 addr ctxt.WordBitSize | _ -> Utils.impossible () -let transOprToExprVec ins insLen ctxt opr = +let transOprToExprVec ir useTmpVar ins insLen ctxt opr = match opr with | OprReg r -> getPseudoRegVars ctxt r | OprMem (b, index, disp, oprSize) -> - transMem ins insLen ctxt b index disp oprSize |> getMemExprs + transMem ir useTmpVar ins insLen ctxt b index disp oprSize |> getMemExprs | OprImm (imm, _) -> [ numI64 imm (getOperationSize ins) ] | _ -> raise InvalidOperandException -let transOprToExpr32 ins insLen ctxt opr = +let transOprToExpr16 ir useTmpVar ins insLen ctxt opr = + match opr with + | OprReg r when Register.toRegType r > 64 -> + getPseudoRegVar ctxt r 1 |> AST.xtlo 16 + | OprReg r -> !.ctxt r + | OprMem (b, index, disp, 16) -> + transMem ir useTmpVar ins insLen ctxt b index disp 16 + | _ -> raise InvalidOperandException + +let transOprToExpr32 ir useTmpVar ins insLen ctxt opr = match opr with | OprReg r when Register.toRegType r > 64 -> getPseudoRegVar ctxt r 1 |> AST.xtlo 32 | OprReg r -> !.ctxt r | OprMem (b, index, disp, 32) -> - transMem ins insLen ctxt b index disp 32 + transMem ir useTmpVar ins insLen ctxt b index disp 32 | _ -> raise InvalidOperandException -let transOprToExpr64 ins insLen ctxt opr = +let transOprToExpr64 ir useTmpVar ins insLen ctxt opr = match opr with | OprReg r when Register.toRegType r > 64 -> getPseudoRegVar ctxt r 1 | OprReg r -> !.ctxt r | OprMem (b, index, disp, 64) -> - transMem ins insLen ctxt b index disp 64 + transMem ir useTmpVar ins insLen ctxt b index disp 64 | _ -> raise InvalidOperandException -let transOprToExpr128 ins insLen ctxt opr = +let transOprToExpr128 ir useTmpVar ins insLen ctxt opr = match opr with | OprReg r -> getPseudoRegVar128 ctxt r | OprMem (b, index, disp, oprSize) -> - transMem ins insLen ctxt b index disp oprSize |> getMemExpr128 + transMem ir useTmpVar ins insLen ctxt b index disp oprSize |> getMemExpr128 | _ -> raise InvalidOperandException -let transOprToExpr256 ins insLen ctxt opr = +let transOprToExpr256 ir useTmpVar ins insLen ctxt opr = match opr with | OprReg r -> getPseudoRegVar256 ctxt r | OprMem (b, index, disp, oprSize) -> - transMem ins insLen ctxt b index disp oprSize |> getMemExpr256 + transMem ir useTmpVar ins insLen ctxt b index disp oprSize |> getMemExpr256 | _ -> raise InvalidOperandException -let transOprToExpr512 ins insLen ctxt opr = +let transOprToExpr512 ir useTmpVar ins insLen ctxt opr = match opr with | OprReg r -> getPseudoRegVar512 ctxt r | OprMem (b, index, disp, oprSize) -> - transMem ins insLen ctxt b index disp oprSize |> getMemExpr512 - | _ -> raise InvalidOperandException - -let transOprToFloat80 ins insLen ctxt opr = - match opr with - | OprReg r when Register.toRegType r = 80 -> !.ctxt r - | OprReg r -> - !.ctxt r |> AST.cast CastKind.FloatCast 80 - | OprMem (b, index, disp, 80) -> - transMem ins insLen ctxt b index disp 80 - | OprMem (b, index, disp, len) -> - transMem ins insLen ctxt b index disp len - |> AST.cast CastKind.FloatCast 80 + transMem ir useTmpVar ins insLen ctxt b index disp oprSize |> getMemExpr512 | _ -> raise InvalidOperandException /// Return a tuple (jump target expr, is pc-relative?) -let transJumpTargetOpr (ins: InsInfo) pc insLen (ctxt: TranslationContext) = - match ins.Operands with +let transJumpTargetOpr ir useTmpVar ins pc insLen (ctxt: TranslationContext) = + match (ins: InsInfo).Operands with | OneOperand (OprDirAddr (Absolute (_, addr, _))) -> struct (numU64 addr ctxt.WordBitSize, false) | OneOperand (OprDirAddr (Relative offset)) -> @@ -278,9 +352,132 @@ let transJumpTargetOpr (ins: InsInfo) pc insLen (ctxt: TranslationContext) = struct (pc .+ offset, true) | OneOperand (OprReg reg) -> struct (!.ctxt reg, false) | OneOperand (OprMem (b, index, disp, oprSize)) -> - struct (transMem ins insLen ctxt b index disp oprSize, false) + struct (transMem ir useTmpVar ins insLen ctxt b index disp oprSize, false) | _ -> raise InvalidOperandException +let transOprToArr ir useTmpVars ins insLen ctxt packSz packNum oprSize opr = + let pos = int packSz + let exprArr = + match opr with + | OprImm _ -> + let opr = transOprToExpr ir false ins insLen ctxt opr + Array.init (oprSize / packSz) (fun i -> AST.extract opr packSz (i * pos)) + | OprMem _ -> + match oprSize with + | 64 -> + let opr = transOprToExpr ir false ins insLen ctxt opr + let mem = !+ir oprSize + !!ir (mem := AST.zext oprSize opr) + Array.init packNum (fun i -> AST.extract mem packSz (i * pos)) + | 128 -> + let oB, oA = transOprToExpr128 ir false ins insLen ctxt opr + let struct (mB, mA) = tmpVars2 ir 64 + !!ir (mA := oA) + !!ir (mB := oB) + let oprA = Array.init packNum (fun i -> AST.extract mA packSz (i * pos)) + let oprB = Array.init packNum (fun i -> AST.extract mB packSz (i * pos)) + Array.append oprA oprB + | 256 -> + let oD, oC, oB, oA = + transOprToExpr256 ir false ins insLen ctxt opr + let struct (mD, mC, mB, mA) = tmpVars4 ir 64 + !!ir (mA := oA) + !!ir (mB := oB) + !!ir (mC := oC) + !!ir (mD := oD) + let oprA = Array.init packNum (fun i -> AST.extract mA packSz (i * pos)) + let oprB = Array.init packNum (fun i -> AST.extract mB packSz (i * pos)) + let oprC = Array.init packNum (fun i -> AST.extract mC packSz (i * pos)) + let oprD = Array.init packNum (fun i -> AST.extract mD packSz (i * pos)) + Array.concat [| oprA; oprB; oprC; oprD |] + | 512 -> + let oH, oG, oF, oE, oD, oC, oB, oA = + transOprToExpr512 ir false ins insLen ctxt opr + let struct (mD, mC, mB, mA) = tmpVars4 ir 64 + let struct (mH, mG, mF, mE) = tmpVars4 ir 64 + !!ir (mA := oA) + !!ir (mB := oB) + !!ir (mC := oC) + !!ir (mD := oD) + !!ir (mE := oE) + !!ir (mF := oF) + !!ir (mG := oG) + !!ir (mH := oH) + let oprA = Array.init packNum (fun i -> AST.extract mA packSz (i * pos)) + let oprB = Array.init packNum (fun i -> AST.extract mB packSz (i * pos)) + let oprC = Array.init packNum (fun i -> AST.extract mC packSz (i * pos)) + let oprD = Array.init packNum (fun i -> AST.extract mD packSz (i * pos)) + let oprE = Array.init packNum (fun i -> AST.extract mE packSz (i * pos)) + let oprF = Array.init packNum (fun i -> AST.extract mF packSz (i * pos)) + let oprG = Array.init packNum (fun i -> AST.extract mG packSz (i * pos)) + let oprH = Array.init packNum (fun i -> AST.extract mH packSz (i * pos)) + Array.concat [| oprA; oprB; oprC; oprD; oprE; oprF; oprG; oprH |] + | _ -> raise InvalidOperandSizeException + | _ -> + match oprSize with + | 64 -> + let opr = transOprToExpr ir false ins insLen ctxt opr + Array.init packNum (fun i -> AST.extract opr packSz (i * pos)) + | 128 -> + let oB, oA = transOprToExpr128 ir false ins insLen ctxt opr + let oprA = Array.init packNum (fun i -> AST.extract oA packSz (i * pos)) + let oprB = Array.init packNum (fun i -> AST.extract oB packSz (i * pos)) + Array.append oprA oprB + | 256 -> + let oD, oC, oB, oA = + transOprToExpr256 ir false ins insLen ctxt opr + let oprA = Array.init packNum (fun i -> AST.extract oA packSz (i * pos)) + let oprB = Array.init packNum (fun i -> AST.extract oB packSz (i * pos)) + let oprC = Array.init packNum (fun i -> AST.extract oC packSz (i * pos)) + let oprD = Array.init packNum (fun i -> AST.extract oD packSz (i * pos)) + Array.concat [| oprA; oprB; oprC; oprD |] + | 512 -> + let oH, oG, oF, oE, oD, oC, oB, oA = + transOprToExpr512 ir false ins insLen ctxt opr + let oprA = Array.init packNum (fun i -> AST.extract oA packSz (i * pos)) + let oprB = Array.init packNum (fun i -> AST.extract oB packSz (i * pos)) + let oprC = Array.init packNum (fun i -> AST.extract oC packSz (i * pos)) + let oprD = Array.init packNum (fun i -> AST.extract oD packSz (i * pos)) + let oprE = Array.init packNum (fun i -> AST.extract oE packSz (i * pos)) + let oprF = Array.init packNum (fun i -> AST.extract oF packSz (i * pos)) + let oprG = Array.init packNum (fun i -> AST.extract oG packSz (i * pos)) + let oprH = Array.init packNum (fun i -> AST.extract oH packSz (i * pos)) + Array.concat [| oprA; oprB; oprC; oprD; oprE; oprF; oprG; oprH |] + | _ -> raise InvalidOperandSizeException + if useTmpVars then + let tmps = Array.init (oprSize / packSz) (fun _ -> !+ir packSz) + Array.iter2 (fun e1 e2 -> !!ir (e1 := e2)) tmps exprArr + tmps + else exprArr + +let assignPackedInstr ir useTmpVar ins insLen ctxt packNum oprSize dst result = + match oprSize with + | 64 -> + let dst = transOprToExpr ir useTmpVar ins insLen ctxt dst + !!ir (dst := result |> AST.concatArr) + | 128 -> + let dstB, dstA = transOprToExpr128 ir useTmpVar ins insLen ctxt dst + !!ir (dstA := Array.sub result 0 packNum |> AST.concatArr) + !!ir (dstB := Array.sub result packNum packNum |> AST.concatArr) + | 256 -> + let dstD, dstC, dstB, dstA = transOprToExpr256 ir false ins insLen ctxt dst + !!ir (dstA := Array.sub result 0 packNum |> AST.concatArr) + !!ir (dstB := Array.sub result (1 * packNum) packNum |> AST.concatArr) + !!ir (dstC := Array.sub result (2 * packNum) packNum |> AST.concatArr) + !!ir (dstD := Array.sub result (3 * packNum) packNum |> AST.concatArr) + | 512 -> + let dstH, dstG, dstF, dstE, dstD, dstC, dstB, dstA = + transOprToExpr512 ir false ins insLen ctxt dst + !!ir (dstA := Array.sub result 0 packNum |> AST.concatArr) + !!ir (dstB := Array.sub result (1 * packNum) packNum |> AST.concatArr) + !!ir (dstC := Array.sub result (2 * packNum) packNum |> AST.concatArr) + !!ir (dstD := Array.sub result (3 * packNum) packNum |> AST.concatArr) + !!ir (dstE := Array.sub result (4 * packNum) packNum |> AST.concatArr) + !!ir (dstF := Array.sub result (5 * packNum) packNum |> AST.concatArr) + !!ir (dstG := Array.sub result (6 * packNum) packNum |> AST.concatArr) + !!ir (dstH := Array.sub result (7 * packNum) packNum |> AST.concatArr) + | _ -> raise InvalidOperandSizeException + let getTwoOprs (ins: InsInfo) = match ins.Operands with | TwoOperands (o1, o2) -> struct (o1, o2) @@ -296,24 +493,35 @@ let getFourOprs (ins: InsInfo) = | FourOperands (o1, o2, o3, o4) -> struct (o1, o2, o3, o4) | _ -> raise InvalidOperandException -let transOneOpr (ins: InsInfo) insLen ctxt = +let transOneOpr ir (ins: InsInfo) insLen ctxt = match ins.Operands with - | OneOperand opr -> transOprToExpr ins insLen ctxt opr + | OneOperand opr -> transOprToExpr ir true ins insLen ctxt opr | _ -> raise InvalidOperandException -let transTwoOprs (ins: InsInfo) insLen ctxt = +let transReg ir useTmpVar expr = + if useTmpVar then + match expr.E with + | Extract (_, rt, _) -> + let t = !+ir rt + !!ir (t := expr) + t + | _ -> expr + else expr + +let transTwoOprs ir useTmpVar (ins: InsInfo) insLen ctxt = match ins.Operands with | TwoOperands (o1, o2) -> - struct (transOprToExpr ins insLen ctxt o1, - transOprToExpr ins insLen ctxt o2) + let o1 = transOprToExpr ir useTmpVar ins insLen ctxt o1 + let o2 = transOprToExpr ir false ins insLen ctxt o2 |> transReg ir useTmpVar + struct (o1, o2) | _ -> raise InvalidOperandException -let transThreeOprs (ins: InsInfo) insLen ctxt = +let transThreeOprs ir useTmpVar (ins: InsInfo) insLen ctxt = match ins.Operands with | ThreeOperands (o1, o2, o3) -> - struct (transOprToExpr ins insLen ctxt o1, - transOprToExpr ins insLen ctxt o2, - transOprToExpr ins insLen ctxt o3) + struct (transOprToExpr ir useTmpVar ins insLen ctxt o1, + transOprToExpr ir useTmpVar ins insLen ctxt o2, + transOprToExpr ir useTmpVar ins insLen ctxt o3) | _ -> raise InvalidOperandException /// This is an Intel-specific assignment to a destination operand. @@ -341,23 +549,23 @@ let extractDstAssign e1 e2 = match e1.E with | Extract ({ E = BinOp (BinOpType.SHR, 16, { E = BinOp (BinOpType.AND, 16, - ({ E = Var (16, rId, _, _) } as e1), mask, _) }, amt, _) }, 8, - 0, _) when int rId = 0x4F (* FSW *) || int rId = 0x50 (* FTW *) -> + ({ E = Var (16, rId, _) } as e1), mask) }, amt) }, 8, 0) + when int rId = 0x4F (* FSW *) || int rId = 0x50 (* FTW *) -> e1 := (e1 .& (AST.not mask)) .| (((AST.zext 16 e2) << amt) .& mask) | e -> printfn "%A" e; raise InvalidAssignmentException let maxNum rt = match rt with - | 8 -> BitVector.maxUInt8 - | 16 -> BitVector.maxUInt16 - | 32 -> BitVector.maxUInt32 - | 64 -> BitVector.maxUInt64 + | 8 -> BitVector.MaxUInt8 + | 16 -> BitVector.MaxUInt16 + | 32 -> BitVector.MaxUInt32 + | 64 -> BitVector.MaxUInt64 | _ -> raise InvalidOperandSizeException |> AST.num let castNum newType e = match e.E with - | Num n -> BitVector.cast n newType |> AST.num + | Num n -> BitVector.Cast (n, newType) |> AST.num | _ -> raise InvalidOperandException let getMask oprSize = @@ -368,8 +576,788 @@ let getMask oprSize = | 64 -> numI64 0xffffffffffffffffL oprSize | _ -> raise InvalidOperandSizeException -let sideEffects insLen name = - let ir = IRBuilder (4) +let sideEffects ctxt insLen name = + let ir = !*ctxt ! ConditionCodeOp.TraceStart then + !!ir (!.ctxt R.CCOP := numI32 (int ctxt.ConditionCodeOp) 8) + else () + ctxt.ConditionCodeOp <- ConditionCodeOp.TraceStart +#endif !!ir (AST.sideEffect name) !>ir insLen + +let hasStackPtr (ins: InsInfo) = + match ins.Operands with + | OneOperand (OprReg Register.ESP) + | OneOperand (OprReg Register.RSP) + | OneOperand (OprMem (Some Register.ESP, _, _, _)) + | OneOperand (OprMem (Some Register.RSP, _, _, _)) + | OneOperand (OprMem (_, Some (Register.ESP, _), _, _)) + | OneOperand (OprMem (_, Some (Register.RSP, _), _, _)) -> true + | _ -> false + +let buildAF ctxt e1 e2 r size = + let t1 = r <+> e1 + let t2 = t1 <+> e2 + let t3 = (AST.num1 size) << (numU32 4ul size) + let t4 = t2 .& t3 + !.ctxt R.AF := t4 == t3 + +let isExprZero e = + match e.E with + | Num bv when bv.IsZero () -> true + | _ -> false + +let buildPF ctxt r size cond ir = + let pf = !.ctxt R.PF + let computedPF = + if isExprZero r then + AST.num1 1 + else + let struct (t1, t2) = tmpVars2 ir size + let s2 = r <+> (r >> (AST.zext size (numU32 4ul 8))) + let s4 = t1 <+> (t1 >> (AST.zext size (numU32 2ul 8))) + let s5 = t2 <+> (t2 >> (AST.zext size (AST.num1 8))) + !!ir (t1 := s2) + !!ir (t2 := s4) + AST.unop UnOpType.NOT (AST.xtlo 1 s5) + !!ir (match cond with + | None -> pf := computedPF + | Some cond -> pf := AST.ite cond pf computedPF) + +let enumSZPFlags ctxt r size sf ir = + !!ir (!.ctxt R.SF := sf) + !!ir (!.ctxt R.ZF := r == (AST.num0 size)) + !?ir (buildPF ctxt r size None) + +let enumASZPFlags ctxt e1 e2 r size sf ir = + !!ir (buildAF ctxt e1 e2 r size) + !?ir (enumSZPFlags ctxt r size sf) + +let enumEFLAGS ctxt e1 e2 e3 size cf ofl sf ir = + !!ir (!.ctxt R.CF := cf) + !!ir (!.ctxt R.OF := ofl) + !!ir (buildAF ctxt e1 e2 e3 size) + !!ir (!.ctxt R.SF := sf) + !!ir (!.ctxt R.ZF := e3 == (AST.num0 size)) + !?ir (buildPF ctxt e3 size None) + +/// CF on add. +let cfOnAdd e1 r = r .< e1 + +/// CF on sub. +let cfOnSub e1 e2 = e1 .< e2 + +/// OF and SF on add. +let osfOnAdd e1 e2 r ir = + if e1 = e2 then + let rHigh = !+ir 1 + let e1High = AST.xthi 1 e1 + !!ir (rHigh := AST.xthi 1 r) + struct ((e1High <+> rHigh), rHigh) + else + let struct (t1, t2) = tmpVars2 ir 1 + let e1High = AST.xthi 1 e1 + let e2High = AST.xthi 1 e2 + let rHigh = AST.xthi 1 r + !!ir (t1 := e1High) + !!ir (t2 := rHigh) + struct ((t1 == e2High) .& (t1 <+> t2), t2) + +/// OF on sub. +let ofOnSub e1 e2 r = + AST.xthi 1 ((e1 <+> e2) .& (e1 <+> r)) + +#if EMULATION +let getCCSrc1 (ctxt: TranslationContext) regType = + match regType with + | 8 -> !.ctxt R.CCSRC1B + | 16 -> !.ctxt R.CCSRC1W + | 32 -> !.ctxt R.CCSRC1D + | 64 -> !.ctxt R.CCSRC1 + | _ -> Utils.impossible () + +let getCCSrc2 (ctxt: TranslationContext) regType = + match regType with + | 8 -> !.ctxt R.CCSRC2B + | 16 -> !.ctxt R.CCSRC2W + | 32 -> !.ctxt R.CCSRC2D + | 64 -> !.ctxt R.CCSRC2 + | _ -> Utils.impossible () + +let getCCDst (ctxt: TranslationContext) regType = + match regType with + | 8 -> !.ctxt R.CCDSTB + | 16 -> !.ctxt R.CCDSTW + | 32 -> !.ctxt R.CCDSTD + | 64 -> !.ctxt R.CCDST + | _ -> Utils.impossible () + +let setCCOperands2 (ctxt: TranslationContext) src1 dst ir = + let ccSrc1 = !.ctxt R.CCSRC1 + let ccDst = !.ctxt R.CCDST + !!ir (ccSrc1 := AST.zext ctxt.WordBitSize src1) + !!ir (ccDst := AST.zext ctxt.WordBitSize dst) + +let setCCOperands3 (ctxt: TranslationContext) src1 src2 dst ir = + let ccSrc1 = !.ctxt R.CCSRC1 + let ccSrc2 = !.ctxt R.CCSRC2 + let ccDst = !.ctxt R.CCDST + !!ir (ccSrc1 := AST.zext ctxt.WordBitSize src1) + !!ir (ccSrc2 := AST.zext ctxt.WordBitSize src2) + !!ir (ccDst := AST.zext ctxt.WordBitSize dst) + +let setCCDst (ctxt: TranslationContext) dst ir = + let ccDst = !.ctxt R.CCDST + !!ir (ccDst := AST.zext ctxt.WordBitSize dst) + +let setCCOp (ctxt: TranslationContext) (ir: IRBuilder) = + if ctxt.ConditionCodeOp <> ConditionCodeOp.TraceStart then + !!ir (!.ctxt R.CCOP := numI32 (int ctxt.ConditionCodeOp) 8) + else () + +let genDynamicFlagsUpdate (ctxt: TranslationContext) (ir: IRBuilder) = + !?ir (setCCOp ctxt) + !!ir (AST.sideEffect FlagsUpdate) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + +let getOFLazy (ctxt: TranslationContext) (ir: IRBuilder) = + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t2 := src1) + !!ir (t1 := t3 .+ t2) + let sf = t3 ?< AST.num0 regType + let cf = cfOnSub t1 t2 + let ofl = ofOnSub t1 t2 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.DECB + | ConditionCodeOp.DECW + | ConditionCodeOp.DECD + | ConditionCodeOp.DECQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t2 := src1) + !!ir (t1 := t3 .+ t2) + let sf = t3 ?< AST.num0 regType + let cf = !.ctxt R.CF + let ofl = ofOnSub t1 t2 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.ADDB + | ConditionCodeOp.ADDW + | ConditionCodeOp.ADDD + | ConditionCodeOp.ADDQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t1 := src1) + !!ir (t2 := t3 .- t1) + let cf = cfOnAdd t1 t3 + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.INCB + | ConditionCodeOp.INCW + | ConditionCodeOp.INCD + | ConditionCodeOp.INCQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t1 := src1) + !!ir (t2 := t3 .- t1) + let cf = !.ctxt R.CF + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.SHLB + | ConditionCodeOp.SHLW + | ConditionCodeOp.SHLD + | ConditionCodeOp.SHLQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let dst = getCCDst ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond1 = src2 == n1 + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let ofl = !.ctxt R.OF + let newOf = AST.xthi 1 dst <+> cf + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := dst) + !!ir (cf := AST.ite cond2 cf (AST.xthi 1 (t1 << (t2 .- n1)))) + !!ir (ofl := AST.ite cond1 newOf ofl) + !!ir (sf := AST.ite cond2 sf (AST.xthi 1 t3)) + !?ir (buildPF ctxt dst regType (Some cond2)) + !!ir (zf := AST.ite cond2 zf (t3 == n0)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.SHRB + | ConditionCodeOp.SHRW + | ConditionCodeOp.SHRD + | ConditionCodeOp.SHRQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let dst = getCCDst ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond1 = src2 == n1 + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let ofl = !.ctxt R.OF + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := dst) + !!ir (cf := AST.ite cond2 cf (AST.xtlo 1 (t1 ?>> (t2 .- n1)))) + !!ir (ofl := AST.ite cond1 (AST.xthi 1 t1) ofl) + !!ir (sf := AST.ite cond2 sf (AST.xthi 1 t3)) + !?ir (buildPF ctxt dst regType (Some cond2)) + !!ir (zf := AST.ite cond2 zf (t3 == n0)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.SARB + | ConditionCodeOp.SARW + | ConditionCodeOp.SARD + | ConditionCodeOp.SARQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let dst = getCCDst ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond1 = src2 == n1 + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let ofl = !.ctxt R.OF + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := dst) + !!ir (cf := AST.ite cond2 cf (AST.xtlo 1 (t1 ?>> (t2 .- n1)))) + !!ir (ofl := AST.ite cond1 AST.b0 ofl) + !!ir (sf := AST.ite cond2 sf (AST.xthi 1 t3)) + !?ir (buildPF ctxt dst regType (Some cond2)) + !!ir (zf := AST.ite cond2 zf (t3 == n0)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.OF + | ConditionCodeOp.LOGICB + | ConditionCodeOp.LOGICW + | ConditionCodeOp.LOGICD + | ConditionCodeOp.LOGICQ + | ConditionCodeOp.XORXX -> + AST.b0 + | ConditionCodeOp.TraceStart -> + !?ir (genDynamicFlagsUpdate ctxt) + !.ctxt R.OF + | ConditionCodeOp.EFlags -> + !.ctxt R.OF + | _ -> Utils.futureFeature () + +let getSFLazy (ctxt: TranslationContext) (ir: IRBuilder) = + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ + | ConditionCodeOp.LOGICB + | ConditionCodeOp.LOGICW + | ConditionCodeOp.LOGICD + | ConditionCodeOp.LOGICQ + | ConditionCodeOp.ADDB + | ConditionCodeOp.ADDW + | ConditionCodeOp.ADDD + | ConditionCodeOp.ADDQ + | ConditionCodeOp.INCB + | ConditionCodeOp.INCW + | ConditionCodeOp.INCD + | ConditionCodeOp.INCQ + | ConditionCodeOp.DECB + | ConditionCodeOp.DECW + | ConditionCodeOp.DECD + | ConditionCodeOp.DECQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let t = getCCDst ctxt regType + t ?< AST.num0 regType + | ConditionCodeOp.SHLB + | ConditionCodeOp.SHLW + | ConditionCodeOp.SHLD + | ConditionCodeOp.SHLQ + | ConditionCodeOp.SHRB + | ConditionCodeOp.SHRW + | ConditionCodeOp.SHRD + | ConditionCodeOp.SHRQ + | ConditionCodeOp.SARB + | ConditionCodeOp.SARW + | ConditionCodeOp.SARD + | ConditionCodeOp.SARQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let t = getCCDst ctxt regType + let cnt = getCCSrc2 ctxt regType + AST.ite (cnt == AST.num0 regType) (!.ctxt R.SF) (t ?< AST.num0 regType) + | ConditionCodeOp.XORXX -> + AST.b0 + | ConditionCodeOp.TraceStart -> + !?ir (genDynamicFlagsUpdate ctxt) + !.ctxt R.SF + | ConditionCodeOp.EFlags -> + !.ctxt R.SF + | _ -> Utils.futureFeature () + +let getZFLazy (ctxt: TranslationContext) (ir: IRBuilder) = + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ + | ConditionCodeOp.LOGICB + | ConditionCodeOp.LOGICW + | ConditionCodeOp.LOGICD + | ConditionCodeOp.LOGICQ + | ConditionCodeOp.ADDB + | ConditionCodeOp.ADDW + | ConditionCodeOp.ADDD + | ConditionCodeOp.ADDQ + | ConditionCodeOp.INCB + | ConditionCodeOp.INCW + | ConditionCodeOp.INCD + | ConditionCodeOp.INCQ + | ConditionCodeOp.DECB + | ConditionCodeOp.DECW + | ConditionCodeOp.DECD + | ConditionCodeOp.DECQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let t = getCCDst ctxt regType + t == AST.num0 regType + | ConditionCodeOp.SHLB + | ConditionCodeOp.SHLW + | ConditionCodeOp.SHLD + | ConditionCodeOp.SHLQ + | ConditionCodeOp.SHRB + | ConditionCodeOp.SHRW + | ConditionCodeOp.SHRD + | ConditionCodeOp.SHRQ + | ConditionCodeOp.SARB + | ConditionCodeOp.SARW + | ConditionCodeOp.SARD + | ConditionCodeOp.SARQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let t = getCCDst ctxt regType + let cnt = getCCSrc2 ctxt regType + AST.ite (cnt == AST.num0 regType) (!.ctxt R.ZF) (t == AST.num0 regType) + | ConditionCodeOp.XORXX -> + AST.b1 + | ConditionCodeOp.TraceStart -> + !?ir (genDynamicFlagsUpdate ctxt) + !.ctxt R.ZF + | ConditionCodeOp.EFlags -> + !.ctxt R.ZF + | _ -> Utils.futureFeature () + +let getAFLazy (ctxt: TranslationContext) (ir: IRBuilder) = + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t2 := src1) + !!ir (t1 := t3 .+ t2) + let sf = t3 ?< AST.num0 regType + let cf = cfOnSub t1 t2 + let ofl = ofOnSub t1 t2 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.AF + | ConditionCodeOp.DECB + | ConditionCodeOp.DECW + | ConditionCodeOp.DECD + | ConditionCodeOp.DECQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t2 := src1) + !!ir (t1 := t3 .+ t2) + let sf = t3 ?< AST.num0 regType + let cf = !.ctxt R.CF + let ofl = ofOnSub t1 t2 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.AF + | ConditionCodeOp.ADDB + | ConditionCodeOp.ADDW + | ConditionCodeOp.ADDD + | ConditionCodeOp.ADDQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t1 := src1) + !!ir (t2 := t3 .- t1) + let cf = cfOnAdd t1 t3 + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.AF + | ConditionCodeOp.INCB + | ConditionCodeOp.INCW + | ConditionCodeOp.INCD + | ConditionCodeOp.INCQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t1 := src1) + !!ir (t2 := t3 .- t1) + let cf = !.ctxt R.CF + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.AF + | ConditionCodeOp.SHLB + | ConditionCodeOp.SHLW + | ConditionCodeOp.SHLD + | ConditionCodeOp.SHLQ + | ConditionCodeOp.SHRB + | ConditionCodeOp.SHRW + | ConditionCodeOp.SHRD + | ConditionCodeOp.SHRQ + | ConditionCodeOp.SARB + | ConditionCodeOp.SARW + | ConditionCodeOp.SARD + | ConditionCodeOp.SARQ + | ConditionCodeOp.LOGICB + | ConditionCodeOp.LOGICW + | ConditionCodeOp.LOGICD + | ConditionCodeOp.LOGICQ + | ConditionCodeOp.XORXX -> + !.ctxt R.AF + | ConditionCodeOp.TraceStart -> + !?ir (genDynamicFlagsUpdate ctxt) + !.ctxt R.AF + | ConditionCodeOp.EFlags -> + !.ctxt R.AF + | _ -> Utils.futureFeature () + +let getPFLazy (ctxt: TranslationContext) (ir: IRBuilder) = + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t2 := src1) + !!ir (t1 := t3 .+ t2) + let sf = t3 ?< AST.num0 regType + let cf = cfOnSub t1 t2 + let ofl = ofOnSub t1 t2 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.DECB + | ConditionCodeOp.DECW + | ConditionCodeOp.DECD + | ConditionCodeOp.DECQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t2 := src1) + !!ir (t1 := t3 .+ t2) + let sf = t3 ?< AST.num0 regType + let cf = !.ctxt R.CF + let ofl = ofOnSub t1 t2 t3 + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.ADDB + | ConditionCodeOp.ADDW + | ConditionCodeOp.ADDD + | ConditionCodeOp.ADDQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t1 := src1) + !!ir (t2 := t3 .- t1) + let cf = cfOnAdd t1 t3 + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.INCB + | ConditionCodeOp.INCW + | ConditionCodeOp.INCD + | ConditionCodeOp.INCQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + !!ir (t3 := dst) + !!ir (t1 := src1) + !!ir (t2 := t3 .- t1) + let cf = !.ctxt R.CF + let struct (ofl, sf) = osfOnAdd t1 t2 t3 ir + !?ir (enumEFLAGS ctxt t1 t2 t3 regType cf ofl sf) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.SHLB + | ConditionCodeOp.SHLW + | ConditionCodeOp.SHLD + | ConditionCodeOp.SHLQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let dst = getCCDst ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond1 = src2 == n1 + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let ofl = !.ctxt R.OF + let newOf = AST.xthi 1 dst <+> cf + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := dst) + !!ir (cf := AST.ite cond2 cf (AST.xthi 1 (t1 << (t2 .- n1)))) + !!ir (ofl := AST.ite cond1 newOf ofl) + !!ir (sf := AST.ite cond2 sf (AST.xthi 1 t3)) + !?ir (buildPF ctxt dst regType (Some cond2)) + !!ir (zf := AST.ite cond2 zf (t3 == n0)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.SHRB + | ConditionCodeOp.SHRW + | ConditionCodeOp.SHRD + | ConditionCodeOp.SHRQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let dst = getCCDst ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond1 = src2 == n1 + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let ofl = !.ctxt R.OF + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := dst) + !!ir (cf := AST.ite cond2 cf (AST.xtlo 1 (t1 ?>> (t2 .- n1)))) + !!ir (ofl := AST.ite cond1 (AST.xthi 1 t1) ofl) + !!ir (sf := AST.ite cond2 sf (AST.xthi 1 t3)) + !?ir (buildPF ctxt dst regType (Some cond2)) + !!ir (zf := AST.ite cond2 zf (t3 == n0)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.SARB + | ConditionCodeOp.SARW + | ConditionCodeOp.SARD + | ConditionCodeOp.SARQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let struct (t1, t2, t3) = tmpVars3 ir regType + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let dst = getCCDst ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond1 = src2 == n1 + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + let sf = !.ctxt R.SF + let zf = !.ctxt R.ZF + let ofl = !.ctxt R.OF + !!ir (t1 := src1) + !!ir (t2 := src2) + !!ir (t3 := dst) + !!ir (cf := AST.ite cond2 cf (AST.xtlo 1 (t1 ?>> (t2 .- n1)))) + !!ir (ofl := AST.ite cond1 AST.b0 ofl) + !!ir (sf := AST.ite cond2 sf (AST.xthi 1 t3)) + !?ir (buildPF ctxt dst regType (Some cond2)) + !!ir (zf := AST.ite cond2 zf (t3 == n0)) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.LOGICB + | ConditionCodeOp.LOGICW + | ConditionCodeOp.LOGICD + | ConditionCodeOp.LOGICQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let t = getCCDst ctxt regType + !!ir (!.ctxt R.SF := AST.xthi 1 t) + !!ir (!.ctxt R.ZF := t == (AST.num0 regType)) + !?ir (buildPF ctxt t regType None) + !!ir (!.ctxt R.CF := AST.b0) + !!ir (!.ctxt R.OF := AST.b0) + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags + !.ctxt R.PF + | ConditionCodeOp.XORXX -> + AST.b1 + | ConditionCodeOp.TraceStart -> + !?ir (genDynamicFlagsUpdate ctxt) + !.ctxt R.PF + | ConditionCodeOp.EFlags -> + !.ctxt R.PF + | _ -> Utils.futureFeature () + +let getCFLazy (ctxt: TranslationContext) (ir: IRBuilder) = + let ccOp = ctxt.ConditionCodeOp + match ccOp with + | ConditionCodeOp.SUBB + | ConditionCodeOp.SUBW + | ConditionCodeOp.SUBD + | ConditionCodeOp.SUBQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + cfOnSub (dst .+ src1) src1 + | ConditionCodeOp.ADDB + | ConditionCodeOp.ADDW + | ConditionCodeOp.ADDD + | ConditionCodeOp.ADDQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src1 = getCCSrc1 ctxt regType + let dst = getCCDst ctxt regType + cfOnAdd src1 dst + | ConditionCodeOp.INCB + | ConditionCodeOp.INCW + | ConditionCodeOp.INCD + | ConditionCodeOp.INCQ + | ConditionCodeOp.DECB + | ConditionCodeOp.DECW + | ConditionCodeOp.DECD + | ConditionCodeOp.DECQ -> + !.ctxt R.CF + | ConditionCodeOp.SHLB + | ConditionCodeOp.SHLW + | ConditionCodeOp.SHLD + | ConditionCodeOp.SHLQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + AST.ite cond2 cf (AST.xthi 1 (src1 << (src2 .- n1))) + | ConditionCodeOp.SHRB + | ConditionCodeOp.SHRW + | ConditionCodeOp.SHRD + | ConditionCodeOp.SHRQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + AST.ite cond2 cf (AST.xtlo 1 (src1 ?>> (src2 .- n1))) + | ConditionCodeOp.SARB + | ConditionCodeOp.SARW + | ConditionCodeOp.SARD + | ConditionCodeOp.SARQ -> + let size = 1 <<< ((int ccOp - int ConditionCodeOp.SUBB) &&& 0b11) + let regType = RegType.fromByteWidth size + let src1 = getCCSrc1 ctxt regType + let src2 = getCCSrc2 ctxt regType + let n0 = AST.num0 regType + let n1 = AST.num1 regType + let cond2 = src2 == n0 + let cf = !.ctxt R.CF + AST.ite cond2 cf (AST.xtlo 1 (src1 ?>> (src2 .- n1))) + | ConditionCodeOp.LOGICB + | ConditionCodeOp.LOGICW + | ConditionCodeOp.LOGICD + | ConditionCodeOp.LOGICQ + | ConditionCodeOp.XORXX -> + AST.b0 + | ConditionCodeOp.TraceStart -> + !?ir (genDynamicFlagsUpdate ctxt) + !.ctxt R.CF + | ConditionCodeOp.EFlags -> + !.ctxt R.CF + | _ -> Utils.futureFeature () +#endif diff --git a/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs b/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs index d59a1189..4f7ad3ab 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelMMXLifter.fs @@ -35,7 +35,7 @@ open B2R2.FrontEnd.BinLifter.Intel open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils let private movdRegToReg ctxt r1 r2 ir = - let tmp = !*ir 32 + let tmp = !+ir 32 match Register.getKind r1, Register.getKind r2 with | Register.Kind.XMM, _ -> !!ir (getPseudoRegVar ctxt r1 1 := AST.zext 64 (!.ctxt r2)) @@ -66,14 +66,14 @@ let private movdMemToReg ctxt src r ir = | _ -> Utils.impossible () let movd ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! movdRegToReg ctxt r1 r2 ir - | OprMem _, OprReg r -> let dst = transOprToExpr ins insLen ctxt dst + | OprMem _, OprReg r -> let dst = transOprToExpr ir false ins insLen ctxt dst movdRegToMem ctxt dst r ir - | OprReg r, OprMem _ -> let src = transOprToExpr ins insLen ctxt src + | OprReg r, OprMem _ -> let src = transOprToExpr ir false ins insLen ctxt src movdMemToReg ctxt src r ir | _, _ -> raise InvalidOperandException !>ir insLen @@ -92,13 +92,13 @@ let private movqRegToReg ctxt r1 r2 ir = | Register.Kind.MMX, Register.Kind.GP | Register.Kind.GP, Register.Kind.MMX -> !!ir (!.ctxt r1 := !.ctxt r2) - | _, _ -> Utils.impossible () + | _ -> raise InvalidOperandException let private movqRegToMem ctxt dst r ir = match Register.getKind r with | Register.Kind.XMM -> !!ir (dst := getPseudoRegVar ctxt r 1) | Register.Kind.MMX -> !!ir (dst := !.ctxt r) - | _ -> Utils.impossible () + | _ -> raise InvalidOperandException let private movqMemToReg ctxt src r ir = match Register.getKind r with @@ -106,17 +106,17 @@ let private movqMemToReg ctxt src r ir = !!ir (getPseudoRegVar ctxt r 1 := src) !!ir (getPseudoRegVar ctxt r 2 := AST.num0 64) | Register.Kind.MMX -> !!ir (!.ctxt r := src) - | _ -> Utils.impossible () + | _ -> raise InvalidOperandException let movq ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! movqRegToReg ctxt r1 r2 ir - | OprMem _, OprReg r -> let dst = transOprToExpr ins insLen ctxt dst + | OprMem _, OprReg r -> let dst = transOprToExpr ir false ins insLen ctxt dst movqRegToMem ctxt dst r ir - | OprReg r, OprMem _ -> let src = transOprToExpr ins insLen ctxt src + | OprReg r, OprMem _ -> let src = transOprToExpr ir false ins insLen ctxt src movqMemToReg ctxt src r ir | _, _ -> raise InvalidOperandException !>ir insLen @@ -143,239 +143,393 @@ let private saturateSignedWordToUnsignedByte expr = AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 8 expr)) let private saturateToSignedByte expr = - let checkMin = AST.slt expr (numI32 -128 8) - let checkMax = AST.sgt expr (numI32 127 8) - let minNum = numI32 -128 8 - let maxNum = numI32 127 8 - AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + let checkMin = AST.slt expr (numI32 0xff80 16) + let checkMax = AST.sgt expr (numI32 0x7f 16) + let minNum = numI32 0x80 8 + let maxNum = numI32 0x7f 8 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 8 expr)) let private saturateToSignedWord expr = - let checkMin = AST.slt expr (numI32 -32768 16) - let checkMax = AST.sgt expr (numI32 32767 16) - let minNum = numI32 -32768 16 - let maxNum = numI32 32767 16 - AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + let checkMin = AST.slt expr (numI32 0xffff8000 32) + let checkMax = AST.sgt expr (numI32 0x7fff 32) + let minNum = numI32 0x8000 16 + let maxNum = numI32 0x7fff 16 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 16 expr)) let private saturateToUnsignedByte expr = - let checkMin = AST.lt expr (numU32 0u 8) - let checkMax = AST.gt expr (numU32 0xffu 8) + let checkMin = AST.slt expr (numI32 0 16) + let checkMax = AST.sgt expr (numI32 0xff 16) let minNum = numU32 0u 8 let maxNum = numU32 0xffu 8 - AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 8 expr)) let private saturateToUnsignedWord expr = - let checkMin = AST.lt expr (numU32 0u 16) - let checkMax = AST.gt expr (numU32 0xffffu 16) + let checkMin = AST.slt expr (numI32 0 32) + let checkMax = AST.sgt expr (numI32 0xffff 32) let minNum = numU32 0u 16 - let maxNum = numU32 0xffu 16 - AST.ite checkMin minNum (AST.ite checkMax maxNum expr) + let maxNum = numU32 0xffffu 16 + AST.ite checkMin minNum (AST.ite checkMax maxNum (AST.xtlo 16 expr)) -let private makeSrc ir packSize packNum src = - let tSrc = Array.init packNum (fun _ -> !*ir packSize) - for i in 0 .. packNum - 1 do - !!ir (tSrc[i] := AST.extract src packSize (i * (int packSize))) - tSrc +let private r128to256 = function + | OprReg R.XMM0 -> R.YMM0 + | OprReg R.XMM1 -> R.YMM1 + | OprReg R.XMM2 -> R.YMM2 + | OprReg R.XMM3 -> R.YMM3 + | OprReg R.XMM4 -> R.YMM4 + | OprReg R.XMM5 -> R.YMM5 + | OprReg R.XMM6 -> R.YMM6 + | OprReg R.XMM7 -> R.YMM7 + | OprReg R.XMM8 -> R.YMM8 + | OprReg R.XMM9 -> R.YMM9 + | OprReg R.XMM10 -> R.YMM10 + | OprReg R.XMM11 -> R.YMM11 + | OprReg R.XMM12 -> R.YMM12 + | OprReg R.XMM13 -> R.YMM13 + | OprReg R.XMM14 -> R.YMM14 + | OprReg R.XMM15 -> R.YMM15 + | _ -> raise InvalidOperandException -let private buildPackedTwoOprs ins insLen ctxt packSz opFn bufSz dst src = - let ir = IRBuilder (bufSz) - let oprSize = getOperationSize ins - let packNum = oprSize / packSz - let makeSrc = makeSrc ir packSz +let private r128to512 = function + | OprReg R.XMM0 -> R.ZMM0 + | OprReg R.XMM1 -> R.ZMM1 + | OprReg R.XMM2 -> R.ZMM2 + | OprReg R.XMM3 -> R.ZMM3 + | OprReg R.XMM4 -> R.ZMM4 + | OprReg R.XMM5 -> R.ZMM5 + | OprReg R.XMM6 -> R.ZMM6 + | OprReg R.XMM7 -> R.ZMM7 + | OprReg R.XMM8 -> R.ZMM8 + | OprReg R.XMM9 -> R.ZMM9 + | OprReg R.XMM10 -> R.ZMM10 + | OprReg R.XMM11 -> R.ZMM11 + | OprReg R.XMM12 -> R.ZMM12 + | OprReg R.XMM13 -> R.ZMM13 + | OprReg R.XMM14 -> R.ZMM14 + | OprReg R.XMM15 -> R.ZMM15 + | _ -> raise InvalidOperandException + +let private r256to512 = function + | OprReg R.YMM0 -> R.ZMM0 + | OprReg R.YMM1 -> R.ZMM1 + | OprReg R.YMM2 -> R.ZMM2 + | OprReg R.YMM3 -> R.ZMM3 + | OprReg R.YMM4 -> R.ZMM4 + | OprReg R.YMM5 -> R.ZMM5 + | OprReg R.YMM6 -> R.ZMM6 + | OprReg R.YMM7 -> R.ZMM7 + | OprReg R.YMM8 -> R.ZMM8 + | OprReg R.YMM9 -> R.ZMM9 + | OprReg R.YMM10 -> R.ZMM10 + | OprReg R.YMM11 -> R.ZMM11 + | OprReg R.YMM12 -> R.ZMM12 + | OprReg R.YMM13 -> R.ZMM13 + | OprReg R.YMM14 -> R.ZMM14 + | OprReg R.YMM15 -> R.ZMM15 + | _ -> raise InvalidOperandException + +let fillZeroHigh128 ctxt dst ir = + let dst = r128to256 dst + let dstC, dstD = getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4 + let n0 = AST.num0 64 + !!ir (dstC := n0) + !!ir (dstD := n0) + +let fillZeroHigh256 ctxt dst ir = + let dst = r256to512 dst + let dstE, dstF, dstG, dstH = + getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, + getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6 + let n0 = AST.num0 64 + !!ir (dstE := n0) + !!ir (dstF := n0) + !!ir (dstG := n0) + !!ir (dstH := n0) + +let fillZeroFromVLToMaxVL ctxt dst vl maxVl ir = + let n0 = AST.num0 64 + match dst with + | OprReg _ -> + match maxVl, vl with + | 512, 128 -> + let dst = r128to512 dst + let dstC, dstD, dstE, dstF, dstG, dstH = + getPseudoRegVar ctxt dst 3, getPseudoRegVar ctxt dst 4, + getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, + getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 + !!ir (dstC := n0) + !!ir (dstD := n0) + !!ir (dstE := n0) + !!ir (dstF := n0) + !!ir (dstG := n0) + !!ir (dstH := n0) + | 512, 256 -> + let dst = r256to512 dst + let dstE, dstF, dstG, dstH = + getPseudoRegVar ctxt dst 5, getPseudoRegVar ctxt dst 6, + getPseudoRegVar ctxt dst 7, getPseudoRegVar ctxt dst 8 + !!ir (dstE := n0) + !!ir (dstF := n0) + !!ir (dstG := n0) + !!ir (dstH := n0) + | 512, 512 -> () + | _ -> raise InvalidOperandSizeException + | _ -> () + +let private buildPackedTwoOprs ins insLen ctxt isFillZero packSz opFn dst src = + let ir = !*ctxt ! -> - let dst = transOprToExpr ins insLen ctxt dst - let src = transOprToExpr ins insLen ctxt src - let src1 = makeSrc packNum dst - let src2 = match src.E with - | Load (_, rt, _, _) -> makeSrc (rt / packSz) src - | _ -> makeSrc packNum src - !!ir (dst := opFn oprSize src1 src2 |> AST.concatArr) - | 128 -> - let packNum = packNum / (oprSize / 64) - let srcAppend src = - let src = transOprToExprVec ins insLen ctxt src - List.map (makeSrc packNum) src |> List.fold Array.append [||] - let tSrc = opFn oprSize (srcAppend dst) (srcAppend src) - let dst = transOprToExprVec ins insLen ctxt dst - let packNum = Array.length tSrc / List.length dst - let assign idx dst = - !!ir (dst := Array.sub tSrc (packNum * idx) packNum |> AST.concatArr) - List.iteri assign dst - | _ -> raise InvalidOperandSizeException + let oprSize = getOperationSize ins + let packNum = 64 / packSz + let src1 = transOprToArr ir true ins insLen ctxt packSz packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt packSz packNum oprSize src + let result = opFn oprSize src1 src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + if isFillZero then fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir else () !>ir insLen -let private buildPackedThreeOprs ins iLen ctxt packSz opFn bufSz dst s1 s2 = - let ir = IRBuilder (bufSz) - let oprSize = getOperationSize ins - let packNum = oprSize / packSz - let makeSrc = makeSrc ir packSz +let private buildPackedThreeOprs i iLen ctxt isFillZero packSz opFn dst s1 s2 = + let ir = !*ctxt ! -> - let dst = transOprToExpr ins iLen ctxt dst - let src1 = transOprToExpr ins iLen ctxt s1 - let src2 = transOprToExpr ins iLen ctxt s2 - let src1 = makeSrc packNum src1 - let src2 = makeSrc packNum src2 - !!ir (dst := opFn oprSize src1 src2 |> AST.concatArr) - | 128 | 256 -> - let packNum = packNum / (oprSize / 64) - let dst = transOprToExprVec ins iLen ctxt dst - let srcAppend src = - let src = transOprToExprVec ins iLen ctxt src - List.map (makeSrc packNum) src |> List.fold Array.append [||] - let tSrc = opFn oprSize (srcAppend s1) (srcAppend s2) - let assign idx dst = - !!ir (dst := Array.sub tSrc (packNum * idx) packNum |> AST.concatArr) - List.iteri assign dst - | _ -> raise InvalidOperandSizeException + let oprSize = getOperationSize i + let packNum = 64 / packSz + let src1 = transOprToArr ir true i iLen ctxt packSz packNum oprSize s1 + let src2 = transOprToArr ir true i iLen ctxt packSz packNum oprSize s2 + let result = opFn oprSize src1 src2 + assignPackedInstr ir false i iLen ctxt packNum oprSize dst result + if isFillZero then fillZeroFromVLToMaxVL ctxt dst oprSize 512 ir else () !>ir iLen -let buildPackedInstr (ins: InsInfo) insLen ctxt packSz opFn bufSz = +let buildPackedInstr (ins: InsInfo) insLen ctxt isFillZero packSz opFn = match ins.Operands with | TwoOperands (o1, o2) -> - buildPackedTwoOprs ins insLen ctxt packSz opFn bufSz o1 o2 + buildPackedTwoOprs ins insLen ctxt isFillZero packSz opFn o1 o2 | ThreeOperands (o1, o2, o3) -> - buildPackedThreeOprs ins insLen ctxt packSz opFn bufSz o1 o2 o3 + buildPackedThreeOprs ins insLen ctxt isFillZero packSz opFn o1 o2 o3 | _ -> raise InvalidOperandException +let private packWithSaturation ins insLen ctxt packSz opFn = + let ir = !*ctxt + ! / sPackSz + let dPackSz = packSz / 2 + let dPackNum = 64 / dPackSz + let struct (dst, src) = getTwoOprs ins + let src1 = transOprToArr ir true ins insLen ctxt sPackSz sPackNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt sPackSz sPackNum oprSize src + let result = opFn oprSize src1 src2 + assignPackedInstr ir false ins insLen ctxt dPackNum oprSize dst result + !>ir insLen + let private opPackssdw _ src1 src2 = Array.append src1 src2 |> Array.map saturateSignedDwordToSignedWord let packssdw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPackssdw 16 + packWithSaturation ins insLen ctxt 32 opPackssdw let private opPacksswb _ src1 src2 = Array.append src1 src2 |> Array.map saturateSignedWordToSignedByte let packsswb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPacksswb 16 + packWithSaturation ins insLen ctxt 16 opPacksswb let private opPackuswb _ src1 src2 = Array.append src1 src2 |> Array.map saturateSignedWordToUnsignedByte let packuswb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPackuswb 16 + packWithSaturation ins insLen ctxt 16 opPackuswb -let private opPunpck oprSize src1 src2 isHigh = - match oprSize with - | 64 | 128 -> - let half = Array.length src1 / 2 - let sPos = if isHigh then half else 0 - let src1 = Array.sub src1 sPos half - let src2 = Array.sub src2 sPos half +let unpackLowHighData ins insLen ctxt packSize isHigh = + let ir = !*ctxt + ! / packSize + let allPackNum = oprSz / packSize + let struct (dst, src1, src2) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt packSize packNum oprSz src1 + let src2 = transOprToArr ir true ins insLen ctxt packSize packNum oprSz src2 + let resultA, resultB = + Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1 src2 + |> List.rev |> List.toArray |> Array.splitAt allPackNum + let result = + if oprSz = 128 then + if isHigh then resultB else resultA + elif oprSz = 256 then + let resALow, resAHigh = Array.splitAt (allPackNum / 2) resultA + let resBLow, resBHigh = Array.splitAt (allPackNum / 2) resultB + if isHigh then Array.append resAHigh resBHigh else + Array.append resALow resBLow + else raise InvalidOperandSizeException + assignPackedInstr ir false ins insLen ctxt packNum oprSz dst result + fillZeroFromVLToMaxVL ctxt dst oprSz 512 ir + !>ir insLen + +let opUnpackHighData oprSize src1 src2 = + let result = Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1 src2 |> List.rev |> List.toArray + let resultA, resultB = Array.splitAt (Array.length result / 2) result + match oprSize with + | 64 | 128 -> resultB | 256 -> - let half = Array.length src1 / 2 - let src1A = Array.sub src1 0 half - let src1B = Array.sub src1 half half - let src2A = Array.sub src2 0 half - let src2B = Array.sub src2 half half - let half = Array.length src1A / 2 - let sPos = if isHigh then half else 0 - let src1A = Array.sub src1A sPos half - let src2A = Array.sub src2A sPos half - let src1B = Array.sub src1B sPos half - let src2B = Array.sub src2B sPos half - List.append - (Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1B src2B) - (Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1A src2A) - |> List.rev |> List.toArray + let _, resAHigh = Array.splitAt (Array.length resultA / 2) resultA + let _, resBHigh = Array.splitAt (Array.length resultB / 2) resultB + Array.append resAHigh resBHigh | _ -> raise InvalidOperandSizeException -let opPunpckHigh oprSize src1 src2 = opPunpck oprSize src1 src2 true - -let opPunpckLow oprSize src1 src2 = opPunpck oprSize src1 src2 false +let opUnpackLowData oprSize src1 src2 = + let result = + Array.fold2 (fun acc e1 e2 -> e2 :: e1 :: acc) [] src1 src2 + |> List.rev |> List.toArray + let resultA, resultB = Array.splitAt (Array.length result / 2) result + match oprSize with + | 64 | 128 -> resultA + | 256 -> + let resALow, _ = Array.splitAt (Array.length resultA / 2) resultA + let resBLow, _ = Array.splitAt (Array.length resultB / 2) resultB + Array.append resALow resBLow + | _ -> raise InvalidOperandSizeException let punpckhbw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPunpckHigh 64 + buildPackedInstr ins insLen ctxt false 8 opUnpackHighData let punpckhwd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPunpckHigh 32 + buildPackedInstr ins insLen ctxt false 16 opUnpackHighData let punpckhdq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPunpckHigh 16 + buildPackedInstr ins insLen ctxt false 32 opUnpackHighData let punpcklbw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPunpckLow 64 + buildPackedInstr ins insLen ctxt false 8 opUnpackLowData let punpcklwd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPunpckLow 32 + buildPackedInstr ins insLen ctxt false 16 opUnpackLowData let punpckldq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPunpckLow 16 + buildPackedInstr ins insLen ctxt false 32 opUnpackLowData let opP op _ = Array.map2 (op) let paddb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 (opP (.+)) 8 + buildPackedInstr ins insLen ctxt false 8 (opP (.+)) let paddw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 (opP (.+)) 8 + buildPackedInstr ins insLen ctxt false 16 (opP (.+)) let paddd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 (opP (.+)) 8 + buildPackedInstr ins insLen ctxt false 32 (opP (.+)) let private opPaddsb oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToSignedByte + let src1 = src1 |> Array.map (AST.sext 16) + let src2 = src2 |> Array.map (AST.sext 16) + (opP (.+)) 16 src1 src2 |> Array.map saturateToSignedByte let paddsb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPaddsb 16 + buildPackedInstr ins insLen ctxt false 8 opPaddsb let private opPaddsw oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToSignedWord + let src1 = src1 |> Array.map (AST.sext 32) + let src2 = src2 |> Array.map (AST.sext 32) + (opP (.+)) 32 src1 src2 |> Array.map saturateToSignedWord let paddsw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPaddsw 16 + buildPackedInstr ins insLen ctxt false 16 opPaddsw let private opPaddusb oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToUnsignedByte + let src1 = src1 |> Array.map (AST.zext 16) + let src2 = src2 |> Array.map (AST.zext 16) + (opP (.+)) 16 src1 src2 |> Array.map saturateToUnsignedByte let paddusb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPaddusb 16 + buildPackedInstr ins insLen ctxt false 8 opPaddusb let private opPaddusw oprSize src1 src2 = - (opP (.+)) oprSize src1 src2 |> Array.map saturateToUnsignedWord + let src1 = src1 |> Array.map (AST.zext 32) + let src2 = src2 |> Array.map (AST.zext 32) + (opP (.+)) 32 src1 src2 |> Array.map saturateToUnsignedWord let paddusw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPaddusw 16 + buildPackedInstr ins insLen ctxt false 16 opPaddusw + +let private makeHorizonSrc src1 src2 = + let (odd, even), _ = + Array.foldi (fun (odd, even) i e -> + if i % 2 = 0 then e :: odd, even + else odd, e :: even) ([], []) (Array.append src1 src2) + odd |> List.rev |> List.toArray, even |> List.rev |> List.toArray -let opPsub _ = Array.map2 (.-) +let packedHorizon ins insLen ctxt packSz opFn = + let ir = !*ctxt + ! / packSz + let src1 = transOprToArr ir true ins insLen ctxt packSz packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt packSz packNum oprSize src + let src1, src2 = makeHorizonSrc src1 src2 + let result = opFn oprSize src1 src2 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + !>ir insLen + +let phaddd ins insLen ctxt = + packedHorizon ins insLen ctxt 32 (opP (.+)) + +let phaddw ins insLen ctxt = + packedHorizon ins insLen ctxt 16 (opP (.+)) + +let phaddsw ins insLen ctxt = + packedHorizon ins insLen ctxt 16 opPaddsw let psubb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPsub 8 + buildPackedInstr ins insLen ctxt false 8 (opP (.-)) let psubw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPsub 8 + buildPackedInstr ins insLen ctxt false 16 (opP (.-)) let psubd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPsub 8 + buildPackedInstr ins insLen ctxt false 32 (opP (.-)) let private opPsubsb oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToSignedByte + let src1 = src1 |> Array.map (AST.sext 16) + let src2 = src2 |> Array.map (AST.sext 16) + (opP (.-)) 16 src1 src2 |> Array.map saturateToSignedByte let psubsb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPsubsb 8 + buildPackedInstr ins insLen ctxt false 8 opPsubsb let private opPsubsw oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToSignedWord + let src1 = src1 |> Array.map (AST.sext 32) + let src2 = src2 |> Array.map (AST.sext 32) + (opP (.-)) 32 src1 src2 |> Array.map saturateToSignedWord let psubsw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPsubsw 8 + buildPackedInstr ins insLen ctxt false 16 opPsubsw -let private opPsubusb oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToUnsignedByte +let private opPsubusb _ src1 src2 = + let src1 = src1 |> Array.map (AST.zext 16) + let src2 = src2 |> Array.map (AST.zext 16) + (opP (.-)) 16 src1 src2 |> Array.map saturateToUnsignedByte let psubusb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPsubusb 8 + buildPackedInstr ins insLen ctxt false 8 opPsubusb -let private opPsubusw oprSize src1 src2 = - opPsub oprSize src1 src2 |> Array.map saturateToUnsignedWord +let private opPsubusw _ src1 src2 = + let src1 = src1 |> Array.map (AST.zext 32) + let src2 = src2 |> Array.map (AST.zext 32) + (opP (.-)) 32 src1 src2 |> Array.map saturateToUnsignedWord let psubusw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPsubusw 8 + buildPackedInstr ins insLen ctxt false 16 opPsubusw + +let phsubd ins insLen ctxt = + packedHorizon ins insLen ctxt 32 (opP (.-)) + +let phsubw ins insLen ctxt = + packedHorizon ins insLen ctxt 16 (opP (.-)) + +let phsubsw ins insLen ctxt = + packedHorizon ins insLen ctxt 16 opPsubsw let opPmul resType extr extSz packSz src1 src2 = Array.map2 (fun e1 e2 -> extr extSz e1 .* extr extSz e2) src1 src2 @@ -384,12 +538,12 @@ let opPmul resType extr extSz packSz src1 src2 = let private opPmulhw _ = opPmul AST.xthi AST.sext 32 16 let pmulhw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPmulhw 32 + buildPackedInstr ins insLen ctxt false 16 opPmulhw -let private opPmullw _ = opPmul AST.xtlo AST.sext 32 16 +let opPmullw _ = opPmul AST.xtlo AST.sext 32 16 let pmullw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPmullw 32 + buildPackedInstr ins insLen ctxt false 16 opPmullw let private opPmaddwd _ = let lowAndSExt expr = AST.xtlo 16 expr |> AST.sext 32 @@ -400,7 +554,7 @@ let private opPmaddwd _ = Array.map2 packAdd let pmaddwd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPmaddwd 16 + buildPackedInstr ins insLen ctxt false 32 opPmaddwd let opPcmp packSz cmpOp = Array.map2 (fun e1 e2 -> @@ -409,120 +563,138 @@ let opPcmp packSz cmpOp = let opPcmpeqb _ = opPcmp 8 (==) let pcmpeqb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPcmpeqb 32 + buildPackedInstr ins insLen ctxt false 8 opPcmpeqb let private opPcmpeqw _ = opPcmp 16 (==) let pcmpeqw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPcmpeqw 32 + buildPackedInstr ins insLen ctxt false 16 opPcmpeqw let opPcmpeqd _ = opPcmp 32 (==) let pcmpeqd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPcmpeqd 16 + buildPackedInstr ins insLen ctxt false 32 opPcmpeqd let opPcmpgtb _ = opPcmp 8 AST.sgt let pcmpgtb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPcmpgtb 32 + buildPackedInstr ins insLen ctxt false 8 opPcmpgtb let private opPcmpgtw _ = opPcmp 16 AST.sgt let pcmpgtw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPcmpgtw 32 + buildPackedInstr ins insLen ctxt false 16 opPcmpgtw let private opPcmpgtd _ = opPcmp 32 AST.sgt let pcmpgtd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPcmpgtd 16 + buildPackedInstr ins insLen ctxt false 32 opPcmpgtd let opPand _ = Array.map2 (.&) let pand ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPand 8 + buildPackedInstr ins insLen ctxt false 64 opPand let opPandn _ = Array.map2 (fun e1 e2 -> (AST.not e1) .& e2) let pandn ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPandn 8 + buildPackedInstr ins insLen ctxt false 64 opPandn let opPor _ = Array.map2 (.|) let por ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPor 8 + buildPackedInstr ins insLen ctxt false 64 opPor let pxor ins insLen ctxt = - let ir = IRBuilder (4) - let oprSize = getOperationSize ins + let ir = !*ctxt ! -> - let struct (dst, src) = transTwoOprs ins insLen ctxt + let struct (dst, src) = transTwoOprs ir false ins insLen ctxt !!ir (dst := dst <+> src) | 128 -> let struct (dst, src) = getTwoOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ir false ins insLen ctxt src !!ir (dstA := dstA <+> srcA) !!ir (dstB := dstB <+> srcB) | _ -> raise InvalidOperandSizeException !>ir insLen let private opShiftPackedDataLogical oprSize packSz shift src1 src2 = - let count = AST.concatArr src2 |> AST.zext oprSize - let cond = AST.gt count (numI32 ((int packSz) - 1) oprSize) - let shifted expr = AST.extract (shift (AST.zext oprSize expr) count) packSz 0 - Array.map (fun e -> AST.ite cond (AST.num0 packSz) (shifted e)) src1 + let pNum = int (oprSize / packSz) + let z = AST.num0 packSz + match oprSize with + | 64 -> + let count = AST.concatArr src2 |> AST.zext 64 + let cond = count .> (numI32 ((int packSz) - 1) 64) + Array.map (fun e -> + AST.ite cond z (AST.xtlo packSz (shift (AST.zext 64 e) count))) src1 + | 128 -> + let count = AST.concatArr (Array.sub src2 0 (pNum / 2)) |> AST.zext 64 + let cond = count .> (numI32 ((int packSz) - 1) 64) + Array.map (fun e -> + AST.ite cond z (AST.xtlo packSz (shift (AST.zext 64 e) count))) src1 + | _ -> raise InvalidOperandSizeException let private opPsllw oprSize = opShiftPackedDataLogical oprSize 16 (<<) let psllw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPsllw 8 + buildPackedInstr ins insLen ctxt false 16 opPsllw let private opPslld oprSize = opShiftPackedDataLogical oprSize 32 (<<) let pslld ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPslld 8 + buildPackedInstr ins insLen ctxt false 32 opPslld let private opPsllq oprSize = opShiftPackedDataLogical oprSize 64 (<<) let psllq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPsllq 8 + buildPackedInstr ins insLen ctxt false 64 opPsllq let private opPsrlw oprSize = opShiftPackedDataLogical oprSize 16 (>>) let psrlw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPsrlw 32 + buildPackedInstr ins insLen ctxt false 16 opPsrlw let private opPsrld oprSize = opShiftPackedDataLogical oprSize 32 (>>) let psrld ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPsrld 16 + buildPackedInstr ins insLen ctxt false 32 opPsrld let private opPsrlq oprSize = opShiftPackedDataLogical oprSize 64 (>>) let psrlq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPsrlq 8 + buildPackedInstr ins insLen ctxt false 64 opPsrlq let private opShiftPackedDataRightArith oprSize packSz src1 src2 = - let count = AST.concatArr src2 |> AST.zext oprSize - let cond = AST.gt count (numI32 ((int packSz) - 1) oprSize) - let count = AST.ite cond (numI32 (int packSz) oprSize) count - let shifted expr = AST.extract ((AST.sext oprSize expr) ?>> count) packSz 0 - Array.map shifted src1 + let pNum = int (oprSize / packSz) + match oprSize with + | 64 -> + let count = AST.concatArr src2 |> AST.zext 64 + let cond = count .> (numI32 ((int packSz) - 1) 64) + let count = AST.ite cond (numI32 (int packSz) 64) count + Array.map (fun e -> AST.xtlo packSz ((AST.sext 64 e) ?>> count)) src1 + | 128 -> + let count = AST.concatArr (Array.sub src2 0 (pNum / 2)) |> AST.zext 64 + let cond = count .> (numI32 ((int packSz) - 1) 64) + let count = AST.ite cond (numI32 (int packSz) 64) count + Array.map (fun e -> AST.xtlo packSz ((AST.sext 64 e) ?>> count)) src1 + | _ -> raise InvalidOperandSizeException let private opPsraw oprSize = opShiftPackedDataRightArith oprSize 16 let psraw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPsraw 32 + buildPackedInstr ins insLen ctxt false 16 opPsraw let private opPsrad oprSize = opShiftPackedDataRightArith oprSize 32 let psrad ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPsrad 16 + buildPackedInstr ins insLen ctxt false 32 opPsrad let emms _ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt !) !>ir insLen diff --git a/src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs b/src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs index 7f03158d..80ebbdfa 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelOpcodes.fs @@ -21,7 +21,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *) - namespace B2R2.FrontEnd.BinLifter.Intel /// @@ -553,2243 +552,2275 @@ type Opcode = | INSW = 260 /// Call to Interrupt (Interrupt vector specified by immediate byte). | INT = 261 + /// Call to Interrupt Procedure (Debug trap). + | INT1 = 262 /// Call to Interrupt (Interrupt 3-trap to debugger). - | INT3 = 262 + | INT3 = 263 /// Call to Interrupt (InteInterrupt 4-if overflow flag is 1). - | INTO = 263 + | INTO = 264 /// Invalidate Internal Caches. - | INVD = 264 + | INVD = 265 /// Invalidate Translations Derived from EPT. - | INVEPT = 265 + | INVEPT = 266 /// Invalidate TLB Entries. - | INVLPG = 266 + | INVLPG = 267 /// Invalidate Process-Context Identifier. - | INVPCID = 267 + | INVPCID = 268 /// Invalidate Translations Based on VPID. - | INVVPID = 268 + | INVVPID = 269 /// Return from interrupt. - | IRET = 269 + | IRET = 270 /// Interrupt return (32-bit operand size). - | IRETD = 270 + | IRETD = 271 /// Interrupt return (64-bit operand size). - | IRETQ = 271 + | IRETQ = 272 /// Interrupt return (16-bit operand size). - | IRETW = 272 + | IRETW = 273 /// Jump if Condition Is Met (Jump near if not below, CF = 0). - | JAE = 273 - | JNC = 273 - | JNB = 273 + | JAE = 274 + | JNC = 274 + | JNB = 274 /// Jump if Condition Is Met (Jump short if below, CF = 1). - | JC = 274 - | JNAE = 274 - | JB = 274 + | JC = 275 + | JNAE = 275 + | JB = 275 /// Jump if Condition Is Met (Jump short if CX register is 0). - | JCXZ = 275 + | JCXZ = 276 /// Jump if Condition Is Met (Jump short if ECX register is 0). - | JECXZ = 276 + | JECXZ = 277 /// Jump if Condition Is Met (Jump near if not less, SF = OF). - | JGE = 277 - | JNL = 277 + | JGE = 278 + | JNL = 278 /// Far jmp. - | JMPFar = 278 + | JMPFar = 279 /// Near jmp. - | JMPNear = 279 + | JMPNear = 280 /// Jump if Condition Is Met (Jump short if below or equal, CF = 1 or ZF). - | JNA = 280 - | JBE = 280 + | JNA = 281 + | JBE = 281 /// Jump if Condition Is Met (Jump short if above, CF = 0 and ZF = 0). - | JNBE = 281 - | JA = 281 + | JNBE = 282 + | JA = 282 /// Jump if Cond Is Met (Jump short if less or equal, ZF = 1 or SF <> OF). - | JNG = 282 - | JLE = 282 + | JNG = 283 + | JLE = 283 /// Jump if Condition Is Met (Jump short if less, SF <> OF). - | JNGE = 283 - | JL = 283 + | JNGE = 284 + | JL = 284 /// Jump if Condition Is Met (Jump short if greater, ZF = 0 and SF = OF). - | JNLE = 284 - | JG = 284 + | JNLE = 285 + | JG = 285 /// Jump if Condition Is Met (Jump near if not overflow, OF = 0). - | JNO = 285 + | JNO = 286 /// Jump if Condition Is Met (Jump near if not sign, SF = 0). - | JNS = 286 + | JNS = 287 /// Jump if Condition Is Met (Jump near if not zero, ZF = 0). - | JNZ = 287 - | JNE = 287 + | JNZ = 288 + | JNE = 288 /// Jump if Condition Is Met (Jump near if overflow, OF = 1). - | JO = 288 + | JO = 289 /// Jump if Condition Is Met (Jump near if parity, PF = 1). - | JP = 289 - | JPE = 289 + | JP = 290 + | JPE = 290 /// Jump if Condition Is Met (Jump near if not parity, PF = 0). - | JPO = 290 - | JNP = 290 + | JPO = 291 + | JNP = 291 /// Jump if Condition Is Met (Jump short if RCX register is 0). - | JRCXZ = 291 + | JRCXZ = 292 /// Jump if Condition Is Met (Jump short if sign, SF = 1). - | JS = 292 + | JS = 293 /// Jump if Condition Is Met (Jump short if zero, ZF = 1). - | JZ = 293 - | JE = 293 + | JZ = 294 + | JE = 294 /// Add two 8-bit opmasks. - | KADDB = 294 + | KADDB = 295 /// Add two 32-bit opmasks. - | KADDD = 295 + | KADDD = 296 /// Add two 64-bit opmasks. - | KADDQ = 296 + | KADDQ = 297 /// Add two 16-bit opmasks. - | KADDW = 297 + | KADDW = 298 /// Logical AND two 8-bit opmasks. - | KANDB = 298 + | KANDB = 299 /// Logical AND two 32-bit opmasks. - | KANDD = 299 + | KANDD = 300 /// Logical AND NOT two 8-bit opmasks. - | KANDNB = 300 + | KANDNB = 301 /// Logical AND NOT two 32-bit opmasks. - | KANDND = 301 + | KANDND = 302 /// Logical AND NOT two 64-bit opmasks. - | KANDNQ = 302 + | KANDNQ = 303 /// Logical AND NOT two 16-bit opmasks. - | KANDNW = 303 + | KANDNW = 304 /// Logical AND two 64-bit opmasks. - | KANDQ = 304 + | KANDQ = 305 /// Logical AND two 16-bit opmasks. - | KANDW = 305 + | KANDW = 306 /// Move from or move to opmask register of 8-bit data. - | KMOVB = 306 + | KMOVB = 307 /// Move from or move to opmask register of 32-bit data. - | KMOVD = 307 + | KMOVD = 308 /// Move from or move to opmask register of 64-bit data. - | KMOVQ = 308 + | KMOVQ = 309 /// Move from or move to opmask register of 16-bit data. - | KMOVW = 309 + | KMOVW = 310 /// Bitwise NOT of two 8-bit opmasks. - | KNOTB = 310 + | KNOTB = 311 /// Bitwise NOT of two 32-bit opmasks. - | KNOTD = 311 + | KNOTD = 312 /// Bitwise NOT of two 64-bit opmasks. - | KNOTQ = 312 + | KNOTQ = 313 /// Bitwise NOT of two 16-bit opmasks. - | KNOTW = 313 + | KNOTW = 314 /// Logical OR two 8-bit opmasks. - | KORB = 314 + | KORB = 315 /// Logical OR two 32-bit opmasks. - | KORD = 315 + | KORD = 316 /// Logical OR two 64-bit opmasks. - | KORQ = 316 + | KORQ = 317 /// Update EFLAGS according to the result of bitwise OR of two 8-bit opmasks. - | KORTESTB = 317 + | KORTESTB = 318 /// Update EFLAGS according to the result of bitwise OR of two 32-bit opmasks. - | KORTESTD = 318 + | KORTESTD = 319 /// Update EFLAGS according to the result of bitwise OR of two 64-bit opmasks. - | KORTESTQ = 319 + | KORTESTQ = 320 /// Update EFLAGS according to the result of bitwise OR of two 16-bit opmasks. - | KORTESTW = 320 + | KORTESTW = 321 /// Logical OR two 16-bit opmasks. - | KORW = 321 + | KORW = 322 /// Shift left 8-bitopmask by specified count. - | KSHIFTLB = 322 + | KSHIFTLB = 323 /// Shift left 32-bitopmask by specified count. - | KSHIFTLD = 323 + | KSHIFTLD = 324 /// Shift left 64-bitopmask by specified count. - | KSHIFTLQ = 324 + | KSHIFTLQ = 325 /// Shift left 16-bitopmask by specified count. - | KSHIFTLW = 325 + | KSHIFTLW = 326 /// Shift right 8-bit opmask by specified count. - | KSHIFTRB = 326 + | KSHIFTRB = 327 /// Shift right 32-bit opmask by specified count. - | KSHIFTRD = 327 + | KSHIFTRD = 328 /// Shift right 64-bit opmask by specified count. - | KSHIFTRQ = 328 + | KSHIFTRQ = 329 /// Shift right 16-bit opmask by specified count. - | KSHIFTRW = 329 + | KSHIFTRW = 330 /// Update EFLAGS according to result of bitwise TEST of two 8-bit opmasks. - | KTESTB = 330 + | KTESTB = 331 /// Update EFLAGS according to result of bitwise TEST of two 32-bit opmasks. - | KTESTD = 331 + | KTESTD = 332 /// Update EFLAGS according to result of bitwise TEST of two 64-bit opmasks. - | KTESTQ = 332 + | KTESTQ = 333 /// Update EFLAGS according to result of bitwise TEST of two 16-bit opmasks. - | KTESTW = 333 + | KTESTW = 334 /// Unpack and interleave two 8-bit opmasks into 16-bit mask. - | KUNPCKBW = 334 + | KUNPCKBW = 335 /// Unpack and interleave two 32-bit opmasks into 64-bit mask. - | KUNPCKDQ = 335 + | KUNPCKDQ = 336 /// Unpack and interleave two 16-bit opmasks into 32-bit mask. - | KUNPCKWD = 336 + | KUNPCKWD = 337 /// Bitwise logical XNOR of two 8-bit opmasks. - | KXNORB = 337 + | KXNORB = 338 /// Bitwise logical XNOR of two 32-bit opmasks. - | KXNORD = 338 + | KXNORD = 339 /// Bitwise logical XNOR of two 64-bit opmasks. - | KXNORQ = 339 + | KXNORQ = 340 /// Bitwise logical XNOR of two 16-bit opmasks. - | KXNORW = 340 + | KXNORW = 341 /// Logical XOR of two 8-bit opmasks. - | KXORB = 341 + | KXORB = 342 /// Logical XOR of two 32-bit opmasks. - | KXORD = 342 + | KXORD = 343 /// Logical XOR of two 64-bit opmasks. - | KXORQ = 343 + | KXORQ = 344 /// Logical XOR of two 16-bit opmasks. - | KXORW = 344 + | KXORW = 345 /// Load Status Flags into AH Register. - | LAHF = 345 + | LAHF = 346 /// Load Access Rights Byte. - | LAR = 346 + | LAR = 347 /// Load Unaligned Integer 128 Bits. - | LDDQU = 347 + | LDDQU = 348 /// Load MXCSR Register. - | LDMXCSR = 348 + | LDMXCSR = 349 /// Load Far Pointer (DS). - | LDS = 349 + | LDS = 350 /// Load Effective Address. - | LEA = 350 + | LEA = 351 /// High Level Procedure Exit. - | LEAVE = 351 + | LEAVE = 352 /// Load Far Pointer (ES). - | LES = 352 + | LES = 353 /// Load Fence. - | LFENCE = 353 + | LFENCE = 354 /// Load Far Pointer (FS). - | LFS = 354 + | LFS = 355 /// Load GlobalDescriptor Table Register. - | LGDT = 355 + | LGDT = 356 /// Load Far Pointer (GS). - | LGS = 356 + | LGS = 357 /// Load Interrupt Descriptor Table Register. - | LIDT = 357 + | LIDT = 358 /// Load Local Descriptor Table Register. - | LLDT = 358 + | LLDT = 359 /// Load Machine Status Word. - | LMSW = 359 + | LMSW = 360 /// Assert LOCK# Signal Prefix. - | LOCK = 360 + | LOCK = 361 /// Load String (byte). - | LODSB = 361 + | LODSB = 362 /// Load String (doubleword). - | LODSD = 362 + | LODSD = 363 /// Load String (quadword). - | LODSQ = 363 + | LODSQ = 364 /// Load String (word). - | LODSW = 364 + | LODSW = 365 /// Loop According to ECX Counter (count <> 0). - | LOOP = 365 + | LOOP = 366 /// Loop According to ECX Counter (count <> 0 and ZF = 1). - | LOOPE = 366 + | LOOPE = 367 /// Loop According to ECX Counter (count <> 0 and ZF = 0). - | LOOPNE = 367 + | LOOPNE = 368 /// Load Segment Limit. - | LSL = 368 + | LSL = 369 /// Load Far Pointer (SS). - | LSS = 369 + | LSS = 370 /// Load Task Register. - | LTR = 370 + | LTR = 371 /// the Number of Leading Zero Bits. - | LZCNT = 371 + | LZCNT = 372 /// Store Selected Bytes of Double Quadword. - | MASKMOVDQU = 372 + | MASKMOVDQU = 373 /// Store Selected Bytes of Quadword. - | MASKMOVQ = 373 + | MASKMOVQ = 374 /// Return Maximum Packed Double-Precision Floating-Point Values. - | MAXPD = 374 + | MAXPD = 375 /// Return Maximum Packed Single-Precision Floating-Point Values. - | MAXPS = 375 + | MAXPS = 376 /// Return Maximum Scalar Double-Precision Floating-Point Values. - | MAXSD = 376 + | MAXSD = 377 /// Return Maximum Scalar Single-Precision Floating-Point Values. - | MAXSS = 377 + | MAXSS = 378 /// Memory Fence. - | MFENCE = 378 + | MFENCE = 379 /// Return Minimum Packed Double-Precision Floating-Point Values. - | MINPD = 379 + | MINPD = 380 /// Return Minimum Packed Single-Precision Floating-Point Values. - | MINPS = 380 + | MINPS = 381 /// Return Minimum Scalar Double-Precision Floating-Point Values. - | MINSD = 381 + | MINSD = 382 /// Return Minimum Scalar Single-Precision Floating-Point Values. - | MINSS = 382 + | MINSS = 383 /// Set Up Monitor Address. - | MONITOR = 383 + | MONITOR = 384 /// MOV. - | MOV = 384 + | MOV = 385 /// Move Aligned Packed Double-Precision Floating-Point Values. - | MOVAPD = 385 + | MOVAPD = 386 /// Move Aligned Packed Single-Precision Floating-Point Values. - | MOVAPS = 386 + | MOVAPS = 387 /// Move Data After Swapping Bytes. - | MOVBE = 387 + | MOVBE = 388 /// Move Doubleword. - | MOVD = 388 + | MOVD = 389 /// Move One Double-FP and Duplicate. - | MOVDDUP = 389 + | MOVDDUP = 390 /// Move Quadword from XMM to MMX Technology Register. - | MOVDQ2Q = 390 + | MOVDQ2Q = 391 /// Move Aligned Double Quadword. - | MOVDQA = 391 + | MOVDQA = 392 /// Move Unaligned Double Quadword. - | MOVDQU = 392 + | MOVDQU = 393 /// Move Packed Single-Precision Floating-Point Values High to Low. - | MOVHLPS = 393 + | MOVHLPS = 394 /// Move High Packed Double-Precision Floating-Point Value. - | MOVHPD = 394 + | MOVHPD = 395 /// Move High Packed Single-Precision Floating-Point Values. - | MOVHPS = 395 + | MOVHPS = 396 /// Move Packed Single-Precision Floating-Point Values Low to High. - | MOVLHPS = 396 + | MOVLHPS = 397 /// Move Low Packed Double-Precision Floating-Point Value. - | MOVLPD = 397 + | MOVLPD = 398 /// Move Low Packed Single-Precision Floating-Point Values. - | MOVLPS = 398 + | MOVLPS = 399 /// Extract Packed Double-Precision Floating-Point Sign Mask. - | MOVMSKPD = 399 + | MOVMSKPD = 400 /// Extract Packed Single-Precision Floating-Point Sign Mask. - | MOVMSKPS = 400 + | MOVMSKPS = 401 /// Load Double Quadword Non-Temporal Aligned Hint. - | MOVNTDQ = 401 + | MOVNTDQ = 402 /// Load Double Quadword Non-Temporal Aligned Hint. - | MOVNTDQA = 402 + | MOVNTDQA = 403 /// Store Doubleword Using Non-Temporal Hint. - | MOVNTI = 403 + | MOVNTI = 404 /// Store Packed Double-Precision FP Values Using Non-Temporal Hint. - | MOVNTPD = 404 + | MOVNTPD = 405 /// Store Packed Single-Precision FP Values Using Non-Temporal Hint. - | MOVNTPS = 405 + | MOVNTPS = 406 /// Store of Quadword Using Non-Temporal Hint. - | MOVNTQ = 406 + | MOVNTQ = 407 /// Move Quadword. - | MOVQ = 407 + | MOVQ = 408 /// Move Quadword from MMX Technology to XMM Register. - | MOVQ2DQ = 408 + | MOVQ2DQ = 409 /// Move Data from String to String (byte). - | MOVSB = 409 + | MOVSB = 410 /// Move Data from String to String (doubleword). - | MOVSD = 410 + | MOVSD = 411 /// Move Packed Single-FP High and Duplicate. - | MOVSHDUP = 411 + | MOVSHDUP = 412 /// Move Packed Single-FP Low and Duplicate. - | MOVSLDUP = 412 + | MOVSLDUP = 413 /// Move Data from String to String (quadword). - | MOVSQ = 413 + | MOVSQ = 414 /// Move Scalar Single-Precision Floating-Point Values. - | MOVSS = 414 + | MOVSS = 415 /// Move Data from String to String (word). - | MOVSW = 415 + | MOVSW = 416 /// Move with Sign-Extension. - | MOVSX = 416 + | MOVSX = 417 /// Move with Sign-Extension (doubleword to quadword). - | MOVSXD = 417 + | MOVSXD = 418 /// Move Unaligned Packed Double-Precision Floating-Point Values. - | MOVUPD = 418 + | MOVUPD = 419 /// Move Unaligned Packed Single-Precision Floating-Point Values. - | MOVUPS = 419 + | MOVUPS = 420 /// Move with Zero-Extend. - | MOVZX = 420 + | MOVZX = 421 /// Compute Multiple Packed Sums of Absolute Difference. - | MPSADBW = 421 + | MPSADBW = 422 /// Unsigned Multiply. - | MUL = 422 + | MUL = 423 /// Multiply Packed Double-Precision Floating-Point Values. - | MULPD = 423 + | MULPD = 424 /// Multiply Packed Single-Precision Floating-Point Values. - | MULPS = 424 + | MULPS = 425 /// Multiply Scalar Double-Precision Floating-Point Values. - | MULSD = 425 + | MULSD = 426 /// Multiply Scalar Single-Precision Floating-Point Values. - | MULSS = 426 + | MULSS = 427 /// Unsigned multiply without affecting arithmetic flags. - | MULX = 427 + | MULX = 428 /// Monitor Wait. - | MWAIT = 428 + | MWAIT = 429 /// Two's Complement Negation. - | NEG = 429 + | NEG = 430 /// No Operation. - | NOP = 430 + | NOP = 431 /// One's Complement Negation. - | NOT = 431 + | NOT = 432 /// Logical Inclusive OR. - | OR = 432 + | OR = 433 /// Bitwise Logical OR of Double-Precision Floating-Point Values. - | ORPD = 433 + | ORPD = 434 /// Bitwise Logical OR of Single-Precision Floating-Point Values. - | ORPS = 434 + | ORPS = 435 /// Output to Port. - | OUT = 435 + | OUT = 436 /// Output String to Port. - | OUTS = 436 + | OUTS = 437 /// Output String to Port (byte). - | OUTSB = 437 + | OUTSB = 438 /// Output String to Port (doubleword). - | OUTSD = 438 + | OUTSD = 439 /// Output String to Port (word). - | OUTSW = 439 + | OUTSW = 440 /// Computes the absolute value of each signed byte data element. - | PABSB = 440 + | PABSB = 441 /// Computes the absolute value of each signed 32-bit data element. - | PABSD = 441 + | PABSD = 442 /// Computes the absolute value of each signed 16-bit data element. - | PABSW = 442 + | PABSW = 443 /// Pack with Signed Saturation. - | PACKSSDW = 443 + | PACKSSDW = 444 /// Pack with Signed Saturation. - | PACKSSWB = 444 + | PACKSSWB = 445 /// Pack with Unsigned Saturation. - | PACKUSDW = 445 + | PACKUSDW = 446 /// Pack with Unsigned Saturation. - | PACKUSWB = 446 + | PACKUSWB = 447 /// Add Packed byte Integers. - | PADDB = 447 + | PADDB = 448 /// Add Packed Doubleword Integers. - | PADDD = 448 + | PADDD = 449 /// Add Packed Quadword Integers. - | PADDQ = 449 + | PADDQ = 450 /// Add Packed Signed Integers with Signed Saturation (byte). - | PADDSB = 450 + | PADDSB = 451 /// Add Packed Signed Integers with Signed Saturation (word). - | PADDSW = 451 + | PADDSW = 452 /// Add Packed Unsigned Integers with Unsigned Saturation (byte). - | PADDUSB = 452 + | PADDUSB = 453 /// Add Packed Unsigned Integers with Unsigned Saturation (word). - | PADDUSW = 453 + | PADDUSW = 454 /// Add Packed word Integers. - | PADDW = 454 + | PADDW = 455 /// Packed Align Right. - | PALIGNR = 455 + | PALIGNR = 456 /// Logical AND. - | PAND = 456 + | PAND = 457 /// Logical AND NOT. - | PANDN = 457 + | PANDN = 458 /// Spin Loop Hint. - | PAUSE = 458 + | PAUSE = 459 /// Average Packed Integers (byte). - | PAVGB = 459 + | PAVGB = 460 /// Average Packed Integers (word). - | PAVGW = 460 + | PAVGW = 461 /// Variable Blend Packed Bytes. - | PBLENDVB = 461 + | PBLENDVB = 462 /// Blend Packed Words. - | PBLENDW = 462 + | PBLENDW = 463 /// Perform carryless multiplication of two 64-bit numbers. - | PCLMULQDQ = 463 + | PCLMULQDQ = 464 /// Compare Packed Data for Equal (byte). - | PCMPEQB = 464 + | PCMPEQB = 465 /// Compare Packed Data for Equal (doubleword). - | PCMPEQD = 465 + | PCMPEQD = 466 /// Compare Packed Data for Equal (quadword). - | PCMPEQQ = 466 + | PCMPEQQ = 467 /// Compare packed words for equal. - | PCMPEQW = 467 + | PCMPEQW = 468 /// Packed Compare Explicit Length Strings, Return Index. - | PCMPESTRI = 468 + | PCMPESTRI = 469 /// Packed Compare Explicit Length Strings, Return Mask. - | PCMPESTRM = 469 + | PCMPESTRM = 470 /// Compare Packed Signed Integers for Greater Than (byte). - | PCMPGTB = 470 + | PCMPGTB = 471 /// Compare Packed Signed Integers for Greater Than (doubleword). - | PCMPGTD = 471 + | PCMPGTD = 472 /// Performs logical compare of greater-than on packed integer quadwords. - | PCMPGTQ = 472 + | PCMPGTQ = 473 /// Compare Packed Signed Integers for Greater Than (word). - | PCMPGTW = 473 + | PCMPGTW = 474 /// Packed Compare Implicit Length Strings, Return Index. - | PCMPISTRI = 474 + | PCMPISTRI = 475 /// Packed Compare Implicit Length Strings, Return Mask. - | PCMPISTRM = 475 + | PCMPISTRM = 476 /// Parallel deposit of bits using a mask. - | PDEP = 476 + | PDEP = 477 /// Parallel extraction of bits using a mask. - | PEXT = 477 + | PEXT = 478 /// Extract Byte. - | PEXTRB = 478 + | PEXTRB = 479 /// Extract Dword. - | PEXTRD = 479 + | PEXTRD = 480 /// Extract Qword. - | PEXTRQ = 480 + | PEXTRQ = 481 /// Extract Word. - | PEXTRW = 481 + | PEXTRW = 482 /// Packed Horizontal Add. - | PHADDD = 482 + | PHADDD = 483 /// Packed Horizontal Add and Saturate. - | PHADDSW = 483 + | PHADDSW = 484 /// Packed Horizontal Add. - | PHADDW = 484 + | PHADDW = 485 /// Packed Horizontal Word Minimum. - | PHMINPOSUW = 485 + | PHMINPOSUW = 486 /// Packed Horizontal Subtract. - | PHSUBD = 486 + | PHSUBD = 487 /// Packed Horizontal Subtract and Saturate. - | PHSUBSW = 487 + | PHSUBSW = 488 /// Packed Horizontal Subtract. - | PHSUBW = 488 + | PHSUBW = 489 /// Insert Byte. - | PINSRB = 489 + | PINSRB = 490 /// Insert a dword value from 32-bit register or memory into an XMM register. - | PINSRD = 490 + | PINSRD = 491 /// Insert a qword value from 64-bit register or memory into an XMM register. - | PINSRQ = 491 + | PINSRQ = 492 /// Insert Word. - | PINSRW = 492 + | PINSRW = 493 /// Multiply and Add Packed Signed and Unsigned Bytes. - | PMADDUBSW = 493 + | PMADDUBSW = 494 /// Multiply and Add Packed Integers. - | PMADDWD = 494 + | PMADDWD = 495 /// Compare packed signed byte integers. - | PMAXSB = 495 + | PMAXSB = 496 /// Compare packed signed dword integers. - | PMAXSD = 496 + | PMAXSD = 497 /// Maximum of Packed Signed Word Integers. - | PMAXSW = 497 + | PMAXSW = 498 /// Maximum of Packed Unsigned Byte Integers. - | PMAXUB = 498 + | PMAXUB = 499 /// Compare packed unsigned dword integers. - | PMAXUD = 499 + | PMAXUD = 500 /// Compare packed unsigned word integers. - | PMAXUW = 500 + | PMAXUW = 501 /// Minimum of Packed Signed Byte Integers. - | PMINSB = 501 + | PMINSB = 502 /// Compare packed signed dword integers. - | PMINSD = 502 + | PMINSD = 503 /// Minimum of Packed Signed Word Integers. - | PMINSW = 503 + | PMINSW = 504 /// Minimum of Packed Unsigned Byte Integers. - | PMINUB = 504 + | PMINUB = 505 /// Minimum of Packed Dword Integers. - | PMINUD = 505 + | PMINUD = 506 /// Compare packed unsigned word integers. - | PMINUW = 506 + | PMINUW = 507 /// Move Byte Mask. - | PMOVMSKB = 507 + | PMOVMSKB = 508 /// Packed Move with Sign Extend. - | PMOVSXBD = 508 + | PMOVSXBD = 509 /// Packed Move with Sign Extend. - | PMOVSXBQ = 509 + | PMOVSXBQ = 510 /// Packed Move with Sign Extend. - | PMOVSXBW = 510 + | PMOVSXBW = 511 /// Packed Move with Sign Extend. - | PMOVSXDQ = 511 + | PMOVSXDQ = 512 /// Packed Move with Sign Extend. - | PMOVSXWD = 512 + | PMOVSXWD = 513 /// Packed Move with Sign Extend. - | PMOVSXWQ = 513 + | PMOVSXWQ = 514 /// Packed Move with Zero Extend. - | PMOVZXBD = 514 + | PMOVZXBD = 515 /// Packed Move with Zero Extend. - | PMOVZXBQ = 515 + | PMOVZXBQ = 516 /// Packed Move with Zero Extend. - | PMOVZXBW = 516 + | PMOVZXBW = 517 /// Packed Move with Zero Extend. - | PMOVZXDQ = 517 + | PMOVZXDQ = 518 /// Packed Move with Zero Extend. - | PMOVZXWD = 518 + | PMOVZXWD = 519 /// Packed Move with Zero Extend. - | PMOVZXWQ = 519 + | PMOVZXWQ = 520 /// Multiply Packed Doubleword Integers. - | PMULDQ = 520 + | PMULDQ = 521 /// Packed Multiply High with Round and Scale. - | PMULHRSW = 521 + | PMULHRSW = 522 /// Multiply Packed Unsigned Integers and Store High Result. - | PMULHUW = 522 + | PMULHUW = 523 /// Multiply Packed Signed Integers and Store High Result. - | PMULHW = 523 + | PMULHW = 524 /// Multiply Packed Integers and Store Low Result. - | PMULLD = 524 + | PMULLD = 525 /// Multiply Packed Signed Integers and Store Low Result. - | PMULLW = 525 + | PMULLW = 526 /// Multiply Packed Unsigned Doubleword Integers. - | PMULUDQ = 526 + | PMULUDQ = 527 /// Pop a Value from the Stack. - | POP = 527 + | POP = 528 /// Pop All General-Purpose Registers (word). - | POPA = 528 + | POPA = 529 /// Pop All General-Purpose Registers (doubleword). - | POPAD = 529 + | POPAD = 530 /// Return the Count of Number of Bits Set to 1. - | POPCNT = 530 + | POPCNT = 531 /// Pop Stack into EFLAGS Register (lower 16bits EFLAGS). - | POPF = 531 + | POPF = 532 /// Pop Stack into EFLAGS Register (EFLAGS). - | POPFD = 532 + | POPFD = 533 /// Pop Stack into EFLAGS Register (RFLAGS). - | POPFQ = 533 + | POPFQ = 534 /// Bitwise Logical OR. - | POR = 534 + | POR = 535 /// Prefetch Data Into Caches (using NTA hint). - | PREFETCHNTA = 535 + | PREFETCHNTA = 536 /// Prefetch Data Into Caches (using T0 hint). - | PREFETCHT0 = 536 + | PREFETCHT0 = 537 /// Prefetch Data Into Caches (using T1 hint). - | PREFETCHT1 = 537 + | PREFETCHT1 = 538 /// Prefetch Data Into Caches (using T2 hint). - | PREFETCHT2 = 538 + | PREFETCHT2 = 539 /// Prefetch Data into Caches in Anticipation of a Write. - | PREFETCHW = 539 + | PREFETCHW = 540 /// Prefetch Vector Data Into Caches with Intent to Write and T1 Hint. - | PREFETCHWT1 = 540 + | PREFETCHWT1 = 541 /// Compute Sum of Absolute Differences. - | PSADBW = 541 + | PSADBW = 542 /// Packed Shuffle Bytes. - | PSHUFB = 542 + | PSHUFB = 543 /// Shuffle Packed Doublewords. - | PSHUFD = 543 + | PSHUFD = 544 /// Shuffle Packed High Words. - | PSHUFHW = 544 + | PSHUFHW = 545 /// Shuffle Packed Low Words. - | PSHUFLW = 545 + | PSHUFLW = 546 /// Shuffle Packed Words. - | PSHUFW = 546 + | PSHUFW = 547 /// Packed Sign Byte. - | PSIGNB = 547 + | PSIGNB = 548 /// Packed Sign Doubleword. - | PSIGND = 548 + | PSIGND = 549 /// Packed Sign Word. - | PSIGNW = 549 + | PSIGNW = 550 /// Shift Packed Data Left Logical (doubleword). - | PSLLD = 550 + | PSLLD = 551 /// Shift Double Quadword Left Logical. - | PSLLDQ = 551 + | PSLLDQ = 552 /// Shift Packed Data Left Logical (quadword). - | PSLLQ = 552 + | PSLLQ = 553 /// Shift Packed Data Left Logical (word). - | PSLLW = 553 + | PSLLW = 554 /// Shift Packed Data Right Arithmetic (doubleword). - | PSRAD = 554 + | PSRAD = 555 /// Shift Packed Data Right Arithmetic (word). - | PSRAW = 555 + | PSRAW = 556 /// Shift Packed Data Right Logical (doubleword). - | PSRLD = 556 + | PSRLD = 557 /// Shift Double Quadword Right Logical. - | PSRLDQ = 557 + | PSRLDQ = 558 /// Shift Packed Data Right Logical (quadword). - | PSRLQ = 558 + | PSRLQ = 559 /// Shift Packed Data Right Logical (word). - | PSRLW = 559 + | PSRLW = 560 /// Subtract Packed Integers (byte). - | PSUBB = 560 + | PSUBB = 561 /// Subtract Packed Integers (doubleword). - | PSUBD = 561 + | PSUBD = 562 /// Subtract Packed Integers (quadword). - | PSUBQ = 562 + | PSUBQ = 563 /// Subtract Packed Signed Integers with Signed Saturation (byte). - | PSUBSB = 563 + | PSUBSB = 564 /// Subtract Packed Signed Integers with Signed Saturation (word). - | PSUBSW = 564 + | PSUBSW = 565 /// Subtract Packed Unsigned Integers with Unsigned Saturation (byte). - | PSUBUSB = 565 + | PSUBUSB = 566 /// Subtract Packed Unsigned Integers with Unsigned Saturation (word). - | PSUBUSW = 566 + | PSUBUSW = 567 /// Subtract Packed Integers (word). - | PSUBW = 567 + | PSUBW = 568 /// Logical Compare. - | PTEST = 568 + | PTEST = 569 /// Unpack High Data. - | PUNPCKHBW = 569 + | PUNPCKHBW = 570 /// Unpack High Data. - | PUNPCKHDQ = 570 + | PUNPCKHDQ = 571 /// Unpack High Data. - | PUNPCKHQDQ = 571 + | PUNPCKHQDQ = 572 /// Unpack High Data. - | PUNPCKHWD = 572 + | PUNPCKHWD = 573 /// Unpack Low Data. - | PUNPCKLBW = 573 + | PUNPCKLBW = 574 /// Unpack Low Data. - | PUNPCKLDQ = 574 + | PUNPCKLDQ = 575 /// Unpack Low Data. - | PUNPCKLQDQ = 575 + | PUNPCKLQDQ = 576 /// Unpack Low Data. - | PUNPCKLWD = 576 + | PUNPCKLWD = 577 /// Push Word, Doubleword or Quadword Onto the Stack. - | PUSH = 577 + | PUSH = 578 /// Push All General-Purpose Registers (word). - | PUSHA = 578 + | PUSHA = 579 /// Push All General-Purpose Registers (doubleword). - | PUSHAD = 579 + | PUSHAD = 580 /// Push EFLAGS Register onto the Stack (16bits of EFLAGS). - | PUSHF = 580 + | PUSHF = 581 /// Push EFLAGS Register onto the Stack (EFLAGS). - | PUSHFD = 581 + | PUSHFD = 582 /// Push EFLAGS Register onto the Stack (RFLAGS). - | PUSHFQ = 582 + | PUSHFQ = 583 /// Logical Exclusive OR. - | PXOR = 583 + | PXOR = 584 /// Rotate x bits (CF, r/m(x)) left once. - | RCL = 584 + | RCL = 585 /// Compute reciprocals of packed single-precision floating-point values. - | RCPPS = 585 + | RCPPS = 586 /// Compute reciprocal of scalar single-precision floating-point values. - | RCPSS = 586 + | RCPSS = 587 /// Rotate x bits (CF, r/m(x)) right once. - | RCR = 587 + | RCR = 588 /// Read FS Segment Base. - | RDFSBASE = 588 + | RDFSBASE = 589 /// Read GS Segment Base. - | RDGSBASE = 589 + | RDGSBASE = 590 /// Read from Model Specific Register. - | RDMSR = 590 + | RDMSR = 591 /// Read Protection Key Rights for User Pages. - | RDPKRU = 591 + | RDPKRU = 592 /// Read Performance-Monitoring Counters. - | RDPMC = 592 + | RDPMC = 593 /// Read Random Number. - | RDRAND = 593 + | RDRAND = 594 /// Read Random SEED. - | RDSEED = 594 + | RDSEED = 595 /// Read shadow stack point (SSP). - | RDSSPD = 595 + | RDSSPD = 596 /// Read shadow stack point (SSP). - | RDSSPQ = 596 + | RDSSPQ = 597 /// Read Time-Stamp Counter. - | RDTSC = 597 + | RDTSC = 598 /// Read Time-Stamp Counter and Processor ID. - | RDTSCP = 598 + | RDTSCP = 599 /// Repeat while ECX not zero. - | REP = 599 + | REP = 600 /// Repeat while equal/Repeat while zero. - | REPE = 600 + | REPE = 601 /// Repeat while not equal/Repeat while not zero. - | REPNE = 601 + | REPNE = 602 /// Repeat while not equal/Repeat while not zero. - | REPNZ = 602 + | REPNZ = 603 /// Repeat while equal/Repeat while zero. - | REPZ = 603 + | REPZ = 604 /// Far return. - | RETFar = 604 + | RETFar = 605 /// Far return w/ immediate. - | RETFarImm = 605 + | RETFarImm = 606 /// Near return. - | RETNear = 606 + | RETNear = 607 /// Near return w/ immediate . - | RETNearImm = 607 + | RETNearImm = 608 /// Rotate x bits r/m(x) left once. - | ROL = 608 + | ROL = 609 /// Rotate x bits r/m(x) right once. - | ROR = 609 + | ROR = 610 /// Rotate right without affecting arithmetic flags. - | RORX = 610 + | RORX = 611 /// Round Packed Double Precision Floating-Point Values. - | ROUNDPD = 611 + | ROUNDPD = 612 /// Round Packed Single Precision Floating-Point Values. - | ROUNDPS = 612 + | ROUNDPS = 613 /// Round Scalar Double Precision Floating-Point Values. - | ROUNDSD = 613 + | ROUNDSD = 614 /// Round Scalar Single Precision Floating-Point Values. - | ROUNDSS = 614 + | ROUNDSS = 615 /// Resume from System Management Mode. - | RSM = 615 + | RSM = 616 /// Compute reciprocals of square roots of packed single-precision FP values. - | RSQRTPS = 616 + | RSQRTPS = 617 /// Compute reciprocal of square root of scalar single-precision FP values. - | RSQRTSS = 617 + | RSQRTSS = 618 /// Restore a shadow stack pointer (SSP). - | RSTORSSP = 618 + | RSTORSSP = 619 /// Store AH into Flags. - | SAHF = 619 + | SAHF = 620 /// Shift. - | SAR = 620 + | SAR = 621 /// Shift arithmetic right. - | SARX = 621 + | SARX = 622 /// Save previous shadow stack pointer (SSP). - | SAVEPREVSSP = 622 + | SAVEPREVSSP = 623 /// Integer Subtraction with Borrow. - | SBB = 623 + | SBB = 624 /// Scan String (byte). - | SCASB = 624 + | SCASB = 625 /// Scan String (doubleword). - | SCASD = 625 + | SCASD = 626 /// Scan String (quadword). - | SCASQ = 626 + | SCASQ = 627 /// Scan String (word). - | SCASW = 627 + | SCASW = 628 /// Set byte if above (CF = 0 and ZF = 0). - | SETA = 628 + | SETA = 629 /// Set byte if below (CF = 1). - | SETB = 629 + | SETB = 630 /// Set byte if below or equal (CF = 1 or ZF = 1). - | SETBE = 630 + | SETBE = 631 /// Set byte if greater (ZF = 0 and SF = OF). - | SETG = 631 + | SETG = 632 /// Set byte if less (SF <> OF). - | SETL = 632 + | SETL = 633 /// Set byte if less or equal (ZF = 1 or SF <> OF). - | SETLE = 633 + | SETLE = 634 /// Set byte if not below (CF = 0). - | SETNB = 634 + | SETNB = 635 /// Set byte if not less (SF = OF). - | SETNL = 635 + | SETNL = 636 /// Set byte if not overflow (OF = 0). - | SETNO = 636 + | SETNO = 637 /// Set byte if not parity (PF = 0). - | SETNP = 637 + | SETNP = 638 /// Set byte if not sign (SF = 0). - | SETNS = 638 + | SETNS = 639 /// Set byte if not zero (ZF = 0). - | SETNZ = 639 + | SETNZ = 640 /// Set byte if overflow (OF = 1). - | SETO = 640 + | SETO = 641 /// Set byte if parity (PF = 1). - | SETP = 641 + | SETP = 642 /// Set byte if sign (SF = 1). - | SETS = 642 + | SETS = 643 /// Set busy bit in a supervisor shadow stack token. - | SETSSBSY = 643 + | SETSSBSY = 644 /// Set byte if sign (ZF = 1). - | SETZ = 644 + | SETZ = 645 /// Store Fence. - | SFENCE = 645 + | SFENCE = 646 /// Store Global Descriptor Table Register. - | SGDT = 646 + | SGDT = 647 /// Perform an Intermediate Calculation for the Next Four SHA1 Message Dwords. - | SHA1MSG1 = 647 + | SHA1MSG1 = 648 /// Perform a Final Calculation for the Next Four SHA1 Message Dwords. - | SHA1MSG2 = 648 + | SHA1MSG2 = 649 /// Calculate SHA1 state E after four rounds. - | SHA1NEXTE = 649 + | SHA1NEXTE = 650 /// Perform four rounds of SHA1 operations. - | SHA1RNDS4 = 650 + | SHA1RNDS4 = 651 /// Perform an intermediate calculation for the next 4 SHA256 message dwords. - | SHA256MSG1 = 651 + | SHA256MSG1 = 652 /// Perform the final calculation for the next four SHA256 message dwords. - | SHA256MSG2 = 652 + | SHA256MSG2 = 653 /// Perform two rounds of SHA256 operations. - | SHA256RNDS2 = 653 + | SHA256RNDS2 = 654 /// Shift. - | SHL = 654 + | SHL = 655 /// Double Precision Shift Left. - | SHLD = 655 + | SHLD = 656 /// Shift logic left. - | SHLX = 656 + | SHLX = 657 /// Shift. - | SHR = 657 + | SHR = 658 /// Double Precision Shift Right. - | SHRD = 658 + | SHRD = 659 /// Shift logic right. - | SHRX = 659 + | SHRX = 660 /// Shuffle Packed Double-Precision Floating-Point Values. - | SHUFPD = 660 + | SHUFPD = 661 /// Shuffle Packed Single-Precision Floating-Point Values. - | SHUFPS = 661 + | SHUFPS = 662 /// Store Interrupt Descriptor Table Register. - | SIDT = 662 + | SIDT = 663 /// Store Local Descriptor Table Register. - | SLDT = 663 + | SLDT = 664 /// Store Machine Status Word. - | SMSW = 664 + | SMSW = 665 /// Compute packed square roots of packed double-precision FP values. - | SQRTPD = 665 + | SQRTPD = 666 /// Compute square roots of packed single-precision floating-point values. - | SQRTPS = 666 + | SQRTPS = 667 /// Compute scalar square root of scalar double-precision FP values. - | SQRTSD = 667 + | SQRTSD = 668 /// Compute square root of scalar single-precision floating-point values. - | SQRTSS = 668 + | SQRTSS = 669 /// Set AC Flag in EFLAGS Register. - | STAC = 669 + | STAC = 670 /// Set Carry Flag. - | STC = 670 + | STC = 671 /// Set Direction Flag. - | STD = 671 + | STD = 672 /// Set Interrupt Flag. - | STI = 672 + | STI = 673 /// Store MXCSR Register State. - | STMXCSR = 673 + | STMXCSR = 674 /// Store String (store AL). - | STOSB = 674 + | STOSB = 675 /// Store String (store EAX). - | STOSD = 675 + | STOSD = 676 /// Store String (store RAX). - | STOSQ = 676 + | STOSQ = 677 /// Store String (store AX). - | STOSW = 677 + | STOSW = 678 /// Store Task Register. - | STR = 678 + | STR = 679 /// Subtract. - | SUB = 679 + | SUB = 680 /// Subtract Packed Double-Precision Floating-Point Values. - | SUBPD = 680 + | SUBPD = 681 /// Subtract Packed Single-Precision Floating-Point Values. - | SUBPS = 681 + | SUBPS = 682 /// Subtract Scalar Double-Precision Floating-Point Values. - | SUBSD = 682 + | SUBSD = 683 /// Subtract Scalar Single-Precision Floating-Point Values. - | SUBSS = 683 + | SUBSS = 684 /// Swap GS Base Register. - | SWAPGS = 684 + | SWAPGS = 685 /// Fast System Call. - | SYSCALL = 685 + | SYSCALL = 686 /// Fast System Call. - | SYSENTER = 686 + | SYSENTER = 687 /// Fast Return from Fast System Call. - | SYSEXIT = 687 + | SYSEXIT = 688 /// Return From Fast System Call. - | SYSRET = 688 + | SYSRET = 689 /// Logical Compare. - | TEST = 689 + | TEST = 690 /// Count the Number of Trailing Zero Bits. - | TZCNT = 690 + | TZCNT = 691 /// Unordered Compare Scalar Double-Precision FP Values and Set EFLAGS. - | UCOMISD = 691 + | UCOMISD = 692 /// Unordered Compare Scalar Single-Precision FPValues and Set EFLAGS. - | UCOMISS = 692 - /// Undefined instruction. - | UD = 693 + | UCOMISS = 693 + /// Undefined instruction (Raise invalid opcode exception). + | UD0 = 694 + /// Undefined Instruction (Raise invalid opcode exception). + | UD1 = 695 /// Undefined Instruction (Raise invalid opcode exception). - | UD2 = 694 + | UD2 = 696 /// Unpack and Interleave High Packed Double-Precision Floating-Point Values. - | UNPCKHPD = 695 + | UNPCKHPD = 697 /// Unpack and Interleave High Packed Single-Precision Floating-Point Values. - | UNPCKHPS = 696 + | UNPCKHPS = 698 /// Unpack and Interleave Low Packed Double-Precision Floating-Point Values. - | UNPCKLPD = 697 + | UNPCKLPD = 699 /// Unpack and Interleave Low Packed Single-Precision Floating-Point Values. - | UNPCKLPS = 698 + | UNPCKLPS = 700 /// Packed Single-Precision Floating-Point Fused Multiply-Add. - | V4FMADDPS = 699 + | V4FMADDPS = 701 /// Scalar Single-Precision Floating-Point Fused Multiply-Add. - | V4FMADDSS = 700 + | V4FMADDSS = 702 /// Packed Single-Precision Floating-Point Fused Multiply-Add and Negate. - | V4FNMADDPS = 701 + | V4FNMADDPS = 703 /// Scalar Single-Precision Floating-Point Fused Multiply-Add and Negate. - | V4FNMADDSS = 702 + | V4FNMADDSS = 704 /// Add Packed Double-Precision Floating-Point Values. - | VADDPD = 703 + | VADDPD = 705 /// Add Packed Double-Precision Floating-Point Values. - | VADDPS = 704 + | VADDPS = 706 /// Add Scalar Double-Precision Floating-Point Values. - | VADDSD = 705 + | VADDSD = 707 /// Add Scalar Single-Precision Floating-Point Values. - | VADDSS = 706 + | VADDSS = 708 /// Packed Double-FP Add/Subtract. - | VADDSUBPD = 707 + | VADDSUBPD = 709 /// Packed Single-FP Add/Subtract. - | VADDSUBPS = 708 + | VADDSUBPS = 710 /// Perform One Round of an AES Decryption Flow. - | VAESDEC = 709 + | VAESDEC = 711 /// Perform Last Round of an AES Decryption Flow. - | VAESDECLAST = 710 + | VAESDECLAST = 712 /// Perform One Round of an AES Encryption Flow. - | VAESENC = 711 + | VAESENC = 713 /// Perform Last Round of an AES Encryption Flow. - | VAESENCLAST = 712 + | VAESENCLAST = 714 /// Perform dword alignment of two concatenated source vectors. - | VALIGND = 713 + | VALIGND = 715 /// Perform qword alignment of two concatenated source vectors. - | VALIGNQ = 714 + | VALIGNQ = 716 /// Bitwise Logical AND of Packed Double-Precision Floating-Point Values. - | VANDNPD = 715 + | VANDNPD = 717 /// Bitwise Logical AND of Packed Single-Precision Floating-Point Values. - | VANDNPS = 716 + | VANDNPS = 718 /// Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values. - | VANDPD = 717 + | VANDPD = 719 /// Bitwise Logical AND NOT of Packed Single-Precision Floating-Point Values. - | VANDPS = 718 + | VANDPS = 720 /// Replace the VBLENDVPD instructions (using opmask as select control). - | VBLENDMPD = 719 + | VBLENDMPD = 721 /// Replace the VBLENDVPS instructions (using opmask as select control). - | VBLENDMPS = 720 + | VBLENDMPS = 722 /// Blend Packed Double-Precision Floats. - | VBLENDPD = 721 + | VBLENDPD = 723 /// Blend Packed Single-Precision Floats. - | VBLENDPS = 722 + | VBLENDPS = 724 /// Variable Blend Packed Double-Precision Floats. - | VBLENDVPD = 723 + | VBLENDVPD = 725 /// Variable Blend Packed Single-Precision Floats. - | VBLENDVPS = 724 + | VBLENDVPS = 726 /// Load with Broadcast Floating-Point Data. - | VBROADCASTF128 = 725 + | VBROADCASTF128 = 727 /// Broadcast 128 bits of int data in mem to low and high 128-bits in ymm1. - | VBROADCASTI128 = 726 + | VBROADCASTI128 = 728 /// Broadcast two dword elements. - | VBROADCASTI32X2 = 727 + | VBROADCASTI32X2 = 729 /// Broadcast four dword elements. - | VBROADCASTI32X4 = 728 + | VBROADCASTI32X4 = 730 /// Broadcast eight dword elements. - | VBROADCASTI32X8 = 729 + | VBROADCASTI32X8 = 731 /// Broadcast two qword elements. - | VBROADCASTI64X2 = 730 + | VBROADCASTI64X2 = 732 /// Broadcast four qword elements. - | VBROADCASTI64X4 = 731 + | VBROADCASTI64X4 = 733 /// Broadcast low double-precision floating-point element. - | VBROADCASTSD = 732 + | VBROADCASTSD = 734 /// Broadcast Floating-Point Data. - | VBROADCASTSS = 733 + | VBROADCASTSS = 735 /// Compare Packed Double-Precision Floating-Point Values. - | VCMPPD = 734 + | VCMPPD = 736 /// Compare Packed Single-Precision Floating-Point Values. - | VCMPPS = 735 + | VCMPPS = 737 /// Compare Scalar Double-Precision Floating-Point Values. - | VCMPSD = 736 + | VCMPSD = 738 /// Scalar Single-Precision Floating-Point Values. - | VCMPSS = 737 + | VCMPSS = 739 /// Compare Scalar Ordered Double-Precision FP Values and Set EFLAGS. - | VCOMISD = 738 + | VCOMISD = 740 /// Compare Scalar Ordered Single-Precision FP Values and Set EFLAGS. - | VCOMISS = 739 + | VCOMISS = 741 /// Compress packed DP elements of a vector. - | VCOMPRESSPD = 740 + | VCOMPRESSPD = 742 /// Compress packed SP elements of a vector. - | VCOMPRESSPS = 741 + | VCOMPRESSPS = 743 /// Convert two packed signed doubleword integers. - | VCVTDQ2PD = 742 + | VCVTDQ2PD = 744 /// Convert Packed Dword Integers to Packed Single-Precision FP Values. - | VCVTDQ2PS = 743 + | VCVTDQ2PS = 745 /// Convert Two Packed Single Data to One Packed BF16 Data. - | VCVTNE2PS2BF16 = 744 + | VCVTNE2PS2BF16 = 746 /// Convert Packed Single Data to Packed BF16 Data. - | VCVTNEPS2BF16 = 745 + | VCVTNEPS2BF16 = 747 /// Convert Packed Double-Precision FP Values to Packed Doubleword Integers. - | VCVTPD2DQ = 746 + | VCVTPD2DQ = 748 /// Convert two packed double-precision floating-point values. - | VCVTPD2PS = 747 + | VCVTPD2PS = 749 /// Convert Packed Double-Precision FP Values to Packed Quadword Integers. - | VCVTPD2QQ = 748 + | VCVTPD2QQ = 750 /// Convert Packed DP FP Values to Packed Unsigned DWord Integers. - | VCVTPD2UDQ = 749 + | VCVTPD2UDQ = 751 /// Convert Packed DP FP Values to Packed Unsigned QWord Integers. - | VCVTPD2UQQ = 750 + | VCVTPD2UQQ = 752 /// Convert 16-bit FP values to Single-Precision FP values. - | VCVTPH2PS = 751 + | VCVTPH2PS = 753 + /// Conv Packed Single-Precision FP Values to Packed Signed DWord Int Values. + | VCVTPS2DQ = 754 /// Conv Packed Single-Precision FP Values to Packed Dbl-Precision FP Values. - | VCVTPS2PD = 752 + | VCVTPS2PD = 755 /// Convert Single-Precision FP value to 16-bit FP value. - | VCVTPS2PH = 753 + | VCVTPS2PH = 756 /// Convert Packed SP FP Values to Packed Signed QWord Int Values. - | VCVTPS2QQ = 754 + | VCVTPS2QQ = 757 /// Convert Packed SP FP Values to Packed Unsigned DWord Int Values. - | VCVTPS2UDQ = 755 + | VCVTPS2UDQ = 758 /// Convert Packed SP FP Values to Packed Unsigned QWord Int Values. - | VCVTPS2UQQ = 756 + | VCVTPS2UQQ = 759 /// Convert Packed Quadword Integers to Packed Double-Precision FP Values. - | VCVTQQ2PD = 757 + | VCVTQQ2PD = 760 /// Convert Packed Quadword Integers to Packed Single-Precision FP Values. - | VCVTQQ2PS = 758 + | VCVTQQ2PS = 761 /// Convert Scalar Double-Precision FP Value to Integer. - | VCVTSD2SI = 759 + | VCVTSD2SI = 762 /// Convert Scalar Double-Precision FP Val to Scalar Single-Precision FP Val. - | VCVTSD2SS = 760 + | VCVTSD2SS = 763 /// Convert Scalar Double-Precision FP Value to Unsigned Doubleword Integer. - | VCVTSD2USI = 761 + | VCVTSD2USI = 764 /// Convert Dword Integer to Scalar Double-Precision FP Value. - | VCVTSI2SD = 762 + | VCVTSI2SD = 765 /// Convert Dword Integer to Scalar Single-Precision FP Value. - | VCVTSI2SS = 763 + | VCVTSI2SS = 766 /// Convert Scalar Single-Precision FP Val to Scalar Double-Precision FP Val. - | VCVTSS2SD = 764 + | VCVTSS2SD = 767 /// Convert Scalar Single-Precision FP Value to Dword Integer. - | VCVTSS2SI = 765 + | VCVTSS2SI = 768 /// Convert Scalar Single-Precision FP Value to Unsigned Doubleword Integer. - | VCVTSS2USI = 766 + | VCVTSS2USI = 769 /// Conv with Trunc Packed Double-Precision FP Val to Packed Dword Integers. - | VCVTTPD2DQ = 767 + | VCVTTPD2DQ = 770 /// Convert with Truncation Packed DP FP Values to Packed QWord Integers. - | VCVTTPD2QQ = 768 + | VCVTTPD2QQ = 771 /// Convert with Truncation Packed DP FP Values to Packed Unsigned DWord Int. - | VCVTTPD2UDQ = 769 + | VCVTTPD2UDQ = 772 /// Convert with Truncation Packed DP FP Values to Packed Unsigned QWord Int. - | VCVTTPD2UQQ = 770 + | VCVTTPD2UQQ = 773 /// Conv with Trunc Packed Single-Precision FP Val to Packed Dword Integers. - | VCVTTPS2DQ = 771 + | VCVTTPS2DQ = 774 /// Convert with Truncation Packed SP FP Values to Packed Signed QWord Int. - | VCVTTPS2QQ = 772 + | VCVTTPS2QQ = 775 /// Convert with Truncation Packed SP FP Values to Packed Unsigned DWord Int. - | VCVTTPS2UDQ = 773 + | VCVTTPS2UDQ = 776 /// Convert with Truncation Packed SP FP Values to Packed Unsigned QWord Int. - | VCVTTPS2UQQ = 774 + | VCVTTPS2UQQ = 777 /// Convert with Truncation Scalar Double-Precision FP Value to Signed. - | VCVTTSD2SI = 775 + | VCVTTSD2SI = 778 /// Convert with Truncation Scalar DP FP Value to Unsigned Integer. - | VCVTTSD2USI = 776 + | VCVTTSD2USI = 779 /// Convert with Truncation Scalar Single-Precision FP Value to Dword Integer. - | VCVTTSS2SI = 777 + | VCVTTSS2SI = 780 /// Convert with Truncation Scalar Single-Precision FP Value to Unsigned Int. - | VCVTTSS2USI = 778 + | VCVTTSS2USI = 781 /// Convert Packed Unsigned DWord Integers to Packed DP FP Values. - | VCVTUDQ2PD = 779 + | VCVTUDQ2PD = 782 /// Convert Packed Unsigned DWord Integers to Packed SP FP Values. - | VCVTUDQ2PS = 780 + | VCVTUDQ2PS = 783 /// Convert Packed Unsigned QWord Integers to Packed DP FP Values. - | VCVTUQQ2PD = 781 + | VCVTUQQ2PD = 784 /// Convert Packed Unsigned QWord Integers to Packed SP FP Values. - | VCVTUQQ2PS = 782 + | VCVTUQQ2PS = 785 /// Convert an signed integer to the low DP FP elem and merge to a vector. - | VCVTUSI2SD = 783 + | VCVTUSI2SD = 786 /// Convert an signed integer to the low SP FP elem and merge to a vector. - | VCVTUSI2SS = 784 + | VCVTUSI2SS = 787 /// Convert an unsigned integer to the low DP FP elem and merge to a vector. - | VCVTUSI2USD = 785 + | VCVTUSI2USD = 788 /// Convert an unsigned integer to the low SP FP elem and merge to a vector. - | VCVTUSI2USS = 786 + | VCVTUSI2USS = 789 /// Double Block Packed Sum-Absolute-Differences (SAD) on Unsigned Bytes. - | VDBPSADBW = 787 + | VDBPSADBW = 790 /// Divide Packed Double-Precision Floating-Point Values. - | VDIVPD = 788 + | VDIVPD = 791 /// Divide Packed Single-Precision Floating-Point Values. - | VDIVPS = 789 + | VDIVPS = 792 /// Divide Scalar Double-Precision Floating-Point Values. - | VDIVSD = 790 + | VDIVSD = 793 /// Divide Scalar Single-Precision Floating-Point Values. - | VDIVSS = 791 + | VDIVSS = 794 /// Dot Product of BF16 Pairs Accumulated into Packed Single Precision. - | VDPBF16PS = 792 + | VDPBF16PS = 795 + /// Packed Double-Precision Dot Products. + | VDPPD = 796 + /// Packed Single-Precision Dot Products. + | VDPPS = 797 /// Verify a Segment for Reading. - | VERR = 793 + | VERR = 798 /// Verify a Segment for Writing. - | VERW = 794 + | VERW = 799 /// Compute approximate base-2 exponential of packed DP FP elems of a vector. - | VEXP2PD = 795 + | VEXP2PD = 800 /// Compute approximate base-2 exponential of packed SP FP elems of a vector. - | VEXP2PS = 796 + | VEXP2PS = 801 /// Compute approximate base-2 exponential of the low DP FP elem of a vector. - | VEXP2SD = 797 + | VEXP2SD = 802 /// Compute approximate base-2 exponential of the low SP FP elem of a vector. - | VEXP2SS = 798 + | VEXP2SS = 803 /// Load Sparse Packed Double-Precision FP Values from Dense Memory. - | VEXPANDPD = 799 + | VEXPANDPD = 804 /// Load Sparse Packed Single-Precision FP Values from Dense Memory. - | VEXPANDPS = 800 + | VEXPANDPS = 805 /// Extract Packed Floating-Point Values. - | VEXTRACTF128 = 801 + | VEXTRACTF128 = 806 /// Extract a vector from a full-length vector with 32-bit granular update. - | VEXTRACTF32X4 = 802 + | VEXTRACTF32X4 = 807 /// Extract a vector from a full-length vector with 32-bit granular update. - | VEXTRACTF32X8 = 803 + | VEXTRACTF32X8 = 808 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTF64X2 = 804 + | VEXTRACTF64X2 = 809 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTF64X4 = 805 + | VEXTRACTF64X4 = 810 /// Extract packed Integer Values. - | VEXTRACTI128 = 806 + | VEXTRACTI128 = 811 /// Extract a vector from a full-length vector with 32-bit granular update. - | VEXTRACTI32X4 = 807 + | VEXTRACTI32X4 = 812 /// Extract a vector from a full-length vector with 32-bit granular update. - | VEXTRACTI32X8 = 808 + | VEXTRACTI32X8 = 813 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTI64X2 = 809 + | VEXTRACTI64X2 = 814 /// Extract a vector from a full-length vector with 64-bit granular update. - | VEXTRACTI64X4 = 810 + | VEXTRACTI64X4 = 815 /// Extract From Packed Single-Precision Floats. - | VEXTRACTPS = 811 + | VEXTRACTPS = 816 /// Fix Up Special Packed Float64 Values. - | VFIXUPIMMPD = 812 + | VFIXUPIMMPD = 817 /// Fix Up Special Packed Float32 Values. - | VFIXUPIMMPS = 813 + | VFIXUPIMMPS = 818 /// Fix Up Special Scalar Float64 Value. - | VFIXUPIMMSD = 814 + | VFIXUPIMMSD = 819 /// Fix Up Special Scalar Float32 Value. - | VFIXUPIMMSS = 815 + | VFIXUPIMMSS = 820 /// Fused Multiply-Add of Packed Double-Precision Floating-Point Values. - | VFMADD132PD = 816 + | VFMADD132PD = 821 /// Fused Multiply-Add of Packed Single-Precision Floating-Point Values. - | VFMADD132PS = 817 + | VFMADD132PS = 822 /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. - | VFMADD132SD = 818 + | VFMADD132SD = 823 /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. - | VFMADD132SS = 819 + | VFMADD132SS = 824 /// Fused Multiply-Add of Packed Double-Precision Floating-Point Values. - | VFMADD213PD = 820 + | VFMADD213PD = 825 /// Fused Multiply-Add of Packed Single-Precision Floating-Point Values. - | VFMADD213PS = 821 + | VFMADD213PS = 826 /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. - | VFMADD213SD = 822 + | VFMADD213SD = 827 /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. - | VFMADD213SS = 823 + | VFMADD213SS = 828 /// Fused Multiply-Add of Packed Double-Precision Floating-Point Value. - | VFMADD231PD = 824 + | VFMADD231PD = 829 /// Fused Multiply-Add of Packed Single-Precision Floating-Point Values. - | VFMADD231PS = 825 + | VFMADD231PS = 830 /// Fused Multiply-Add of Scalar Double-Precision Floating-Point Values. - | VFMADD231SD = 826 + | VFMADD231SD = 831 /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. - | VFMADD231SS = 827 + | VFMADD231SS = 832 + /// Multiply and Add Packed Double-Precision Floating-Point(Only AMD). + | VFMADDPD = 833 + /// Multiply and Add Packed Single-Precision Floating-Point(Only AMD). + | VFMADDPS = 834 + /// Multiply and Add Scalar Double-Precision Floating-Point(Only AMD). + | VFMADDSD = 835 + /// Multiply and Add Scalar Single-Precision Floating-Point(Only AMD). + | VFMADDSS = 836 /// Fused Multiply-Alternating Add/Sub of Packed Double-Precision FP Values. - | VFMADDSUB132PD = 828 + | VFMADDSUB132PD = 837 /// Fused Multiply-Alternating Add/Sub of Packed Single-Precision FP Values. - | VFMADDSUB132PS = 829 + | VFMADDSUB132PS = 838 /// Fused Multiply-Alternating Add/Sub of Packed Double-Precision FP Values. - | VFMADDSUB213PD = 830 + | VFMADDSUB213PD = 839 /// Fused Multiply-Alternating Add/Sub of Packed Single-Precision FP Values. - | VFMADDSUB213PS = 831 + | VFMADDSUB213PS = 840 /// Fused Multiply-Alternating Add/Sub of Packed Double-Precision FP Values. - | VFMADDSUB231PD = 832 + | VFMADDSUB231PD = 841 /// Fused Multiply-Alternating Add/Sub of Packed Single-Precision FP Values. - | VFMADDSUB231PS = 833 + | VFMADDSUB231PS = 842 /// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. - | VFMSUB132PD = 834 + | VFMSUB132PD = 843 /// Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values. - | VFMSUB132PS = 835 + | VFMSUB132PS = 844 /// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. - | VFMSUB132SD = 836 + | VFMSUB132SD = 845 /// Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values. - | VFMSUB132SS = 837 + | VFMSUB132SS = 846 /// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. - | VFMSUB213PD = 838 + | VFMSUB213PD = 847 /// Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values. - | VFMSUB213PS = 839 + | VFMSUB213PS = 848 /// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. - | VFMSUB213SD = 840 + | VFMSUB213SD = 849 /// Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values. - | VFMSUB213SS = 841 + | VFMSUB213SS = 850 /// Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values. - | VFMSUB231PD = 842 + | VFMSUB231PD = 851 /// Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values. - | VFMSUB231PS = 843 + | VFMSUB231PS = 852 /// Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values. - | VFMSUB231SD = 844 + | VFMSUB231SD = 853 /// Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values. - | VFMSUB231SS = 845 + | VFMSUB231SS = 854 /// Fused Multiply-Alternating Sub/Add of Packed Double-Precision FP Values. - | VFMSUBADD132PD = 846 + | VFMSUBADD132PD = 855 /// Fused Multiply-Alternating Sub/Add of Packed Single-Precision FP Values. - | VFMSUBADD132PS = 847 + | VFMSUBADD132PS = 856 /// Fused Multiply-Alternating Sub/Add of Packed Double-Precision FP Values. - | VFMSUBADD213PD = 848 + | VFMSUBADD213PD = 857 /// Fused Multiply-Alternating Sub/Add of Packed Single-Precision FP Values. - | VFMSUBADD213PS = 849 + | VFMSUBADD213PS = 858 /// Fused Multiply-Alternating Sub/Add of Packed Double-Precision FP Values. - | VFMSUBADD231PD = 850 + | VFMSUBADD231PD = 859 /// Fused Multiply-Alternating Sub/Add of Packed Single-Precision FP Values. - | VFMSUBADD231PS = 851 + | VFMSUBADD231PS = 860 /// Fused Negative Multiply-Add of Packed Double-Precision FP Values. - | VFNMADD132PD = 852 + | VFNMADD132PD = 861 /// Fused Negative Mul-Add of Packed Single-Precision Floating-Point Values. - | VFNMADD132PS = 853 + | VFNMADD132PS = 862 /// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. - | VFNMADD132SD = 854 + | VFNMADD132SD = 863 /// Fused Negative Mul-Add of Scalar Single-Precision Floating-Point Values. - | VFNMADD132SS = 855 + | VFNMADD132SS = 864 /// Fused Negative Multiply-Add of Packed Double-Precision FP Values. - | VFNMADD213PD = 856 + | VFNMADD213PD = 865 /// Fused Negative Mul-Add of Packed Single-Precision Floating-Point Values. - | VFNMADD213PS = 857 + | VFNMADD213PS = 866 /// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. - | VFNMADD213SD = 858 + | VFNMADD213SD = 867 /// Fused Negative Mul-Add of Scalar Single-Precision Floating-Point Values. - | VFNMADD213SS = 859 + | VFNMADD213SS = 868 /// Fused Negative Multiply-Add of Packed Double-Precision FP Values. - | VFNMADD231PD = 860 + | VFNMADD231PD = 869 /// Fused Negative Mul-Add of Packed Single-Precision Floating-Point Values. - | VFNMADD231PS = 861 + | VFNMADD231PS = 870 /// Fused Negative Multiply-Add of Scalar Double-Precision FP Values. - | VFNMADD231SD = 862 + | VFNMADD231SD = 871 /// Fused Negative Mul-Add of Scalar Single-Precision Floating-Point Values. - | VFNMADD231SS = 863 + | VFNMADD231SS = 872 /// Fused Negative Multiply-Subtract of Packed Double-Precision FP Values. - | VFNMSUB132PD = 864 + | VFNMSUB132PD = 873 /// Fused Negative Multiply-Subtract of Packed Single-Precision FP Values. - | VFNMSUB132PS = 865 + | VFNMSUB132PS = 874 /// Fused Negative Multiply-Subtract of Scalar Double-Precision FP Values. - | VFNMSUB132SD = 866 + | VFNMSUB132SD = 875 /// Fused Negative Multiply-Subtract of Scalar Single-Precision FP Values. - | VFNMSUB132SS = 867 + | VFNMSUB132SS = 876 /// Fused Negative Multiply-Subtract of Packed Double-Precision FP Values. - | VFNMSUB213PD = 868 + | VFNMSUB213PD = 877 /// Fused Negative Multiply-Subtract of Packed Single-Precision FP Values. - | VFNMSUB213PS = 869 + | VFNMSUB213PS = 878 /// Fused Negative Multiply-Subtract of Scalar Double-Precision FP Values. - | VFNMSUB213SD = 870 + | VFNMSUB213SD = 879 /// Fused Negative Multiply-Subtract of Scalar Single-Precision FP Values. - | VFNMSUB213SS = 871 + | VFNMSUB213SS = 880 /// Fused Negative Multiply-Subtract of Packed Double-Precision FP Values. - | VFNMSUB231PD = 872 + | VFNMSUB231PD = 881 /// Fused Negative Multiply-Subtract of Packed Single-Precision FP Values. - | VFNMSUB231PS = 873 + | VFNMSUB231PS = 882 /// Fused Negative Multiply-Subtract of Scalar Double-Precision FP Values. - | VFNMSUB231SD = 874 + | VFNMSUB231SD = 883 /// Fused Negative Multiply-Subtract of Scalar Single-Precision FP Values. - | VFNMSUB231SS = 875 + | VFNMSUB231SS = 884 /// Tests Types Of a Packed Float64 Values. - | VFPCLASSPD = 876 + | VFPCLASSPD = 885 /// Tests Types Of a Packed Float32 Values. - | VFPCLASSPS = 877 + | VFPCLASSPS = 886 /// Tests Types Of a Scalar Float64 Values. - | VFPCLASSSD = 878 + | VFPCLASSSD = 887 /// Tests Types Of a Scalar Float32 Values. - | VFPCLASSSS = 879 + | VFPCLASSSS = 888 /// Gather Packed DP FP Values Using Signed Dword/Qword Indices. - | VGATHERDPD = 880 + | VGATHERDPD = 889 /// Gather Packed SP FP values Using Signed Dword/Qword Indices. - | VGATHERDPS = 881 + | VGATHERDPS = 890 /// Sparse prefetch of packed DP FP vector with T0 hint using dword indices. - | VGATHERPF0DPD = 882 + | VGATHERPF0DPD = 891 /// Sparse prefetch of packed SP FP vector with T0 hint using dword indices. - | VGATHERPF0DPS = 883 + | VGATHERPF0DPS = 892 /// Sparse prefetch of packed DP FP vector with T0 hint using qword indices. - | VGATHERPF0QPD = 884 + | VGATHERPF0QPD = 893 /// Sparse prefetch of packed SP FP vector with T0 hint using qword indices. - | VGATHERPF0QPS = 885 + | VGATHERPF0QPS = 894 /// Sparse prefetch of packed DP FP vector with T1 hint using dword indices. - | VGATHERPF1DPD = 886 + | VGATHERPF1DPD = 895 /// Sparse prefetch of packed SP FP vector with T1 hint using dword indices. - | VGATHERPF1DPS = 887 + | VGATHERPF1DPS = 896 /// Sparse prefetch of packed DP FP vector with T1 hint using qword indices. - | VGATHERPF1QPD = 888 + | VGATHERPF1QPD = 897 /// Sparse prefetch of packed SP FP vector with T1 hint using qword indices. - | VGATHERPF1QPS = 889 + | VGATHERPF1QPS = 898 /// Gather Packed DP FP Values Using Signed Dword/Qword Indices. - | VGATHERQPD = 890 + | VGATHERQPD = 899 /// Gather Packed SP FP values Using Signed Dword/Qword Indices. - | VGATHERQPS = 891 + | VGATHERQPS = 900 /// Convert Exponents of Packed DP FP Values to DP FP Values. - | VGETEXPPD = 892 + | VGETEXPPD = 901 /// Convert Exponents of Packed SP FP Values to SP FP Values. - | VGETEXPPS = 893 + | VGETEXPPS = 902 /// Convert Exponents of Scalar DP FP Values to DP FP Value. - | VGETEXPSD = 894 + | VGETEXPSD = 903 /// Convert Exponents of Scalar SP FP Values to SP FP Value. - | VGETEXPSS = 895 + | VGETEXPSS = 904 /// Extract Float64 Vector of Normalized Mantissas from Float64 Vector. - | VGETMANTPD = 896 + | VGETMANTPD = 905 /// Extract Float32 Vector of Normalized Mantissas from Float32 Vector. - | VGETMANTPS = 897 + | VGETMANTPS = 906 /// Extract Float64 of Normalized Mantissas from Float64 Scalar. - | VGETMANTSD = 898 + | VGETMANTSD = 907 /// Extract Float32 Vector of Normalized Mantissa from Float32 Vector. - | VGETMANTSS = 899 + | VGETMANTSS = 908 /// Galois Field Affine Transformation Inverse. - | VGF2P8AFFINEINVQB = 900 + | VGF2P8AFFINEINVQB = 909 /// Galois Field Affine Transformation. - | VGF2P8AFFINEQB = 901 + | VGF2P8AFFINEQB = 910 /// Galois Field Multiply Bytes. - | VGF2P8MULB = 902 + | VGF2P8MULB = 911 /// Packed Double-FP Horizontal Add. - | VHADDPD = 903 + | VHADDPD = 912 /// Packed Single-FP Horizontal Add. - | VHADDPS = 904 + | VHADDPS = 913 /// Packed Double-FP Horizontal Subtract. - | VHSUBPD = 905 + | VHSUBPD = 914 /// Packed Single-FP Horizontal Subtract. - | VHSUBPS = 906 + | VHSUBPS = 915 /// Insert Packed Floating-Point Values. - | VINSERTF128 = 907 + | VINSERTF128 = 916 /// Insert Packed Floating-Point Values. - | VINSERTF32X4 = 908 + | VINSERTF32X4 = 917 /// Insert Packed Floating-Point Values. - | VINSERTF64X2 = 909 + | VINSERTF64X2 = 918 /// Insert Packed Floating-Point Values. - | VINSERTF64X4 = 910 + | VINSERTF64X4 = 919 /// Insert Packed Integer Values. - | VINSERTI128 = 911 + | VINSERTI128 = 920 /// Insert 256 bits of packed doubleword integer values. - | VINSERTI32X8 = 912 + | VINSERTI32X8 = 921 /// Insert Packed Floating-Point Values. - | VINSERTI64X2 = 913 + | VINSERTI64X2 = 922 /// Insert 256 bits of packed quadword integer values. - | VINSERTI64X4 = 914 + | VINSERTI64X4 = 923 /// Insert Into Packed Single-Precision Floats. - | VINSERTPS = 915 + | VINSERTPS = 924 /// Load Unaligned Integer 128 Bits. - | VLDDQU = 916 + | VLDDQU = 925 + /// Store Selected Bytes of Double Quadword. + | VMASKMOVDQU = 926 /// Conditional SIMD Packed Loads and Stores. - | VMASKMOVPD = 917 + | VMASKMOVPD = 927 /// Conditional SIMD Packed Loads and Stores. - | VMASKMOVPS = 918 + | VMASKMOVPS = 928 /// Return Maximum Packed Double-Precision Floating-Point Values. - | VMAXPD = 919 + | VMAXPD = 929 /// Maximum of Packed Single-Precision Floating-Point Values. - | VMAXPS = 920 + | VMAXPS = 930 /// Return Maximum Scalar Double-Precision Floating-Point Value. - | VMAXSD = 921 + | VMAXSD = 931 /// Return Maximum Scalar Single-Precision Floating-Point Value. - | VMAXSS = 922 + | VMAXSS = 932 /// Call to VM Monitor. - | VMCALL = 923 + | VMCALL = 933 /// Clear Virtual-Machine Control Structure. - | VMCLEAR = 924 + | VMCLEAR = 934 /// Invoke VM function. - | VMFUNC = 925 + | VMFUNC = 935 /// Return Minimum Packed Double-Precision Floating-Point Values. - | VMINPD = 926 + | VMINPD = 936 /// Return Minimum Packed Single-Precision Floating-Point Values. - | VMINPS = 927 + | VMINPS = 937 /// Return Minimum Scalar Double-Precision Floating-Point Value. - | VMINSD = 928 + | VMINSD = 938 /// Return Minimum Scalar Single-Precision Floating-Point Value. - | VMINSS = 929 + | VMINSS = 939 /// Launch Virtual Machine. - | VMLAUNCH = 930 + | VMLAUNCH = 940 /// Move Aligned Packed Double-Precision Floating-Point Values. - | VMOVAPD = 931 + | VMOVAPD = 941 /// Move Aligned Packed Single-Precision Floating-Point Values. - | VMOVAPS = 932 + | VMOVAPS = 942 /// Move Doubleword. - | VMOVD = 933 + | VMOVD = 943 /// Move One Double-FP and Duplicate. - | VMOVDDUP = 934 + | VMOVDDUP = 944 /// Move Aligned Double Quadword. - | VMOVDQA = 935 + | VMOVDQA = 945 /// Move Aligned Double Quadword. - | VMOVDQA32 = 936 + | VMOVDQA32 = 946 /// Move Aligned Double Quadword. - | VMOVDQA64 = 937 + | VMOVDQA64 = 947 /// Move Unaligned Double Quadword. - | VMOVDQU = 938 + | VMOVDQU = 948 /// VMOVDQU with 16-bit granular conditional update. - | VMOVDQU16 = 939 + | VMOVDQU16 = 949 /// Move Unaligned Double Quadword. - | VMOVDQU32 = 940 + | VMOVDQU32 = 950 /// Move Unaligned Double Quadword. - | VMOVDQU64 = 941 + | VMOVDQU64 = 951 /// VMOVDQU with 8-bit granular conditional update. - | VMOVDQU8 = 942 + | VMOVDQU8 = 952 /// Move Packed Single-Precision Floating-Point Values High to Low. - | VMOVHLPS = 943 + | VMOVHLPS = 953 /// Move High Packed Double-Precision Floating-Point Value. - | VMOVHPD = 944 + | VMOVHPD = 954 /// Move High Packed Single-Precision Floating-Point Values. - | VMOVHPS = 945 + | VMOVHPS = 955 /// Move Packed Single-Precision Floating-Point Values Low to High. - | VMOVLHPS = 946 + | VMOVLHPS = 956 /// Move Low Packed Double-Precision Floating-Point Value. - | VMOVLPD = 947 + | VMOVLPD = 957 /// Move Low Packed Single-Precision Floating-Point Values. - | VMOVLPS = 948 + | VMOVLPS = 958 /// Extract Packed Double-Precision Floating-Point Sign Mask. - | VMOVMSKPD = 949 + | VMOVMSKPD = 959 /// Extract Packed Single-Precision Floating-Point Sign Mask. - | VMOVMSKPS = 950 + | VMOVMSKPS = 960 /// Load Double Quadword Non-Temporal Aligned Hint. - | VMOVNTDQ = 951 + | VMOVNTDQ = 961 + /// Load Double Quadword Non-temporal Aligned. + | VMOVNTDQA = 962 /// Store Packed Double-Precision FP Values Using Non-Temporal Hint. - | VMOVNTPD = 952 + | VMOVNTPD = 963 /// Store Packed Single-Precision FP Values Using Non-Temporal Hint. - | VMOVNTPS = 953 + | VMOVNTPS = 964 /// Move Quadword. - | VMOVQ = 954 + | VMOVQ = 965 /// Move Data from String to String (doubleword). - | VMOVSD = 955 + | VMOVSD = 966 /// Move Packed Single-FP High and Duplicate. - | VMOVSHDUP = 956 + | VMOVSHDUP = 967 /// Move Packed Single-FP Low and Duplicate. - | VMOVSLDUP = 957 + | VMOVSLDUP = 968 /// Move Scalar Single-Precision Floating-Point Values. - | VMOVSS = 958 + | VMOVSS = 969 /// Move Unaligned Packed Double-Precision Floating-Point Values. - | VMOVUPD = 959 + | VMOVUPD = 970 /// Move Unaligned Packed Single-Precision Floating-Point Values. - | VMOVUPS = 960 + | VMOVUPS = 971 + /// Compute Multiple Packed Sums of Absolute Difference. + | VMPSADBW = 972 /// Load Pointer to Virtual-Machine Control Structure. - | VMPTRLD = 961 + | VMPTRLD = 973 /// Store Pointer to Virtual-Machine Control Structure. - | VMPTRST = 962 + | VMPTRST = 974 /// Reads a component from the VMCS and stores it into a destination operand. - | VMREAD = 963 + | VMREAD = 975 /// Resume Virtual Machine. - | VMRESUME = 964 + | VMRESUME = 976 /// Multiply Packed Double-Precision Floating-Point Values. - | VMULPD = 965 + | VMULPD = 977 /// Multiply Packed Single-Precision Floating-Point Values. - | VMULPS = 966 + | VMULPS = 978 /// Multiply Scalar Double-Precision Floating-Point Values. - | VMULSD = 967 + | VMULSD = 979 /// Multiply Scalar Single-Precision Floating-Point Values. - | VMULSS = 968 + | VMULSS = 980 /// Writes a component to the VMCS from a source operand. - | VMWRITE = 969 + | VMWRITE = 981 /// Leave VMX Operation. - | VMXOFF = 970 + | VMXOFF = 982 /// Enter VMX Operation. - | VMXON = 971 + | VMXON = 983 /// Bitwise Logical OR of Double-Precision Floating-Point Values. - | VORPD = 972 + | VORPD = 984 /// Bitwise Logical OR of Single-Precision Floating-Point Values. - | VORPS = 973 + | VORPS = 985 /// Compute Intersection Between dwords. - | VP2INTERSECTD = 974 + | VP2INTERSECTD = 986 /// Compute Intersection Between qwords. - | VP2INTERSECTQ = 975 + | VP2INTERSECTQ = 987 /// Dot Product of Signed Words with Dword Accumulation. - | VP4DPWSSD = 976 + | VP4DPWSSD = 988 /// Dot Product of Signed Words with Dword Accumulation and Saturation. - | VP4DPWSSDS = 977 + | VP4DPWSSDS = 989 /// Packed Absolute Value (byte). - | VPABSB = 978 + | VPABSB = 990 /// Packed Absolute Value (dword). - | VPABSD = 979 + | VPABSD = 991 /// Packed Absolute Value (qword). - | VPABSQ = 980 + | VPABSQ = 992 /// Packed Absolute Value (word). - | VPABSW = 981 + | VPABSW = 993 /// Pack with Signed Saturation. - | VPACKSSDW = 982 + | VPACKSSDW = 994 /// Pack with Signed Saturation. - | VPACKSSWB = 983 + | VPACKSSWB = 995 /// Pack with Unsigned Saturation. - | VPACKUSDW = 984 + | VPACKUSDW = 996 /// Pack with Unsigned Saturation. - | VPACKUSWB = 985 + | VPACKUSWB = 997 /// Add Packed byte Integers. - | VPADDB = 986 + | VPADDB = 998 /// Add Packed Doubleword Integers. - | VPADDD = 987 + | VPADDD = 999 /// Add Packed Quadword Integers. - | VPADDQ = 988 + | VPADDQ = 1000 /// Add Packed Signed Integers with Signed Saturation (byte). - | VPADDSB = 989 + | VPADDSB = 1001 /// Add Packed Signed Integers with Signed Saturation (word). - | VPADDSW = 990 + | VPADDSW = 1002 /// Add Packed Unsigned Integers with Unsigned Saturation (byte). - | VPADDUSB = 991 + | VPADDUSB = 1003 /// Add Packed Unsigned Integers with Unsigned Saturation (word). - | VPADDUSW = 992 + | VPADDUSW = 1004 /// Add Packed word Integers. - | VPADDW = 993 + | VPADDW = 1005 /// Packed Align Right. - | VPALIGNR = 994 + | VPALIGNR = 1006 /// Logical AND. - | VPAND = 995 + | VPAND = 1007 /// Logical AND NOT. - | VPANDN = 996 + | VPANDN = 1008 /// Average Packed Integers (byte). - | VPAVGB = 997 + | VPAVGB = 1009 /// Average Packed Integers (word). - | VPAVGW = 998 + | VPAVGW = 1010 /// Blend Packed Dwords. - | VPBLENDD = 999 + | VPBLENDD = 1011 /// Blend Byte/Word Vectors Using an Opmask Control. - | VPBLENDMB = 1000 + | VPBLENDMB = 1012 /// Blend Int32/Int64 Vectors Using an OpMask Control. - | VPBLENDMD = 1001 + | VPBLENDMD = 1013 /// Blend qword elements using opmask as select control. - | VPBLENDMQ = 1002 + | VPBLENDMQ = 1014 /// Blend word elements using opmask as select control. - | VPBLENDMW = 1003 + | VPBLENDMW = 1015 /// Variable Blend Packed Bytes. - | VPBLENDVB = 1004 + | VPBLENDVB = 1016 /// Blend Packed Words. - | VPBLENDW = 1005 + | VPBLENDW = 1017 /// Broadcast Integer Data. - | VPBROADCASTB = 1006 + | VPBROADCASTB = 1018 /// Broadcast from general-purpose register to vector register. - | VPBROADCASTD = 1007 + | VPBROADCASTD = 1019 /// Broadcast Mask to Vector Register. - | VPBROADCASTM = 1008 + | VPBROADCASTM = 1020 /// Broadcast low byte value in k1. - | VPBROADCASTMB2Q = 1009 + | VPBROADCASTMB2Q = 1021 /// Broadcast low word value in k1. - | VPBROADCASTMW2D = 1010 + | VPBROADCASTMW2D = 1022 /// Broadcast from general-purpose register to vector register. - | VPBROADCASTQ = 1011 + | VPBROADCASTQ = 1023 /// Broadcast from general-purpose register to vector register. - | VPBROADCASTW = 1012 + | VPBROADCASTW = 1024 /// Carry-Less Multiplication Quadword. - | VPCLMULQDQ = 1013 + | VPCLMULQDQ = 1025 /// Compare packed signed bytes using specified primitive. - | VPCMPB = 1014 + | VPCMPB = 1026 /// Compare packed signed dwords using specified primitive. - | VPCMPD = 1015 + | VPCMPD = 1027 /// Compare Packed Data for Equal (byte). - | VPCMPEQB = 1016 + | VPCMPEQB = 1028 /// Compare Packed Data for Equal (doubleword). - | VPCMPEQD = 1017 + | VPCMPEQD = 1029 /// Compare Packed Data for Equal (quadword). - | VPCMPEQQ = 1018 + | VPCMPEQQ = 1030 /// Compare Packed Data for Equal (word). - | VPCMPEQW = 1019 + | VPCMPEQW = 1031 /// Packed Compare Explicit Length Strings, Return Index. - | VPCMPESTRI = 1020 + | VPCMPESTRI = 1032 /// Packed Compare Explicit Length Strings, Return Mask. - | VPCMPESTRM = 1021 + | VPCMPESTRM = 1033 /// Compare Packed Signed Integers for Greater Than (byte). - | VPCMPGTB = 1022 + | VPCMPGTB = 1034 /// Compare Packed Signed Integers for Greater Than (doubleword). - | VPCMPGTD = 1023 + | VPCMPGTD = 1035 /// Compare Packed Data for Greater Than (qword). - | VPCMPGTQ = 1024 + | VPCMPGTQ = 1036 /// Compare Packed Signed Integers for Greater Than (word). - | VPCMPGTW = 1025 + | VPCMPGTW = 1037 /// Packed Compare Implicit Length Strings, Return Index. - | VPCMPISTRI = 1026 + | VPCMPISTRI = 1038 /// Packed Compare Implicit Length Strings, Return Mask. - | VPCMPISTRM = 1027 + | VPCMPISTRM = 1039 /// Compare packed signed quadwords using specified primitive. - | VPCMPQ = 1028 + | VPCMPQ = 1040 /// Compare packed unsigned bytes using specified primitive. - | VPCMPUB = 1029 + | VPCMPUB = 1041 /// Compare packed unsigned dwords using specified primitive. - | VPCMPUD = 1030 + | VPCMPUD = 1042 /// Compare packed unsigned quadwords using specified primitive. - | VPCMPUQ = 1031 + | VPCMPUQ = 1043 /// Compare packed unsigned words using specified primitive. - | VPCMPUW = 1032 + | VPCMPUW = 1044 /// Compare packed signed words using specified primitive. - | VPCMPW = 1033 + | VPCMPW = 1045 /// Compare packed unsigned bytes using specified primitive. - | VPCMUB = 1034 + | VPCMUB = 1046 /// Compare packed unsigned dwords using specified primitive. - | VPCMUD = 1035 + | VPCMUD = 1047 /// Compare packed unsigned quadwords using specified primitive. - | VPCMUQ = 1036 + | VPCMUQ = 1048 /// Compare packed unsigned words using specified primitive. - | VPCMUW = 1037 + | VPCMUW = 1049 /// Store Sparse Packed Byte Integer Values into Dense Memory/Register. - | VPCOMPRESSB = 1038 + | VPCOMPRESSB = 1050 /// Store Sparse Packed Doubleword Integer Values into Dense Memory/Register. - | VPCOMPRESSD = 1039 + | VPCOMPRESSD = 1051 /// Store Sparse Packed Quadword Integer Values into Dense Memory/Register. - | VPCOMPRESSQ = 1040 + | VPCOMPRESSQ = 1052 /// Store Sparse Packed Word Integer Values into Dense Memory/Register. - | VPCOMPRESSW = 1041 + | VPCOMPRESSW = 1053 /// Detect conflicts within a vector of packed 32/64-bit integers. - | VPCONFLICTD = 1042 + | VPCONFLICTD = 1054 /// Detect conflicts within a vector of packed 64-bit integers. - | VPCONFLICTQ = 1043 + | VPCONFLICTQ = 1055 /// Multiply and Add Unsigned and Signed Bytes. - | VPDPBUSD = 1044 + | VPDPBUSD = 1056 /// Multiply and Add Unsigned and Signed Bytes with Saturation. - | VPDPBUSDS = 1045 + | VPDPBUSDS = 1057 /// Multiply and Add Signed Word Integers. - | VPDPWSSD = 1046 + | VPDPWSSD = 1058 /// Multiply and Add Signed Word Integers with Saturation. - | VPDPWSSDS = 1047 + | VPDPWSSDS = 1059 /// Permute Floating-Point Values. - | VPERM2F128 = 1048 + | VPERM2F128 = 1060 /// Permute Integer Values. - | VPERM2I128 = 1049 + | VPERM2I128 = 1061 /// Permute packed bytes elements. - | VPERMB = 1050 + | VPERMB = 1062 /// Permute Packed Doublewords/Words Elements. - | VPERMD = 1051 + | VPERMD = 1063 /// Full Permute of Bytes from Two Tables Overwriting the Index. - | VPERMI2B = 1052 + | VPERMI2B = 1064 /// Full permute of two tables of dword elements overwriting the index vector. - | VPERMI2D = 1053 + | VPERMI2D = 1065 /// Full permute of two tables of DP elements overwriting the index vector. - | VPERMI2PD = 1054 + | VPERMI2PD = 1066 /// Full permute of two tables of SP elements overwriting the index vector. - | VPERMI2PS = 1055 + | VPERMI2PS = 1067 /// Full permute of two tables of qword elements overwriting the index vector. - | VPERMI2Q = 1056 + | VPERMI2Q = 1068 /// Full Permute From Two Tables Overwriting the Index. - | VPERMI2W = 1057 + | VPERMI2W = 1069 /// Permute Double-Precision Floating-Point Values. - | VPERMILPD = 1058 + | VPERMILPD = 1070 /// Permute Single-Precision Floating-Point Values. - | VPERMILPS = 1059 + | VPERMILPS = 1071 /// Permute Double-Precision Floating-Point Elements. - | VPERMPD = 1060 + | VPERMPD = 1072 /// Permute Single-Precision Floating-Point Elements. - | VPERMPS = 1061 + | VPERMPS = 1073 /// Qwords Element Permutation. - | VPERMQ = 1062 + | VPERMQ = 1074 /// Full permute of two tables of byte elements overwriting one source table. - | VPERMT2B = 1063 + | VPERMT2B = 1075 /// Full permute of two tables of dword elements overwriting one source table. - | VPERMT2D = 1064 + | VPERMT2D = 1076 /// Full permute of two tables of DP elements overwriting one source table. - | VPERMT2PD = 1065 + | VPERMT2PD = 1077 /// Full permute of two tables of SP elements overwriting one source table. - | VPERMT2PS = 1066 + | VPERMT2PS = 1078 /// Full permute of two tables of qword elements overwriting one source table. - | VPERMT2Q = 1067 + | VPERMT2Q = 1079 /// Full permute of two tables of word elements overwriting one source table. - | VPERMT2W = 1068 + | VPERMT2W = 1080 /// Permute packed word elements. - | VPERMW = 1069 + | VPERMW = 1081 /// Load Sparse Packed Byte Integer Values from Dense Memory / Register. - | VPEXPANDB = 1070 + | VPEXPANDB = 1082 /// Load Sparse Packed Doubleword Integer Values from Dense Memory / Register. - | VPEXPANDD = 1071 + | VPEXPANDD = 1083 /// Load Sparse Packed Quadword Integer Values from Dense Memory / Register. - | VPEXPANDQ = 1072 + | VPEXPANDQ = 1084 /// Load Sparse Packed Word Integer Values from Dense Memory / Register. - | VPEXPANDW = 1073 + | VPEXPANDW = 1085 /// Extract Byte. - | VPEXTRB = 1074 - /// Extract DWord. - | VPEXTRD = 1075 + | VPEXTRB = 1086 + /// Extract Dword. + | VPEXTRD = 1087 + /// Extract Qword. + | VPEXTRQ = 1088 /// Extract Word. - | VPEXTRW = 1076 + | VPEXTRW = 1089 /// Gather packed dword values using signed Dword/Qword indices. - | VPGATHERDD = 1077 + | VPGATHERDD = 1090 /// Gather Packed Qword Values Using Signed Dword/Qword Indices. - | VPGATHERDQ = 1078 + | VPGATHERDQ = 1091 /// Gather Packed Dword Values Using Signed Dword/Qword Indices. - | VPGATHERQD = 1079 + | VPGATHERQD = 1092 /// Gather Packed Qword Values Using Signed Dword/Qword Indices. - | VPGATHERQQ = 1080 + | VPGATHERQQ = 1093 /// Packed Horizontal Add (32-bit). - | VPHADDD = 1081 + | VPHADDD = 1094 /// Packed Horizontal Add and Saturate (16-bit). - | VPHADDSW = 1082 + | VPHADDSW = 1095 /// Packed Horizontal Add (16-bit). - | VPHADDW = 1083 + | VPHADDW = 1096 /// Packed Horizontal Word Minimum. - | VPHMINPOSUW = 1084 + | VPHMINPOSUW = 1097 /// Packed Horizontal Subtract (32-bit). - | VPHSUBD = 1085 + | VPHSUBD = 1098 /// Packed Horizontal Subtract and Saturate (16-bit). - | VPHSUBSW = 1086 + | VPHSUBSW = 1099 /// Packed Horizontal Subtract (16-bit). - | VPHSUBW = 1087 + | VPHSUBW = 1100 /// Insert Byte. - | VPINSRB = 1088 + | VPINSRB = 1101 /// Insert Dword. - | VPINSRD = 1089 + | VPINSRD = 1102 /// Insert Qword. - | VPINSRQ = 1090 + | VPINSRQ = 1103 /// Insert Word. - | VPINSRW = 1091 + | VPINSRW = 1104 /// Count the number of leading zero bits of packed dword elements. - | VPLZCNTD = 1092 + | VPLZCNTD = 1105 /// Count the number of leading zero bits of packed qword elements. - | VPLZCNTQ = 1093 + | VPLZCNTQ = 1106 /// Packed Multiply of Unsigned 52-bit and Add High 52-bit Products. - | VPMADD52HUQ = 1094 + | VPMADD52HUQ = 1107 /// Packed Multiply of Unsigned 52-bit and Add Low 52-bit Products. - | VPMADD52LUQ = 1095 + | VPMADD52LUQ = 1108 + /// Multiply and Add Packed Signed and Unsigned Bytes. + | VPMADDUBSW = 1109 /// Multiply and Add Packed Integers. - | VPMADDWD = 1096 + | VPMADDWD = 1110 /// Conditional SIMD Integer Packed Loads and Stores. - | VPMASKMOVD = 1097 + | VPMASKMOVD = 1111 /// Conditional SIMD Integer Packed Loads and Stores. - | VPMASKMOVQ = 1098 + | VPMASKMOVQ = 1112 /// Maximum of Packed Signed Integers (byte). - | VPMAXSB = 1099 + | VPMAXSB = 1113 /// Maximum of Packed Signed Integers (dword). - | VPMAXSD = 1100 + | VPMAXSD = 1114 /// Compute maximum of packed signed 64-bit integer elements. - | VPMAXSQ = 1101 + | VPMAXSQ = 1115 /// Maximum of Packed Signed Word Integers. - | VPMAXSW = 1102 + | VPMAXSW = 1116 /// Maximum of Packed Unsigned Byte Integers. - | VPMAXUB = 1103 + | VPMAXUB = 1117 /// Maximum of Packed Unsigned Integers (dword). - | VPMAXUD = 1104 + | VPMAXUD = 1118 /// Compute maximum of packed unsigned 64-bit integer elements. - | VPMAXUQ = 1105 + | VPMAXUQ = 1119 /// Maximum of Packed Unsigned Integers (word). - | VPMAXUW = 1106 + | VPMAXUW = 1120 /// Minimum of Packed Signed Integers (byte). - | VPMINSB = 1107 + | VPMINSB = 1121 /// Minimum of Packed Signed Integers (dword). - | VPMINSD = 1108 + | VPMINSD = 1122 /// Compute minimum of packed signed 64-bit integer elements. - | VPMINSQ = 1109 + | VPMINSQ = 1123 /// Minimum of Packed Signed Word Integers. - | VPMINSW = 1110 + | VPMINSW = 1124 /// Minimum of Packed Unsigned Byte Integers. - | VPMINUB = 1111 + | VPMINUB = 1125 /// Minimum of Packed Dword Integers. - | VPMINUD = 1112 + | VPMINUD = 1126 /// Compute minimum of packed unsigned 64-bit integer elements. - | VPMINUQ = 1113 + | VPMINUQ = 1127 /// Minimum of Packed Unsigned Integers (word). - | VPMINUW = 1114 + | VPMINUW = 1128 /// Convert a vector register in 32/64-bit granularity to an opmask register. - | VPMOVB2D = 1115 + | VPMOVB2D = 1129 /// Convert a Vector Register to a Mask. - | VPMOVB2M = 1116 + | VPMOVB2M = 1130 /// Convert dword vector register to mask register. - | VPMOVD2M = 1117 + | VPMOVD2M = 1131 /// Down Convert DWord to Byte. - | VPMOVDB = 1118 + | VPMOVDB = 1132 /// Down Convert DWord to Word. - | VPMOVDW = 1119 + | VPMOVDW = 1133 /// Convert opmask register to vector register in 8-bit granularity. - | VPMOVM2B = 1120 + | VPMOVM2B = 1134 /// Convert opmask register to vector register in 32-bit granularity. - | VPMOVM2D = 1121 + | VPMOVM2D = 1135 /// Convert opmask register to vector register in 64-bit granularity. - | VPMOVM2Q = 1122 + | VPMOVM2Q = 1136 /// Convert opmask register to vector register in 16-bit granularity. - | VPMOVM2W = 1123 + | VPMOVM2W = 1137 /// Move Byte Mask. - | VPMOVMSKB = 1124 + | VPMOVMSKB = 1138 /// Convert qword vector register to mask register. - | VPMOVQ2M = 1125 + | VPMOVQ2M = 1139 /// Down Convert QWord to Byte. - | VPMOVQB = 1126 + | VPMOVQB = 1140 /// Down Convert QWord to DWord. - | VPMOVQD = 1127 + | VPMOVQD = 1141 /// Down Convert QWord to Word. - | VPMOVQW = 1128 + | VPMOVQW = 1142 /// Down Convert DWord to Byte. - | VPMOVSDB = 1129 + | VPMOVSDB = 1143 /// Down Convert DWord to Word. - | VPMOVSDW = 1130 + | VPMOVSDW = 1144 /// Down Convert QWord to Byte. - | VPMOVSQB = 1131 + | VPMOVSQB = 1145 /// Down Convert QWord to Dword. - | VPMOVSQD = 1132 + | VPMOVSQD = 1146 /// Down Convert QWord to Word. - | VPMOVSQW = 1133 + | VPMOVSQW = 1147 /// Down Convert Word to Byte. - | VPMOVSWB = 1134 + | VPMOVSWB = 1148 /// Packed Move with Sign Extend (8-bit to 32-bit). - | VPMOVSXBD = 1135 + | VPMOVSXBD = 1149 /// Packed Move with Sign Extend (8-bit to 64-bit). - | VPMOVSXBQ = 1136 + | VPMOVSXBQ = 1150 /// Packed Move with Sign Extend (8-bit to 16-bit). - | VPMOVSXBW = 1137 + | VPMOVSXBW = 1151 /// Packed Move with Sign Extend (32-bit to 64-bit). - | VPMOVSXDQ = 1138 + | VPMOVSXDQ = 1152 /// Packed Move with Sign Extend (16-bit to 32-bit). - | VPMOVSXWD = 1139 + | VPMOVSXWD = 1153 /// Packed Move with Sign Extend (16-bit to 64-bit). - | VPMOVSXWQ = 1140 + | VPMOVSXWQ = 1154 /// Down Convert DWord to Byte. - | VPMOVUSDB = 1141 + | VPMOVUSDB = 1155 /// Down Convert DWord to Word. - | VPMOVUSDW = 1142 + | VPMOVUSDW = 1156 /// Down Convert QWord to Byte. - | VPMOVUSQB = 1143 + | VPMOVUSQB = 1157 /// Down Convert QWord to DWord. - | VPMOVUSQD = 1144 + | VPMOVUSQD = 1158 /// Down Convert QWord to Word. - | VPMOVUSQW = 1145 + | VPMOVUSQW = 1159 /// Down Convert Word to Byte. - | VPMOVUSWB = 1146 + | VPMOVUSWB = 1160 /// Convert a vector register in 16-bit granularity to an opmask register. - | VPMOVW2M = 1147 + | VPMOVW2M = 1161 /// Down convert word elements in a vector to byte elements using truncation. - | VPMOVWB = 1148 + | VPMOVWB = 1162 /// Packed Move with Zero Extend (8-bit to 32-bit). - | VPMOVZXBD = 1149 + | VPMOVZXBD = 1163 /// Packed Move with Zero Extend (8-bit to 64-bit). - | VPMOVZXBQ = 1150 + | VPMOVZXBQ = 1164 /// Packed Move with Zero Extend (8-bit to 16-bit). - | VPMOVZXBW = 1151 + | VPMOVZXBW = 1165 /// Packed Move with Zero Extend (32-bit to 64-bit). - | VPMOVZXDQ = 1152 + | VPMOVZXDQ = 1166 /// Packed Move with Zero Extend (16-bit to 32-bit). - | VPMOVZXWD = 1153 + | VPMOVZXWD = 1167 /// Packed Move with Zero Extend (16-bit to 64-bit). - | VPMOVZXWQ = 1154 + | VPMOVZXWQ = 1168 /// Multiply Packed Doubleword Integers. - | VPMULDQ = 1155 + | VPMULDQ = 1169 /// Packed Multiply High with Round and Scale. - | VPMULHRSW = 1156 + | VPMULHRSW = 1170 /// Multiply Packed Unsigned Integers and Store High Result. - | VPMULHUW = 1157 + | VPMULHUW = 1171 /// Multiply Packed Signed Integers and Store High Result. - | VPMULHW = 1158 + | VPMULHW = 1172 /// Multiply Packed Integers and Store Low Result. - | VPMULLD = 1159 + | VPMULLD = 1173 /// Multiply Packed Integers and Store Low Result. - | VPMULLQ = 1160 + | VPMULLQ = 1174 /// Multiply Packed Signed Integers and Store Low Result. - | VPMULLW = 1161 + | VPMULLW = 1175 /// Select Packed Unaligned Bytes from Quadword Sources. - | VPMULTISHIFTQB = 1162 + | VPMULTISHIFTQB = 1176 /// Multiply Packed Unsigned Doubleword Integers. - | VPMULUDQ = 1163 + | VPMULUDQ = 1177 /// Return the Count of Number of Bits Set to 1 in byte. - | VPOPCNTB = 1164 + | VPOPCNTB = 1178 /// Return the Count of Number of Bits Set to 1 in dword. - | VPOPCNTD = 1165 + | VPOPCNTD = 1179 /// Return the Count of Number of Bits Set to 1 in qword. - | VPOPCNTQ = 1166 + | VPOPCNTQ = 1180 /// Return the Count of Number of Bits Set to 1 in word. - | VPOPCNTW = 1167 + | VPOPCNTW = 1181 /// Bitwise Logical OR. - | VPOR = 1168 + | VPOR = 1182 /// Rotate dword elem left by a constant shift count with conditional update. - | VPROLD = 1169 + | VPROLD = 1183 /// Rotate qword elem left by a constant shift count with conditional update. - | VPROLQ = 1170 + | VPROLQ = 1184 /// Rotate dword element left by shift counts specified. - | VPROLVD = 1171 + | VPROLVD = 1185 /// Rotate qword element left by shift counts specified. - | VPROLVQ = 1172 + | VPROLVQ = 1186 /// Rotate dword element right by a constant shift count. - | VPRORD = 1173 + | VPRORD = 1187 /// Rotate qword element right by a constant shift count. - | VPRORQ = 1174 + | VPRORQ = 1188 /// Rotate dword element right by shift counts specified. - | VPRORRD = 1175 + | VPRORRD = 1189 /// Rotate qword element right by shift counts specified. - | VPRORRQ = 1176 + | VPRORRQ = 1190 /// Rotate dword element right by shift counts specified. - | VPRORVD = 1177 + | VPRORVD = 1191 /// Rotate qword element right by shift counts specified. - | VPRORVQ = 1178 + | VPRORVQ = 1192 /// Compute Sum of Absolute Differences. - | VPSADBW = 1179 + | VPSADBW = 1193 /// Scatter dword elements in a vector to memory using dword indices. - | VPSCATTERDD = 1180 + | VPSCATTERDD = 1194 /// Scatter qword elements in a vector to memory using dword indices. - | VPSCATTERDQ = 1181 + | VPSCATTERDQ = 1195 /// Scatter dword elements in a vector to memory using qword indices. - | VPSCATTERQD = 1182 + | VPSCATTERQD = 1196 /// Scatter qword elements in a vector to memory using qword indices. - | VPSCATTERQQ = 1183 + | VPSCATTERQQ = 1197 /// Concatenate and Shift Packed Data Left Logical. - | VPSHLDD = 1184 + | VPSHLDD = 1198 /// Concatenate and Shift Packed Data Left Logical. - | VPSHLDQ = 1185 + | VPSHLDQ = 1199 /// Concatenate and Variable Shift Packed Data Left Logical. - | VPSHLDVD = 1186 + | VPSHLDVD = 1200 /// Concatenate and Variable Shift Packed Data Left Logical. - | VPSHLDVQ = 1187 + | VPSHLDVQ = 1201 /// Concatenate and Variable Shift Packed Data Left Logical. - | VPSHLDVW = 1188 + | VPSHLDVW = 1202 /// Concatenate and Shift Packed Data Left Logical. - | VPSHLDW = 1189 + | VPSHLDW = 1203 /// Concatenate and Shift Packed Data Right Logical. - | VPSHRDD = 1190 + | VPSHRDD = 1204 /// Concatenate and Shift Packed Data Right Logical. - | VPSHRDQ = 1191 + | VPSHRDQ = 1205 /// Concatenate and Variable Shift Packed Data Right Logical. - | VPSHRDVD = 1192 + | VPSHRDVD = 1206 /// Concatenate and Variable Shift Packed Data Right Logical. - | VPSHRDVQ = 1193 + | VPSHRDVQ = 1207 /// Concatenate and Variable Shift Packed Data Right Logical. - | VPSHRDVW = 1194 + | VPSHRDVW = 1208 /// Concatenate and Shift Packed Data Right Logical. - | VPSHRDW = 1195 + | VPSHRDW = 1209 /// Packed Shuffle Bytes. - | VPSHUFB = 1196 + | VPSHUFB = 1210 /// Shuffle Bits from Quadword Elements Using Byte Indexes into Mask. - | VPSHUFBITQMB = 1197 + | VPSHUFBITQMB = 1211 /// Shuffle Packed Doublewords. - | VPSHUFD = 1198 + | VPSHUFD = 1212 /// Shuffle Packed High Words. - | VPSHUFHW = 1199 + | VPSHUFHW = 1213 /// Shuffle Packed Low Words. - | VPSHUFLW = 1200 + | VPSHUFLW = 1214 /// Packed SIGN (byte). - | VPSIGNB = 1201 + | VPSIGNB = 1215 /// Packed SIGN (doubleword). - | VPSIGND = 1202 + | VPSIGND = 1216 /// Packed SIGN (word). - | VPSIGNW = 1203 + | VPSIGNW = 1217 /// Shift Packed Data Left Logical (doubleword). - | VPSLLD = 1204 + | VPSLLD = 1218 /// Shift Double Quadword Left Logical. - | VPSLLDQ = 1205 + | VPSLLDQ = 1219 /// Shift Packed Data Left Logical (quadword). - | VPSLLQ = 1206 + | VPSLLQ = 1220 /// Variable Bit Shift Left Logical. - | VPSLLVD = 1207 + | VPSLLVD = 1221 /// Variable Bit Shift Left Logical. - | VPSLLVQ = 1208 + | VPSLLVQ = 1222 /// Variable Bit Shift Left Logical. - | VPSLLVW = 1209 + | VPSLLVW = 1223 /// Shift Packed Data Left Logical (word). - | VPSLLW = 1210 + | VPSLLW = 1224 /// Shift Packed Data Right Arithmetic (doubleword). - | VPSRAD = 1211 + | VPSRAD = 1225 /// Shift qwords right by a constant shift count and shifting in sign bits. - | VPSRAQ = 1212 + | VPSRAQ = 1226 /// Variable Bit Shift Right Arithmetic. - | VPSRAVD = 1213 + | VPSRAVD = 1227 /// Shift qwords right by shift counts in a vector and shifting in sign bits. - | VPSRAVQ = 1214 + | VPSRAVQ = 1228 /// Variable Bit Shift Right Arithmetic. - | VPSRAVW = 1215 + | VPSRAVW = 1229 /// Shift Packed Data Right Arithmetic (word). - | VPSRAW = 1216 + | VPSRAW = 1230 /// Shift Packed Data Right Logical (doubleword). - | VPSRLD = 1217 + | VPSRLD = 1231 /// Shift Double Quadword Right Logical. - | VPSRLDQ = 1218 + | VPSRLDQ = 1232 /// Shift Packed Data Right Logical (quadword). - | VPSRLQ = 1219 + | VPSRLQ = 1233 /// Variable Bit Shift Right Logical. - | VPSRLVD = 1220 + | VPSRLVD = 1234 /// Variable Bit Shift Right Logical. - | VPSRLVQ = 1221 + | VPSRLVQ = 1235 /// Variable Bit Shift Right Logical. - | VPSRLVW = 1222 + | VPSRLVW = 1236 /// Shift Packed Data Right Logical (word). - | VPSRLW = 1223 + | VPSRLW = 1237 /// Subtract Packed Integers (byte). - | VPSUBB = 1224 + | VPSUBB = 1238 /// Subtract Packed Integers (doubleword). - | VPSUBD = 1225 + | VPSUBD = 1239 /// Subtract Packed Integers (quadword). - | VPSUBQ = 1226 + | VPSUBQ = 1240 /// Subtract Packed Signed Integers with Signed Saturation (byte). - | VPSUBSB = 1227 + | VPSUBSB = 1241 /// Subtract Packed Signed Integers with Signed Saturation (word). - | VPSUBSW = 1228 + | VPSUBSW = 1242 /// Subtract Packed Unsigned Integers with Unsigned Saturation (byte). - | VPSUBUSB = 1229 + | VPSUBUSB = 1243 /// Subtract Packed Unsigned Integers with Unsigned Saturation (word). - | VPSUBUSW = 1230 + | VPSUBUSW = 1244 /// Subtract Packed Integers (word). - | VPSUBW = 1231 + | VPSUBW = 1245 /// Perform bitwise ternary logic operation of three vectors. - | VPTERLOGD = 1232 + | VPTERLOGD = 1246 /// Perform bitwise ternary logic operation of three vectors. - | VPTERLOGQ = 1233 + | VPTERLOGQ = 1247 /// Bitwise Ternary Logic. - | VPTERNLOGD = 1234 + | VPTERNLOGD = 1248 /// Bitwise Ternary Logic. - | VPTERNLOGQ = 1235 + | VPTERNLOGQ = 1249 /// Logical Compare. - | VPTEST = 1236 + | VPTEST = 1250 /// Perform bitwise AND of byte elems of two vecs and write results to opmask. - | VPTESTMB = 1237 + | VPTESTMB = 1251 /// Perform bitwise AND of dword elems of 2-vecs and write results to opmask. - | VPTESTMD = 1238 + | VPTESTMD = 1252 /// Perform bitwise AND of qword elems of 2-vecs and write results to opmask. - | VPTESTMQ = 1239 + | VPTESTMQ = 1253 /// Perform bitwise AND of word elems of two vecs and write results to opmask. - | VPTESTMW = 1240 + | VPTESTMW = 1254 /// Perform bitwise NAND of byte elems of 2-vecs and write results to opmask. - | VPTESTNMB = 1241 + | VPTESTNMB = 1255 /// Perform bitwise NAND of dword elems of 2-vecs and write results to opmask. - | VPTESTNMD = 1242 + | VPTESTNMD = 1256 /// Perform bitwise NAND of qword elems of 2-vecs and write results to opmask. - | VPTESTNMQ = 1243 + | VPTESTNMQ = 1257 /// Perform bitwise NAND of word elems of 2-vecs and write results to opmask. - | VPTESTNMW = 1244 + | VPTESTNMW = 1258 /// Unpack High Data. - | VPUNPCKHBW = 1245 + | VPUNPCKHBW = 1259 /// Unpack High Data. - | VPUNPCKHDQ = 1246 + | VPUNPCKHDQ = 1260 /// Unpack High Data. - | VPUNPCKHQDQ = 1247 + | VPUNPCKHQDQ = 1261 /// Unpack High Data. - | VPUNPCKHWD = 1248 + | VPUNPCKHWD = 1262 /// Unpack Low Data. - | VPUNPCKLBW = 1249 + | VPUNPCKLBW = 1263 /// Unpack Low Data. - | VPUNPCKLDQ = 1250 + | VPUNPCKLDQ = 1264 /// Unpack Low Data. - | VPUNPCKLQDQ = 1251 + | VPUNPCKLQDQ = 1265 /// Unpack Low Data. - | VPUNPCKLWD = 1252 + | VPUNPCKLWD = 1266 /// Logical Exclusive OR. - | VPXOR = 1253 + | VPXOR = 1267 /// Bitwise XOR of packed doubleword integers. - | VPXORD = 1254 + | VPXORD = 1268 /// Bitwise XOR of packed quadword integers. - | VPXORQ = 1255 + | VPXORQ = 1269 /// Range Restriction Calculation For Packed Pairs of Float64 Values. - | VRANGEPD = 1256 + | VRANGEPD = 1270 /// Range Restriction Calculation For Packed Pairs of Float32 Values. - | VRANGEPS = 1257 + | VRANGEPS = 1271 /// Range Restriction Calculation From a pair of Scalar Float64 Values. - | VRANGESD = 1258 + | VRANGESD = 1272 /// Range Restriction Calculation From a Pair of Scalar Float32 Values. - | VRANGESS = 1259 + | VRANGESS = 1273 /// Compute Approximate Reciprocals of Packed Float64 Values. - | VRCP14PD = 1260 + | VRCP14PD = 1274 /// Compute Approximate Reciprocals of Packed Float32 Values. - | VRCP14PS = 1261 + | VRCP14PS = 1275 /// Compute Approximate Reciprocal of Scalar Float64 Value. - | VRCP14SD = 1262 + | VRCP14SD = 1276 /// Compute Approximate Reciprocal of Scalar Float32 Value. - | VRCP14SS = 1263 + | VRCP14SS = 1277 /// Computes the reciprocal approximation of the float64 values. - | VRCP28PD = 1264 + | VRCP28PD = 1278 /// Computes the reciprocal approximation of the float32 values. - | VRCP28PS = 1265 + | VRCP28PS = 1279 /// Computes the reciprocal approximation of the low float64 value. - | VRCP28SD = 1266 + | VRCP28SD = 1280 /// Computes the reciprocal approximation of the low float32 value. - | VRCP28SS = 1267 + | VRCP28SS = 1281 /// Compute reciprocals of packed single-precision floating-point values. - | VRCPPS = 1268 + | VRCPPS = 1282 /// Compute Reciprocal of Scalar Single-Precision Floating-Point Values. - | VRCPSS = 1269 + | VRCPSS = 1283 /// Perform Reduction Transformation on Packed Float64 Values. - | VREDUCEPD = 1270 + | VREDUCEPD = 1284 /// Perform Reduction Transformation on Packed Float32 Values. - | VREDUCEPS = 1271 + | VREDUCEPS = 1285 /// Perform a Reduction Transformation on a Scalar Float64 Value. - | VREDUCESD = 1272 + | VREDUCESD = 1286 /// Perform a Reduction Transformation on a Scalar Float32 Value. - | VREDUCESS = 1273 + | VREDUCESS = 1287 /// Round Packed Float64 Values To Include A Given Number Of Fraction Bits. - | VRNDSCALEPD = 1274 + | VRNDSCALEPD = 1288 /// Round Packed Float32 Values To Include A Given Number Of Fraction Bits. - | VRNDSCALEPS = 1275 + | VRNDSCALEPS = 1289 /// Round Scalar Float64 Value To Include A Given Number Of Fraction Bits. - | VRNDSCALESD = 1276 + | VRNDSCALESD = 1290 /// Round Scalar Float32 Value To Include A Given Number Of Fraction Bits. - | VRNDSCALESS = 1277 + | VRNDSCALESS = 1291 /// Round Packed Double-Precision Values. - | VROUNDPD = 1278 + | VROUNDPD = 1292 /// Round Packed Single-Precision Values. - | VROUNDPS = 1279 + | VROUNDPS = 1293 /// Round Scalar Double-Precision Value. - | VROUNDSD = 1280 + | VROUNDSD = 1294 /// Round Scalar Single-Precision Value. - | VROUNDSS = 1281 + | VROUNDSS = 1295 /// Compute Approximate Reciprocals of Square Roots of Packed Float64 Values. - | VRSQRT14PD = 1282 + | VRSQRT14PD = 1296 /// Compute Approximate Reciprocals of Square Roots of Packed Float32 Values. - | VRSQRT14PS = 1283 + | VRSQRT14PS = 1297 /// Compute Approximate Reciprocal of Square Root of Scalar Float64 Value. - | VRSQRT14SD = 1284 + | VRSQRT14SD = 1298 /// Compute Approximate Reciprocal of Square Root of Scalar Float32 Value. - | VRSQRT14SS = 1285 + | VRSQRT14SS = 1299 /// Computes the reciprocal square root of the float64 values. - | VRSQRT28PD = 1286 + | VRSQRT28PD = 1300 /// Computes the reciprocal square root of the float32 values. - | VRSQRT28PS = 1287 + | VRSQRT28PS = 1301 /// Computes the reciprocal square root of the low float64 value. - | VRSQRT28SD = 1288 + | VRSQRT28SD = 1302 /// Computes the reciprocal square root of the low float32 value. - | VRSQRT28SS = 1289 + | VRSQRT28SS = 1303 /// Compute Reciprocals of Square Roots of Packed Single-Precision FP Values. - | VRSQRTPS = 1290 + | VRSQRTPS = 1304 /// Compute Reciprocal of Square Root of Scalar Single-Precision FP Value. - | VRSQRTSS = 1291 + | VRSQRTSS = 1305 /// Scale Packed Float64 Values With Float64 Values. - | VSCALEFPD = 1292 + | VSCALEFPD = 1306 /// Scale Packed Float32 Values With Float32 Values. - | VSCALEFPS = 1293 + | VSCALEFPS = 1307 /// Scale Scalar Float64 Values With Float64 Values. - | VSCALEFSD = 1294 + | VSCALEFSD = 1308 /// Scale Scalar Float32 Value With Float32 Value. - | VSCALEFSS = 1295 + | VSCALEFSS = 1309 /// Multiply packed DP FP elements of a vector by powers. - | VSCALEPD = 1296 + | VSCALEPD = 1310 /// Multiply packed SP FP elements of a vector by powers. - | VSCALEPS = 1297 + | VSCALEPS = 1311 /// Multiply the low DP FP element of a vector by powers. - | VSCALESD = 1298 + | VSCALESD = 1312 /// Multiply the low SP FP element of a vector by powers. - | VSCALESS = 1299 + | VSCALESS = 1313 /// Scatter SP/DP FP elements in a vector to memory using dword indices. - | VSCATTERDD = 1300 + | VSCATTERDD = 1314 /// Scatter packed double with signed dword indices. - | VSCATTERDPD = 1301 + | VSCATTERDPD = 1315 /// Scatter packed single with signed dword indices. - | VSCATTERDPS = 1302 + | VSCATTERDPS = 1316 /// Scatter SP/DP FP elements in a vector to memory using dword indices. - | VSCATTERDQ = 1303 + | VSCATTERDQ = 1317 /// Sparse prefetch packed DP FP with T0 hint to write using dword indices. - | VSCATTERPF0DPD = 1304 + | VSCATTERPF0DPD = 1318 /// Sparse prefetch packed SP FP with T0 hint to write using dword indices. - | VSCATTERPF0DPS = 1305 + | VSCATTERPF0DPS = 1319 /// Sparse prefetch packed DP FP with T0 hint to write using qword indices. - | VSCATTERPF0QPD = 1306 + | VSCATTERPF0QPD = 1320 /// Sparse prefetch packed SP FP with T0 hint to write using qword indices. - | VSCATTERPF0QPS = 1307 + | VSCATTERPF0QPS = 1321 /// Sparse prefetch packed DP FP with T1 hint to write using dword indices. - | VSCATTERPF1DPD = 1308 + | VSCATTERPF1DPD = 1322 /// Sparse prefetch packed SP FP with T1 hint to write using dword indices. - | VSCATTERPF1DPS = 1309 + | VSCATTERPF1DPS = 1323 /// Sparse prefetch packed DP FP with T1 hint to write using qword indices. - | VSCATTERPF1QPD = 1310 + | VSCATTERPF1QPD = 1324 /// Sparse prefetch packed SP FP with T1 hint to write using qword indices. - | VSCATTERPF1QPS = 1311 + | VSCATTERPF1QPS = 1325 /// Scatter SP/DP FP elements in a vector to memory using qword indices. - | VSCATTERQD = 1312 + | VSCATTERQD = 1326 /// Scatter packed double with signed qword indices. - | VSCATTERQPD = 1313 + | VSCATTERQPD = 1327 /// Scatter packed single with signed qword indices. - | VSCATTERQPS = 1314 + | VSCATTERQPS = 1328 /// Scatter SP/DP FP elements in a vector to memory using qword indices. - | VSCATTERQQ = 1315 + | VSCATTERQQ = 1329 /// Shuffle 128-bit lanes of a vector with 32 bit granular conditional update. - | VSHUFF32X4 = 1316 + | VSHUFF32X4 = 1330 /// Shuffle 128-bit lanes of a vector with 64 bit granular conditional update. - | VSHUFF64X2 = 1317 + | VSHUFF64X2 = 1331 /// Shuffle 128-bit lanes of a vector with 32 bit granular conditional update. - | VSHUFI32X4 = 1318 + | VSHUFI32X4 = 1332 /// Shuffle 128-bit lanes of a vector with 64 bit granular conditional update. - | VSHUFI64X2 = 1319 + | VSHUFI64X2 = 1333 /// Shuffle Packed Double-Precision Floating-Point Values. - | VSHUFPD = 1320 + | VSHUFPD = 1334 /// Shuffle Packed Single-Precision Floating-Point Values. - | VSHUFPS = 1321 + | VSHUFPS = 1335 /// Compute packed square roots of packed double-precision FP values. - | VSQRTPD = 1322 + | VSQRTPD = 1336 /// Compute square roots of packed single-precision floating-point values. - | VSQRTPS = 1323 + | VSQRTPS = 1337 /// Compute scalar square root of scalar double-precision FP values. - | VSQRTSD = 1324 + | VSQRTSD = 1338 /// Compute square root of scalar single-precision floating-point values. - | VSQRTSS = 1325 + | VSQRTSS = 1339 /// Subtract Packed Double-Precision Floating-Point Values. - | VSUBPD = 1326 + | VSUBPD = 1340 /// Subtract Packed Single-Precision Floating-Point Values. - | VSUBPS = 1327 + | VSUBPS = 1341 /// Subtract Scalar Double-Precision Floating-Point Values. - | VSUBSD = 1328 + | VSUBSD = 1342 /// Subtract Scalar Single-Precision Floating-Point Values. - | VSUBSS = 1329 + | VSUBSS = 1343 + /// Packed Bit Test. + | VTESTPD = 1344 + /// Packed Bit Test. + | VTESTPS = 1345 /// Unordered Compare Scalar Double-Precision FP Values and Set EFLAGS. - | VUCOMISD = 1330 + | VUCOMISD = 1346 /// Unordered Compare Scalar Single-Precision FPValues and Set EFLAGS. - | VUCOMISS = 1331 + | VUCOMISS = 1347 /// Unpack and Interleave High Packed Double-Precision Floating-Point Values. - | VUNPCKHPD = 1332 + | VUNPCKHPD = 1348 /// Unpack and Interleave High Packed Single-Precision Floating-Point Values. - | VUNPCKHPS = 1333 + | VUNPCKHPS = 1349 /// Unpack and Interleave Low Packed Double-Precision Floating-Point Values. - | VUNPCKLPD = 1334 + | VUNPCKLPD = 1350 /// Unpack and Interleave Low Packed Single-Precision Floating-Point Values. - | VUNPCKLPS = 1335 + | VUNPCKLPS = 1351 /// Bitwise Logical XOR for Double-Precision Floating-Point Values. - | VXORPD = 1336 + | VXORPD = 1352 /// Bitwise Logical XOR for Single-Precision Floating-Point Values. - | VXORPS = 1337 + | VXORPS = 1353 /// Zero Upper Bits of YMM Registers. - | VZEROUPPER = 1338 + | VZEROUPPER = 1354 /// Wait. - | WAIT = 1339 + | WAIT = 1355 /// Write Back and Invalidate Cache. - | WBINVD = 1340 + | WBINVD = 1356 /// Write FS Segment Base. - | WRFSBASE = 1341 + | WRFSBASE = 1357 /// Write GS Segment Base. - | WRGSBASE = 1342 + | WRGSBASE = 1358 /// Write to Model Specific Register. - | WRMSR = 1343 + | WRMSR = 1359 /// Write Data to User Page Key Register. - | WRPKRU = 1344 + | WRPKRU = 1360 /// Write to a shadow stack. - | WRSSD = 1345 + | WRSSD = 1361 /// Write to a shadow stack. - | WRSSQ = 1346 + | WRSSQ = 1362 /// Write to a user mode shadow stack. - | WRUSSD = 1347 + | WRUSSD = 1363 /// Write to a user mode shadow stack. - | WRUSSQ = 1348 + | WRUSSQ = 1364 /// Transactional Abort. - | XABORT = 1349 + | XABORT = 1365 /// Prefix hint to the beginning of an HLE transaction region. - | XACQUIRE = 1350 + | XACQUIRE = 1366 /// Exchange and Add. - | XADD = 1351 + | XADD = 1367 /// Transactional Begin. - | XBEGIN = 1352 + | XBEGIN = 1368 /// Exchange Register/Memory with Register. - | XCHG = 1353 + | XCHG = 1369 /// Transactional End. - | XEND = 1354 + | XEND = 1370 /// Value of Extended Control Register. - | XGETBV = 1355 + | XGETBV = 1371 /// Table lookup translation. - | XLAT = 1356 + | XLAT = 1372 /// Table Look-up Translation. - | XLATB = 1357 + | XLATB = 1373 /// Logical Exclusive OR. - | XOR = 1358 + | XOR = 1374 /// Bitwise Logical XOR for Double-Precision Floating-Point Values. - | XORPD = 1359 + | XORPD = 1375 /// Bitwise Logical XOR for Single-Precision Floating-Point Values. - | XORPS = 1360 + | XORPS = 1376 /// Prefix hint to the end of an HLE transaction region. - | XRELEASE = 1361 + | XRELEASE = 1377 /// Restore Processor Extended States. - | XRSTOR = 1362 + | XRSTOR = 1378 /// Restore processor supervisor-mode extended states from memory. - | XRSTORS = 1363 + | XRSTORS = 1379 /// Restore processor supervisor-mode extended states from memory. - | XRSTORS64 = 1364 + | XRSTORS64 = 1380 /// Save Processor Extended States. - | XSAVE = 1365 + | XSAVE = 1381 /// Save processor extended states with compaction to memory. - | XSAVEC = 1366 + | XSAVEC = 1382 /// Save processor extended states with compaction to memory. - | XSAVEC64 = 1367 + | XSAVEC64 = 1383 /// Save Processor Extended States Optimized. - | XSAVEOPT = 1368 + | XSAVEOPT = 1384 /// Save processor supervisor-mode extended states to memory. - | XSAVES = 1369 + | XSAVES = 1385 /// Save processor supervisor-mode extended states to memory. - | XSAVES64 = 1370 + | XSAVES64 = 1386 /// Set Extended Control Register. - | XSETBV = 1371 + | XSETBV = 1387 /// Test If In Transactional Execution. - | XTEST = 1372 + | XTEST = 1388 /// Invalid Opcode. - | InvalOP = 1373 + | InvalOP = 1389 // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelOperands.fs b/src/FrontEnd/BinLifter/Intel/IntelOperands.fs index 1934cdef..08035148 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelOperands.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelOperands.fs @@ -49,103 +49,108 @@ type OprDesc = | DbgGpr = 15 | MmxRm = 16 | MmxMm = 17 - | GprRMm = 18 - | RegImm8 = 19 - | Imm8Reg = 20 - | Imm8 = 21 - | Imm16 = 22 - | RegImm = 23 - | SImm8 = 24 - | Imm = 25 - | Es = 26 - | Cs = 27 - | Ss = 28 - | Ds = 29 - | Fs = 30 - | Gs = 31 - | ALDx = 32 - | EaxDx = 33 - | DxEax = 34 - | DxAL = 35 - | No = 36 - | Eax = 37 - | Ecx = 38 - | Edx = 39 - | Ebx = 40 - | Esp = 41 - | Ebp = 42 - | Esi = 43 - | Edi = 44 - | Rax = 45 - | Rcx = 46 - | Rdx = 47 - | Rbx = 48 - | Rsp = 49 - | Rbp = 50 - | Rsi = 51 - | Rdi = 52 - | RaxRax = 53 - | RaxRcx = 54 - | RaxRdx = 55 - | RaxRbx = 56 - | RaxRsp = 57 - | RaxRbp = 58 - | RaxRsi = 59 - | RaxRdi = 60 - | GprRmImm8 = 61 - | GprRmImm = 62 - | Rel8 = 63 - | Rel = 64 - | Dir = 65 - | RaxFar = 66 - | FarRax = 67 - | ALImm8 = 68 - | CLImm8 = 69 - | DLImm8 = 70 - | BLImm8 = 71 - | AhImm8 = 72 - | ChImm8 = 73 - | DhImm8 = 74 - | BhImm8 = 75 - | RaxImm = 76 - | RcxImm = 77 - | RdxImm = 78 - | RbxImm = 79 - | RspImm = 80 - | RbpImm = 81 - | RsiImm = 82 - | RdiImm = 83 - | ImmImm = 84 - | RmImm = 85 - | RmImm8 = 86 - | MmxImm8 = 87 - | Mem = 88 - | M1 = 89 - | RmCL = 90 - | XmmVvXm = 91 - | GprVvRm = 92 - | XmVvXmm = 93 - | Gpr = 94 - | RmXmmImm8 = 95 - | XmmRmImm8 = 96 - | MmxMmImm8 = 97 - | MmxRmImm8 = 98 - | GprMmxImm8 = 99 - | XmmVvXmImm8 = 100 - | XmmVvXmXmm = 101 - | XmRegImm8 = 102 - | GprRmVv = 103 - | VvRmImm8 = 104 - | RmGprCL = 105 - | XmmXmXmm0 = 106 - | XmmXmVv = 107 - | VvRm = 108 - | GprRmImm8Imm8 = 109 - | RmImm8Imm8 = 110 - | KnVvXm = 111 - | GprKn = 112 - | KnVvXmImm8 = 113 - | KnGpr = 114 + | MxMx = 18 + | GprRMm = 19 + | RegImm8 = 20 + | Imm8Reg = 21 + | Imm8 = 22 + | Imm16 = 23 + | RegImm = 24 + | SImm8 = 25 + | Imm = 26 + | Es = 27 + | Cs = 28 + | Ss = 29 + | Ds = 30 + | Fs = 31 + | Gs = 32 + | ALDx = 33 + | EaxDx = 34 + | DxEax = 35 + | DxAL = 36 + | No = 37 + | Eax = 38 + | Ecx = 39 + | Edx = 40 + | Ebx = 41 + | Esp = 42 + | Ebp = 43 + | Esi = 44 + | Edi = 45 + | Rax = 46 + | Rcx = 47 + | Rdx = 48 + | Rbx = 49 + | Rsp = 50 + | Rbp = 51 + | Rsi = 52 + | Rdi = 53 + | RaxRax = 54 + | RaxRcx = 55 + | RaxRdx = 56 + | RaxRbx = 57 + | RaxRsp = 58 + | RaxRbp = 59 + | RaxRsi = 60 + | RaxRdi = 61 + | GprRmImm8 = 62 + | GprRmImm = 63 + | Rel8 = 64 + | Rel = 65 + | Dir = 66 + | RaxFar = 67 + | FarRax = 68 + | ALImm8 = 69 + | CLImm8 = 70 + | DLImm8 = 71 + | BLImm8 = 72 + | AhImm8 = 73 + | ChImm8 = 74 + | DhImm8 = 75 + | BhImm8 = 76 + | RaxImm = 77 + | RcxImm = 78 + | RdxImm = 79 + | RbxImm = 80 + | RspImm = 81 + | RbpImm = 82 + | RsiImm = 83 + | RdiImm = 84 + | ImmImm = 85 + | RmImm = 86 + | RmImm8 = 87 + | RmSImm8 = 88 + | MmxImm8 = 89 + | Mem = 90 + | M1 = 91 + | RmCL = 92 + | XmmVvXm = 93 + | GprVvRm = 94 + | XmVvXmm = 95 + | Gpr = 96 + | RmXmmImm8 = 97 + | XmmRmImm8 = 98 + | MmxMmImm8 = 99 + | MmxRmImm8 = 100 + | GprMmxImm8 = 101 + | XmmVvXmImm8 = 102 + | XmmVvXmXmm = 103 + | XmRegImm8 = 104 + | GprRmVv = 105 + | VvRmImm8 = 106 + | RmGprCL = 107 + | XmmXmXmm0 = 108 + | XmmXmVv = 109 + | VvRm = 110 + | GprRmImm8Imm8 = 111 + | RmImm8Imm8 = 112 + | KnVvXm = 113 + | GprKn = 114 + | KnVvXmImm8 = 115 + | KnGpr = 116 + | XmmVvXmmXm = 117 + | KnKm = 118 + | MKn = 119 module internal OperandParsingHelper = /// Find a specific reg. The bitmask will be used to extract a specific REX @@ -336,12 +341,12 @@ module internal OperandParsingHelper = open type RegGrp - /// The first 24 rows of Table 2-2. of the manual Vol. 2A. - /// The index of this tbl is a number that is a concatenation of (mod) and - /// (r/m) field of the ModR/M byte. Each element is a tuple of (MemLookupType, - /// and the size of the displacement). If the first value of the tuple (register - /// group) is None, it means we need to look up the SIB tbl (Table 2-3). If - /// not, then it represents the reg group of the base reigster. + /// The first 24 rows of Table 2-2. of the manual Vol. 2A. The index of this + /// tbl is a number that is a concatenation of (mod) and (r/m) field of the + /// ModR/M byte. Each element is a tuple of (MemLookupType, and the size of + /// the displacement). If the first value of the tuple (register group) is + /// None, it means we need to look up the SIB tbl (Table 2-3). If not, then it + /// represents the reg group of the base reigster. let parseMEM32 span rhlp modRM = let modVal = modRM &&& 0b11000000uy match modVal >>> 3 ||| (modRM &&& 0b00000111uy) with @@ -398,7 +403,7 @@ module internal OperandParsingHelper = match rhlp.VEXInfo with | None -> raise ParsingFailureException | Some vInfo -> - let grp = (int vInfo.VVVV) &&& 0b111 + let grp = (int vInfo.VVVV) &&& 0b1111 int (grpEAX rhlp.RegSize) + grp |> LanguagePrimitives.EnumOfValue |> OprReg @@ -411,7 +416,8 @@ module internal OperandParsingHelper = else raise ParsingFailureException let parseBoundRegister n = - Register.bound n |> OprReg + if n < 4 then Register.bound n |> OprReg + else raise ParsingFailureException let parseControlReg n = Register.control n |> OprReg @@ -614,6 +620,16 @@ type internal OpMmxMm () = let opr2 = parseMemOrReg modRM span rhlp TwoOperands (opr1, opr2) +type internal OpMxMx () = + inherit OperandParser () + override __.Render (span, rhlp) = + let modRM = rhlp.ReadByte span + let opr1 = parseMMXReg (getReg modRM) + let opr2 = + if modIsMemory modRM then raise ParsingFailureException + else parseMMXReg (getRM modRM) + TwoOperands (opr1, opr2) + type internal OpGprRMm () = inherit OperandParser () override __.Render (span, rhlp) = @@ -1059,6 +1075,14 @@ type internal OpRmImm () = TwoOperands (opr1, opr2) type internal OpRmImm8 () = + inherit OperandParser () + override __.Render (span, rhlp) = + let modRM = rhlp.ReadByte span + let opr1 = parseMemOrReg modRM span rhlp + let opr2 = parseOprImm span rhlp 8 + TwoOperands (opr1, opr2) + +type internal OpRmSImm8 () = inherit OperandParser () override __.Render (span, rhlp) = let modRM = rhlp.ReadByte span @@ -1088,7 +1112,7 @@ type internal OpM1 () = override __.Render (span, rhlp) = let modRM = rhlp.ReadByte span let opr = parseMemOrReg modRM span rhlp - TwoOperands (opr, OprImm (1L, 0)) + TwoOperands (opr, OprImm (1L, rhlp.OperationSize)) type internal OpRmCL () = inherit OperandParser () @@ -1320,5 +1344,36 @@ type internal OpKnGpr () = override __.Render (span, rhlp) = let modRM = rhlp.ReadByte span let opr1 = parseOpMaskReg (getReg modRM) - let opr2 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getRM modRM) |> OprReg + let opr2 = + findRegRmAndSIBBase rhlp.RegSize rhlp.REXPrefix (getRM modRM) |> OprReg + TwoOperands (opr1, opr2) + +type internal OpXmmVvXmmXm () = + inherit OperandParser () + override __.Render (span, rhlp) = + let modRM = rhlp.ReadByte span + let opr1 = findRegRBits rhlp.RegSize rhlp.REXPrefix (getReg modRM) |> OprReg + let opr2 = parseVVVVReg rhlp + let mask = if rhlp.WordSize = WordSize.Bit32 then 0b0111uy else 0b1111uy + let opr4 = parseMemOrReg modRM span rhlp + let imm8 = (rhlp.ReadUInt8 (span) >>> 4) &&& mask |> int (* imm8[7:4] *) + let opr3 = findRegNoREX rhlp.RegSize rhlp.REXPrefix imm8 |> OprReg + FourOperands (opr1, opr2, opr3, opr4) + +type internal OpKnKm () = + inherit OperandParser () + override __.Render (span, rhlp) = + let modRM = rhlp.ReadByte span + let opr1 = parseOpMaskReg (getReg modRM) + let opr2 = if modIsMemory modRM then parseMemory modRM span rhlp + else parseOpMaskReg (getRM modRM) + TwoOperands (opr1, opr2) + +type internal OpMKn () = + inherit OperandParser () + override __.Render (span, rhlp) = + let modRM = rhlp.ReadByte span + let opr1 = if modIsMemory modRM then parseMemory modRM span rhlp + else raise ParsingFailureException + let opr2 = parseOpMaskReg (getReg modRM) TwoOperands (opr1, opr2) diff --git a/src/FrontEnd/BinLifter/Intel/IntelParser.fs b/src/FrontEnd/BinLifter/Intel/IntelParser.fs index 5eebf77e..49cd2553 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelParser.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelParser.fs @@ -35,8 +35,6 @@ open type Prefix /// Parser for Intel (x86 or x86-64) instructions. Parser will return a /// platform-agnostic instruction type (Instruction). type IntelParser (wordSz) = - inherit Parser () - let oparsers = [| OpRmGpr () :> OperandParser OpRmSeg () :> OperandParser @@ -56,6 +54,7 @@ type IntelParser (wordSz) = OpDbgGpr () :> OperandParser OpMmxRm () :> OperandParser OpMmxMm () :> OperandParser + OpMxMx () :> OperandParser OpGprRMm () :> OperandParser OpRegImm8 () :> OperandParser OpImm8Reg () :> OperandParser @@ -125,6 +124,7 @@ type IntelParser (wordSz) = OpImmImm () :> OperandParser OpRmImm () :> OperandParser OpRmImm8 () :> OperandParser + OpRmSImm8 () :> OperandParser OpMmxImm8 () :> OperandParser OpMem () :> OperandParser OpM1 () :> OperandParser @@ -152,7 +152,10 @@ type IntelParser (wordSz) = OpKnVvXm () :> OperandParser OpGprKn () :> OperandParser OpKnVvXmImm8 () :> OperandParser - OpKnGpr () :> OperandParser |] + OpKnGpr () :> OperandParser + OpXmmVvXmmXm () :> OperandParser + OpKnKm () :> OperandParser + OpMKn () :> OperandParser |] let szcomputers = [| SzByte () :> InsSizeComputer @@ -227,7 +230,10 @@ type IntelParser (wordSz) = SzYDq () :> InsSizeComputer SzQq () :> InsSizeComputer SzDqwdX () :> InsSizeComputer - SzY () :> InsSizeComputer |] + SzY () :> InsSizeComputer + SzQQb () :> InsSizeComputer + SzQQd () :> InsSizeComputer + SzQQw () :> InsSizeComputer |] let oneByteParsers = [| OneOp00 () :> ParsingJob @@ -536,22 +542,23 @@ type IntelParser (wordSz) = pos + 1 else pos - override __.Parse (bs: byte[], addr) = - __.Parse (ReadOnlySpan bs, addr) + interface IInstructionParsable with + member __.Parse (bs: byte[], addr) = + (__ :> IInstructionParsable).Parse (ReadOnlySpan bs, addr) - override __.Parse (span: ByteSpan, addr) = - let mutable rex = REXPrefix.NOREX - let prefEndPos = __.ParsePrefix span - let nextPos = __.ParseREX (span, prefEndPos, &rex) - rhlp.VEXInfo <- None - rhlp.InsAddr <- addr - rhlp.REXPrefix <- rex - rhlp.CurrPos <- nextPos + member __.Parse (span: ByteSpan, addr) = + let mutable rex = REXPrefix.NOREX + let prefEndPos = __.ParsePrefix span + let nextPos = __.ParseREX (span, prefEndPos, &rex) + rhlp.VEXInfo <- None + rhlp.InsAddr <- addr + rhlp.REXPrefix <- rex + rhlp.CurrPos <- nextPos #if LCACHE - rhlp.MarkPrefixEnd (prefEndPos) + rhlp.MarkPrefixEnd (prefEndPos) #endif - oneByteParsers[int (rhlp.ReadByte span)].Run (span, rhlp) :> Instruction + oneByteParsers[int (rhlp.ReadByte span)].Run (span, rhlp) :> Instruction - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () + member __.MaxInstructionSize = 15 -// vim: set tw=80 sts=2 sw=2: + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs b/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs index e605bd53..5b5f5f31 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelParsingHelper.fs @@ -102,12 +102,16 @@ module internal ParsingHelper = begin let getEVEXInfo (span: ByteSpan) (rex: byref) pos = let b1 = span[pos] + if ((b1 >>> 2) &&& 0b11uy) <> 0uy then raise ParsingFailureException + else () let b2 = span[pos + 1] + if ((b2 >>> 2) &&& 0b1uy) <> 1uy then raise ParsingFailureException + else () let l'l = span[pos + 2] >>> 5 &&& 0b011uy let vLen = getVLen l'l let aaa = span[pos + 2] &&& 0b111uy let z = - if (span[pos + 2] >>> 7 &&& 0b1uy) = 0uy then Zeroing + if (span[pos + 2] >>> 7 &&& 0b1uy) = 1uy then Zeroing else Merging let b = (span[pos + 2] >>> 4) &&& 0b1uy let e = Some { AAA = aaa; Z = z; B = b } @@ -128,6 +132,25 @@ module internal ParsingHelper = begin | Opcode.OUTSD -> rhlp.OperationSize <- 32 | _ -> () + /// If VMOVL/H is encoded with VEX.L or EVEX.L'L= 1, an attempt to execute + /// the instruction encoded with VEX.L or EVEX.L'L= 1 will cause an #UD + /// exception. + let exceptionUD opcode (rhlp: ReadHelper) = + let isVMOVLorH = + match opcode with + | Opcode.VMOVHLPS | Opcode.VMOVHPD | Opcode.VMOVHPS | Opcode.VMOVLHPS + | Opcode.VMOVLPD | Opcode.VMOVLPS -> true + | _ -> false + let isNotVLen128 = + match rhlp.VEXInfo with + | Some vex when vex.VectorLength <> 128 -> true + | _ -> false + if isVMOVLorH && isNotVLen128 then raise ParsingFailureException else () + + let exceptionHandling opcode rhlp = + exceptionalOperationSize opcode rhlp + exceptionUD opcode rhlp + let inline newInsInfo (rhlp: ReadHelper) opcode oprs = IntelInstruction (rhlp.InsAddr, uint32 (rhlp.ParsedLen ()), @@ -138,8 +161,7 @@ module internal ParsingHelper = begin opcode, oprs, rhlp.OperationSize, - rhlp.MemEffAddrSize - (* rhlp.GetInsID () *)) + rhlp.MemEffAddrSize) (* Table A-7/15 of Volume 2 (D8/DC Opcode Map When ModR/M Byte is within 00H to BFH) *) @@ -341,7 +363,9 @@ module internal ParsingHelper = begin | _ -> raise ParsingFailureException let getD8OverBF b = - getD8OpcodeOutside00toBF b, TwoOperands (OprReg R.ST0, getRM b |> getSTReg) + match getD8OpcodeOutside00toBF b with + | Opcode.FCOM | Opcode.FCOMP as op -> op, OneOperand (getRM b |> getSTReg) + | op -> op, TwoOperands (OprReg R.ST0, getRM b |> getSTReg) let getD9OverBF b = getD9OpcodeOutside00toBF b, @@ -362,9 +386,7 @@ module internal ParsingHelper = begin getDCOpcodeOutside00toBF b, TwoOperands (getRM b |> getSTReg, OprReg R.ST0) let getDDOverBF b = - getDDOpcodeOutside00toBF b, - if b < 0xE0uy || b >= 0xE8uy then getRM b |> getSTReg |> OneOperand - else TwoOperands (getRM b |> getSTReg, OprReg R.ST0) + getDDOpcodeOutside00toBF b, getRM b |> getSTReg |> OneOperand let getDEOverBF b = getDEOpcodeOutside00toBF b, @@ -775,10 +797,8 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F54 = function - | MPref.MPrxNP -> - struct (VANDPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VANDPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxNP -> struct (VANDPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VANDPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -791,10 +811,8 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F55 = function - | MPref.MPrxNP -> - struct (VANDNPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VANDNPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxNP -> struct (VANDNPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VANDNPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -821,10 +839,8 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F57 = function - | MPref.MPrxNP -> - struct (VXORPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VXORPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxNP -> struct (VXORPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VXORPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -837,14 +853,10 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F58 = function - | MPref.MPrxNP -> - struct (VADDPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VADDPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) - | MPref.MPrxF3 -> - struct (VADDSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VADDSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxNP -> struct (VADDPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VADDPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> struct (VADDSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VADDSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F59 = function @@ -855,14 +867,10 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F59 = function - | MPref.MPrxNP -> - struct (VMULPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VMULPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) - | MPref.MPrxF3 -> - struct (VMULSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VMULSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxNP -> struct (VMULPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VMULPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> struct (VMULSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VMULSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F5A = function @@ -873,13 +881,10 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F5A = function - | MPref.MPrxNP -> - struct (VCVTPS2PD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) + | MPref.MPrxNP -> struct (VCVTPS2PD, OD.GprRm, SZ.DqqDq) (* VdqWdqq *) | MPref.MPrx66 -> struct (VCVTPD2PS, OD.GprRm, SZ.DqDq) (* VdqWdq *) - | MPref.MPrxF3 -> - struct (VCVTSS2SD, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VCVTSD2SS, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF3 -> struct (VCVTSS2SD, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VCVTSD2SS, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let evex0F5AW0 = function @@ -905,7 +910,7 @@ module internal ParsingHelper = begin let vex0F5B = function | MPref.MPrxNP -> struct (VCVTDQ2PS, OD.GprRm, SZ.VecDef) (* VxWx *) - | MPref.MPrx66 -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VCVTPS2DQ, OD.GprRm, SZ.VecDef) (* VdqWps *) | MPref.MPrxF3 -> struct (VCVTTPS2DQ, OD.GprRm, SZ.VecDef) (* VxWx *) | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -918,14 +923,10 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F5C = function - | MPref.MPrxNP -> - struct (VSUBPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VSUBPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) - | MPref.MPrxF3 -> - struct (VSUBSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VSUBSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxNP -> struct (VSUBPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VSUBPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> struct (VSUBSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VSUBSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F5D = function @@ -936,21 +937,16 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F5D = function - | MPref.MPrxNP -> - struct (VMINPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VMINPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) - | MPref.MPrxF3 -> - struct (VMINSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VMINSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxNP -> struct (VMINPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VMINPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> struct (VMINSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VMINSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let evex0F5DW0 = function | MPref.MPrxNP | MPref.MPrx66 -> raise ParsingFailureException - | MPref.MPrxF3 -> - struct (VMINSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF3 -> struct (VMINSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -962,14 +958,10 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F5E = function - | MPref.MPrxNP -> - struct (VDIVPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VDIVPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) - | MPref.MPrxF3 -> - struct (VDIVSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VDIVSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxNP -> struct (VDIVPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VDIVPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> struct (VDIVSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VDIVSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F5F = function @@ -980,21 +972,16 @@ module internal ParsingHelper = begin | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F5F = function - | MPref.MPrxNP -> - struct (VMAXPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) - | MPref.MPrx66 -> - struct (VMAXPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) - | MPref.MPrxF3 -> - struct (VMAXSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) - | MPref.MPrxF2 -> - struct (VMAXSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxNP -> struct (VMAXPS, OD.XmmVvXm, SZ.VecDef) (* VpsHpsWps *) + | MPref.MPrx66 -> struct (VMAXPD, OD.XmmVvXm, SZ.VecDef) (* VpdHpdWpd *) + | MPref.MPrxF3 -> struct (VMAXSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF2 -> struct (VMAXSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let evex0F5FW0 = function | MPref.MPrxNP -> struct (VMAXPS, OD.XmmVvXm, SZ.XzXz) (* VZxzHxWZxz *) | MPref.MPrx66 -> raise ParsingFailureException - | MPref.MPrxF3 -> - struct (VMAXSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + | MPref.MPrxF3 -> struct (VMAXSS, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1002,8 +989,7 @@ module internal ParsingHelper = begin | MPref.MPrxNP | MPref.MPrx66 | MPref.MPrxF3 -> raise ParsingFailureException - | MPref.MPrxF2 -> - struct (VMAXSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) + | MPref.MPrxF2 -> struct (VMAXSD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F60 = function @@ -1015,8 +1001,7 @@ module internal ParsingHelper = begin let vex0F60 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPUNPCKLBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VPUNPCKLBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1045,8 +1030,7 @@ module internal ParsingHelper = begin let vex0F62 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPUNPCKLDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VPUNPCKLDQ, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1060,8 +1044,7 @@ module internal ParsingHelper = begin let vex0F63 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPACKSSWB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VPACKSSWB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1117,8 +1100,7 @@ module internal ParsingHelper = begin let vex0F67 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPACKUSWB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VPACKUSWB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1132,8 +1114,7 @@ module internal ParsingHelper = begin let vex0F68 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPUNPCKHBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VPUNPCKHBW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1404,6 +1385,13 @@ module internal ParsingHelper = begin struct (VCVTUSI2SD, OD.XmmVvXm, SZ.QDq) (* VdqHdqWq *) | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F7C = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (HADDPD, OD.GprRm, SZ.Dq) + | MPref.MPrxF3 + | MPref.MPrxF2 -> struct (HADDPS, OD.GprRm, SZ.Dq) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F7C = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -1413,6 +1401,13 @@ module internal ParsingHelper = begin struct (VHADDPS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F7D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (HSUBPD, OD.GprRm, SZ.Dq) + | MPref.MPrxF3 + | MPref.MPrxF2 -> struct (HSUBPS, OD.GprRm, SZ.Dq) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F7D = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -1484,6 +1479,90 @@ module internal ParsingHelper = begin struct (VMOVDQU8, OD.RmGpr, SZ.VecDef) (* WZxzVZxz *) | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F90 = function + | MPref.MPrxNP -> struct (SETO, OD.Mem, SZ.Byte) (* Eb *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F90W0 = function + | MPref.MPrxNP -> struct (KMOVW, OD.KnKm, SZ.QQw) (* k1, k2/m16 *) + | MPref.MPrx66 -> struct (KMOVB, OD.KnKm, SZ.QQb) (* k1, k2/m8 *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F90W1 = function + | MPref.MPrxNP -> struct (KMOVQ, OD.KnKm, SZ.Q) (* k1, k2/m64 *) + | MPref.MPrx66 -> struct (KMOVD, OD.KnKm, SZ.QQd) (* k1, k2/m32 *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F91 = function + | MPref.MPrxNP -> struct (SETNO, OD.Mem, SZ.Byte) (* Eb *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F91W0 = function + | MPref.MPrxNP -> struct (KMOVW, OD.MKn, SZ.QQw) (* m16, k1 *) + | MPref.MPrx66 -> struct (KMOVB, OD.MKn, SZ.QQb) (* m8, k1 *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F91W1 = function + | MPref.MPrxNP -> struct (KMOVQ, OD.MKn, SZ.Q) (* m64, k1 *) + | MPref.MPrx66 -> struct (KMOVD, OD.MKn, SZ.QQd) (* m32, k1 *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F92 = function + | MPref.MPrxNP -> struct (SETB, OD.Mem, SZ.Byte) (* Eb *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F92W0 = function + | MPref.MPrxNP -> struct (KMOVW, OD.KnGpr, SZ.Def) (* k1, r32 *) + | MPref.MPrx66 -> struct (KMOVB, OD.KnGpr, SZ.Def) (* k1, r32 *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (KMOVD, OD.KnGpr, SZ.Def) (* k1, r32 *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F92W1 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (KMOVQ, OD.KnGpr, SZ.Def) (* k1, r64 *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F93 = function + | MPref.MPrxNP -> struct (SETNB, OD.Mem, SZ.Byte) (* Eb *) + | MPref.MPrx66 + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F93W0 = function + | MPref.MPrxNP -> struct (KMOVW, OD.GprKn, SZ.Def) (* r32, k1 *) + | MPref.MPrx66 -> struct (KMOVB, OD.GprKn, SZ.Def) (* r32, k1 *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (KMOVD, OD.GprKn, SZ.Def) (* r32, k1 *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F93W1 = function + | MPref.MPrxNP + | MPref.MPrx66 + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (KMOVQ, OD.GprKn, SZ.Def) (* r64, k1 *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0FC2 = function | MPref.MPrxNP -> struct (CMPPS, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) @@ -1501,9 +1580,9 @@ module internal ParsingHelper = begin | MPref.MPrx66 -> struct (VCMPPD, OD.XmmVvXmImm8, SZ.VecDef) (* VpdHpdWpdIb *) | MPref.MPrxF3 -> - struct (VCMPSS, OD.XmmVvXmImm8, SZ.VecDef) (* VssHssWssIb *) + struct (VCMPSS, OD.XmmVvXmImm8, SZ.DqdDq) (* VssHssWssIb *) | MPref.MPrxF2 -> - struct (VCMPSD, OD.XmmVvXmImm8, SZ.VecDef) (* VsdHsdWsdIb *) + struct (VCMPSD, OD.XmmVvXmImm8, SZ.DqqDq) (* VsdHsdWsdIb *) | _ (* MPrx66F2 *) -> raise ParsingFailureException let evex0FC2W0 = function @@ -1568,6 +1647,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0FD0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (ADDSUBPD, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 -> struct (ADDSUBPS, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0FD0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -1586,7 +1672,7 @@ module internal ParsingHelper = begin let vex0FD1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSRLW, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSRLW, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1600,7 +1686,7 @@ module internal ParsingHelper = begin let vex0FD2 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSRLD, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSRLD, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1614,7 +1700,7 @@ module internal ParsingHelper = begin let vex0FD3 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSRLQ, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSRLQ, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1810,7 +1896,7 @@ module internal ParsingHelper = begin let vex0FE1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSRAW, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSRAW, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -1824,7 +1910,7 @@ module internal ParsingHelper = begin let vex0FE2 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSRAD, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSRAD, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -2076,7 +2162,7 @@ module internal ParsingHelper = begin let vex0FF1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSLLW, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSLLW, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -2090,7 +2176,7 @@ module internal ParsingHelper = begin let vex0FF2 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSLLD, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSLLD, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -2104,7 +2190,7 @@ module internal ParsingHelper = begin let vex0FF3 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPSLLQ, OD.XmmVvXm, SZ.DqX) (* VxHxWdq *) + | MPref.MPrx66 -> struct (VPSLLQ, OD.XmmVvXm, SZ.XDq) (* VxHxWdq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -2151,6 +2237,20 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0FF7 = function + | MPref.MPrxNP -> struct (MASKMOVQ, OD.MxMx, SZ.QQ) (* PqNq *) + | MPref.MPrx66 -> struct (MASKMOVDQU, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0FF7 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VMASKMOVDQU, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0FF8 = function | MPref.MPrxNP -> struct (PSUBB, OD.MmxRm, SZ.QQ) (* PqQq *) | MPref.MPrx66 -> struct (PSUBB, OD.GprRm, SZ.DqDq) (* VdqWdq *) @@ -2298,6 +2398,20 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3804 = function + | MPref.MPrxNP -> struct (PMADDUBSW, OD.MmxRm, SZ.QQ) (* PqQq *) + | MPref.MPrx66 -> struct (PMADDUBSW, OD.GprRm, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3804 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPMADDUBSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3803 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> struct (VPHADDSW, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) @@ -2412,6 +2526,48 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F380DW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPERMILPD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F380EW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VTESTPS, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F380FW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VTESTPD, OD.GprRm, SZ.VecDef) (* VxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3810 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (PBLENDVB, OD.XmmXmXmm0, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3813W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VCVTPH2PS, OD.GprRm, SZ.DqqdqX) (* VxWdqqdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3814 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (BLENDVPS, OD.XmmXmXmm0, SZ.DqDq) (* VdqWdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F3814W0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> struct (VPRORVD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) @@ -2457,7 +2613,7 @@ module internal ParsingHelper = begin let vex0F3818W0 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VBROADCASTSS, OD.GprRm, SZ.DX) (* VxMd *) + | MPref.MPrx66 -> struct (VBROADCASTSS, OD.GprRm, SZ.DqdX) (* VxWdqd *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -2659,6 +2815,20 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F382A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (MOVNTDQA, OD.GprRm, SZ.Dq) (* VdqMdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F382A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VMOVNTDQA, OD.GprRm, SZ.VecDef) (* VxMx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F382AW1 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> raise ParsingFailureException @@ -3382,6 +3552,14 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F3879W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (VPBROADCASTW, OD.GprRm, SZ.DqwX) (* VxWdqw *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F387AW0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -3428,9 +3606,17 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3882 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (INVPCID, OD.GprM, SZ.DqY) (* GyMdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F3883W1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VPMULTISHIFTQB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> + struct (VPMULTISHIFTQB, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -3760,16 +3946,14 @@ module internal ParsingHelper = begin let vex0F389EW0 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VFNMSUB132PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VFNMSUB132PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F389EW1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VFNMSUB132PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VFNMSUB132PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -3892,14 +4076,14 @@ module internal ParsingHelper = begin let vex0F38AAW0 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VFMSUB213PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWdqq *) + | MPref.MPrx66 -> struct (VFMSUB213PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F38AAW1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> struct (VFMSUB213PD, OD.XmmVvXm, SZ.DqqX) (* VxHxWdqq *) + | MPref.MPrx66 -> struct (VFMSUB213PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -3974,16 +4158,14 @@ module internal ParsingHelper = begin let vex0F38AEW0 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VFNMSUB213PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VFNMSUB213PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F38AEW1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VFNMSUB213PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VFNMSUB213PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4180,16 +4362,14 @@ module internal ParsingHelper = begin let vex0F38BEW0 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VFNMSUB231PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VFNMSUB231PS, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F38BEW1 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VFNMSUB231PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) + | MPref.MPrx66 -> struct (VFNMSUB231PD, OD.XmmVvXm, SZ.VecDef) (* VxHxWx *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4205,7 +4385,7 @@ module internal ParsingHelper = begin let vex0F38BFW1 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> - struct (VFNMSUB231SD, OD.XmmVvXm, SZ.DqdDq) (* VdqHdqWdqd *) + struct (VFNMSUB231SD, OD.XmmVvXm, SZ.DqqDq) (* VdqHdqWdqq *) | MPref.MPrxF3 -> raise ParsingFailureException | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4354,6 +4534,20 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F38DB = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (AESIMC, OD.GprRm, SZ.Dq) (* VxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F38DC = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (AESENC, OD.GprRm, SZ.Dq) (* VxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F38DC = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4370,6 +4564,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F38DD = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (AESENCLAST, OD.GprRm, SZ.Dq) (* VxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F38DD = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4386,6 +4587,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F38DE = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (AESDEC, OD.GprRm, SZ.Dq) (* VxWx *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F38DE = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4402,6 +4610,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F38DF = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (AESDECLAST, OD.GprRm, SZ.Dq) (* VdqWdq *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F38DF = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4472,14 +4687,14 @@ module internal ParsingHelper = begin let nor0F38F6W0 = function | MPref.MPrxNP -> struct (WRSSD, OD.GprRm, SZ.Def) (* GyEy *) | MPref.MPrx66 -> struct (ADCX, OD.GprRm, SZ.Def) (* GyEy *) - | MPref.MPrxF3 + | MPref.MPrxF3 -> struct (ADOX, OD.GprRm, SZ.Def) (* GyEy *) | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F38F6W1 = function | MPref.MPrxNP -> struct (WRSSQ, OD.GprRm, SZ.Def) (* GyEy *) | MPref.MPrx66 -> struct (ADCX, OD.GprRm, SZ.Def) (* GyEy *) - | MPref.MPrxF3 + | MPref.MPrxF3 -> struct (ADOX, OD.GprRm, SZ.Def) (* GyEy *) | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4586,7 +4801,14 @@ module internal ParsingHelper = begin let vex0F3A09 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> - struct (VROUNDPD, OD.XmmVvXmImm8, SZ.VecDef) (* VxHxWxIb *) + struct (VROUNDPD, OD.XmmRmImm8, SZ.VecDef) (* VxWxIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A0A = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (ROUNDSS, OD.GprRmImm8, SZ.DqdDq) (* VdqWdqdIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4631,6 +4853,14 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A0D = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (BLENDPD, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A0C = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4647,6 +4877,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A0E = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (PBLENDW, OD.GprRmImm8, SZ.Dq) (* VxWxIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A0E = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4671,10 +4908,10 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException - let nor0F3A15 = function + let nor0F3A14 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> - struct (PEXTRW, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + struct (PEXTRB, OD.XmRegImm8, SZ.DbDq) (* EbVdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4687,6 +4924,14 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A15 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (PEXTRW, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A15 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4695,18 +4940,46 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException - let nor0F3A16 = function + let nor0F3A16W0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> - struct (PEXTRD, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + struct (PEXTRD, OD.XmRegImm8, SZ.VyDqMR) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException - let vex0F3A16 = function + let nor0F3A16W1 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> - struct (VPEXTRD, OD.XmRegImm8, SZ.DwDq) (* EdwVdqIb *) + struct (PEXTRQ, OD.XmRegImm8, SZ.VyDqMR) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A16W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPEXTRD, OD.XmRegImm8, SZ.VyDqMR) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A16W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPEXTRQ, OD.XmRegImm8, SZ.VyDqMR) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A16W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPEXTRD, OD.XmRegImm8, SZ.VyDqMR) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let evex0F3A16W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPEXTRQ, OD.XmRegImm8, SZ.VyDqMR) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -4783,6 +5056,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A1DW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VCVTPS2PH, OD.RmXmmImm8, SZ.DqqdqX) (* WxVxIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F3A1EW0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4814,6 +5094,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A21 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (INSERTPS, OD.GprRmImm8, SZ.DqdDq) (* VdqUdqdIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A21 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4822,6 +5109,22 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A22W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (PINSRD, OD.GprRmImm8, SZ.DDq) (* VdqEdIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A22W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (PINSRQ, OD.GprRmImm8, SZ.QDq) (* VdqEqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A22W0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4949,6 +5252,49 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A40 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (DPPS, OD.GprRmImm8, SZ.Dq) (* VdqWdqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A40 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VDPPS, OD.XmmVvXmImm8, SZ.VecDef) (* VxVxWxIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A41 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (DPPD, OD.GprRmImm8, SZ.Dq) (* VdqWdqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A41 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VDPPD, OD.XmmVvXmImm8, SZ.Dq) (* VdqVdqWdqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let nor0F3A42 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (MPSADBW, OD.GprRmImm8, SZ.Dq) (* VdqWdqIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A42 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (VMPSADBW, OD.XmmVvXmImm8, SZ.VecDef) (* VxHXWxIb *) + | MPref.MPrxF3 -> raise ParsingFailureException + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let evex0F3A43W0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4965,6 +5311,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3A44 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (PCLMULQDQ, OD.GprRmImm8, SZ.Dq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let vex0F3A44 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -4981,7 +5334,6 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException - let vex0F3A46W0 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> @@ -5024,64 +5376,116 @@ module internal ParsingHelper = begin let nor0F3A60 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (PCMPESTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (PCMPESTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F3A60 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPCMPESTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (VPCMPESTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F3A61 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (PCMPESTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (PCMPESTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F3A61 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPCMPESTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (VPCMPESTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F3A62 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (PCMPISTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (PCMPISTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F3A62 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (VPCMPISTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (VPCMPISTRM, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let nor0F3A63 = function | MPref.MPrxNP -> raise ParsingFailureException - | MPref.MPrx66 -> - struct (PCMPISTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrx66 -> struct (PCMPISTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException let vex0F3A63 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VPCMPISTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A68W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VFMADDPS, OD.XmmVvXmXmm, SZ.VecDef) (* VxHxWxLx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A68W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VFMADDPS, OD.XmmVvXmmXm, SZ.VecDef) (* VxHxLxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A69W0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VFMADDPD, OD.XmmVvXmXmm, SZ.VecDef) (* VxHxWxLx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A69W1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (VFMADDPD, OD.XmmVvXmmXm, SZ.VecDef) (* VxHxLxWx *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A6AW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (VFMADDSS, OD.XmmVvXmXmm, SZ.DqdDq) (* VdqHdqWdqdLdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A6AW1 = function | MPref.MPrxNP -> raise ParsingFailureException | MPref.MPrx66 -> - struct (VPCMPISTRI, OD.XmmRmImm8, SZ.DqDq) (* VdqWdqIb *) + struct (VFMADDSS, OD.XmmVvXmmXm, SZ.DqdDq) (* VdqHdqLdqWdqd *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A6BW0 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (VFMADDSD, OD.XmmVvXmXmm, SZ.DqqDq) (* VdqHdqWdqqLdq *) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + + let vex0F3A6BW1 = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> + struct (VFMADDSD, OD.XmmVvXmmXm, SZ.DqqDq) (* VdqHdqLdqWdqq *) | MPref.MPrxF3 | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException @@ -5160,6 +5564,13 @@ module internal ParsingHelper = begin | MPref.MPrxF2 | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3ADF = function + | MPref.MPrxNP -> raise ParsingFailureException + | MPref.MPrx66 -> struct (AESKEYGENASSIST,OD.XmmRmImm8, SZ.DqDq) + | MPref.MPrxF3 + | MPref.MPrxF2 + | _ (* MPrx66F2 *) -> raise ParsingFailureException + let nor0F3AF0 = function | MPref.MPrxNP | MPref.MPrx66 @@ -5192,7 +5603,6 @@ module internal ParsingHelper = begin | 3 -> RCR | 4 -> SHL | 5 -> SHR - | 6 -> InvalOP | 7 -> SAR | _ -> raise ParsingFailureException @@ -5201,13 +5611,14 @@ module internal ParsingHelper = begin | 1 -> DEC | _ -> raise ParsingFailureException - let grp5 = function + let grp5 b = function | 0 -> struct (INC, OD.Mem, SZ.Def, SzCond.Nor) | 1 -> struct (DEC, OD.Mem, SZ.Def, SzCond.Nor) | 2 -> struct (CALLNear, OD.Mem, SZ.Def, SzCond.F64) | 3 -> struct (CALLFar, OD.Mem, SZ.P, SzCond.Nor) | 4 -> struct (JMPNear, OD.Mem, SZ.Def, SzCond.F64) - | 5 -> struct (JMPFar, OD.Dir, SZ.P, SzCond.Nor) + | 5 -> if modIsMemory b then struct (JMPFar, OD.Mem, SZ.P, SzCond.Nor) + else raise ParsingFailureException | 6 -> struct (PUSH, OD.Mem, SZ.Def, SzCond.D64) | _ -> raise ParsingFailureException @@ -5223,10 +5634,6 @@ module internal ParsingHelper = begin | _ -> raise ParsingFailureException let grp8Op = function - | 0 -> InvalOP - | 1 -> InvalOP - | 2 -> InvalOP - | 3 -> InvalOP | 4 -> BT | 5 -> BTS | 6 -> BTR @@ -5249,7 +5656,7 @@ module internal ParsingHelper = begin let getGrp3OpKind oidx sidx oprGrp regBits = match regBits with | 0b000 when oprGrp = OpGroup.G3A -> - struct (TEST, OD.RmImm8, SZ.Byte, SzCond.Nor) + struct (TEST, OD.RmSImm8, SZ.Byte, SzCond.Nor) | 0b000 when oprGrp = OpGroup.G3B -> struct (TEST, OD.RmImm, SZ.Def, SzCond.Nor) | 0b010 -> struct (NOT, oidx, sidx, SzCond.Nor) @@ -5373,17 +5780,17 @@ module internal ParsingHelper = begin | false, 0b010, false -> struct (PSRLW, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b010, true -> if rhlp.VEXInfo = None then - struct (PSRLW, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSRLW, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSRLW, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | false, 0b100, false -> struct (PSRAW, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b100, true -> if rhlp.VEXInfo = None then - struct (PSRAW, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSRAW, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSRAW, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | false, 0b110, false -> struct (PSLLW, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b110, true -> if rhlp.VEXInfo = None then - struct (PSLLW, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSLLW, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSLLW, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | _ -> raise ParsingFailureException @@ -5392,17 +5799,17 @@ module internal ParsingHelper = begin | false, 0b010, false -> struct (PSRLD, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b010, true -> if rhlp.VEXInfo = None then - struct (PSRLD, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSRLD, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSRLD, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | false, 0b100, false -> struct (PSRAD, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b100, true -> if rhlp.VEXInfo = None then - struct (PSRAD, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSRAD, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSRAD, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | false, 0b110, false -> struct (PSLLD, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b110, true -> if rhlp.VEXInfo = None then - struct (PSLLD, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSLLD, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSLLD, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | _ -> raise ParsingFailureException @@ -5412,7 +5819,7 @@ module internal ParsingHelper = begin struct (PSRLQ, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b010, true -> if rhlp.VEXInfo = None then - struct (PSRLQ, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSRLQ, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSRLQ, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | false, 0b011, true -> if rhlp.VEXInfo = None then @@ -5421,7 +5828,7 @@ module internal ParsingHelper = begin | false, 0b110, false -> struct (PSLLQ, OD.MmxImm8, SZ.Q, SzCond.Nor) | false, 0b110, true -> if rhlp.VEXInfo = None then - struct (PSLLQ, OD.RmImm8, SZ.Dq, SzCond.Nor) + struct (PSLLQ, OD.RmSImm8, SZ.Dq, SzCond.Nor) else struct (VPSLLQ, OD.VvRmImm8, SZ.VecDef, SzCond.Nor) | false, 0b111, true -> if rhlp.VEXInfo = None then @@ -5432,12 +5839,15 @@ module internal ParsingHelper = begin let parseGrp15OpKind (rhlp: ReadHelper) b regBits = match modIsMemory b, regBits, rhlp.Prefixes with | true, 0b000, Prefix.PrxNone -> - let op = if hasREXW rhlp.REXPrefix then FXSAVE64 else FXSAVE - struct (op, OD.Mem, SZ.Def, SzCond.Nor) + if rhlp.VEXInfo = None then + let op = if hasREXW rhlp.REXPrefix then FXSAVE64 else FXSAVE + struct (op, OD.Mem, SZ.Def, SzCond.Nor) + else raise ParsingFailureException | true, 0b001, Prefix.PrxNone -> - let op = - if hasREXW rhlp.REXPrefix then FXRSTOR64 else FXRSTOR - struct (op, OD.Mem, SZ.Def, SzCond.Nor) + if rhlp.VEXInfo = None then + let op = if hasREXW rhlp.REXPrefix then FXRSTOR64 else FXRSTOR + struct (op, OD.Mem, SZ.Def, SzCond.Nor) + else raise ParsingFailureException | true, 0b010, Prefix.PrxNone -> struct (LDMXCSR, OD.Mem, SZ.D, SzCond.Nor) | true, 0b011, Prefix.PrxNone -> struct (STMXCSR, OD.Mem, SZ.D, SzCond.Nor) | true, 0b100, Prefix.PrxNone -> struct (XSAVE, OD.Mem, SZ.Def, SzCond.Nor) @@ -5448,6 +5858,8 @@ module internal ParsingHelper = begin struct (CLWB, OD.Mem, SZ.Byte, SzCond.Nor) | true, 0b110, Prefix.PrxREPZ -> struct (CLRSSBSY, OD.Mem, SZ.Q, SzCond.Nor) | true, 0b111, Prefix.PrxNone -> struct (CLFLUSH, OD.Mem, SZ.BV, SzCond.Nor) + | true, 0b111, Prefix.PrxOPSIZE -> + struct (CLFLUSHOPT, OD.Mem, SZ.BV, SzCond.Nor) | false, 0b101, Prefix.PrxNone -> rhlp.IncPos (); struct (LFENCE, OD.No, SZ.Def, SzCond.Nor) | false, 0b110, Prefix.PrxNone -> @@ -5482,7 +5894,7 @@ module internal ParsingHelper = begin | OpGroup.G2 -> struct (grp2Op r, oidx, sidx, SzCond.Nor) | OpGroup.G3A | OpGroup.G3B -> getGrp3OpKind oidx sidx oprGrp r | OpGroup.G4 -> struct (grp4Op r, OD.Mem, SZ.Byte, SzCond.Nor) - | OpGroup.G5 -> grp5 r + | OpGroup.G5 -> grp5 b r | OpGroup.G6 -> getGrp6OpKind b r | OpGroup.G7 -> parseGrp7OpKind rhlp b r | OpGroup.G8 -> struct (grp8Op r, oidx, sidx, SzCond.Nor) @@ -5524,12 +5936,16 @@ module internal ParsingHelper = begin /// prefix to decide the opcode. let inline filterPrefs (prefix: Prefix) = prefix &&& ClearVEXPrefMask + let inline filterREPZPrefs (prefix: Prefix) = prefix &&& ClearREPZPrefMask + + let inline filterREXWPrefs (rex: REXPrefix) = rex &&& ClearREXWPrefMask + let getInstr prefix fnInstr = fnInstr (getMandPrx prefix) /// The main instruction rendering function. let render span rhlp opcode szCond (oidx: OprDesc) (sidx: SizeKind) = (rhlp: ReadHelper).SzComputers[int sidx].Render rhlp szCond - exceptionalOperationSize opcode rhlp + exceptionHandling opcode rhlp let oprs = rhlp.OprParsers[int oidx].Render (span, rhlp) newInsInfo rhlp opcode oprs @@ -5554,7 +5970,7 @@ module internal ParsingHelper = begin let struct (op, oidx, sidx) = fnVex (getMandPrx v.VPrefixes) render span rhlp op SzCond.Nor oidx sidx - /// Normal(REX.W), VEX(REX.W) + /// Select Normal(REX.W), VEX(REX.W) let selectVEXW (span: ByteSpan) rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 = match (rhlp: ReadHelper).VEXInfo with | None -> @@ -5566,14 +5982,13 @@ module internal ParsingHelper = begin let fnVex = if hasREXW rhlp.REXPrefix then fnVexW1 else fnVexW0 getInstr v.VPrefixes fnVex - /// Normal/VEX (Both REX.W) + /// Normal(REX.W)/VEX(REX.W) let parseVEXW span rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 = let struct (op, oidx, sidx) = selectVEXW span rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 render span rhlp op SzCond.Nor oidx sidx - /// Normal(REX.W), VEX(REX.W) - /// Normal, VEX, EVEX(REX.W) + /// Select Normal, VEX, EVEX(REX.W) let selectEVEX (rhlp: ReadHelper) fnNor fnVex fnEVexW0 fnEVexW1 = match rhlp.VEXInfo with | None -> @@ -5586,13 +6001,12 @@ module internal ParsingHelper = begin getInstr v.VPrefixes fnEVex else getInstr v.VPrefixes fnVex - /// Normal/VEX/EVEX (EVEX REX.W) + /// Normal/VEX/EVEX(REX.W) let parseEVEX span rhlp fnNor fnVex fnEVexW0 fnEVexW1 = - let struct (op, oidx, sidx) = - selectEVEX rhlp fnNor fnVex fnEVexW0 fnEVexW1 + let struct (op, oidx, sidx) = selectEVEX rhlp fnNor fnVex fnEVexW0 fnEVexW1 render span rhlp op SzCond.Nor oidx sidx - /// VEX(REX.W), EVEX(REX.W) + /// Select VEX(REX.W), EVEX(REX.W) let selectEVEXW (rhlp: ReadHelper) fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 = match rhlp.VEXInfo with | None -> raise ParsingFailureException @@ -5604,12 +6018,35 @@ module internal ParsingHelper = begin let fnVex = if hasREXW rhlp.REXPrefix then fnVexW1 else fnVexW0 getInstr v.VPrefixes fnVex - /// VEX/EVEX (Both REX.W) + /// VEX(REX.W)/EVEX(REX.W) let parseEVEXW span rhlp fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 = let struct (op, oidx, sidx) = selectEVEXW rhlp fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 render span rhlp op SzCond.Nor oidx sidx + /// Select Normal(REX.W), VEX(REX.W), EVEX(REX.W) + let selectEVEXAll (rhlp: ReadHelper) fnNorW0 fnNorW1 fnVexW0 fnVexW1 fnEVexW0 + fnEVexW1 = + match (rhlp: ReadHelper).VEXInfo with + | None -> + let fnNor = if hasREXW rhlp.REXPrefix then fnNorW1 else fnNorW0 + let ins = getInstr rhlp.Prefixes fnNor + rhlp.Prefixes <- filterPrefs rhlp.Prefixes + ins + | Some v -> + if v.VEXType &&& VEXType.EVEX = VEXType.EVEX then + let fnEVex = if hasREXW rhlp.REXPrefix then fnEVexW1 else fnEVexW0 + getInstr v.VPrefixes fnEVex + else + let fnVex = if hasREXW rhlp.REXPrefix then fnVexW1 else fnVexW0 + getInstr v.VPrefixes fnVex + + /// Normal(REX.W)/VEX(REX.W)/EVEX(REX.W) + let parseEVEXAll span rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 = + let struct (op, oidx, sidx) = + selectEVEXAll rhlp fnNorW0 fnNorW1 fnVexW0 fnVexW1 fnEVexW0 fnEVexW1 + render span rhlp op SzCond.Nor oidx sidx + /// Parse non-VEX instructions. let parseNonVEX span (rhlp: ReadHelper) fnNor = let struct (op, oidx, sidx) = getInstr rhlp.Prefixes fnNor @@ -5669,6 +6106,7 @@ module internal ParsingHelper = begin | 0x01uy -> parseVEX span rhlp nor0F3801 vex0F3801 | 0x02uy -> parseVEX span rhlp nor0F3802 vex0F3802 | 0x03uy -> parseVEX span rhlp nor0F3803 vex0F3803 + | 0x04uy -> parseEVEX span rhlp nor0F3804 vex0F3804 notEn notEn | 0x05uy -> parseVEX span rhlp nor0F3805 vex0F3805 | 0x06uy -> parseVEX span rhlp nor0F3806 vex0F3806 | 0x07uy -> parseVEX span rhlp nor0F3807 vex0F3807 @@ -5677,7 +6115,12 @@ module internal ParsingHelper = begin | 0x0auy -> parseVEX span rhlp nor0F380A vex0F380A | 0x0buy -> parseVEX span rhlp nor0F380B vex0F380B | 0x0cuy -> parseEVEXW span rhlp vex0F380CW0 notEn notEn notEn - | 0x14uy -> parseEVEXW span rhlp notEn notEn evex0F3814W0 evex0F3814W1 + | 0x0duy -> parseEVEXW span rhlp vex0F380DW0 notEn notEn notEn + | 0x0euy -> parseEVEXW span rhlp vex0F380EW0 notEn notEn notEn + | 0x0fuy -> parseEVEXW span rhlp vex0F380FW0 notEn notEn notEn + | 0x10uy -> parseVEX span rhlp nor0F3810 notEn + | 0x13uy -> parseEVEXW span rhlp vex0F3813W0 notEn notEn notEn + | 0x14uy -> parseEVEX span rhlp nor0F3814 notEn evex0F3814W0 evex0F3814W1 | 0x15uy -> parseVEX span rhlp nor0F3815 notEn | 0x16uy -> parseVEXW span rhlp notEn notEn vex0F3816W0 notEn | 0x17uy -> parseVEX span rhlp nor0F3817 vex0F3817 @@ -5696,7 +6139,7 @@ module internal ParsingHelper = begin | 0x25uy -> parseVEX span rhlp nor0F3825 vex0F3825 | 0x28uy -> parseVEX span rhlp nor0F3828 vex0F3828 | 0x29uy -> parseVEX span rhlp nor0F3829 vex0F3829 - | 0X2auy -> parseEVEXW span rhlp notEn notEn notEn evex0F382AW1 + | 0x2auy -> parseEVEX span rhlp nor0F382A vex0F382A notEn evex0F382AW1 | 0x2buy -> parseVEX span rhlp nor0F382B vex0F382B | 0x2cuy -> parseEVEXW span rhlp vex0F382CW0 notEn evex0F382CW0 evex0F382CW1 | 0x2duy -> parseEVEXW span rhlp vex0F382DW0 notEn evex0F382DW0 evex0F382DW1 @@ -5746,11 +6189,12 @@ module internal ParsingHelper = begin | 0x76uy -> parseEVEXW span rhlp notEn notEn evex0F3876W0 notEn | 0x77uy -> parseEVEXW span rhlp notEn notEn notEn evex0F3877W1 | 0x78uy -> parseVEX span rhlp nor0F3878 vex0F3878 - | 0x79uy -> parseEVEXW span rhlp vex0F3879W0 notEn notEn notEn + | 0x79uy -> parseEVEXW span rhlp vex0F3879W0 notEn evex0F3879W0 notEn | 0x7Auy -> parseEVEXW span rhlp notEn notEn evex0F387AW0 notEn | 0x7Buy -> parseEVEXW span rhlp notEn notEn evex0F387BW0 notEn | 0x7Cuy -> parseEVEXW span rhlp notEn notEn evex0F387CW0 evex0F387CW1 | 0x7Duy -> parseEVEXW span rhlp notEn notEn evex0F387DW0 evex0F387DW1 + | 0x82uy -> parseVEX span rhlp nor0F3882 notEn | 0x83uy -> parseEVEXW span rhlp notEn notEn notEn evex0F3883W1 | 0x8Cuy -> parseVEXW span rhlp notEn notEn vex0F388CW0 vex0F388CW1 | 0x8Duy -> parseEVEXW span rhlp notEn notEn evex0F388DW0 notEn @@ -5815,10 +6259,11 @@ module internal ParsingHelper = begin | 0xCBuy -> parseEVEXW span rhlp notEn notEn notEn evex0F38CBW1 | 0xCDuy -> parseEVEXW span rhlp notEn notEn notEn evex0F38CDW1 | 0xCFuy -> parseEVEXW span rhlp evex0F38CFW0 notEn evex0F38CFW0 notEn - | 0xDCuy -> parseEVEX span rhlp notEn vex0F38DC evex0F38DC evex0F38DC - | 0xDDuy -> parseEVEX span rhlp notEn vex0F38DD evex0F38DD evex0F38DD - | 0xDEuy -> parseEVEX span rhlp notEn vex0F38DE evex0F38DE evex0F38DE - | 0xDFuy -> parseEVEX span rhlp notEn vex0F38DF evex0F38DF evex0F38DF + | 0xDBuy -> parseVEX span rhlp nor0F38DB notEn + | 0xDCuy -> parseEVEX span rhlp nor0F38DC vex0F38DC evex0F38DC evex0F38DC + | 0xDDuy -> parseEVEX span rhlp nor0F38DD vex0F38DD evex0F38DD evex0F38DD + | 0xDEuy -> parseEVEX span rhlp nor0F38DE vex0F38DE evex0F38DE evex0F38DE + | 0xDFuy -> parseEVEX span rhlp nor0F38DF vex0F38DF evex0F38DF evex0F38DF | 0xF0uy -> parseNonVEX span rhlp nor0F38F0 | 0xF1uy -> parseNonVEX span rhlp nor0F38F1 | 0xF2uy -> parseVEX span rhlp notEn vex0F38F2 @@ -5844,25 +6289,33 @@ module internal ParsingHelper = begin | 0x06uy -> parseVEXW span rhlp notEn notEn vex0F3A06W0 notEn | 0x08uy -> parseVEX span rhlp nor0F3A08 vex0F3A08 | 0x09uy -> parseVEX span rhlp nor0F3A09 vex0F3A09 - | 0x0Auy -> parseVEX span rhlp notEn vex0F3A0A + | 0x0Auy -> parseVEX span rhlp nor0F3A0A vex0F3A0A | 0x0Buy -> parseEVEX span rhlp nor0F3A0B vex0F3A0B notEn evex0F3A0BW1 | 0x0Cuy -> parseVEX span rhlp nor0F3A0C vex0F3A0C - | 0x0Duy -> parseVEX span rhlp notEn vex0F3A0D - | 0x0Euy -> parseVEX span rhlp notEn vex0F3A0E + | 0x0Duy -> parseVEX span rhlp nor0F3A0D vex0F3A0D + | 0x0Euy -> parseVEX span rhlp nor0F3A0E vex0F3A0E | 0x0Fuy -> parseVEX span rhlp nor0F3A0F vex0F3A0F - | 0x14uy -> parseVEXW span rhlp notEn notEn vex0F3A14W0 notEn + | 0x14uy -> parseVEXW span rhlp nor0F3A14 nor0F3A14 vex0F3A14W0 notEn | 0x15uy -> parseVEX span rhlp nor0F3A15 vex0F3A15 - | 0x16uy -> parseVEX span rhlp nor0F3A16 vex0F3A16 + | 0x16uy -> + /// VEX.W/EVEX.W in non-64 bit is ignored; the instructions behaves as + /// if the W0 version is used. + if rhlp.WordSize = WordSize.Bit64 then () + else rhlp.REXPrefix <- filterREXWPrefs rhlp.REXPrefix + parseEVEXAll span rhlp nor0F3A16W0 nor0F3A16W1 vex0F3A16W0 vex0F3A16W1 + evex0F3A16W0 evex0F3A16W1 | 0x17uy -> parseEVEX span rhlp nor0F3A17 vex0F3A17 notEn notEn | 0x18uy -> parseEVEXW span rhlp vex0F3A18W0 notEn notEn notEn | 0x19uy -> parseEVEXW span rhlp vex0F3A19W0 notEn evex0F3A19W0 evex0F3A19W1 | 0x1Auy -> parseEVEXW span rhlp notEn notEn notEn evex0F3A1AW1 | 0x1Buy -> parseEVEXW span rhlp notEn notEn evex0F3A1BW0 evex0F3A1BW1 + | 0x1Duy -> parseEVEXW span rhlp vex0F3A1DW0 notEn notEn notEn | 0x1Euy -> parseEVEXW span rhlp notEn notEn evex0F3A1EW0 evex0F3A1EW1 | 0x20uy -> parseVEX span rhlp nor0F3A20 vex0F3A20 - | 0x21uy -> parseVEX span rhlp notEn vex0F3A21 + | 0x21uy -> parseVEX span rhlp nor0F3A21 vex0F3A21 | 0x22uy -> - parseEVEXW span rhlp vex0F3A22W0 vex0F3A22W1 evex0F3A22W0 evex0F3A22W1 + parseEVEXAll span rhlp nor0F3A22W0 nor0F3A22W1 vex0F3A22W0 vex0F3A22W1 + evex0F3A22W0 evex0F3A22W1 | 0x25uy -> parseEVEXW span rhlp notEn notEn evex0F3A25W0 evex0F3A25W1 | 0x27uy -> parseEVEXW span rhlp notEn notEn notEn evex0F3A27W1 | 0x38uy -> parseVEX span rhlp nor0F3A38 vex0F3A38 @@ -5870,8 +6323,11 @@ module internal ParsingHelper = begin | 0x3Auy -> parseEVEXW span rhlp notEn notEn evex0F3A3AW0 evex0F3A3AW1 | 0x3Buy -> parseEVEXW span rhlp notEn notEn evex0F3A3BW0 evex0F3A3BW1 | 0x3Euy -> parseEVEXW span rhlp notEn notEn evex0F3A3EW0 evex0F3A3EW1 + | 0x40uy -> parseVEX span rhlp nor0F3A40 vex0F3A40 + | 0x41uy -> parseVEX span rhlp nor0F3A41 vex0F3A41 + | 0x42uy -> parseVEX span rhlp nor0F3A42 vex0F3A42 | 0x43uy -> parseEVEXW span rhlp notEn notEn evex0F3A43W0 evex0F3A43W1 - | 0x44uy -> parseEVEX span rhlp notEn vex0F3A44 evex0F3A44 evex0F3A44 + | 0x44uy -> parseEVEX span rhlp nor0F3A44 vex0F3A44 evex0F3A44 evex0F3A44 | 0x46uy -> parseEVEXW span rhlp vex0F3A46W0 notEn notEn notEn | 0x4Auy -> parseVEXW span rhlp notEn notEn vex0F3A4AW0 notEn | 0x4Buy -> parseVEXW span rhlp notEn notEn vex0F3A4BW0 notEn @@ -5881,12 +6337,17 @@ module internal ParsingHelper = begin | 0x61uy -> parseVEX span rhlp nor0F3A61 vex0F3A61 | 0x62uy -> parseVEX span rhlp nor0F3A62 vex0F3A62 | 0x63uy -> parseVEX span rhlp nor0F3A63 vex0F3A63 + | 0x68uy -> parseVEXW span rhlp notEn notEn vex0F3A68W0 vex0F3A68W1 + | 0x69uy -> parseVEXW span rhlp notEn notEn vex0F3A69W0 vex0F3A69W1 + | 0x6Auy -> parseVEXW span rhlp notEn notEn vex0F3A6AW0 vex0F3A6AW1 + | 0x6Buy -> parseVEXW span rhlp notEn notEn vex0F3A6BW0 vex0F3A6BW1 | 0x70uy -> parseEVEXW span rhlp notEn notEn notEn evex0F3A70W1 | 0x71uy -> parseEVEXW span rhlp notEn notEn evex0F3A71W0 evex0F3A71W1 | 0x72uy -> parseEVEXW span rhlp notEn notEn notEn evex0F3A72W1 | 0x73uy -> parseEVEXW span rhlp notEn notEn evex0F3A73W0 evex0F3A73W1 | 0xCEuy -> parseEVEXW span rhlp notEn vex0F3ACEW1 notEn evex0F3ACEW1 | 0xCFuy -> parseEVEXW span rhlp notEn vex0F3ACFW1 notEn evex0F3ACFW1 + | 0xDFuy -> parseVEX span rhlp nor0F3ADF notEn | 0xF0uy -> parseVEX span rhlp nor0F3AF0 vex0F3AF0 | _ -> raise ParsingFailureException @@ -5902,8 +6363,18 @@ module internal ParsingHelper = begin rhlp let pTwoByteOp span (rhlp: ReadHelper) byte = + (* + printfn "============= %X =============" byte + printfn "MemEffAddrSize %A" rhlp.MemEffAddrSize + printfn "MemEffOprSize %A" rhlp.MemEffOprSize + printfn "MemEffRegSize %A" rhlp.MemEffRegSize + printfn "RegSize %A" rhlp.RegSize + printfn "OperationSize %A" rhlp.OperationSize + *) match byte with - | 0x02uy -> render span rhlp LAR SzCond.Nor OD.GprRm SZ.WV + | 0x02uy -> + if rhlp.VEXInfo.IsSome then raise ParsingFailureException + else render span rhlp LAR SzCond.Nor OD.GprRm SZ.WV | 0x03uy -> render span rhlp LSL SzCond.Nor OD.GprRm SZ.WV | 0x05uy -> #if !EMULATION @@ -6010,8 +6481,8 @@ module internal ParsingHelper = begin | 0x78uy -> parseEVEX span rhlp nor0F78 notEn evex0F78W0 evex0F78W1 | 0x7Auy -> parseEVEX span rhlp notEn notEn evex0F7AW0 evex0F7AW1 | 0x7Buy -> parseEVEXW span rhlp notEn notEn evex0F7BW0 evex0F7BW1 - | 0x7Cuy -> parseVEX span rhlp notEn vex0F7C - | 0x7Duy -> parseVEX span rhlp notEn vex0F7D + | 0x7Cuy -> parseVEX span rhlp nor0F7C vex0F7C + | 0x7Duy -> parseVEX span rhlp nor0F7D vex0F7D | 0x7Euy -> parseVEXW span rhlp nor0F7EW0 nor0F7EW1 vex0F7EW0 vex0F7EW1 | 0x7Fuy -> parseEVEX span rhlp nor0F7F vex0F7F evex0F7FW0 evex0F7FW1 | 0x80uy -> addBND rhlp; render span rhlp JO SzCond.F64 OD.Rel SZ.D64 @@ -6030,10 +6501,10 @@ module internal ParsingHelper = begin | 0x8Duy -> addBND rhlp; render span rhlp JNL SzCond.F64 OD.Rel SZ.D64 | 0x8Euy -> addBND rhlp; render span rhlp JLE SzCond.F64 OD.Rel SZ.D64 | 0x8Fuy -> addBND rhlp; render span rhlp JG SzCond.F64 OD.Rel SZ.D64 - | 0x90uy -> render span rhlp SETO SzCond.Nor OD.Mem SZ.Byte - | 0x91uy -> render span rhlp SETNO SzCond.Nor OD.Mem SZ.Byte - | 0x92uy -> render span rhlp SETB SzCond.Nor OD.Mem SZ.Byte - | 0x93uy -> render span rhlp SETNB SzCond.Nor OD.Mem SZ.Byte + | 0x90uy -> parseVEXW span rhlp nor0F90 nor0F90 vex0F90W0 vex0F90W1 + | 0x91uy -> parseVEXW span rhlp nor0F91 nor0F91 vex0F91W0 vex0F91W1 + | 0x92uy -> parseVEXW span rhlp nor0F92 nor0F92 vex0F92W0 vex0F92W1 + | 0x93uy -> parseVEXW span rhlp nor0F93 nor0F93 vex0F93W0 vex0F93W1 | 0x94uy -> render span rhlp SETZ SzCond.Nor OD.Mem SZ.Byte | 0x95uy -> render span rhlp SETNZ SzCond.Nor OD.Mem SZ.Byte | 0x96uy -> render span rhlp SETBE SzCond.Nor OD.Mem SZ.Byte @@ -6069,16 +6540,17 @@ module internal ParsingHelper = begin | 0xB7uy -> render span rhlp MOVZX SzCond.Nor OD.GprRm SZ.WV | 0xB8uy when not <| hasREPZ rhlp.Prefixes -> raise ParsingFailureException | 0xB8uy -> - rhlp.Prefixes <- filterPrefs rhlp.Prefixes + rhlp.Prefixes <- filterREPZPrefs rhlp.Prefixes render span rhlp POPCNT SzCond.Nor OD.GprRm SZ.Def + | 0xB9uy -> render span rhlp UD1 SzCond.Nor OD.GprRm SZ.Def | 0xBBuy when hasREPZ rhlp.Prefixes -> raise ParsingFailureException | 0xBBuy -> render span rhlp BTC SzCond.Nor OD.RmGpr SZ.Def | 0xBCuy when hasREPZ rhlp.Prefixes -> - rhlp.Prefixes <- filterPrefs rhlp.Prefixes + rhlp.Prefixes <- filterREPZPrefs rhlp.Prefixes render span rhlp TZCNT SzCond.Nor OD.GprRm SZ.Def | 0xBCuy -> render span rhlp BSF SzCond.Nor OD.GprRm SZ.Def | 0xBDuy when hasREPZ rhlp.Prefixes -> - rhlp.Prefixes <- filterPrefs rhlp.Prefixes + rhlp.Prefixes <- filterREPZPrefs rhlp.Prefixes render span rhlp LZCNT SzCond.Nor OD.GprRm SZ.Def | 0xBDuy -> render span rhlp BSR SzCond.Nor OD.GprRm SZ.Def | 0xBEuy -> render span rhlp MOVSX SzCond.Nor OD.GprRm SZ.BV @@ -6090,6 +6562,8 @@ module internal ParsingHelper = begin | 0xC4uy -> parseVEX span rhlp nor0FC4 vex0FC4 | 0xC5uy -> parseVEX span rhlp nor0FC5 vex0FC5 | 0xC6uy -> parseVEX span rhlp nor0FC6 vex0FC6 + | 0xC7uy when isReg111 span rhlp -> + render span rhlp RDSEED SzCond.Nor OD.Gpr SZ.Def | 0xC8uy -> render span (ignOpSz rhlp) BSWAP SzCond.Nor OD.Rax SZ.Def | 0xC9uy -> render span (ignOpSz rhlp) BSWAP SzCond.Nor OD.Rcx SZ.Def | 0xCAuy -> render span (ignOpSz rhlp) BSWAP SzCond.Nor OD.Rdx SZ.Def @@ -6098,7 +6572,7 @@ module internal ParsingHelper = begin | 0xCDuy -> render span (ignOpSz rhlp) BSWAP SzCond.Nor OD.Rbp SZ.Def | 0xCEuy -> render span (ignOpSz rhlp) BSWAP SzCond.Nor OD.Rsi SZ.Def | 0xCFuy -> render span (ignOpSz rhlp) BSWAP SzCond.Nor OD.Rdi SZ.Def - | 0xD0uy -> parseVEX span rhlp notEn vex0FD0 + | 0xD0uy -> parseVEX span rhlp nor0FD0 vex0FD0 | 0xD1uy -> parseVEX span rhlp nor0FD1 vex0FD1 | 0xD2uy -> parseVEX span rhlp nor0FD2 vex0FD2 | 0xD3uy -> parseVEX span rhlp nor0FD3 vex0FD3 @@ -6141,6 +6615,7 @@ module internal ParsingHelper = begin | 0xF4uy -> parseVEX span rhlp nor0FF4 vex0FF4 | 0xF5uy -> parseVEX span rhlp nor0FF5 vex0FF5 | 0xF6uy -> parseVEX span rhlp nor0FF6 vex0FF6 + | 0xF7uy -> parseVEX span rhlp nor0FF7 vex0FF7 | 0xF8uy -> parseVEX span rhlp nor0FF8 vex0FF8 | 0xF9uy -> parseVEX span rhlp nor0FF9 vex0FF9 | 0xFAuy -> parseVEX span rhlp nor0FFA vex0FFA @@ -6148,9 +6623,10 @@ module internal ParsingHelper = begin | 0xFCuy -> parseVEX span rhlp nor0FFC vex0FFC | 0xFDuy -> parseVEX span rhlp nor0FFD vex0FFD | 0xFEuy -> parseVEX span rhlp nor0FFE vex0FFE + | 0xFFuy -> render span rhlp UD0 SzCond.Nor OD.GprRm SZ.Def | 0x00uy -> parseGrpOp span rhlp OpGroup.G6 OD.No SZ.Def | 0x01uy -> parseGrpOp span rhlp OpGroup.G7 OD.No SZ.Def - | 0xBAuy -> parseGrpOp span rhlp OpGroup.G8 OD.RmImm8 SZ.Def + | 0xBAuy -> parseGrpOp span rhlp OpGroup.G8 OD.RmSImm8 SZ.Def | 0xC7uy -> parseGrpOp span rhlp OpGroup.G9 OD.No SZ.Def | 0x71uy -> parseGrpOp span rhlp OpGroup.G12 OD.No SZ.Def | 0x72uy -> parseGrpOp span rhlp OpGroup.G13 OD.No SZ.Def diff --git a/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs b/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs index bd1a6d16..5866bf4f 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelParsingJob.fs @@ -1053,7 +1053,7 @@ type internal OneOp80 () = inherit ParsingJob () override __.Run (span, rhlp) = let struct (op, oidx, szidx, szCond) = - parseGrpOpKind span rhlp OD.RmImm8 SZ.Byte OpGroup.G1 + parseGrpOpKind span rhlp OD.RmSImm8 SZ.Byte OpGroup.G1 render span rhlp op szCond oidx szidx type internal OneOp81 () = @@ -1067,14 +1067,14 @@ type internal OneOp82 () = inherit ParsingJob () override __.Run (span, rhlp) = let struct (op, oidx, szidx, szCond) = - parseGrpOpKind span rhlp OD.RmImm8 SZ.Byte OpGroup.G1Inv64 + parseGrpOpKind span rhlp OD.RmSImm8 SZ.Byte OpGroup.G1Inv64 render span rhlp op szCond oidx szidx type internal OneOp83 () = inherit ParsingJob () override __.Run (span, rhlp) = let struct (op, oidx, szidx, szCond) = - parseGrpOpKind span rhlp OD.RmImm8 SZ.Def OpGroup.G1 + parseGrpOpKind span rhlp OD.RmSImm8 SZ.Def OpGroup.G1 render span rhlp op szCond oidx szidx type internal OneOp84 () = @@ -1323,7 +1323,8 @@ type internal OneOpA4 () = rhlp.SzComputers[int SZ.Def].Render rhlp SzCond.Nor rhlp.OperationSize <- 8 let oprs = rhlp.OprParsers[int OD.No].Render (span, rhlp) - newInsInfo rhlp Opcode.MOVSB oprs + if hasREPNZ rhlp.Prefixes then raise ParsingFailureException + else newInsInfo rhlp Opcode.MOVSB oprs type internal OneOpA5 () = inherit ParsingJob () @@ -1531,14 +1532,14 @@ type internal OneOpC0 () = inherit ParsingJob () override __.Run (span, rhlp) = let struct (op, oidx, szidx, szCond) = - parseGrpOpKind span rhlp OD.RmImm8 SZ.Byte OpGroup.G2 + parseGrpOpKind span rhlp OD.RmSImm8 SZ.Byte OpGroup.G2 render span rhlp op szCond oidx szidx type internal OneOpC1 () = inherit ParsingJob () override __.Run (span, rhlp) = let struct (op, oidx, szidx, szCond) = - parseGrpOpKind span rhlp OD.RmImm8 SZ.Def OpGroup.G2 + parseGrpOpKind span rhlp OD.RmSImm8 SZ.Def OpGroup.G2 render span rhlp op szCond oidx szidx type internal OneOpC2 () = @@ -1594,7 +1595,7 @@ type internal OneOpC6 () = inherit ParsingJob () override __.Run (span, rhlp) = let struct (op, oidx, szidx, szCond) = - parseGrpOpKind span rhlp OD.RmImm8 SZ.Byte OpGroup.G11A + parseGrpOpKind span rhlp OD.RmSImm8 SZ.Byte OpGroup.G11A render span rhlp op szCond oidx szidx type internal OneOpC7 () = @@ -1895,6 +1896,7 @@ type internal OneOpE4 () = type internal OneOpE5 () = inherit ParsingJob () override __.Run (span, rhlp) = + rhlp.REXPrefix <- REXPrefix.NOREX rhlp.SzComputers[int SZ.Def].Render rhlp SzCond.Nor let oprs = rhlp.OprParsers[int OD.RegImm8].Render (span, rhlp) newInsInfo rhlp Opcode.IN oprs @@ -1909,6 +1911,7 @@ type internal OneOpE6 () = type internal OneOpE7 () = inherit ParsingJob () override __.Run (span, rhlp) = + rhlp.REXPrefix <- REXPrefix.NOREX rhlp.SzComputers[int SZ.Def].Render rhlp SzCond.Nor let oprs = rhlp.OprParsers[int OD.Imm8Reg].Render (span, rhlp) newInsInfo rhlp Opcode.OUT oprs @@ -1982,7 +1985,10 @@ type internal OneOpF0 () = type internal OneOpF1 () = inherit ParsingJob () - override __.Run (_, _) = raise ParsingFailureException + override __.Run (span, rhlp) = + rhlp.SzComputers[int SZ.Def].Render rhlp SzCond.Nor + let oprs = rhlp.OprParsers[int OD.No].Render (span, rhlp) + newInsInfo rhlp Opcode.INT1 oprs type internal OneOpF2 () = inherit ParsingJob () diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs b/src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs index c78b46fa..c853b78b 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelRegExprs.fs @@ -27,122 +27,151 @@ namespace B2R2.FrontEnd.BinLifter.Intel open B2R2 open B2R2.BinIR.LowUIR open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter open B2R2.FrontEnd.BinLifter.LiftingUtils +open type Register +open type WordSize /// This is a fatal error that happens when B2R2 tries to access non-existing /// register symbol. This exception should not happen in general. exception internal InvalidRegAccessException -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (IntelRegisterSet.singleton t) +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name let reg64 wordSize t name = - if wordSize = WordSize.Bit32 then AST.undef 64 name + if wordSize = Bit32 then AST.undef 64 name else var 64 t name let reg32 wordSize t name r64 = - if wordSize = WordSize.Bit32 then var 32 t name + if wordSize = Bit32 then var 32 t name else AST.xtlo 32 r64 let reg32ext wordSize name r64 = - if wordSize = WordSize.Bit32 then AST.undef 32 name + if wordSize = Bit32 then AST.undef 32 name else AST.xtlo 32 r64 let reg16 wordSize r32 r64 = - AST.xtlo 16 (if wordSize = WordSize.Bit32 then r32 else r64) + AST.xtlo 16 (if wordSize = Bit32 then r32 else r64) let reg16ext wordSize name r64 = - if wordSize = WordSize.Bit32 then AST.undef 16 name + if wordSize = Bit32 then AST.undef 16 name else AST.xtlo 16 r64 let regL8 wordSize r32 r64 = - AST.xtlo 8 (if wordSize = WordSize.Bit32 then r32 else r64) + AST.xtlo 8 (if wordSize = Bit32 then r32 else r64) let regH8 wordSize r32 r64 = - AST.extract (if wordSize = WordSize.Bit32 then r32 else r64) 8 8 + AST.extract (if wordSize = Bit32 then r32 else r64) 8 8 let regL8ext wordSize name r64 = - if wordSize = WordSize.Bit32 then AST.undef 16 name + if wordSize = Bit32 then AST.undef 16 name else AST.xtlo 8 r64 #if DEBUG let assert64Bit wordSize = - if wordSize = WordSize.Bit64 then () else raise InvalidRegAccessException + if wordSize = Bit64 then () else raise InvalidRegAccessException let assert32Bit wordSize = - if wordSize = WordSize.Bit32 then () else raise InvalidRegAccessException + if wordSize = Bit32 then () else raise InvalidRegAccessException #endif (* Registers *) - let rax = reg64 wordSize (Register.toRegID Register.RAX) "RAX" - let rbx = reg64 wordSize (Register.toRegID Register.RBX) "RBX" - let rcx = reg64 wordSize (Register.toRegID Register.RCX) "RCX" - let rdx = reg64 wordSize (Register.toRegID Register.RDX) "RDX" - let rsi = reg64 wordSize (Register.toRegID Register.RSI) "RSI" - let rdi = reg64 wordSize (Register.toRegID Register.RDI) "RDI" - let rsp = reg64 wordSize (Register.toRegID Register.RSP) "RSP" - let rbp = reg64 wordSize (Register.toRegID Register.RBP) "RBP" - let r8 = reg64 wordSize (Register.toRegID Register.R8) "R8" - let r9 = reg64 wordSize (Register.toRegID Register.R9) "R9" - let r10 = reg64 wordSize (Register.toRegID Register.R10) "R10" - let r11 = reg64 wordSize (Register.toRegID Register.R11) "R11" - let r12 = reg64 wordSize (Register.toRegID Register.R12) "R12" - let r13 = reg64 wordSize (Register.toRegID Register.R13) "R13" - let r14 = reg64 wordSize (Register.toRegID Register.R14) "R14" - let r15 = reg64 wordSize (Register.toRegID Register.R15) "R15" - let eax = reg32 wordSize (Register.toRegID Register.EAX) "EAX" rax - let ebx = reg32 wordSize (Register.toRegID Register.EBX) "EBX" rbx - let ecx = reg32 wordSize (Register.toRegID Register.ECX) "ECX" rcx - let edx = reg32 wordSize (Register.toRegID Register.EDX) "EDX" rdx - let esi = reg32 wordSize (Register.toRegID Register.ESI) "ESI" rsi - let edi = reg32 wordSize (Register.toRegID Register.EDI) "EDI" rdi - let esp = reg32 wordSize (Register.toRegID Register.ESP) "ESP" rsp - let ebp = reg32 wordSize (Register.toRegID Register.EBP) "EBP" rbp + let rax = reg64 wordSize (Register.toRegID RAX) "RAX" + let rbx = reg64 wordSize (Register.toRegID RBX) "RBX" + let rcx = reg64 wordSize (Register.toRegID RCX) "RCX" + let rdx = reg64 wordSize (Register.toRegID RDX) "RDX" + let rsi = reg64 wordSize (Register.toRegID RSI) "RSI" + let rdi = reg64 wordSize (Register.toRegID RDI) "RDI" + let rsp = reg64 wordSize (Register.toRegID RSP) "RSP" + let rbp = reg64 wordSize (Register.toRegID RBP) "RBP" + let r8 = reg64 wordSize (Register.toRegID R8) "R8" + let r9 = reg64 wordSize (Register.toRegID R9) "R9" + let r10 = reg64 wordSize (Register.toRegID R10) "R10" + let r11 = reg64 wordSize (Register.toRegID R11) "R11" + let r12 = reg64 wordSize (Register.toRegID R12) "R12" + let r13 = reg64 wordSize (Register.toRegID R13) "R13" + let r14 = reg64 wordSize (Register.toRegID R14) "R14" + let r15 = reg64 wordSize (Register.toRegID R15) "R15" + let eax = reg32 wordSize (Register.toRegID EAX) "EAX" rax + let ebx = reg32 wordSize (Register.toRegID EBX) "EBX" rbx + let ecx = reg32 wordSize (Register.toRegID ECX) "ECX" rcx + let edx = reg32 wordSize (Register.toRegID EDX) "EDX" rdx + let esi = reg32 wordSize (Register.toRegID ESI) "ESI" rsi + let edi = reg32 wordSize (Register.toRegID EDI) "EDI" rdi + let esp = reg32 wordSize (Register.toRegID ESP) "ESP" rsp + let ebp = reg32 wordSize (Register.toRegID EBP) "EBP" rbp let ax = reg16 wordSize eax rax let bx = reg16 wordSize ebx rbx let cx = reg16 wordSize ecx rcx let dx = reg16 wordSize edx rdx - let fcw = var 16 (Register.toRegID Register.FCW) "FCW" - let fsw = var 16 (Register.toRegID Register.FSW) "FSW" - let ftw = var 16 (Register.toRegID Register.FTW) "FTW" - let fop = var 16 (Register.toRegID Register.FOP) "FOP" - let fip = var 64 (Register.toRegID Register.FIP) "FIP" - let fcs = var 16 (Register.toRegID Register.FCS) "FCS" - let fdp = var 64 (Register.toRegID Register.FDP) "FDP" - let fds = var 16 (Register.toRegID Register.FDS) "FDS" - let st0a = var 64 (Register.toRegID Register.ST0A) "ST0A" - let st0b = var 16 (Register.toRegID Register.ST0B) "ST0B" - let st1a = var 64 (Register.toRegID Register.ST1A) "ST1A" - let st1b = var 16 (Register.toRegID Register.ST1B) "ST1B" - let st2a = var 64 (Register.toRegID Register.ST2A) "ST2A" - let st2b = var 16 (Register.toRegID Register.ST2B) "ST2B" - let st3a = var 64 (Register.toRegID Register.ST3A) "ST3A" - let st3b = var 16 (Register.toRegID Register.ST3B) "ST3B" - let st4a = var 64 (Register.toRegID Register.ST4A) "ST4A" - let st4b = var 16 (Register.toRegID Register.ST4B) "ST4B" - let st5a = var 64 (Register.toRegID Register.ST5A) "ST5A" - let st5b = var 16 (Register.toRegID Register.ST5B) "ST5B" - let st6a = var 64 (Register.toRegID Register.ST6A) "ST6A" - let st6b = var 16 (Register.toRegID Register.ST6B) "ST6B" - let st7a = var 64 (Register.toRegID Register.ST7A) "ST7A" - let st7b = var 16 (Register.toRegID Register.ST7B) "ST7B" - let mxcsr = var 32 (Register.toRegID Register.MXCSR) "MXCSR" - let mxcsrmask = var 32 (Register.toRegID Register.MXCSRMASK) "MXCSR_MASK" - let pkru = var 32 (Register.toRegID Register.PKRU) "PKRU" - let k0 = var 64 (Register.toRegID Register.K0) "K0" - let k1 = var 64 (Register.toRegID Register.K1) "K1" - let k2 = var 64 (Register.toRegID Register.K2) "K2" - let k3 = var 64 (Register.toRegID Register.K3) "K3" - let k4 = var 64 (Register.toRegID Register.K4) "K4" - let k5 = var 64 (Register.toRegID Register.K5) "K5" - let k6 = var 64 (Register.toRegID Register.K6) "K6" - let k7 = var 64 (Register.toRegID Register.K7) "K7" - let dr0 = var 32 (Register.toRegID Register.DR0) "DR0" - let dr1 = var 32 (Register.toRegID Register.DR1) "DR1" - let dr2 = var 32 (Register.toRegID Register.DR2) "DR2" - let dr3 = var 32 (Register.toRegID Register.DR3) "DR3" - let dr6 = var 32 (Register.toRegID Register.DR6) "DR6" - let dr7 = var 32 (Register.toRegID Register.DR7) "DR7" + let fcw = var 16 (Register.toRegID FCW) "FCW" + let fsw = var 16 (Register.toRegID FSW) "FSW" + let ftw = var 16 (Register.toRegID FTW) "FTW" + let fop = var 16 (Register.toRegID FOP) "FOP" + let fip = var 64 (Register.toRegID FIP) "FIP" + let fcs = var 16 (Register.toRegID FCS) "FCS" + let fdp = var 64 (Register.toRegID FDP) "FDP" + let fds = var 16 (Register.toRegID FDS) "FDS" + let st0a = var 64 (Register.toRegID ST0A) "ST0A" + let st0b = var 16 (Register.toRegID ST0B) "ST0B" + let st1a = var 64 (Register.toRegID ST1A) "ST1A" + let st1b = var 16 (Register.toRegID ST1B) "ST1B" + let st2a = var 64 (Register.toRegID ST2A) "ST2A" + let st2b = var 16 (Register.toRegID ST2B) "ST2B" + let st3a = var 64 (Register.toRegID ST3A) "ST3A" + let st3b = var 16 (Register.toRegID ST3B) "ST3B" + let st4a = var 64 (Register.toRegID ST4A) "ST4A" + let st4b = var 16 (Register.toRegID ST4B) "ST4B" + let st5a = var 64 (Register.toRegID ST5A) "ST5A" + let st5b = var 16 (Register.toRegID ST5B) "ST5B" + let st6a = var 64 (Register.toRegID ST6A) "ST6A" + let st6b = var 16 (Register.toRegID ST6B) "ST6B" + let st7a = var 64 (Register.toRegID ST7A) "ST7A" + let st7b = var 16 (Register.toRegID ST7B) "ST7B" + let mxcsr = var 32 (Register.toRegID MXCSR) "MXCSR" + let mxcsrmask = var 32 (Register.toRegID MXCSRMASK) "MXCSR_MASK" + let pkru = var 32 (Register.toRegID PKRU) "PKRU" + let k0 = var 64 (Register.toRegID K0) "K0" + let k1 = var 64 (Register.toRegID K1) "K1" + let k2 = var 64 (Register.toRegID K2) "K2" + let k3 = var 64 (Register.toRegID K3) "K3" + let k4 = var 64 (Register.toRegID K4) "K4" + let k5 = var 64 (Register.toRegID K5) "K5" + let k6 = var 64 (Register.toRegID K6) "K6" + let k7 = var 64 (Register.toRegID K7) "K7" + let dr0 = var 32 (Register.toRegID DR0) "DR0" + let dr1 = var 32 (Register.toRegID DR1) "DR1" + let dr2 = var 32 (Register.toRegID DR2) "DR2" + let dr3 = var 32 (Register.toRegID DR3) "DR3" + let dr6 = var 32 (Register.toRegID DR6) "DR6" + let dr7 = var 32 (Register.toRegID DR7) "DR7" + +#if EMULATION + let ccOp = + var 8 (Register.toRegID CCOP) "CCOP" + let ccDst = + var (WordSize.toRegType wordSize) (Register.toRegID CCDST) "CCDST" + let ccDstD = + if wordSize = Bit32 then ccDst + else AST.xtlo 32 ccDst + let ccDstW = AST.xtlo 16 ccDst + let ccDstB = AST.xtlo 8 ccDst + let ccSrc1 = + var (WordSize.toRegType wordSize) (Register.toRegID CCSRC1) "CCSRC1" + let ccSrc1D = + if wordSize = Bit32 then ccSrc1 + else AST.xtlo 32 ccSrc1 + let ccSrc1W = AST.xtlo 16 ccSrc1 + let ccSrc1B = AST.xtlo 8 ccSrc1 + let ccSrc2 = + var (WordSize.toRegType wordSize) (Register.toRegID CCSRC2) "CCSRC2" + let ccSrc2D = + if wordSize = Bit32 then ccSrc2 + else AST.xtlo 32 ccSrc2 + let ccSrc2W = AST.xtlo 16 ccSrc2 + let ccSrc2B = AST.xtlo 8 ccSrc2 +#endif (* QWORD regs *) member val RAX = rax with get @@ -204,14 +233,14 @@ type internal RegExprs (wordSize) = member val CH = regH8 wordSize ecx rcx with get member val DL = regL8 wordSize edx rdx with get member val DH = regH8 wordSize edx rdx with get - member val R8L = regL8ext wordSize "R8L" r8 with get - member val R9L = regL8ext wordSize "R9L" r9 with get - member val R10L = regL8ext wordSize "R10L" r10 with get - member val R11L = regL8ext wordSize "R11L" r11 with get - member val R12L = regL8ext wordSize "R12L" r12 with get - member val R13L = regL8ext wordSize "R13L" r13 with get - member val R14L = regL8ext wordSize "R14L" r14 with get - member val R15L = regL8ext wordSize "R15L" r15 with get + member val R8B = regL8ext wordSize "R8B" r8 with get + member val R9B = regL8ext wordSize "R9B" r9 with get + member val R10B = regL8ext wordSize "R10B" r10 with get + member val R11B = regL8ext wordSize "R11B" r11 with get + member val R12B = regL8ext wordSize "R12B" r12 with get + member val R13B = regL8ext wordSize "R13B" r13 with get + member val R14B = regL8ext wordSize "R14B" r14 with get + member val R15B = regL8ext wordSize "R15B" r15 with get member val SPL = regL8ext wordSize "SPL" rsp with get member val BPL = regL8ext wordSize "BPL" rbp with get member val SIL = regL8ext wordSize "SIL" rsi with get @@ -220,46 +249,46 @@ type internal RegExprs (wordSize) = member val EIP = AST.pcvar 32 "EIP" member val RIP = AST.pcvar 64 "RIP" (* Segment selector *) - member val CS = var 16 (Register.toRegID Register.CS) "CS" - member val DS = var 16 (Register.toRegID Register.DS) "DS" - member val ES = var 16 (Register.toRegID Register.ES) "ES" - member val FS = var 16 (Register.toRegID Register.FS) "FS" - member val GS = var 16 (Register.toRegID Register.GS) "GS" - member val SS = var 16 (Register.toRegID Register.SS) "SS" + member val CS = var 16 (Register.toRegID CS) "CS" + member val DS = var 16 (Register.toRegID DS) "DS" + member val ES = var 16 (Register.toRegID ES) "ES" + member val FS = var 16 (Register.toRegID FS) "FS" + member val GS = var 16 (Register.toRegID GS) "GS" + member val SS = var 16 (Register.toRegID SS) "SS" (* Segment base regs *) member val CSBase = - var (WordSize.toRegType wordSize) (Register.toRegID Register.CSBase) "CSBase" + var (WordSize.toRegType wordSize) (Register.toRegID CSBase) "CSBase" member val DSBase = - var (WordSize.toRegType wordSize) (Register.toRegID Register.DSBase) "DSBase" + var (WordSize.toRegType wordSize) (Register.toRegID DSBase) "DSBase" member val ESBase = - var (WordSize.toRegType wordSize) (Register.toRegID Register.ESBase) "ESBase" + var (WordSize.toRegType wordSize) (Register.toRegID ESBase) "ESBase" member val FSBase = - var (WordSize.toRegType wordSize) (Register.toRegID Register.FSBase) "FSBase" + var (WordSize.toRegType wordSize) (Register.toRegID FSBase) "FSBase" member val GSBase = - var (WordSize.toRegType wordSize) (Register.toRegID Register.GSBase) "GSBase" + var (WordSize.toRegType wordSize) (Register.toRegID GSBase) "GSBase" member val SSBase = - var (WordSize.toRegType wordSize) (Register.toRegID Register.SSBase) "SSBase" + var (WordSize.toRegType wordSize) (Register.toRegID SSBase) "SSBase" (* Control regs *) member val CR0 = - var (WordSize.toRegType wordSize) (Register.toRegID Register.CR0) "CR0" + var (WordSize.toRegType wordSize) (Register.toRegID CR0) "CR0" member val CR2 = - var (WordSize.toRegType wordSize) (Register.toRegID Register.CR2) "CR2" + var (WordSize.toRegType wordSize) (Register.toRegID CR2) "CR2" member val CR3 = - var (WordSize.toRegType wordSize) (Register.toRegID Register.CR3) "CR3" + var (WordSize.toRegType wordSize) (Register.toRegID CR3) "CR3" member val CR4 = - var (WordSize.toRegType wordSize) (Register.toRegID Register.CR4) "CR4" + var (WordSize.toRegType wordSize) (Register.toRegID CR4) "CR4" member val CR8 = - var (WordSize.toRegType wordSize) (Register.toRegID Register.CR8) "CR8" + var (WordSize.toRegType wordSize) (Register.toRegID CR8) "CR8" (* EFLAGS *) - member val OF = var 1 (Register.toRegID Register.OF) "OF" with get - member val DF = var 1 (Register.toRegID Register.DF) "DF" with get - member val IF = var 1 (Register.toRegID Register.IF) "IF" with get - member val TF = var 1 (Register.toRegID Register.TF) "TF" with get - member val SF = var 1 (Register.toRegID Register.SF) "SF" with get - member val ZF = var 1 (Register.toRegID Register.ZF) "ZF" with get - member val AF = var 1 (Register.toRegID Register.AF) "AF" with get - member val PF = var 1 (Register.toRegID Register.PF) "PF" with get - member val CF = var 1 (Register.toRegID Register.CF) "CF" with get + member val OF = var 1 (Register.toRegID OF) "OF" with get + member val DF = var 1 (Register.toRegID DF) "DF" with get + member val IF = var 1 (Register.toRegID IF) "IF" with get + member val TF = var 1 (Register.toRegID TF) "TF" with get + member val SF = var 1 (Register.toRegID SF) "SF" with get + member val ZF = var 1 (Register.toRegID ZF) "ZF" with get + member val AF = var 1 (Register.toRegID AF) "AF" with get + member val PF = var 1 (Register.toRegID PF) "PF" with get + member val CF = var 1 (Register.toRegID CF) "CF" with get (* MMX Registers *) member val MM0 = st0a member val MM1 = st1a @@ -271,279 +300,271 @@ type internal RegExprs (wordSize) = member val MM7 = st7a (* SSE Registers *) member val ZMM0A = - var 64 (Register.toRegID Register.ZMM0A) "ZMM0A" with get + var 64 (Register.toRegID ZMM0A) "ZMM0A" with get member val ZMM0B = - var 64 (Register.toRegID Register.ZMM0B) "ZMM0B" with get + var 64 (Register.toRegID ZMM0B) "ZMM0B" with get member val ZMM0C = - var 64 (Register.toRegID Register.ZMM0C) "ZMM0C" with get + var 64 (Register.toRegID ZMM0C) "ZMM0C" with get member val ZMM0D = - var 64 (Register.toRegID Register.ZMM0D) "ZMM0D" with get + var 64 (Register.toRegID ZMM0D) "ZMM0D" with get member val ZMM0E = - var 64 (Register.toRegID Register.ZMM0E) "ZMM0E" with get + var 64 (Register.toRegID ZMM0E) "ZMM0E" with get member val ZMM0F = - var 64 (Register.toRegID Register.ZMM0F) "ZMM0F" with get + var 64 (Register.toRegID ZMM0F) "ZMM0F" with get member val ZMM0G = - var 64 (Register.toRegID Register.ZMM0G) "ZMM0G" with get + var 64 (Register.toRegID ZMM0G) "ZMM0G" with get member val ZMM0H = - var 64 (Register.toRegID Register.ZMM0H) "ZMM0H" with get + var 64 (Register.toRegID ZMM0H) "ZMM0H" with get member val ZMM1A = - var 64 (Register.toRegID Register.ZMM1A) "ZMM1A" with get + var 64 (Register.toRegID ZMM1A) "ZMM1A" with get member val ZMM1B = - var 64 (Register.toRegID Register.ZMM1B) "ZMM1B" with get + var 64 (Register.toRegID ZMM1B) "ZMM1B" with get member val ZMM1C = - var 64 (Register.toRegID Register.ZMM1C) "ZMM1C" with get + var 64 (Register.toRegID ZMM1C) "ZMM1C" with get member val ZMM1D = - var 64 (Register.toRegID Register.ZMM1D) "ZMM1D" with get + var 64 (Register.toRegID ZMM1D) "ZMM1D" with get member val ZMM1E = - var 64 (Register.toRegID Register.ZMM1E) "ZMM1E" with get + var 64 (Register.toRegID ZMM1E) "ZMM1E" with get member val ZMM1F = - var 64 (Register.toRegID Register.ZMM1F) "ZMM1F" with get + var 64 (Register.toRegID ZMM1F) "ZMM1F" with get member val ZMM1G = - var 64 (Register.toRegID Register.ZMM1G) "ZMM1G" with get + var 64 (Register.toRegID ZMM1G) "ZMM1G" with get member val ZMM1H = - var 64 (Register.toRegID Register.ZMM1H) "ZMM1H" with get + var 64 (Register.toRegID ZMM1H) "ZMM1H" with get member val ZMM2A = - var 64 (Register.toRegID Register.ZMM2A) "ZMM2A" with get + var 64 (Register.toRegID ZMM2A) "ZMM2A" with get member val ZMM2B = - var 64 (Register.toRegID Register.ZMM2B) "ZMM2B" with get + var 64 (Register.toRegID ZMM2B) "ZMM2B" with get member val ZMM2C = - var 64 (Register.toRegID Register.ZMM2C) "ZMM2C" with get + var 64 (Register.toRegID ZMM2C) "ZMM2C" with get member val ZMM2D = - var 64 (Register.toRegID Register.ZMM2D) "ZMM2D" with get + var 64 (Register.toRegID ZMM2D) "ZMM2D" with get member val ZMM2E = - var 64 (Register.toRegID Register.ZMM2E) "ZMM2E" with get + var 64 (Register.toRegID ZMM2E) "ZMM2E" with get member val ZMM2F = - var 64 (Register.toRegID Register.ZMM2F) "ZMM2F" with get + var 64 (Register.toRegID ZMM2F) "ZMM2F" with get member val ZMM2G = - var 64 (Register.toRegID Register.ZMM2G) "ZMM2G" with get + var 64 (Register.toRegID ZMM2G) "ZMM2G" with get member val ZMM2H = - var 64 (Register.toRegID Register.ZMM2H) "ZMM2H" with get + var 64 (Register.toRegID ZMM2H) "ZMM2H" with get member val ZMM3A = - var 64 (Register.toRegID Register.ZMM3A) "ZMM3A" with get + var 64 (Register.toRegID ZMM3A) "ZMM3A" with get member val ZMM3B = - var 64 (Register.toRegID Register.ZMM3B) "ZMM3B" with get + var 64 (Register.toRegID ZMM3B) "ZMM3B" with get member val ZMM3C = - var 64 (Register.toRegID Register.ZMM3C) "ZMM3C" with get + var 64 (Register.toRegID ZMM3C) "ZMM3C" with get member val ZMM3D = - var 64 (Register.toRegID Register.ZMM3D) "ZMM3D" with get + var 64 (Register.toRegID ZMM3D) "ZMM3D" with get member val ZMM3E = - var 64 (Register.toRegID Register.ZMM3E) "ZMM3E" with get + var 64 (Register.toRegID ZMM3E) "ZMM3E" with get member val ZMM3F = - var 64 (Register.toRegID Register.ZMM3F) "ZMM3F" with get + var 64 (Register.toRegID ZMM3F) "ZMM3F" with get member val ZMM3G = - var 64 (Register.toRegID Register.ZMM3G) "ZMM3G" with get + var 64 (Register.toRegID ZMM3G) "ZMM3G" with get member val ZMM3H = - var 64 (Register.toRegID Register.ZMM3H) "ZMM3H" with get + var 64 (Register.toRegID ZMM3H) "ZMM3H" with get member val ZMM4A = - var 64 (Register.toRegID Register.ZMM4A) "ZMM4A" with get + var 64 (Register.toRegID ZMM4A) "ZMM4A" with get member val ZMM4B = - var 64 (Register.toRegID Register.ZMM4B) "ZMM4B" with get + var 64 (Register.toRegID ZMM4B) "ZMM4B" with get member val ZMM4C = - var 64 (Register.toRegID Register.ZMM4C) "ZMM4C" with get + var 64 (Register.toRegID ZMM4C) "ZMM4C" with get member val ZMM4D = - var 64 (Register.toRegID Register.ZMM4D) "ZMM4D" with get + var 64 (Register.toRegID ZMM4D) "ZMM4D" with get member val ZMM4E = - var 64 (Register.toRegID Register.ZMM4E) "ZMM4E" with get + var 64 (Register.toRegID ZMM4E) "ZMM4E" with get member val ZMM4F = - var 64 (Register.toRegID Register.ZMM4F) "ZMM4F" with get + var 64 (Register.toRegID ZMM4F) "ZMM4F" with get member val ZMM4G = - var 64 (Register.toRegID Register.ZMM4G) "ZMM4G" with get + var 64 (Register.toRegID ZMM4G) "ZMM4G" with get member val ZMM4H = - var 64 (Register.toRegID Register.ZMM4H) "ZMM4H" with get + var 64 (Register.toRegID ZMM4H) "ZMM4H" with get member val ZMM5A = - var 64 (Register.toRegID Register.ZMM5A) "ZMM5A" with get + var 64 (Register.toRegID ZMM5A) "ZMM5A" with get member val ZMM5B = - var 64 (Register.toRegID Register.ZMM5B) "ZMM5B" with get + var 64 (Register.toRegID ZMM5B) "ZMM5B" with get member val ZMM5C = - var 64 (Register.toRegID Register.ZMM5C) "ZMM5C" with get + var 64 (Register.toRegID ZMM5C) "ZMM5C" with get member val ZMM5D = - var 64 (Register.toRegID Register.ZMM5D) "ZMM5D" with get + var 64 (Register.toRegID ZMM5D) "ZMM5D" with get member val ZMM5E = - var 64 (Register.toRegID Register.ZMM5E) "ZMM5E" with get + var 64 (Register.toRegID ZMM5E) "ZMM5E" with get member val ZMM5F = - var 64 (Register.toRegID Register.ZMM5F) "ZMM5F" with get + var 64 (Register.toRegID ZMM5F) "ZMM5F" with get member val ZMM5G = - var 64 (Register.toRegID Register.ZMM5G) "ZMM5G" with get + var 64 (Register.toRegID ZMM5G) "ZMM5G" with get member val ZMM5H = - var 64 (Register.toRegID Register.ZMM5H) "ZMM5H" with get + var 64 (Register.toRegID ZMM5H) "ZMM5H" with get member val ZMM6A = - var 64 (Register.toRegID Register.ZMM6A) "ZMM6A" with get + var 64 (Register.toRegID ZMM6A) "ZMM6A" with get member val ZMM6B = - var 64 (Register.toRegID Register.ZMM6B) "ZMM6B" with get + var 64 (Register.toRegID ZMM6B) "ZMM6B" with get member val ZMM6C = - var 64 (Register.toRegID Register.ZMM6C) "ZMM6C" with get + var 64 (Register.toRegID ZMM6C) "ZMM6C" with get member val ZMM6D = - var 64 (Register.toRegID Register.ZMM6D) "ZMM6D" with get + var 64 (Register.toRegID ZMM6D) "ZMM6D" with get member val ZMM6E = - var 64 (Register.toRegID Register.ZMM6E) "ZMM6E" with get + var 64 (Register.toRegID ZMM6E) "ZMM6E" with get member val ZMM6F = - var 64 (Register.toRegID Register.ZMM6F) "ZMM6F" with get + var 64 (Register.toRegID ZMM6F) "ZMM6F" with get member val ZMM6G = - var 64 (Register.toRegID Register.ZMM6G) "ZMM6G" with get + var 64 (Register.toRegID ZMM6G) "ZMM6G" with get member val ZMM6H = - var 64 (Register.toRegID Register.ZMM6H) "ZMM6H" with get + var 64 (Register.toRegID ZMM6H) "ZMM6H" with get member val ZMM7A = - var 64 (Register.toRegID Register.ZMM7A) "ZMM7A" with get + var 64 (Register.toRegID ZMM7A) "ZMM7A" with get member val ZMM7B = - var 64 (Register.toRegID Register.ZMM7B) "ZMM7B" with get + var 64 (Register.toRegID ZMM7B) "ZMM7B" with get member val ZMM7C = - var 64 (Register.toRegID Register.ZMM7C) "ZMM7C" with get + var 64 (Register.toRegID ZMM7C) "ZMM7C" with get member val ZMM7D = - var 64 (Register.toRegID Register.ZMM7D) "ZMM7D" with get + var 64 (Register.toRegID ZMM7D) "ZMM7D" with get member val ZMM7E = - var 64 (Register.toRegID Register.ZMM7E) "ZMM7E" with get + var 64 (Register.toRegID ZMM7E) "ZMM7E" with get member val ZMM7F = - var 64 (Register.toRegID Register.ZMM7F) "ZMM7F" with get + var 64 (Register.toRegID ZMM7F) "ZMM7F" with get member val ZMM7G = - var 64 (Register.toRegID Register.ZMM7G) "ZMM7G" with get + var 64 (Register.toRegID ZMM7G) "ZMM7G" with get member val ZMM7H = - var 64 (Register.toRegID Register.ZMM7H) "ZMM7H" with get + var 64 (Register.toRegID ZMM7H) "ZMM7H" with get member val ZMM8A = - var 64 (Register.toRegID Register.ZMM8A) "ZMM8A" with get + var 64 (Register.toRegID ZMM8A) "ZMM8A" with get member val ZMM8B = - var 64 (Register.toRegID Register.ZMM8B) "ZMM8B" with get + var 64 (Register.toRegID ZMM8B) "ZMM8B" with get member val ZMM8C = - var 64 (Register.toRegID Register.ZMM8C) "ZMM8C" with get + var 64 (Register.toRegID ZMM8C) "ZMM8C" with get member val ZMM8D = - var 64 (Register.toRegID Register.ZMM8D) "ZMM8D" with get + var 64 (Register.toRegID ZMM8D) "ZMM8D" with get member val ZMM8E = - var 64 (Register.toRegID Register.ZMM8E) "ZMM8E" with get + var 64 (Register.toRegID ZMM8E) "ZMM8E" with get member val ZMM8F = - var 64 (Register.toRegID Register.ZMM8F) "ZMM8F" with get + var 64 (Register.toRegID ZMM8F) "ZMM8F" with get member val ZMM8G = - var 64 (Register.toRegID Register.ZMM8G) "ZMM8G" with get + var 64 (Register.toRegID ZMM8G) "ZMM8G" with get member val ZMM8H = - var 64 (Register.toRegID Register.ZMM8H) "ZMM8H" with get + var 64 (Register.toRegID ZMM8H) "ZMM8H" with get member val ZMM9A = - var 64 (Register.toRegID Register.ZMM9A) "ZMM9A" with get + var 64 (Register.toRegID ZMM9A) "ZMM9A" with get member val ZMM9B = - var 64 (Register.toRegID Register.ZMM9B) "ZMM9B" with get + var 64 (Register.toRegID ZMM9B) "ZMM9B" with get member val ZMM9C = - var 64 (Register.toRegID Register.ZMM9C) "ZMM9C" with get + var 64 (Register.toRegID ZMM9C) "ZMM9C" with get member val ZMM9D = - var 64 (Register.toRegID Register.ZMM9D) "ZMM9D" with get + var 64 (Register.toRegID ZMM9D) "ZMM9D" with get member val ZMM9E = - var 64 (Register.toRegID Register.ZMM9E) "ZMM9E" with get + var 64 (Register.toRegID ZMM9E) "ZMM9E" with get member val ZMM9F = - var 64 (Register.toRegID Register.ZMM9F) "ZMM9F" with get + var 64 (Register.toRegID ZMM9F) "ZMM9F" with get member val ZMM9G = - var 64 (Register.toRegID Register.ZMM9G) "ZMM9G" with get + var 64 (Register.toRegID ZMM9G) "ZMM9G" with get member val ZMM9H = - var 64 (Register.toRegID Register.ZMM9H) "ZMM9H" with get + var 64 (Register.toRegID ZMM9H) "ZMM9H" with get member val ZMM10A = - var 64 (Register.toRegID Register.ZMM10A) "ZMM10A" with get + var 64 (Register.toRegID ZMM10A) "ZMM10A" with get member val ZMM10B = - var 64 (Register.toRegID Register.ZMM10B) "ZMM10B" with get + var 64 (Register.toRegID ZMM10B) "ZMM10B" with get member val ZMM10C = - var 64 (Register.toRegID Register.ZMM10C) "ZMM10C" with get + var 64 (Register.toRegID ZMM10C) "ZMM10C" with get member val ZMM10D = - var 64 (Register.toRegID Register.ZMM10D) "ZMM10D" with get + var 64 (Register.toRegID ZMM10D) "ZMM10D" with get member val ZMM10E = - var 64 (Register.toRegID Register.ZMM10E) "ZMM10E" with get + var 64 (Register.toRegID ZMM10E) "ZMM10E" with get member val ZMM10F = - var 64 (Register.toRegID Register.ZMM10F) "ZMM10F" with get + var 64 (Register.toRegID ZMM10F) "ZMM10F" with get member val ZMM10G = - var 64 (Register.toRegID Register.ZMM10G) "ZMM10G" with get + var 64 (Register.toRegID ZMM10G) "ZMM10G" with get member val ZMM10H = - var 64 (Register.toRegID Register.ZMM10H) "ZMM10H" with get + var 64 (Register.toRegID ZMM10H) "ZMM10H" with get member val ZMM11A = - var 64 (Register.toRegID Register.ZMM11A) "ZMM11A" with get + var 64 (Register.toRegID ZMM11A) "ZMM11A" with get member val ZMM11B = - var 64 (Register.toRegID Register.ZMM11B) "ZMM11B" with get + var 64 (Register.toRegID ZMM11B) "ZMM11B" with get member val ZMM11C = - var 64 (Register.toRegID Register.ZMM11C) "ZMM11C" with get + var 64 (Register.toRegID ZMM11C) "ZMM11C" with get member val ZMM11D = - var 64 (Register.toRegID Register.ZMM11D) "ZMM11D" with get + var 64 (Register.toRegID ZMM11D) "ZMM11D" with get member val ZMM11E = - var 64 (Register.toRegID Register.ZMM11E) "ZMM11E" with get + var 64 (Register.toRegID ZMM11E) "ZMM11E" with get member val ZMM11F = - var 64 (Register.toRegID Register.ZMM11F) "ZMM11F" with get + var 64 (Register.toRegID ZMM11F) "ZMM11F" with get member val ZMM11G = - var 64 (Register.toRegID Register.ZMM11G) "ZMM11G" with get + var 64 (Register.toRegID ZMM11G) "ZMM11G" with get member val ZMM11H = - var 64 (Register.toRegID Register.ZMM11H) "ZMM11H" with get + var 64 (Register.toRegID ZMM11H) "ZMM11H" with get member val ZMM12A = - var 64 (Register.toRegID Register.ZMM12A) "ZMM12A" with get + var 64 (Register.toRegID ZMM12A) "ZMM12A" with get member val ZMM12B = - var 64 (Register.toRegID Register.ZMM12B) "ZMM12B" with get + var 64 (Register.toRegID ZMM12B) "ZMM12B" with get member val ZMM12C = - var 64 (Register.toRegID Register.ZMM12C) "ZMM12C" with get + var 64 (Register.toRegID ZMM12C) "ZMM12C" with get member val ZMM12D = - var 64 (Register.toRegID Register.ZMM12D) "ZMM12D" with get + var 64 (Register.toRegID ZMM12D) "ZMM12D" with get member val ZMM12E = - var 64 (Register.toRegID Register.ZMM12E) "ZMM12E" with get + var 64 (Register.toRegID ZMM12E) "ZMM12E" with get member val ZMM12F = - var 64 (Register.toRegID Register.ZMM12F) "ZMM12F" with get + var 64 (Register.toRegID ZMM12F) "ZMM12F" with get member val ZMM12G = - var 64 (Register.toRegID Register.ZMM12G) "ZMM12G" with get + var 64 (Register.toRegID ZMM12G) "ZMM12G" with get member val ZMM12H = - var 64 (Register.toRegID Register.ZMM12H) "ZMM12H" with get + var 64 (Register.toRegID ZMM12H) "ZMM12H" with get member val ZMM13A = - var 64 (Register.toRegID Register.ZMM13A) "ZMM13A" with get + var 64 (Register.toRegID ZMM13A) "ZMM13A" with get member val ZMM13B = - var 64 (Register.toRegID Register.ZMM13B) "ZMM13B" with get + var 64 (Register.toRegID ZMM13B) "ZMM13B" with get member val ZMM13C = - var 64 (Register.toRegID Register.ZMM13C) "ZMM13C" with get + var 64 (Register.toRegID ZMM13C) "ZMM13C" with get member val ZMM13D = - var 64 (Register.toRegID Register.ZMM13D) "ZMM13D" with get + var 64 (Register.toRegID ZMM13D) "ZMM13D" with get member val ZMM13E = - var 64 (Register.toRegID Register.ZMM13E) "ZMM13E" with get + var 64 (Register.toRegID ZMM13E) "ZMM13E" with get member val ZMM13F = - var 64 (Register.toRegID Register.ZMM13F) "ZMM13F" with get + var 64 (Register.toRegID ZMM13F) "ZMM13F" with get member val ZMM13G = - var 64 (Register.toRegID Register.ZMM13G) "ZMM13G" with get + var 64 (Register.toRegID ZMM13G) "ZMM13G" with get member val ZMM13H = - var 64 (Register.toRegID Register.ZMM13H) "ZMM13H" with get + var 64 (Register.toRegID ZMM13H) "ZMM13H" with get member val ZMM14A = - var 64 (Register.toRegID Register.ZMM14A) "ZMM14A" with get + var 64 (Register.toRegID ZMM14A) "ZMM14A" with get member val ZMM14B = - var 64 (Register.toRegID Register.ZMM14B) "ZMM14B" with get + var 64 (Register.toRegID ZMM14B) "ZMM14B" with get member val ZMM14C = - var 64 (Register.toRegID Register.ZMM14C) "ZMM14C" with get + var 64 (Register.toRegID ZMM14C) "ZMM14C" with get member val ZMM14D = - var 64 (Register.toRegID Register.ZMM14D) "ZMM14D" with get + var 64 (Register.toRegID ZMM14D) "ZMM14D" with get member val ZMM14E = - var 64 (Register.toRegID Register.ZMM14E) "ZMM14E" with get + var 64 (Register.toRegID ZMM14E) "ZMM14E" with get member val ZMM14F = - var 64 (Register.toRegID Register.ZMM14F) "ZMM14F" with get + var 64 (Register.toRegID ZMM14F) "ZMM14F" with get member val ZMM14G = - var 64 (Register.toRegID Register.ZMM14G) "ZMM14G" with get + var 64 (Register.toRegID ZMM14G) "ZMM14G" with get member val ZMM14H = - var 64 (Register.toRegID Register.ZMM14H) "ZMM14H" with get + var 64 (Register.toRegID ZMM14H) "ZMM14H" with get member val ZMM15A = - var 64 (Register.toRegID Register.ZMM15A) "ZMM15A" with get + var 64 (Register.toRegID ZMM15A) "ZMM15A" with get member val ZMM15B = - var 64 (Register.toRegID Register.ZMM15B) "ZMM15B" with get + var 64 (Register.toRegID ZMM15B) "ZMM15B" with get member val ZMM15C = - var 64 (Register.toRegID Register.ZMM15C) "ZMM15C" with get + var 64 (Register.toRegID ZMM15C) "ZMM15C" with get member val ZMM15D = - var 64 (Register.toRegID Register.ZMM15D) "ZMM15D" with get + var 64 (Register.toRegID ZMM15D) "ZMM15D" with get member val ZMM15E = - var 64 (Register.toRegID Register.ZMM15E) "ZMM15E" with get + var 64 (Register.toRegID ZMM15E) "ZMM15E" with get member val ZMM15F = - var 64 (Register.toRegID Register.ZMM15F) "ZMM15F" with get + var 64 (Register.toRegID ZMM15F) "ZMM15F" with get member val ZMM15G = - var 64 (Register.toRegID Register.ZMM15G) "ZMM15G" with get + var 64 (Register.toRegID ZMM15G) "ZMM15G" with get member val ZMM15H = - var 64 (Register.toRegID Register.ZMM15H) "ZMM15H" with get + var 64 (Register.toRegID ZMM15H) "ZMM15H" with get (* MPX Registers *) - member val BND0A = - var 64 (Register.toRegID Register.BND0A) "BND0A" with get - member val BND0B = - var 64 (Register.toRegID Register.BND0B) "BND0B" with get - member val BND1A = - var 64 (Register.toRegID Register.BND1A) "BND1A" with get - member val BND1B = - var 64 (Register.toRegID Register.BND1B) "BND1B" with get - member val BND2A = - var 64 (Register.toRegID Register.BND2A) "BND2A" with get - member val BND2B = - var 64 (Register.toRegID Register.BND2B) "BND2B" with get - member val BND3A = - var 64 (Register.toRegID Register.BND3A) "BND3A" with get - member val BND3B = - var 64 (Register.toRegID Register.BND3B) "BND3B" with get + member val BND0A = var 64 (Register.toRegID BND0A) "BND0A" with get + member val BND0B = var 64 (Register.toRegID BND0B) "BND0B" with get + member val BND1A = var 64 (Register.toRegID BND1A) "BND1A" with get + member val BND1B = var 64 (Register.toRegID BND1B) "BND1B" with get + member val BND2A = var 64 (Register.toRegID BND2A) "BND2A" with get + member val BND2B = var 64 (Register.toRegID BND2B) "BND2B" with get + member val BND3A = var 64 (Register.toRegID BND3A) "BND3A" with get + member val BND3B = var 64 (Register.toRegID BND3B) "BND3B" with get (* x87 FPU registers *) member val FCW = fcw with get member val FSW = fsw with get @@ -615,6 +636,22 @@ type internal RegExprs (wordSize) = member val DR6 = dr6 with get member val DR7 = dr7 with get +#if EMULATION + member val CCOP = ccOp with get + member val CCDST = ccDst with get + member val CCDSTD = ccDstD with get + member val CCDSTW = ccDstW with get + member val CCDSTB = ccDstB with get + member val CCSRC1 = ccSrc1 with get + member val CCSRC1D = ccSrc1D with get + member val CCSRC1W = ccSrc1W with get + member val CCSRC1B = ccSrc1B with get + member val CCSRC2 = ccSrc2 with get + member val CCSRC2D = ccSrc2D with get + member val CCSRC2W = ccSrc2W with get + member val CCSRC2B = ccSrc2B with get +#endif + member __.GetRegVar (name) = match name with | R.RAX -> @@ -801,46 +838,46 @@ type internal RegExprs (wordSize) = assert64Bit wordSize #endif __.R15W - | R.R8L -> + | R.R8B -> #if DEBUG assert64Bit wordSize #endif - __.R8L - | R.R9L -> + __.R8B + | R.R9B -> #if DEBUG assert64Bit wordSize #endif - __.R9L - | R.R10L -> + __.R9B + | R.R10B -> #if DEBUG assert64Bit wordSize #endif - __.R10L - | R.R11L -> + __.R10B + | R.R11B -> #if DEBUG assert64Bit wordSize #endif - __.R11L - | R.R12L -> + __.R11B + | R.R12B -> #if DEBUG assert64Bit wordSize #endif - __.R12L - | R.R13L -> + __.R12B + | R.R13B -> #if DEBUG assert64Bit wordSize #endif - __.R13L - | R.R14L -> + __.R13B + | R.R14B -> #if DEBUG assert64Bit wordSize #endif - __.R14L - | R.R15L -> + __.R14B + | R.R15B -> #if DEBUG assert64Bit wordSize #endif - __.R15L + __.R15B | R.SPL -> #if DEBUG assert64Bit wordSize @@ -862,9 +899,6 @@ type internal RegExprs (wordSize) = #endif __.DIL | R.EIP -> -#if DEBUG - assert32Bit wordSize -#endif __.EIP | R.RIP -> #if DEBUG @@ -955,6 +989,21 @@ type internal RegExprs (wordSize) = | R.DR3 -> __.DR3 | R.DR6 -> __.DR6 | R.DR7 -> __.DR7 +#if EMULATION + | R.CCOP -> __.CCOP + | R.CCDST -> __.CCDST + | R.CCDSTD -> __.CCDSTD + | R.CCDSTW -> __.CCDSTW + | R.CCDSTB -> __.CCDSTB + | R.CCSRC1 -> __.CCSRC1 + | R.CCSRC1D -> __.CCSRC1D + | R.CCSRC1W -> __.CCSRC1W + | R.CCSRC1B -> __.CCSRC1B + | R.CCSRC2 -> __.CCSRC2 + | R.CCSRC2D -> __.CCSRC2D + | R.CCSRC2W -> __.CCSRC2W + | R.CCSRC2B -> __.CCSRC2B +#endif | _ -> failwith "Unhandled register." member __.GetPseudoRegVar name pos = @@ -1350,7 +1399,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM8F + __.ZMM8H | R.ZMM9, 1 -> #if DEBUG assert64Bit wordSize @@ -1390,7 +1439,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM9F + __.ZMM9H | R.ZMM10, 1 -> #if DEBUG assert64Bit wordSize @@ -1430,7 +1479,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM10F + __.ZMM10H | R.ZMM11, 1 -> #if DEBUG assert64Bit wordSize @@ -1470,7 +1519,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM11F + __.ZMM11H | R.ZMM12, 1 -> #if DEBUG assert64Bit wordSize @@ -1510,7 +1559,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM12F + __.ZMM12H | R.ZMM13, 1 -> #if DEBUG assert64Bit wordSize @@ -1550,7 +1599,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM13F + __.ZMM13H | R.ZMM14, 1 -> #if DEBUG assert64Bit wordSize @@ -1590,7 +1639,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM14F + __.ZMM14H | R.ZMM15, 1 -> #if DEBUG assert64Bit wordSize @@ -1630,7 +1679,7 @@ type internal RegExprs (wordSize) = #if DEBUG assert64Bit wordSize #endif - __.ZMM15F + __.ZMM15H | R.BND0, 1 -> __.BND0A | R.BND0, 2 -> __.BND0B | R.BND1, 1 -> __.BND1A @@ -1655,6 +1704,6 @@ type internal RegExprs (wordSize) = | R.ST6, 2 -> __.ST6B | R.ST7, 1 -> __.ST7A | R.ST7, 2 -> __.ST7B - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegister.fs b/src/FrontEnd/BinLifter/Intel/IntelRegister.fs index 13603064..1539e0f6 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelRegister.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelRegister.fs @@ -151,21 +151,21 @@ type Register = /// General-Purpose Registers (Higher 8bits BX). | BH = 0x37 /// General-Purpose Registers for 64bit Mode (Byte Register). - | R8L = 0x38 + | R8B = 0x38 /// General-Purpose Registers for 64bit Mode (Byte Register). - | R9L = 0x39 + | R9B = 0x39 /// General-Purpose Registers for 64bit Mode (Byte Register). - | R10L = 0x3A + | R10B = 0x3A /// General-Purpose Registers for 64bit Mode (Byte Register). - | R11L = 0x3B + | R11B = 0x3B /// General-Purpose Registers for 64bit Mode (Byte Register). - | R12L = 0x3C + | R12B = 0x3C /// General-Purpose Registers for 64bit Mode (Byte Register). - | R13L = 0x3D + | R13B = 0x3D /// General-Purpose Registers for 64bit Mode (Byte Register). - | R14L = 0x3E + | R14B = 0x3E /// General-Purpose Registers for 64bit Mode (Byte Register). - | R15L = 0x3F + | R15B = 0x3F /// General-Purpose Registers for 64bit Mode (Byte Register). | SPL = 0x40 /// General-Purpose Registers for 64bit Mode (Byte Register). @@ -748,6 +748,25 @@ type Register = | K7 = 0x161 /// Unknown Register. | UnknownReg = 0x162 +#if EMULATION + /// Opcode of the last instruction that modified EFlags + | CCOP = 0x163 + /// Result value of the last instruction that modified EFlags + | CCDST = 0x164 + | CCDSTD = 0x165 + | CCDSTW = 0x166 + | CCDSTB = 0x167 + /// First source operand of the last instruction that modified EFlags + | CCSRC1 = 0x168 + | CCSRC1D = 0x169 + | CCSRC1W = 0x16a + | CCSRC1B = 0x16b + /// Second source operand of the last instruction that modified EFlags + | CCSRC2 = 0x16c + | CCSRC2D = 0x16d + | CCSRC2W = 0x16e + | CCSRC2B = 0x16f +#endif /// Shortcut for Register type. type internal R = Register @@ -868,7 +887,7 @@ module Register = begin LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "rax" -> R.RAX | "rbx" -> R.RBX | "rcx" -> R.RCX @@ -925,14 +944,14 @@ module Register = begin | "r13w" -> R.R13W | "r14w" -> R.R14W | "r15w" -> R.R15W - | "r8l" -> R.R8L - | "r9l" -> R.R9L - | "r10l" -> R.R10L - | "r11l" -> R.R11L - | "r12l" -> R.R12L - | "r13l" -> R.R13L - | "r14l" -> R.R14L - | "r15l" -> R.R15L + | "r8b" -> R.R8B + | "r9b" -> R.R9B + | "r10b" -> R.R10B + | "r11b" -> R.R11B + | "r12b" -> R.R12B + | "r13b" -> R.R13B + | "r14b" -> R.R14B + | "r15b" -> R.R15B | "spl" -> R.SPL | "bpl" -> R.BPL | "sil" -> R.SIL @@ -1282,14 +1301,14 @@ module Register = begin | R.R13W -> "R13W" | R.R14W -> "R14W" | R.R15W -> "R15W" - | R.R8L -> "R8L" - | R.R9L -> "R9L" - | R.R10L -> "R10L" - | R.R11L -> "R11L" - | R.R12L -> "R12L" - | R.R13L -> "R13L" - | R.R14L -> "R14L" - | R.R15L -> "R15L" + | R.R8B -> "R8B" + | R.R9B -> "R9B" + | R.R10B -> "R10B" + | R.R11B -> "R11B" + | R.R12B -> "R12B" + | R.R13B -> "R13B" + | R.R14B -> "R14B" + | R.R15B -> "R15B" | R.SPL -> "SPL" | R.BPL -> "BPL" | R.SIL -> "SIL" @@ -1572,6 +1591,12 @@ module Register = begin | R.K6 -> "K6" | R.K7 -> "K7" | R.PKRU -> "PKRU" +#if EMULATION + | R.CCOP -> "CCOP" + | R.CCDST -> "CCDST" + | R.CCSRC1 -> "CCSRC1" + | R.CCSRC2 -> "CCSRC2" +#endif #if DEBUG | _ -> Utils.impossible () #else @@ -1628,8 +1653,8 @@ module Register = begin | R.AX | R.BX | R.CX | R.DX | R.SP | R.BP | R.SI | R.DI | R.FCW | R.FSW | R.FTW | R.FOP | R.FCS | R.FDS | R.K0 | R.K1 | R.K2 | R.K3 | R.K4 | R.K5 | R.K6 | R.K7 -> 16 - | R.R8L | R.R9L | R.R10L | R.R11L - | R.R12L | R.R13L | R.R14L | R.R15L + | R.R8B | R.R9B | R.R10B | R.R11B + | R.R12B | R.R13B | R.R14B | R.R15B | R.SPL | R.BPL | R.SIL | R.DIL | R.AL | R.BL | R.CL | R.DL | R.AH | R.BH | R.CH | R.DH -> 8 | R.XMM0 | R.XMM1 | R.XMM2 | R.XMM3 @@ -1690,14 +1715,14 @@ module Register = begin | R.RBP | R.EBP | R.BP | R.BPL -> R.RBP | R.RSI | R.ESI | R.SI | R.SIL -> R.RSI | R.RDI | R.EDI | R.DI | R.DIL-> R.RDI - | R.R8 | R.R8D | R.R8L | R.R8W -> R.R8 - | R.R9 | R.R9D | R.R9L | R.R9W -> R.R9 - | R.R10 | R.R10D | R.R10L | R.R10W -> R.R10 - | R.R11 | R.R11D | R.R11L | R.R11W -> R.R11 - | R.R12 | R.R12D | R.R12L | R.R12W -> R.R12 - | R.R13 | R.R13D | R.R13L | R.R13W -> R.R13 - | R.R14 | R.R14D | R.R14L | R.R14W -> R.R14 - | R.R15 | R.R15D | R.R15L | R.R15W -> R.R15 + | R.R8 | R.R8D | R.R8B | R.R8W -> R.R8 + | R.R9 | R.R9D | R.R9B | R.R9W -> R.R9 + | R.R10 | R.R10D | R.R10B | R.R10W -> R.R10 + | R.R11 | R.R11D | R.R11B | R.R11W -> R.R11 + | R.R12 | R.R12D | R.R12B | R.R12W -> R.R12 + | R.R13 | R.R13D | R.R13B | R.R13W -> R.R13 + | R.R14 | R.R14D | R.R14B | R.R14W -> R.R14 + | R.R15 | R.R15D | R.R15B | R.R15W -> R.R15 | R.XMM0 | R.YMM0 | R.ZMM0 -> R.YMM0 | R.XMM1 | R.YMM1 | R.ZMM1 -> R.YMM1 | R.XMM2 | R.YMM2 | R.ZMM2 -> R.YMM2 @@ -1734,14 +1759,14 @@ module Register = begin | R.RBP | R.EBP | R.BP | R.BPL -> [| R.RBP; R.EBP; R.BP; R.BPL |] | R.RSI | R.ESI | R.SI | R.SIL -> [| R.RSI; R.ESI; R.SI; R.SIL |] | R.RDI | R.EDI | R.DI | R.DIL -> [| R.RDI; R.EDI; R.DI; R.DIL |] - | R.R8 | R.R8D | R.R8L | R.R8W -> [| R.R8; R.R8D; R.R8L; R.R8W |] - | R.R9 | R.R9D | R.R9L | R.R9W -> [| R.R9; R.R9D; R.R9L; R.R9W |] - | R.R10 | R.R10D | R.R10L | R.R10W -> [| R.R10; R.R10D; R.R10L; R.R10W |] - | R.R11 | R.R11D | R.R11L | R.R11W -> [| R.R11; R.R11D; R.R11L; R.R11W |] - | R.R12 | R.R12D | R.R12L | R.R12W -> [| R.R12; R.R12D; R.R12L; R.R12W |] - | R.R13 | R.R13D | R.R13L | R.R13W -> [| R.R13; R.R13D; R.R13L; R.R13W |] - | R.R14 | R.R14D | R.R14L | R.R14W -> [| R.R14; R.R14D; R.R14L; R.R14W |] - | R.R15 | R.R15D | R.R15L | R.R15W -> [| R.R15; R.R15D; R.R15L; R.R15W |] + | R.R8 | R.R8D | R.R8B | R.R8W -> [| R.R8; R.R8D; R.R8B; R.R8W |] + | R.R9 | R.R9D | R.R9B | R.R9W -> [| R.R9; R.R9D; R.R9B; R.R9W |] + | R.R10 | R.R10D | R.R10B | R.R10W -> [| R.R10; R.R10D; R.R10B; R.R10W |] + | R.R11 | R.R11D | R.R11B | R.R11W -> [| R.R11; R.R11D; R.R11B; R.R11W |] + | R.R12 | R.R12D | R.R12B | R.R12W -> [| R.R12; R.R12D; R.R12B; R.R12W |] + | R.R13 | R.R13D | R.R13B | R.R13W -> [| R.R13; R.R13D; R.R13B; R.R13W |] + | R.R14 | R.R14D | R.R14B | R.R14W -> [| R.R14; R.R14D; R.R14B; R.R14W |] + | R.R15 | R.R15D | R.R15B | R.R15W -> [| R.R15; R.R15D; R.R15B; R.R15W |] | R.XMM0 | R.YMM0 | R.ZMM0 -> [| R.XMM0; R.YMM0; R.ZMM0 |] | R.XMM1 | R.YMM1 | R.ZMM1 -> [| R.XMM1; R.YMM1; R.ZMM1 |] | R.XMM2 | R.YMM2 | R.ZMM2 -> [| R.XMM2; R.YMM2; R.ZMM2 |] diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs b/src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs deleted file mode 100644 index 100a82ea..00000000 --- a/src/FrontEnd/BinLifter/Intel/IntelRegisterBay.fs +++ /dev/null @@ -1,430 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.Intel - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR.LowUIR - -type IntelRegisterBay internal (wordSize, R: RegExprs) = - - inherit RegisterBay () - - override __.GetAllRegExprs () = - if WordSize.is32 wordSize then - [ R.EAX; R.EBX; R.ECX; R.EDX; R.ESP; R.EBP; R.ESI; R.EDI; R.EIP; R.CSBase; - R.DSBase; R.ESBase; R.FSBase; R.GSBase; R.SSBase; R.CR0; R.CR2; R.CR3; - R.CR4; R.OF; R.DF; R.IF; R.TF; R.SF; R.ZF; R.AF; R.PF; R.CF; R.FCW; - R.FSW; R.FTW; R.FOP; R.FIP; R.FCS; R.FDP; R.FDS; R.MXCSR; R.MXCSRMASK; - R.PKRU; R.K0; R.K1; R.K2; R.K3; R.K4; R.K5; R.K6; R.K7; R.ST0A; R.ST0B; - R.ST1A; R.ST1B; R.ST2A; R.ST2B; R.ST3A; R.ST3B; R.ST4A; R.ST4B; R.ST5A; - R.ST5B; R.ST6A; R.ST6B; R.ST7A; R.ST7B; R.ZMM0A; R.ZMM0B; R.ZMM0C; - R.ZMM0D; R.ZMM0E; R.ZMM0F; R.ZMM0G; R.ZMM0H; R.ZMM1A; R.ZMM1B; R.ZMM1C; - R.ZMM1D; R.ZMM1E; R.ZMM1F; R.ZMM1G; R.ZMM1H; R.ZMM2A; R.ZMM2B; R.ZMM2C; - R.ZMM2D; R.ZMM2E; R.ZMM2F; R.ZMM2G; R.ZMM2H; R.ZMM3A; R.ZMM3B; R.ZMM3C; - R.ZMM3D; R.ZMM3E; R.ZMM3F; R.ZMM3G; R.ZMM3H; R.ZMM4A; R.ZMM4B; R.ZMM4C; - R.ZMM4D; R.ZMM4E; R.ZMM4F; R.ZMM4G; R.ZMM4H; R.ZMM5A; R.ZMM5B; R.ZMM5C; - R.ZMM5D; R.ZMM5E; R.ZMM5F; R.ZMM5G; R.ZMM5H; R.ZMM6A; R.ZMM6B; R.ZMM6C; - R.ZMM6D; R.ZMM6E; R.ZMM6F; R.ZMM6G; R.ZMM6H; R.ZMM7A; R.ZMM7B; R.ZMM7C; - R.ZMM7D; R.ZMM7E; R.ZMM7F; R.ZMM7G; R.ZMM7H; R.CS; R.DS; R.ES; R.FS; - R.GS; R.SS; R.DR0; R.DR1; R.DR2; R.DR3; R.DR6; R.DR7 ] - else - [ R.RAX; R.RBX; R.RCX; R.RDX; R.RSP; R.RBP; R.RSI; R.RDI; R.R8; R.R9; - R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.RIP; R.CSBase; R.DSBase; - R.ESBase; R.FSBase; R.GSBase; R.SSBase; R.CR0;R.CR2; R.CR3; R.CR4; - R.CR8; R.OF; R.DF; R.IF; R.TF; R.SF; R.ZF; R.AF; R.PF; R.CF; R.FCW; - R.FSW; R.FTW; R.FOP; R.FIP; R.FCS; R.FDP; R.FDS; R.MXCSR; R.MXCSRMASK; - R.PKRU; R.K0; R.K1; R.K2; R.K3; R.K4; R.K5; R.K6; R.K7; R.ST0A; R.ST0B; - R.ST1A; R.ST1B; R.ST2A; R.ST2B; R.ST3A; R.ST3B; R.ST4A; R.ST4B; R.ST5A; - R.ST5B; R.ST6A; R.ST6B; R.ST7A; R.ST7B; R.ZMM0A; R.ZMM0B; R.ZMM0C; - R.ZMM0D; R.ZMM0E; R.ZMM0F; R.ZMM0G; R.ZMM0H; R.ZMM1A; R.ZMM1B; R.ZMM1C; - R.ZMM1D; R.ZMM1E; R.ZMM1F; R.ZMM1G; R.ZMM1H; R.ZMM2A; R.ZMM2B; R.ZMM2C; - R.ZMM2D; R.ZMM2E; R.ZMM2F; R.ZMM2G; R.ZMM2H; R.ZMM3A; R.ZMM3B; R.ZMM3C; - R.ZMM3D; R.ZMM3E; R.ZMM3F; R.ZMM3G; R.ZMM3H; R.ZMM4A; R.ZMM4B; R.ZMM4C; - R.ZMM4D; R.ZMM4E; R.ZMM4F; R.ZMM4G; R.ZMM4H; R.ZMM5A; R.ZMM5B; R.ZMM5C; - R.ZMM5D; R.ZMM5E; R.ZMM5F; R.ZMM5G; R.ZMM5H; R.ZMM6A; R.ZMM6B; R.ZMM6C; - R.ZMM6D; R.ZMM6E; R.ZMM6F; R.ZMM6G; R.ZMM6H; R.ZMM7A; R.ZMM7B; R.ZMM7C; - R.ZMM7D; R.ZMM7E; R.ZMM7F; R.ZMM7G; R.ZMM7H; R.ZMM8A; R.ZMM8B; R.ZMM8C; - R.ZMM8D; R.ZMM8E; R.ZMM8F; R.ZMM8G; R.ZMM8H; R.ZMM9A; R.ZMM9B; R.ZMM9C; - R.ZMM9D; R.ZMM9E; R.ZMM9F; R.ZMM9G; R.ZMM9H; R.ZMM10A; R.ZMM10B; - R.ZMM10C; R.ZMM10D; R.ZMM10E; R.ZMM10F; R.ZMM10G; R.ZMM10H; R.ZMM11A; - R.ZMM11B; R.ZMM11C; R.ZMM11D; R.ZMM11E; R.ZMM11F; R.ZMM11G; R.ZMM11H; - R.ZMM12A; R.ZMM12B; R.ZMM12C; R.ZMM12D; R.ZMM12E; R.ZMM12F; R.ZMM12G; - R.ZMM12H; R.ZMM13A; R.ZMM13B; R.ZMM13C; R.ZMM13D; R.ZMM13E; R.ZMM13F; - R.ZMM13G; R.ZMM13H; R.ZMM14A; R.ZMM14B; R.ZMM14C; R.ZMM14D; R.ZMM14E; - R.ZMM14F; R.ZMM14G; R.ZMM14H; R.ZMM15A; R.ZMM15B; R.ZMM15C; R.ZMM15D; - R.ZMM15E; R.ZMM15F; R.ZMM15G; R.ZMM15H; R.CS; R.DS; R.ES; R.FS; R.GS; - R.SS; R.DR0; R.DR1; R.DR2; R.DR3; R.DR6; R.DR7 ] - - override __.GetAllRegNames () = - __.GetAllRegExprs () - |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) - - override __.GetGeneralRegExprs () = - if WordSize.is32 wordSize then - [ R.EAX; R.EBX; R.ECX; R.EDX; R.ESP; R.EBP; R.ESI; R.EDI; R.EIP - R.OF; R.DF; R.IF; R.SF; R.ZF; R.AF; R.PF; R.CF ] - else - [ R.RAX; R.RBX; R.RCX; R.RDX; R.RSP; R.RBP; R.RSI; R.RDI; R.R8; R.R9 - R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.RIP - R.OF; R.DF; R.IF; R.SF; R.ZF; R.AF; R.PF; R.CF ] - - override __.RegIDFromRegExpr (e) = - match e.E with - | Var (_,id, _,_) -> id - | PCVar (regT, _) -> - if regT = 32 then Register.toRegID Register.EIP - else Register.toRegID Register.RIP - | _ -> failwith "not a register expression" - - override __.RegIDToRegExpr (id) = - Register.ofRegID id |> R.GetRegVar - - override __.StrToRegExpr (s: string) = - match s.ToUpper () with - | "RAX" -> R.RAX - | "RBX" -> R.RBX - | "RCX" -> R.RCX - | "RDX" -> R.RDX - | "RSP" -> R.RSP - | "RBP" -> R.RBP - | "RSI" -> R.RSI - | "RDI" -> R.RDI - | "EAX" -> R.EAX - | "EBX" -> R.EBX - | "ECX" -> R.ECX - | "EDX" -> R.EDX - | "ESP" -> R.ESP - | "EBP" -> R.EBP - | "ESI" -> R.ESI - | "EDI" -> R.EDI - | "AX" -> R.AX - | "BX" -> R.BX - | "CX" -> R.CX - | "DX" -> R.DX - | "SP" -> R.SP - | "BP" -> R.BP - | "SI" -> R.SI - | "DI" -> R.DI - | "AL" -> R.AL - | "BL" -> R.BL - | "CL" -> R.CL - | "DL" -> R.DL - | "AH" -> R.AH - | "BH" -> R.BH - | "CH" -> R.CH - | "DH" -> R.DH - | "R8" -> R.R8 - | "R9" -> R.R9 - | "R10" -> R.R10 - | "R11" -> R.R11 - | "R12" -> R.R12 - | "R13" -> R.R13 - | "R14" -> R.R14 - | "R15" -> R.R15 - | "R8D" -> R.R8D - | "R9D" -> R.R9D - | "R10D" -> R.R10D - | "R11D" -> R.R11D - | "R12D" -> R.R12D - | "R13D" -> R.R13D - | "R14D" -> R.R14D - | "R15D" -> R.R15D - | "R8W" -> R.R8W - | "R9W" -> R.R9W - | "R10W" -> R.R10W - | "R11W" -> R.R11W - | "R12W" -> R.R12W - | "R13W" -> R.R13W - | "R14W" -> R.R14W - | "R15W" -> R.R15W - | "R8L" -> R.R8L - | "R9L" -> R.R9L - | "R10L" -> R.R10L - | "R11L" -> R.R11L - | "R12L" -> R.R12L - | "R13L" -> R.R13L - | "R14L" -> R.R14L - | "R15L" -> R.R15L - | "SPL" -> R.SPL - | "BPL" -> R.BPL - | "SIL" -> R.SIL - | "DIL" -> R.DIL - | "EIP" -> R.EIP - | "RIP" -> R.RIP - | "MM0" -> R.MM0 - | "MM1" -> R.MM1 - | "MM2" -> R.MM2 - | "MM3" -> R.MM3 - | "MM4" -> R.MM4 - | "MM5" -> R.MM5 - | "MM6" -> R.MM6 - | "MM7" -> R.MM7 - | "CS" -> R.CS - | "DS" -> R.DS - | "SS" -> R.SS - | "ES" -> R.ES - | "FS" -> R.FS - | "GS" -> R.GS - | "CSBASE" -> R.CSBase - | "DSBASE" -> R.DSBase - | "ESBASE" -> R.ESBase - | "FSBASE" -> R.FSBase - | "GSBASE" -> R.GSBase - | "SSBASE" -> R.SSBase - | "CR0" -> R.CR0 - | "CR2" -> R.CR2 - | "CR3" -> R.CR3 - | "CR4" -> R.CR4 - | "CR8" -> R.CR8 - | "OF" -> R.OF - | "DF" -> R.DF - | "IF" -> R.IF - | "TF" -> R.TF - | "SF" -> R.SF - | "ZF" -> R.ZF - | "AF" -> R.AF - | "PF" -> R.PF - | "CF" -> R.CF - | "K0" -> R.K0 - | "K1" -> R.K1 - | "K2" -> R.K2 - | "K3" -> R.K3 - | "K4" -> R.K4 - | "K5" -> R.K5 - | "K6" -> R.K6 - | "K7" -> R.K7 - | "ST0A" -> R.ST0A - | "ST0B" -> R.ST0B - | "ST1A" -> R.ST1A - | "ST1B" -> R.ST1B - | "ST2A" -> R.ST2A - | "ST2B" -> R.ST2B - | "ST3A" -> R.ST3A - | "ST3B" -> R.ST3B - | "ST4A" -> R.ST4A - | "ST4B" -> R.ST4B - | "ST5A" -> R.ST5A - | "ST5B" -> R.ST5B - | "ST6A" -> R.ST6A - | "ST6B" -> R.ST6B - | "ST7A" -> R.ST7A - | "ST7B" -> R.ST7B - | "FCW" -> R.FCW - | "FSW" -> R.FSW - | "FTW" -> R.FTW - | "FOP" -> R.FOP - | "FIP" -> R.FIP - | "FCS" -> R.FCS - | "FDP" -> R.FDP - | "FDS" -> R.FDS - | "FTOP" -> R.FTOP - | "FTW0" -> R.FTW0 - | "FTW1" -> R.FTW1 - | "FTW2" -> R.FTW2 - | "FTW3" -> R.FTW3 - | "FTW4" -> R.FTW4 - | "FTW5" -> R.FTW5 - | "FTW6" -> R.FTW6 - | "FTW7" -> R.FTW7 - | "FSWC0" -> R.FSWC0 - | "FSWC1" -> R.FSWC1 - | "FSWC2" -> R.FSWC2 - | "FSWC3" -> R.FSWC3 - | "MXCSR" -> R.MXCSR - | "MXCSRMASK" -> R.MXCSRMASK - | "ZMM0A" -> R.ZMM0A - | "ZMM0B" -> R.ZMM0B - | "ZMM0C" -> R.ZMM0C - | "ZMM0D" -> R.ZMM0D - | "ZMM0E" -> R.ZMM0E - | "ZMM0F" -> R.ZMM0F - | "ZMM0G" -> R.ZMM0G - | "ZMM0H" -> R.ZMM0H - | "ZMM1A" -> R.ZMM1A - | "ZMM1B" -> R.ZMM1B - | "ZMM1C" -> R.ZMM1C - | "ZMM1D" -> R.ZMM1D - | "ZMM1E" -> R.ZMM1E - | "ZMM1F" -> R.ZMM1F - | "ZMM1G" -> R.ZMM1G - | "ZMM1H" -> R.ZMM1H - | "ZMM2A" -> R.ZMM2A - | "ZMM2B" -> R.ZMM2B - | "ZMM2C" -> R.ZMM2C - | "ZMM2D" -> R.ZMM2D - | "ZMM2E" -> R.ZMM2E - | "ZMM2F" -> R.ZMM2F - | "ZMM2G" -> R.ZMM2G - | "ZMM2H" -> R.ZMM2H - | "ZMM3A" -> R.ZMM3A - | "ZMM3B" -> R.ZMM3B - | "ZMM3C" -> R.ZMM3C - | "ZMM3D" -> R.ZMM3D - | "ZMM3E" -> R.ZMM3E - | "ZMM3F" -> R.ZMM3F - | "ZMM3G" -> R.ZMM3G - | "ZMM3H" -> R.ZMM3H - | "ZMM4A" -> R.ZMM4A - | "ZMM4B" -> R.ZMM4B - | "ZMM4C" -> R.ZMM4C - | "ZMM4D" -> R.ZMM4D - | "ZMM4E" -> R.ZMM4E - | "ZMM4F" -> R.ZMM4F - | "ZMM4G" -> R.ZMM4G - | "ZMM4H" -> R.ZMM4H - | "ZMM5A" -> R.ZMM5A - | "ZMM5B" -> R.ZMM5B - | "ZMM5C" -> R.ZMM5C - | "ZMM5D" -> R.ZMM5D - | "ZMM5E" -> R.ZMM5E - | "ZMM5F" -> R.ZMM5F - | "ZMM5G" -> R.ZMM5G - | "ZMM5H" -> R.ZMM5H - | "ZMM6A" -> R.ZMM6A - | "ZMM6B" -> R.ZMM6B - | "ZMM6C" -> R.ZMM6C - | "ZMM6D" -> R.ZMM6D - | "ZMM6E" -> R.ZMM6E - | "ZMM6F" -> R.ZMM6F - | "ZMM6G" -> R.ZMM6G - | "ZMM6H" -> R.ZMM6H - | "ZMM7A" -> R.ZMM7A - | "ZMM7B" -> R.ZMM7B - | "ZMM7C" -> R.ZMM7C - | "ZMM7D" -> R.ZMM7D - | "ZMM7E" -> R.ZMM7E - | "ZMM7F" -> R.ZMM7F - | "ZMM7G" -> R.ZMM7G - | "ZMM7H" -> R.ZMM7H - | "ZMM8A" -> R.ZMM8A - | "ZMM8B" -> R.ZMM8B - | "ZMM8C" -> R.ZMM8C - | "ZMM8D" -> R.ZMM8D - | "ZMM8E" -> R.ZMM8E - | "ZMM8F" -> R.ZMM8F - | "ZMM8G" -> R.ZMM8G - | "ZMM8H" -> R.ZMM8H - | "ZMM9A" -> R.ZMM9A - | "ZMM9B" -> R.ZMM9B - | "ZMM9C" -> R.ZMM9C - | "ZMM9D" -> R.ZMM9D - | "ZMM9E" -> R.ZMM9E - | "ZMM9F" -> R.ZMM9F - | "ZMM9G" -> R.ZMM9G - | "ZMM9H" -> R.ZMM9H - | "ZMM10A" -> R.ZMM10A - | "ZMM10B" -> R.ZMM10B - | "ZMM10C" -> R.ZMM10C - | "ZMM10D" -> R.ZMM10D - | "ZMM10E" -> R.ZMM10E - | "ZMM10F" -> R.ZMM10F - | "ZMM10G" -> R.ZMM10G - | "ZMM10H" -> R.ZMM10H - | "ZMM11A" -> R.ZMM11A - | "ZMM11B" -> R.ZMM11B - | "ZMM11C" -> R.ZMM11C - | "ZMM11D" -> R.ZMM11D - | "ZMM11E" -> R.ZMM11E - | "ZMM11F" -> R.ZMM11F - | "ZMM11G" -> R.ZMM11G - | "ZMM11H" -> R.ZMM11H - | "ZMM12A" -> R.ZMM12A - | "ZMM12B" -> R.ZMM12B - | "ZMM12C" -> R.ZMM12C - | "ZMM12D" -> R.ZMM12D - | "ZMM12E" -> R.ZMM12E - | "ZMM12F" -> R.ZMM12F - | "ZMM12G" -> R.ZMM12G - | "ZMM12H" -> R.ZMM12H - | "ZMM13A" -> R.ZMM13A - | "ZMM13B" -> R.ZMM13B - | "ZMM13C" -> R.ZMM13C - | "ZMM13D" -> R.ZMM13D - | "ZMM13E" -> R.ZMM13E - | "ZMM13F" -> R.ZMM13F - | "ZMM13G" -> R.ZMM13G - | "ZMM13H" -> R.ZMM13H - | "ZMM14A" -> R.ZMM14A - | "ZMM14B" -> R.ZMM14B - | "ZMM14C" -> R.ZMM14C - | "ZMM14D" -> R.ZMM14D - | "ZMM14E" -> R.ZMM14E - | "ZMM14F" -> R.ZMM14F - | "ZMM14G" -> R.ZMM14G - | "ZMM14H" -> R.ZMM14H - | "ZMM15A" -> R.ZMM15A - | "ZMM15B" -> R.ZMM15B - | "ZMM15C" -> R.ZMM15C - | "ZMM15D" -> R.ZMM15D - | "ZMM15E" -> R.ZMM15E - | "ZMM15F" -> R.ZMM15F - | "ZMM15G" -> R.ZMM15G - | "ZMM15H" -> R.ZMM15H - | "PKRU" -> R.PKRU - | "DR0" -> R.DR0 - | "DR1" -> R.DR1 - | "DR2" -> R.DR2 - | "DR3" -> R.DR3 - | "DR6" -> R.DR6 - | "DR7" -> R.DR7 - | _ -> raise UnhandledRegExprException - - override __.RegIDFromString str = - Register.ofString str |> Register.toRegID - - override __.RegIDToString rid = - Register.ofRegID rid |> Register.toString - - override __.RegIDToRegType rid = - Register.ofRegID rid |> Register.toRegType - - override __.GetRegisterAliases rid = - Register.ofRegID rid - |> Register.getAliases - |> Array.map Register.toRegID - - override __.ProgramCounter = - if WordSize.is32 wordSize then Register.EIP |> Register.toRegID - else Register.RIP |> Register.toRegID - - override __.StackPointer = - if WordSize.is32 wordSize then Register.ESP |> Register.toRegID - else Register.RSP |> Register.toRegID - |> Some - - override __.FramePointer = - if WordSize.is32 wordSize then Register.EBP |> Register.toRegID - else Register.RBP |> Register.toRegID - |> Some - - override __.IsProgramCounter regid = - __.ProgramCounter = regid - - override __.IsStackPointer regid = - (__.StackPointer |> Option.get) = regid - - override __.IsFramePointer regid = - (__.FramePointer |> Option.get) = regid diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegisterFactory.fs b/src/FrontEnd/BinLifter/Intel/IntelRegisterFactory.fs new file mode 100644 index 00000000..38b542df --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelRegisterFactory.fs @@ -0,0 +1,429 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type IntelRegisterFactory (wordSize, r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + if WordSize.is32 wordSize then + [ r.EAX; r.EBX; r.ECX; r.EDX; r.ESP; r.EBP; r.ESI; r.EDI; r.EIP; r.CSBase; + r.DSBase; r.ESBase; r.FSBase; r.GSBase; r.SSBase; r.CR0; r.CR2; r.CR3; + r.CR4; r.OF; r.DF; r.IF; r.TF; r.SF; r.ZF; r.AF; r.PF; r.CF; r.FCW; + r.FSW; r.FTW; r.FOP; r.FIP; r.FCS; r.FDP; r.FDS; r.MXCSR; r.MXCSRMASK; + r.PKRU; r.K0; r.K1; r.K2; r.K3; r.K4; r.K5; r.K6; r.K7; r.ST0A; r.ST0B; + r.ST1A; r.ST1B; r.ST2A; r.ST2B; r.ST3A; r.ST3B; r.ST4A; r.ST4B; r.ST5A; + r.ST5B; r.ST6A; r.ST6B; r.ST7A; r.ST7B; r.ZMM0A; r.ZMM0B; r.ZMM0C; + r.ZMM0D; r.ZMM0E; r.ZMM0F; r.ZMM0G; r.ZMM0H; r.ZMM1A; r.ZMM1B; r.ZMM1C; + r.ZMM1D; r.ZMM1E; r.ZMM1F; r.ZMM1G; r.ZMM1H; r.ZMM2A; r.ZMM2B; r.ZMM2C; + r.ZMM2D; r.ZMM2E; r.ZMM2F; r.ZMM2G; r.ZMM2H; r.ZMM3A; r.ZMM3B; r.ZMM3C; + r.ZMM3D; r.ZMM3E; r.ZMM3F; r.ZMM3G; r.ZMM3H; r.ZMM4A; r.ZMM4B; r.ZMM4C; + r.ZMM4D; r.ZMM4E; r.ZMM4F; r.ZMM4G; r.ZMM4H; r.ZMM5A; r.ZMM5B; r.ZMM5C; + r.ZMM5D; r.ZMM5E; r.ZMM5F; r.ZMM5G; r.ZMM5H; r.ZMM6A; r.ZMM6B; r.ZMM6C; + r.ZMM6D; r.ZMM6E; r.ZMM6F; r.ZMM6G; r.ZMM6H; r.ZMM7A; r.ZMM7B; r.ZMM7C; + r.ZMM7D; r.ZMM7E; r.ZMM7F; r.ZMM7G; r.ZMM7H; r.CS; r.DS; r.ES; r.FS; + r.GS; r.SS; r.DR0; r.DR1; r.DR2; r.DR3; r.DR6; r.DR7 ] + else + [ r.RAX; r.RBX; r.RCX; r.RDX; r.RSP; r.RBP; r.RSI; r.RDI; r.R8; r.R9; + r.R10; r.R11; r.R12; r.R13; r.R14; r.R15; r.RIP; r.CSBase; r.DSBase; + r.ESBase; r.FSBase; r.GSBase; r.SSBase; r.CR0;r.CR2; r.CR3; r.CR4; + r.CR8; r.OF; r.DF; r.IF; r.TF; r.SF; r.ZF; r.AF; r.PF; r.CF; r.FCW; + r.FSW; r.FTW; r.FOP; r.FIP; r.FCS; r.FDP; r.FDS; r.MXCSR; r.MXCSRMASK; + r.PKRU; r.K0; r.K1; r.K2; r.K3; r.K4; r.K5; r.K6; r.K7; r.ST0A; r.ST0B; + r.ST1A; r.ST1B; r.ST2A; r.ST2B; r.ST3A; r.ST3B; r.ST4A; r.ST4B; r.ST5A; + r.ST5B; r.ST6A; r.ST6B; r.ST7A; r.ST7B; r.ZMM0A; r.ZMM0B; r.ZMM0C; + r.ZMM0D; r.ZMM0E; r.ZMM0F; r.ZMM0G; r.ZMM0H; r.ZMM1A; r.ZMM1B; r.ZMM1C; + r.ZMM1D; r.ZMM1E; r.ZMM1F; r.ZMM1G; r.ZMM1H; r.ZMM2A; r.ZMM2B; r.ZMM2C; + r.ZMM2D; r.ZMM2E; r.ZMM2F; r.ZMM2G; r.ZMM2H; r.ZMM3A; r.ZMM3B; r.ZMM3C; + r.ZMM3D; r.ZMM3E; r.ZMM3F; r.ZMM3G; r.ZMM3H; r.ZMM4A; r.ZMM4B; r.ZMM4C; + r.ZMM4D; r.ZMM4E; r.ZMM4F; r.ZMM4G; r.ZMM4H; r.ZMM5A; r.ZMM5B; r.ZMM5C; + r.ZMM5D; r.ZMM5E; r.ZMM5F; r.ZMM5G; r.ZMM5H; r.ZMM6A; r.ZMM6B; r.ZMM6C; + r.ZMM6D; r.ZMM6E; r.ZMM6F; r.ZMM6G; r.ZMM6H; r.ZMM7A; r.ZMM7B; r.ZMM7C; + r.ZMM7D; r.ZMM7E; r.ZMM7F; r.ZMM7G; r.ZMM7H; r.ZMM8A; r.ZMM8B; r.ZMM8C; + r.ZMM8D; r.ZMM8E; r.ZMM8F; r.ZMM8G; r.ZMM8H; r.ZMM9A; r.ZMM9B; r.ZMM9C; + r.ZMM9D; r.ZMM9E; r.ZMM9F; r.ZMM9G; r.ZMM9H; r.ZMM10A; r.ZMM10B; + r.ZMM10C; r.ZMM10D; r.ZMM10E; r.ZMM10F; r.ZMM10G; r.ZMM10H; r.ZMM11A; + r.ZMM11B; r.ZMM11C; r.ZMM11D; r.ZMM11E; r.ZMM11F; r.ZMM11G; r.ZMM11H; + r.ZMM12A; r.ZMM12B; r.ZMM12C; r.ZMM12D; r.ZMM12E; r.ZMM12F; r.ZMM12G; + r.ZMM12H; r.ZMM13A; r.ZMM13B; r.ZMM13C; r.ZMM13D; r.ZMM13E; r.ZMM13F; + r.ZMM13G; r.ZMM13H; r.ZMM14A; r.ZMM14B; r.ZMM14C; r.ZMM14D; r.ZMM14E; + r.ZMM14F; r.ZMM14G; r.ZMM14H; r.ZMM15A; r.ZMM15B; r.ZMM15C; r.ZMM15D; + r.ZMM15E; r.ZMM15F; r.ZMM15G; r.ZMM15H; r.CS; r.DS; r.ES; r.FS; r.GS; + r.SS; r.DR0; r.DR1; r.DR2; r.DR3; r.DR6; r.DR7 ] + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + if WordSize.is32 wordSize then + [ r.EAX; r.EBX; r.ECX; r.EDX; r.ESP; r.EBP; r.ESI; r.EDI; r.EIP + r.OF; r.DF; r.IF; r.SF; r.ZF; r.AF; r.PF; r.CF ] + else + [ r.RAX; r.RBX; r.RCX; r.RDX; r.RSP; r.RBP; r.RSI; r.RDI; r.R8; r.R9 + r.R10; r.R11; r.R12; r.R13; r.R14; r.R15; r.RIP + r.OF; r.DF; r.IF; r.SF; r.ZF; r.AF; r.PF; r.CF ] + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_,id, _) -> id + | PCVar (regT, _) -> + if regT = 32 then Register.toRegID Register.EIP + else Register.toRegID Register.RIP + | _ -> raise InvalidRegisterException + + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> r.GetRegVar + + override __.StrToRegExpr (s: string) = + match s.ToUpper () with + | "RAX" -> r.RAX + | "RBX" -> r.RBX + | "RCX" -> r.RCX + | "RDX" -> r.RDX + | "RSP" -> r.RSP + | "RBP" -> r.RBP + | "RSI" -> r.RSI + | "RDI" -> r.RDI + | "EAX" -> r.EAX + | "EBX" -> r.EBX + | "ECX" -> r.ECX + | "EDX" -> r.EDX + | "ESP" -> r.ESP + | "EBP" -> r.EBP + | "ESI" -> r.ESI + | "EDI" -> r.EDI + | "AX" -> r.AX + | "BX" -> r.BX + | "CX" -> r.CX + | "DX" -> r.DX + | "SP" -> r.SP + | "BP" -> r.BP + | "SI" -> r.SI + | "DI" -> r.DI + | "AL" -> r.AL + | "BL" -> r.BL + | "CL" -> r.CL + | "DL" -> r.DL + | "AH" -> r.AH + | "BH" -> r.BH + | "CH" -> r.CH + | "DH" -> r.DH + | "R8" -> r.R8 + | "R9" -> r.R9 + | "R10" -> r.R10 + | "R11" -> r.R11 + | "R12" -> r.R12 + | "R13" -> r.R13 + | "R14" -> r.R14 + | "R15" -> r.R15 + | "R8D" -> r.R8D + | "R9D" -> r.R9D + | "R10D" -> r.R10D + | "R11D" -> r.R11D + | "R12D" -> r.R12D + | "R13D" -> r.R13D + | "R14D" -> r.R14D + | "R15D" -> r.R15D + | "R8W" -> r.R8W + | "R9W" -> r.R9W + | "R10W" -> r.R10W + | "R11W" -> r.R11W + | "R12W" -> r.R12W + | "R13W" -> r.R13W + | "R14W" -> r.R14W + | "R15W" -> r.R15W + | "R8B" -> r.R8B + | "R9B" -> r.R9B + | "R10B" -> r.R10B + | "R11B" -> r.R11B + | "R12B" -> r.R12B + | "R13B" -> r.R13B + | "R14B" -> r.R14B + | "R15B" -> r.R15B + | "SPL" -> r.SPL + | "BPL" -> r.BPL + | "SIL" -> r.SIL + | "DIL" -> r.DIL + | "EIP" -> r.EIP + | "RIP" -> r.RIP + | "MM0" -> r.MM0 + | "MM1" -> r.MM1 + | "MM2" -> r.MM2 + | "MM3" -> r.MM3 + | "MM4" -> r.MM4 + | "MM5" -> r.MM5 + | "MM6" -> r.MM6 + | "MM7" -> r.MM7 + | "CS" -> r.CS + | "DS" -> r.DS + | "SS" -> r.SS + | "ES" -> r.ES + | "FS" -> r.FS + | "GS" -> r.GS + | "CSBASE" -> r.CSBase + | "DSBASE" -> r.DSBase + | "ESBASE" -> r.ESBase + | "FSBASE" -> r.FSBase + | "GSBASE" -> r.GSBase + | "SSBASE" -> r.SSBase + | "CR0" -> r.CR0 + | "CR2" -> r.CR2 + | "CR3" -> r.CR3 + | "CR4" -> r.CR4 + | "CR8" -> r.CR8 + | "OF" -> r.OF + | "DF" -> r.DF + | "IF" -> r.IF + | "TF" -> r.TF + | "SF" -> r.SF + | "ZF" -> r.ZF + | "AF" -> r.AF + | "PF" -> r.PF + | "CF" -> r.CF + | "K0" -> r.K0 + | "K1" -> r.K1 + | "K2" -> r.K2 + | "K3" -> r.K3 + | "K4" -> r.K4 + | "K5" -> r.K5 + | "K6" -> r.K6 + | "K7" -> r.K7 + | "ST0A" -> r.ST0A + | "ST0B" -> r.ST0B + | "ST1A" -> r.ST1A + | "ST1B" -> r.ST1B + | "ST2A" -> r.ST2A + | "ST2B" -> r.ST2B + | "ST3A" -> r.ST3A + | "ST3B" -> r.ST3B + | "ST4A" -> r.ST4A + | "ST4B" -> r.ST4B + | "ST5A" -> r.ST5A + | "ST5B" -> r.ST5B + | "ST6A" -> r.ST6A + | "ST6B" -> r.ST6B + | "ST7A" -> r.ST7A + | "ST7B" -> r.ST7B + | "FCW" -> r.FCW + | "FSW" -> r.FSW + | "FTW" -> r.FTW + | "FOP" -> r.FOP + | "FIP" -> r.FIP + | "FCS" -> r.FCS + | "FDP" -> r.FDP + | "FDS" -> r.FDS + | "FTOP" -> r.FTOP + | "FTW0" -> r.FTW0 + | "FTW1" -> r.FTW1 + | "FTW2" -> r.FTW2 + | "FTW3" -> r.FTW3 + | "FTW4" -> r.FTW4 + | "FTW5" -> r.FTW5 + | "FTW6" -> r.FTW6 + | "FTW7" -> r.FTW7 + | "FSWC0" -> r.FSWC0 + | "FSWC1" -> r.FSWC1 + | "FSWC2" -> r.FSWC2 + | "FSWC3" -> r.FSWC3 + | "MXCSR" -> r.MXCSR + | "MXCSRMASK" -> r.MXCSRMASK + | "ZMM0A" -> r.ZMM0A + | "ZMM0B" -> r.ZMM0B + | "ZMM0C" -> r.ZMM0C + | "ZMM0D" -> r.ZMM0D + | "ZMM0E" -> r.ZMM0E + | "ZMM0F" -> r.ZMM0F + | "ZMM0G" -> r.ZMM0G + | "ZMM0H" -> r.ZMM0H + | "ZMM1A" -> r.ZMM1A + | "ZMM1B" -> r.ZMM1B + | "ZMM1C" -> r.ZMM1C + | "ZMM1D" -> r.ZMM1D + | "ZMM1E" -> r.ZMM1E + | "ZMM1F" -> r.ZMM1F + | "ZMM1G" -> r.ZMM1G + | "ZMM1H" -> r.ZMM1H + | "ZMM2A" -> r.ZMM2A + | "ZMM2B" -> r.ZMM2B + | "ZMM2C" -> r.ZMM2C + | "ZMM2D" -> r.ZMM2D + | "ZMM2E" -> r.ZMM2E + | "ZMM2F" -> r.ZMM2F + | "ZMM2G" -> r.ZMM2G + | "ZMM2H" -> r.ZMM2H + | "ZMM3A" -> r.ZMM3A + | "ZMM3B" -> r.ZMM3B + | "ZMM3C" -> r.ZMM3C + | "ZMM3D" -> r.ZMM3D + | "ZMM3E" -> r.ZMM3E + | "ZMM3F" -> r.ZMM3F + | "ZMM3G" -> r.ZMM3G + | "ZMM3H" -> r.ZMM3H + | "ZMM4A" -> r.ZMM4A + | "ZMM4B" -> r.ZMM4B + | "ZMM4C" -> r.ZMM4C + | "ZMM4D" -> r.ZMM4D + | "ZMM4E" -> r.ZMM4E + | "ZMM4F" -> r.ZMM4F + | "ZMM4G" -> r.ZMM4G + | "ZMM4H" -> r.ZMM4H + | "ZMM5A" -> r.ZMM5A + | "ZMM5B" -> r.ZMM5B + | "ZMM5C" -> r.ZMM5C + | "ZMM5D" -> r.ZMM5D + | "ZMM5E" -> r.ZMM5E + | "ZMM5F" -> r.ZMM5F + | "ZMM5G" -> r.ZMM5G + | "ZMM5H" -> r.ZMM5H + | "ZMM6A" -> r.ZMM6A + | "ZMM6B" -> r.ZMM6B + | "ZMM6C" -> r.ZMM6C + | "ZMM6D" -> r.ZMM6D + | "ZMM6E" -> r.ZMM6E + | "ZMM6F" -> r.ZMM6F + | "ZMM6G" -> r.ZMM6G + | "ZMM6H" -> r.ZMM6H + | "ZMM7A" -> r.ZMM7A + | "ZMM7B" -> r.ZMM7B + | "ZMM7C" -> r.ZMM7C + | "ZMM7D" -> r.ZMM7D + | "ZMM7E" -> r.ZMM7E + | "ZMM7F" -> r.ZMM7F + | "ZMM7G" -> r.ZMM7G + | "ZMM7H" -> r.ZMM7H + | "ZMM8A" -> r.ZMM8A + | "ZMM8B" -> r.ZMM8B + | "ZMM8C" -> r.ZMM8C + | "ZMM8D" -> r.ZMM8D + | "ZMM8E" -> r.ZMM8E + | "ZMM8F" -> r.ZMM8F + | "ZMM8G" -> r.ZMM8G + | "ZMM8H" -> r.ZMM8H + | "ZMM9A" -> r.ZMM9A + | "ZMM9B" -> r.ZMM9B + | "ZMM9C" -> r.ZMM9C + | "ZMM9D" -> r.ZMM9D + | "ZMM9E" -> r.ZMM9E + | "ZMM9F" -> r.ZMM9F + | "ZMM9G" -> r.ZMM9G + | "ZMM9H" -> r.ZMM9H + | "ZMM10A" -> r.ZMM10A + | "ZMM10B" -> r.ZMM10B + | "ZMM10C" -> r.ZMM10C + | "ZMM10D" -> r.ZMM10D + | "ZMM10E" -> r.ZMM10E + | "ZMM10F" -> r.ZMM10F + | "ZMM10G" -> r.ZMM10G + | "ZMM10H" -> r.ZMM10H + | "ZMM11A" -> r.ZMM11A + | "ZMM11B" -> r.ZMM11B + | "ZMM11C" -> r.ZMM11C + | "ZMM11D" -> r.ZMM11D + | "ZMM11E" -> r.ZMM11E + | "ZMM11F" -> r.ZMM11F + | "ZMM11G" -> r.ZMM11G + | "ZMM11H" -> r.ZMM11H + | "ZMM12A" -> r.ZMM12A + | "ZMM12B" -> r.ZMM12B + | "ZMM12C" -> r.ZMM12C + | "ZMM12D" -> r.ZMM12D + | "ZMM12E" -> r.ZMM12E + | "ZMM12F" -> r.ZMM12F + | "ZMM12G" -> r.ZMM12G + | "ZMM12H" -> r.ZMM12H + | "ZMM13A" -> r.ZMM13A + | "ZMM13B" -> r.ZMM13B + | "ZMM13C" -> r.ZMM13C + | "ZMM13D" -> r.ZMM13D + | "ZMM13E" -> r.ZMM13E + | "ZMM13F" -> r.ZMM13F + | "ZMM13G" -> r.ZMM13G + | "ZMM13H" -> r.ZMM13H + | "ZMM14A" -> r.ZMM14A + | "ZMM14B" -> r.ZMM14B + | "ZMM14C" -> r.ZMM14C + | "ZMM14D" -> r.ZMM14D + | "ZMM14E" -> r.ZMM14E + | "ZMM14F" -> r.ZMM14F + | "ZMM14G" -> r.ZMM14G + | "ZMM14H" -> r.ZMM14H + | "ZMM15A" -> r.ZMM15A + | "ZMM15B" -> r.ZMM15B + | "ZMM15C" -> r.ZMM15C + | "ZMM15D" -> r.ZMM15D + | "ZMM15E" -> r.ZMM15E + | "ZMM15F" -> r.ZMM15F + | "ZMM15G" -> r.ZMM15G + | "ZMM15H" -> r.ZMM15H + | "PKRU" -> r.PKRU + | "DR0" -> r.DR0 + | "DR1" -> r.DR1 + | "DR2" -> r.DR2 + | "DR3" -> r.DR3 + | "DR6" -> r.DR6 + | "DR7" -> r.DR7 + | _ -> raise UnhandledRegExprException + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + Register.ofRegID rid |> Register.toRegType + + override __.GetRegisterAliases rid = + Register.ofRegID rid + |> Register.getAliases + |> Array.map Register.toRegID + + override __.ProgramCounter = + if WordSize.is32 wordSize then Register.EIP |> Register.toRegID + else Register.RIP |> Register.toRegID + + override __.StackPointer = + if WordSize.is32 wordSize then Register.ESP |> Register.toRegID + else Register.RSP |> Register.toRegID + |> Some + + override __.FramePointer = + if WordSize.is32 wordSize then Register.EBP |> Register.toRegID + else Register.RBP |> Register.toRegID + |> Some + + override __.IsProgramCounter regid = + __.ProgramCounter = regid + + override __.IsStackPointer regid = + (__.StackPointer |> Option.get) = regid + + override __.IsFramePointer regid = + (__.FramePointer |> Option.get) = regid diff --git a/src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs b/src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs deleted file mode 100644 index 91587b3b..00000000 --- a/src/FrontEnd/BinLifter/Intel/IntelRegisterSet.fs +++ /dev/null @@ -1,481 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.Intel - -open B2R2 - -module private RegisterSetLiteral = - let [] ArrLen = 4 - -open RegisterSetLiteral - -type IntelRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = IntelRegisterSet (RegisterSet.MakeInternalBitArray ArrLen, Set.empty) - - override __.Tag = RegisterSetTag.Intel - - override __.ArrSize = ArrLen - - override __.New arr s = new IntelRegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | R.EAX -> 0 - | R.EBX -> 1 - | R.ECX -> 2 - | R.EDX -> 3 - | R.ESP -> 4 - | R.EBP -> 5 - | R.ESI -> 6 - | R.EDI -> 7 - | R.RAX -> 8 - | R.RBX -> 9 - | R.RCX -> 10 - | R.RDX -> 11 - | R.RSP -> 12 - | R.RBP -> 13 - | R.RSI -> 14 - | R.RDI -> 15 - | R.R8 -> 16 - | R.R9 -> 17 - | R.R10 -> 18 - | R.R11 -> 19 - | R.R12 -> 20 - | R.R13 -> 21 - | R.R14 -> 22 - | R.R15 -> 23 - | R.SPL -> 24 - | R.BPL -> 25 - | R.SIL -> 26 - | R.DIL -> 27 - | R.ES -> 28 - | R.CS -> 29 - | R.SS -> 30 - | R.DS -> 31 - | R.FS -> 32 - | R.GS -> 33 - | R.ESBase -> 34 - | R.CSBase -> 35 - | R.SSBase -> 36 - | R.DSBase -> 37 - | R.FSBase -> 38 - | R.GSBase -> 39 - | R.OF -> 40 - | R.DF -> 41 - | R.IF -> 42 - | R.TF -> 43 - | R.SF -> 44 - | R.ZF -> 45 - | R.AF -> 46 - | R.PF -> 47 - | R.CF -> 48 - | R.MM0 -> 49 - | R.MM1 -> 50 - | R.MM2 -> 51 - | R.MM3 -> 52 - | R.MM4 -> 53 - | R.MM5 -> 54 - | R.MM6 -> 55 - | R.MM7 -> 56 - | R.ZMM0A -> 57 - | R.ZMM0B -> 58 - | R.ZMM0C -> 59 - | R.ZMM0D -> 60 - | R.ZMM0E -> 61 - | R.ZMM0F -> 62 - | R.ZMM0G -> 63 - | R.ZMM0H -> 64 - | R.ZMM1A -> 65 - | R.ZMM1B -> 66 - | R.ZMM1C -> 67 - | R.ZMM1D -> 68 - | R.ZMM1E -> 69 - | R.ZMM1F -> 70 - | R.ZMM1G -> 71 - | R.ZMM1H -> 72 - | R.ZMM2A -> 73 - | R.ZMM2B -> 74 - | R.ZMM2C -> 75 - | R.ZMM2D -> 76 - | R.ZMM2E -> 77 - | R.ZMM2F -> 78 - | R.ZMM2G -> 79 - | R.ZMM2H -> 80 - | R.ZMM3A -> 81 - | R.ZMM3B -> 82 - | R.ZMM3C -> 83 - | R.ZMM3D -> 84 - | R.ZMM3E -> 85 - | R.ZMM3F -> 86 - | R.ZMM3G -> 87 - | R.ZMM3H -> 88 - | R.ZMM4A -> 89 - | R.ZMM4B -> 90 - | R.ZMM4C -> 91 - | R.ZMM4D -> 92 - | R.ZMM4E -> 93 - | R.ZMM4F -> 94 - | R.ZMM4G -> 95 - | R.ZMM4H -> 96 - | R.ZMM5A -> 97 - | R.ZMM5B -> 98 - | R.ZMM5C -> 99 - | R.ZMM5D -> 100 - | R.ZMM5E -> 101 - | R.ZMM5F -> 102 - | R.ZMM5G -> 103 - | R.ZMM5H -> 104 - | R.ZMM6A -> 105 - | R.ZMM6B -> 106 - | R.ZMM6C -> 107 - | R.ZMM6D -> 108 - | R.ZMM6E -> 109 - | R.ZMM6F -> 110 - | R.ZMM6G -> 111 - | R.ZMM6H -> 112 - | R.ZMM7A -> 113 - | R.ZMM7B -> 114 - | R.ZMM7C -> 115 - | R.ZMM7D -> 116 - | R.ZMM7E -> 117 - | R.ZMM7F -> 118 - | R.ZMM7G -> 119 - | R.ZMM7H -> 120 - | R.ZMM8A -> 121 - | R.ZMM8B -> 122 - | R.ZMM8C -> 123 - | R.ZMM8D -> 124 - | R.ZMM8E -> 125 - | R.ZMM8F -> 126 - | R.ZMM8G -> 127 - | R.ZMM8H -> 128 - | R.ZMM9A -> 129 - | R.ZMM9B -> 130 - | R.ZMM9C -> 131 - | R.ZMM9D -> 132 - | R.ZMM9E -> 133 - | R.ZMM9F -> 134 - | R.ZMM9G -> 135 - | R.ZMM9H -> 136 - | R.ZMM10A -> 137 - | R.ZMM10B -> 138 - | R.ZMM10C -> 139 - | R.ZMM10D -> 140 - | R.ZMM10E -> 141 - | R.ZMM10F -> 142 - | R.ZMM10G -> 143 - | R.ZMM10H -> 144 - | R.ZMM11A -> 145 - | R.ZMM11B -> 146 - | R.ZMM11C -> 147 - | R.ZMM11D -> 148 - | R.ZMM11E -> 149 - | R.ZMM11F -> 150 - | R.ZMM11G -> 151 - | R.ZMM11H -> 152 - | R.ZMM12A -> 153 - | R.ZMM12B -> 154 - | R.ZMM12C -> 155 - | R.ZMM12D -> 156 - | R.ZMM12E -> 157 - | R.ZMM12F -> 158 - | R.ZMM12G -> 159 - | R.ZMM12H -> 160 - | R.ZMM13A -> 161 - | R.ZMM13B -> 162 - | R.ZMM13C -> 163 - | R.ZMM13D -> 164 - | R.ZMM13E -> 165 - | R.ZMM13F -> 166 - | R.ZMM13G -> 167 - | R.ZMM13H -> 168 - | R.ZMM14A -> 169 - | R.ZMM14B -> 170 - | R.ZMM14C -> 171 - | R.ZMM14D -> 172 - | R.ZMM14E -> 173 - | R.ZMM14F -> 174 - | R.ZMM14G -> 175 - | R.ZMM14H -> 176 - | R.ZMM15A -> 177 - | R.ZMM15B -> 178 - | R.ZMM15C -> 179 - | R.ZMM15D -> 180 - | R.ZMM15E -> 181 - | R.ZMM15F -> 182 - | R.ZMM15G -> 183 - | R.ZMM15H -> 184 - | R.BND0A -> 185 - | R.BND0B -> 186 - | R.BND1A -> 187 - | R.BND1B -> 188 - | R.BND2A -> 189 - | R.BND2B -> 190 - | R.BND3A -> 191 - | R.BND3B -> 192 - | R.FCW -> 193 - | R.FSW -> 194 - | R.FTW -> 195 - | R.FOP -> 196 - | R.FIP -> 197 - | R.FCS -> 198 - | R.FDP -> 199 - | R.FDS -> 200 - | R.MXCSR -> 201 - | R.MXCSRMASK -> 202 - | R.PKRU -> 203 - | R.DR0 -> 204 - | R.DR1 -> 205 - | R.DR2 -> 206 - | R.DR3 -> 207 - | R.DR6 -> 208 - | R.DR7 -> 209 - | _ -> -1 - - override __.IndexToRegID index = - match index with - | 0 -> R.EAX - | 1 -> R.EBX - | 2 -> R.ECX - | 3 -> R.EDX - | 4 -> R.ESP - | 5 -> R.EBP - | 6 -> R.ESI - | 7 -> R.EDI - | 8 -> R.RAX - | 9 -> R.RBX - | 10 -> R.RCX - | 11 -> R.RDX - | 12 -> R.RSP - | 13 -> R.RBP - | 14 -> R.RSI - | 15 -> R.RDI - | 16 -> R.R8 - | 17 -> R.R9 - | 18 -> R.R10 - | 19 -> R.R11 - | 20 -> R.R12 - | 21 -> R.R13 - | 22 -> R.R14 - | 23 -> R.R15 - | 24 -> R.SPL - | 25 -> R.BPL - | 26 -> R.SIL - | 27 -> R.DIL - | 28 -> R.ES - | 29 -> R.CS - | 30 -> R.SS - | 31 -> R.DS - | 32 -> R.FS - | 33 -> R.GS - | 34 -> R.ESBase - | 35 -> R.CSBase - | 36 -> R.SSBase - | 37 -> R.DSBase - | 38 -> R.FSBase - | 39 -> R.GSBase - | 40 -> R.OF - | 41 -> R.DF - | 42 -> R.IF - | 43 -> R.TF - | 44 -> R.SF - | 45 -> R.ZF - | 46 -> R.AF - | 47 -> R.PF - | 48 -> R.CF - | 49 -> R.MM0 - | 50 -> R.MM1 - | 51 -> R.MM2 - | 52 -> R.MM3 - | 53 -> R.MM4 - | 54 -> R.MM5 - | 55 -> R.MM6 - | 56 -> R.MM7 - | 57 -> R.ZMM0A - | 58 -> R.ZMM0B - | 59 -> R.ZMM0C - | 60 -> R.ZMM0D - | 61 -> R.ZMM0E - | 62 -> R.ZMM0F - | 63 -> R.ZMM0G - | 64 -> R.ZMM0H - | 65 -> R.ZMM1A - | 66 -> R.ZMM1B - | 67 -> R.ZMM1C - | 68 -> R.ZMM1D - | 69 -> R.ZMM1E - | 70 -> R.ZMM1F - | 71 -> R.ZMM1G - | 72 -> R.ZMM1H - | 73 -> R.ZMM2A - | 74 -> R.ZMM2B - | 75 -> R.ZMM2C - | 76 -> R.ZMM2D - | 77 -> R.ZMM2E - | 78 -> R.ZMM2F - | 79 -> R.ZMM2G - | 80 -> R.ZMM2H - | 81 -> R.ZMM3A - | 82 -> R.ZMM3B - | 83 -> R.ZMM3C - | 84 -> R.ZMM3D - | 85 -> R.ZMM3E - | 86 -> R.ZMM3F - | 87 -> R.ZMM3G - | 88 -> R.ZMM3H - | 89 -> R.ZMM4A - | 90 -> R.ZMM4B - | 91 -> R.ZMM4C - | 92 -> R.ZMM4D - | 93 -> R.ZMM4E - | 94 -> R.ZMM4F - | 95 -> R.ZMM4G - | 96 -> R.ZMM4H - | 97 -> R.ZMM5A - | 98 -> R.ZMM5B - | 99 -> R.ZMM5C - | 100 -> R.ZMM5D - | 101 -> R.ZMM5E - | 102 -> R.ZMM5F - | 103 -> R.ZMM5G - | 104 -> R.ZMM5H - | 105 -> R.ZMM6A - | 106 -> R.ZMM6B - | 107 -> R.ZMM6C - | 108 -> R.ZMM6D - | 109 -> R.ZMM6E - | 110 -> R.ZMM6F - | 111 -> R.ZMM6G - | 112 -> R.ZMM6H - | 113 -> R.ZMM7A - | 114 -> R.ZMM7B - | 115 -> R.ZMM7C - | 116 -> R.ZMM7D - | 117 -> R.ZMM7E - | 118 -> R.ZMM7F - | 119 -> R.ZMM7G - | 120 -> R.ZMM7H - | 121 -> R.ZMM8A - | 122 -> R.ZMM8B - | 123 -> R.ZMM8C - | 124 -> R.ZMM8D - | 125 -> R.ZMM8E - | 126 -> R.ZMM8F - | 127 -> R.ZMM8G - | 128 -> R.ZMM8H - | 129 -> R.ZMM9A - | 130 -> R.ZMM9B - | 131 -> R.ZMM9C - | 132 -> R.ZMM9D - | 133 -> R.ZMM9E - | 134 -> R.ZMM9F - | 135 -> R.ZMM9G - | 136 -> R.ZMM9H - | 137 -> R.ZMM10A - | 138 -> R.ZMM10B - | 139 -> R.ZMM10C - | 140 -> R.ZMM10D - | 141 -> R.ZMM10E - | 142 -> R.ZMM10F - | 143 -> R.ZMM10G - | 144 -> R.ZMM10H - | 145 -> R.ZMM11A - | 146 -> R.ZMM11B - | 147 -> R.ZMM11C - | 148 -> R.ZMM11D - | 149 -> R.ZMM11E - | 150 -> R.ZMM11F - | 151 -> R.ZMM11G - | 152 -> R.ZMM11H - | 153 -> R.ZMM12A - | 154 -> R.ZMM12B - | 155 -> R.ZMM12C - | 156 -> R.ZMM12D - | 157 -> R.ZMM12E - | 158 -> R.ZMM12F - | 159 -> R.ZMM12G - | 160 -> R.ZMM12H - | 161 -> R.ZMM13A - | 162 -> R.ZMM13B - | 163 -> R.ZMM13C - | 164 -> R.ZMM13D - | 165 -> R.ZMM13E - | 166 -> R.ZMM13F - | 167 -> R.ZMM13G - | 168 -> R.ZMM13H - | 169 -> R.ZMM14A - | 170 -> R.ZMM14B - | 171 -> R.ZMM14C - | 172 -> R.ZMM14D - | 173 -> R.ZMM14E - | 174 -> R.ZMM14F - | 175 -> R.ZMM14G - | 176 -> R.ZMM14H - | 177 -> R.ZMM15A - | 178 -> R.ZMM15B - | 179 -> R.ZMM15C - | 180 -> R.ZMM15D - | 181 -> R.ZMM15E - | 182 -> R.ZMM15F - | 183 -> R.ZMM15G - | 184 -> R.ZMM15H - | 185 -> R.BND0A - | 186 -> R.BND0B - | 187 -> R.BND1A - | 188 -> R.BND1B - | 189 -> R.BND2A - | 190 -> R.BND2B - | 191 -> R.BND3A - | 192 -> R.BND3B - | 193 -> R.FCW - | 194 -> R.FSW - | 195 -> R.FTW - | 196 -> R.FOP - | 197 -> R.FIP - | 198 -> R.FCS - | 199 -> R.FDP - | 200 -> R.FDS - | 201 -> R.MXCSR - | 202 -> R.MXCSRMASK - | 203 -> R.PKRU - | 204 -> R.DR0 - | 205 -> R.DR1 - | 206 -> R.DR2 - | 207 -> R.DR3 - | 208 -> R.DR6 - | 209 -> R.DR7 - | _ -> Utils.impossible () - |> Register.toRegID - - override __.ToString () = - sprintf "IntelRegisterSet<%x, %x, %x, %x>" __.BitArray[0] __.BitArray[1] - __.BitArray[2] __.BitArray[3] - -[] -module IntelRegisterSet = - let singleton rid = IntelRegisterSet().Add(rid) - let empty = IntelRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs b/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs index 2ac25aee..2b34d6b9 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelSSELifter.fs @@ -36,77 +36,125 @@ open B2R2.FrontEnd.BinLifter.Intel.Helper open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils open B2R2.FrontEnd.BinLifter.Intel.MMXLifter -let buildMove ins insLen ctxt bufSize = - let ir = IRBuilder (bufSize) - let oprSize = getOperationSize ins +let getExponent isDouble src = + if isDouble then + let numMantissa = numI32 52 64 + let mask = numI32 0x7FF 64 + AST.xtlo 32 ((src >> numMantissa) .& mask) + else + let numMantissa = numI32 23 32 + let mask = numI32 0xff 32 + (src >> numMantissa) .& mask + +let getMantissa isDouble src = + let mask = + if isDouble then numU64 0xfffffffffffffUL 64 + else numU64 0x7fffffUL 32 + src .& mask + +let isNan isDouble expr = + let exponent = getExponent isDouble expr + let mantissa = getMantissa isDouble expr + let e = if isDouble then numI32 0x7ff 32 else numI32 0xff 32 + let zero = if isDouble then AST.num0 64 else AST.num0 32 + (exponent == e) .& (mantissa != zero) + +let addsubpd ins insLen ctxt = + let ir = !*ctxt + !ir insLen + +let addsubps ins insLen ctxt = + let ir = !*ctxt + ! + !!ir (t1 := AST.fsub (AST.xtlo 32 dstA) (AST.xtlo 32 srcA)) + !!ir (t2 := AST.fadd (AST.xthi 32 dstA) (AST.xthi 32 srcA)) + !!ir (t3 := AST.fsub (AST.xtlo 32 dstB) (AST.xtlo 32 srcB)) + !!ir (t4 := AST.fadd (AST.xthi 32 dstB) (AST.xthi 32 srcB)) + !!ir (dstA := AST.concat t2 t1) + !!ir (dstB := AST.concat t4 t3) + !>ir insLen + +let buildMove ins insLen ctxt = + let ir = !*ctxt ! / 64 match oprSize with | 32 | 64 -> - let struct (dst, src) = transTwoOprs ins insLen ctxt + let struct (dst, src) = transTwoOprs ir false ins insLen ctxt !!ir (dst := src) | 128 | 256 | 512 -> let struct (dst, src) = getTwoOprs ins - let dst = transOprToExprVec ins insLen ctxt dst - let src = transOprToExprVec ins insLen ctxt src - List.iter2 (fun d s -> !!ir (d := s)) dst src + let src = transOprToArr ir false ins insLen ctxt 64 packNum oprSize src + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst src | _ -> raise InvalidOperandSizeException !>ir insLen -let movaps ins insLen ctxt = buildMove ins insLen ctxt 4 +let movaps ins insLen ctxt = buildMove ins insLen ctxt -let movapd ins insLen ctxt = buildMove ins insLen ctxt 4 +let movapd ins insLen ctxt = buildMove ins insLen ctxt -let movups ins insLen ctxt = buildMove ins insLen ctxt 4 +let movups ins insLen ctxt = buildMove ins insLen ctxt -let movupd ins insLen ctxt = buildMove ins insLen ctxt 4 +let movupd ins insLen ctxt = buildMove ins insLen ctxt let movhps ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt !), OprReg r -> - let dst = transOprToExpr ins insLen ctxt dst + let dst = transOprToExpr ir false ins insLen ctxt dst !!ir (dst := getPseudoRegVar ctxt r 2) | OprReg r, OprMem (_, _, _, 64)-> - let src = transOprToExpr ins insLen ctxt src + let src = transOprToExpr ir false ins insLen ctxt src !!ir (getPseudoRegVar ctxt r 2 := src) | _ -> raise InvalidOperandException !>ir insLen let movhpd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! - let src = transOprToExpr ins insLen ctxt src + let src = transOprToExpr ir false ins insLen ctxt src !!ir (getPseudoRegVar ctxt r 2 := src) | OprMem _, OprReg r -> - let dst = transOprToExpr ins insLen ctxt dst - !!ir (dst := getPseudoRegVar ctxt r 1) + let dst = transOprToExpr ir false ins insLen ctxt dst + !!ir (dst := getPseudoRegVar ctxt r 2) | _ -> raise InvalidOperandException !>ir insLen let movhlps ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr128 ins insLen ctxt dst |> snd - let src = transOprToExpr128 ins insLen ctxt src |> fst + let ir = !*ctxt ! snd + let src = transOprToExpr128 ir false ins insLen ctxt src |> fst !!ir (dst := src) !>ir insLen let movlpd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! - let src = transOprToExpr ins insLen ctxt src + let src = transOprToExpr ir false ins insLen ctxt src !!ir (getPseudoRegVar ctxt r 1 := src) | OprMem _, OprReg r -> - let dst = transOprToExpr ins insLen ctxt dst + let dst = transOprToExpr ir false ins insLen ctxt dst !!ir (dst := getPseudoRegVar ctxt r 1) | _ -> raise InvalidOperandException !>ir insLen @@ -114,42 +162,42 @@ let movlpd ins insLen ctxt = let movlps ins insLen ctxt = movlpd ins insLen ctxt let movlhps ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr128 ins insLen ctxt dst |> fst - let src = transOprToExpr128 ins insLen ctxt src |> snd + let ir = !*ctxt ! fst + let src = transOprToExpr128 ir false ins insLen ctxt src |> snd !!ir (dst := src) !>ir insLen let movmskps ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! 63) (AST.extract srcA 1 31) let srcB = AST.concat (AST.extract srcB 1 63) (AST.extract srcB 1 31) !!ir (dst := AST.zext oprSize <| AST.concat srcB srcA) !>ir insLen let movmskpd ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt + ! src2) - let src127 = (AST.sext oprSize (AST.xthi 1 src1)) << AST.num1 oprSize - !!ir (dst := src63 .| src127) + let src63 = AST.zext oprSize (AST.xthi 1 src2) + let src127 = (AST.zext oprSize (AST.xthi 1 src1)) << AST.num1 oprSize + !!ir (dstAssign oprSize dst (src63 .| src127)) !>ir insLen let movss (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins + let ir = !*ctxt ! let dst = getPseudoRegVar ctxt r1 1 |> AST.xtlo 32 @@ -157,23 +205,23 @@ let movss (ins: InsInfo) insLen ctxt = !!ir (dst := src) | OprReg r1, OprMem _ -> let dst2, dst1 = getPseudoRegVar128 ctxt r1 - let src = transOprToExpr ins insLen ctxt src + let src = transOprToExpr ir false ins insLen ctxt src !!ir (dstAssign 32 dst1 src) !!ir (dst2 := AST.num0 64) | OprMem _ , OprReg r1 -> - let dst = transOprToExpr ins insLen ctxt dst + let dst = transOprToExpr ir false ins insLen ctxt dst let src = getPseudoRegVar ctxt r1 1 |> AST.xtlo 32 !!ir (dstAssign 32 dst src) | _ -> raise InvalidOperandException !>ir insLen let movsd (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt if ins.Operands = NoOperand then GeneralLifter.movs ins insLen ctxt else - let struct (dst, src) = getTwoOprs ins ! let dst = getPseudoRegVar ctxt r1 1 @@ -181,21 +229,21 @@ let movsd (ins: InsInfo) insLen ctxt = !!ir (dst := src) | OprReg r1, OprMem _ -> let dst2, dst1 = getPseudoRegVar128 ctxt r1 - let src = transOprToExpr ins insLen ctxt src + let src = transOprToExpr ir false ins insLen ctxt src !!ir (dst1 := src) !!ir (dst2 := AST.num0 64) | OprMem _ , OprReg r1 -> - let dst = transOprToExpr ins insLen ctxt dst + let dst = transOprToExpr ir false ins insLen ctxt dst let src = getPseudoRegVar ctxt r1 1 !!ir (dstAssign 64 dst src) | _ -> raise InvalidOperandException !>ir insLen let addps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 (opP AST.fadd) 8 + buildPackedInstr ins insLen ctxt false 32 (opP AST.fadd) let addpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 (opP AST.fadd) 8 + buildPackedInstr ins insLen ctxt false 64 (opP AST.fadd) let private getFstOperand = function | OneOperand o -> o @@ -210,19 +258,19 @@ let private getTwoSrcOperands = function | _ -> raise InvalidOperandException let private handleScalarFPOp (ins: InsInfo) insLen ctxt sz op = - let ir = IRBuilder(8) + let ir = !*ctxt + ! getFstOperand |> transOprToExpr128 ins insLen ctxt + ins.Operands |> getFstOperand |> transOprToExpr128 ir false ins insLen ctxt let src1, src2 = getTwoSrcOperands ins.Operands - let src1 = transOprToExpr64 ins insLen ctxt src1 + let src1 = transOprToExpr64 ir false ins insLen ctxt src1 let src2 = - if sz = 32 then transOprToExpr32 ins insLen ctxt src2 - else transOprToExpr64 ins insLen ctxt src2 + if sz = 32 then transOprToExpr32 ir false ins insLen ctxt src2 + else transOprToExpr64 ir false ins insLen ctxt src2 let dst1, src1 = if sz = 32 then AST.xtlo 32 dst1, AST.xtlo 32 src1 else dst1, src1 let struct (t1, t2, t3) = tmpVars3 ir sz - ! AST.fadd let subps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 (opP AST.fsub) 8 + buildPackedInstr ins insLen ctxt false 32 (opP AST.fsub) let subpd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - !ir insLen + buildPackedInstr ins insLen ctxt false 64 (opP AST.fsub) let subss ins insLen ctxt = handleScalarFPOp ins insLen ctxt 32 AST.fsub @@ -255,10 +296,10 @@ let subsd ins insLen ctxt = handleScalarFPOp ins insLen ctxt 64 AST.fsub let mulps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 (opP AST.fmul) 8 + buildPackedInstr ins insLen ctxt false 32 (opP AST.fmul) let mulpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 (opP AST.fmul) 8 + buildPackedInstr ins insLen ctxt false 64 (opP AST.fmul) let mulss ins insLen ctxt = handleScalarFPOp ins insLen ctxt 32 AST.fmul @@ -267,10 +308,10 @@ let mulsd ins insLen ctxt = handleScalarFPOp ins insLen ctxt 64 AST.fmul let divps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 (opP AST.fdiv) 8 + buildPackedInstr ins insLen ctxt false 32 (opP AST.fdiv) let divpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 (opP AST.fdiv) 8 + buildPackedInstr ins insLen ctxt false 64 (opP AST.fdiv) let divss ins insLen ctxt = handleScalarFPOp ins insLen ctxt 32 AST.fdiv @@ -279,17 +320,17 @@ let divsd ins insLen ctxt = handleScalarFPOp ins insLen ctxt 64 AST.fdiv let rcpps ins insLen ctxt = - let ir = IRBuilder(8) + let ir = !*ctxt + ! dst1, AST.xtlo 32 dst1 let dst2b, dst2a = AST.xthi 32 dst2, AST.xtlo 32 dst2 let src1b, src1a = AST.xthi 32 src1, AST.xtlo 32 src1 let src2b, src2a = AST.xthi 32 src2, AST.xtlo 32 src2 - let tmp = !*ir 32 + let tmp = !+ir 32 let flt1 = numI32 0x3f800000 32 - !ir insLen let rcpss ins insLen ctxt = - let ir = IRBuilder(4) + let ir = !*ctxt + ! + let dst = transOprToExpr32 ir false ins insLen ctxt opr1 + let src = transOprToExpr32 ir false ins insLen ctxt opr2 + let tmp = !+ir 32 let flt1 = numI32 0x3f800000 32 - !ir insLen let sqrtps ins insLen ctxt = - let ir = IRBuilder (16) - let struct (opr1, opr2) = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt opr1 - let src2, src1 = transOprToExpr128 ins insLen ctxt opr2 - let struct (tmp1, tmp2, tmp3, tmp4) = tmpVars4 ir 32 + let ir = !*ctxt + let oprSize = getOperationSize ins + let packNum = 64 / 32 ! src1) - !!ir (tmp2 := AST.xthi 32 src1) - !!ir (tmp3 := AST.xtlo 32 src2) - !!ir (tmp4 := AST.xthi 32 src2) - !!ir (AST.xtlo 32 dst1 := AST.unop UnOpType.FSQRT tmp1) - !!ir (AST.xthi 32 dst1 := AST.unop UnOpType.FSQRT tmp2) - !!ir (AST.xtlo 32 dst2 := AST.unop UnOpType.FSQRT tmp3) - !!ir (AST.xthi 32 dst2 := AST.unop UnOpType.FSQRT tmp4) + let struct (dst, src) = getTwoOprs ins + let src = transOprToArr ir false ins insLen ctxt 32 packNum oprSize src + let result = Array.map (AST.unop UnOpType.FSQRT) src + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result !>ir insLen let sqrtpd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (opr1, opr2) = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt opr1 - let src2, src1 = transOprToExpr128 ins insLen ctxt opr2 + let ir = !*ctxt !ir insLen let sqrtss ins insLen ctxt = - let ir = IRBuilder (4) - let struct (opr1, opr2) = getTwoOprs ins - let dst = transOprToExpr32 ins insLen ctxt opr1 - let src = transOprToExpr32 ins insLen ctxt opr2 + let ir = !*ctxt !ir insLen let sqrtsd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (opr1, opr2) = getTwoOprs ins - let dst = transOprToExpr64 ins insLen ctxt opr1 - let src = transOprToExpr64 ins insLen ctxt opr2 + let ir = !*ctxt !ir insLen let rsqrtps ins insLen ctxt = - let ir = IRBuilder(16) + let ir = !*ctxt + ! dst1, AST.xtlo 32 dst1 let dst2b, dst2a = AST.xthi 32 dst2, AST.xtlo 32 dst2 let src1b, src1a = AST.xthi 32 src1, AST.xtlo 32 src1 let src2b, src2a = AST.xthi 32 src2, AST.xtlo 32 src2 - let tmp = !*ir 32 + let tmp = !+ir 32 let flt1 = numI32 0x3f800000 32 - !ir insLen let rsqrtss ins insLen ctxt = - let ir = IRBuilder(4) + let ir = !*ctxt + ! + let dst = transOprToExpr32 ir false ins insLen ctxt opr1 + let src = transOprToExpr32 ir false ins insLen ctxt opr2 + let tmp = !+ir 32 let flt1 = numI32 0x3f800000 32 - !ir insLen let private minMaxPS ins insLen ctxt compare = - let ir = IRBuilder (16) + let ir = !*ctxt + ! dst1, AST.xthi 32 dst1 let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 let struct (val4, val3, val2, val1) = tmpVars4 ir 32 - !ir insLen let private minMaxPD ins insLen ctxt compare = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - !ir insLen let private minMaxSS ins insLen ctxt compare = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr32 ins insLen ctxt dst - let src = transOprToExpr32 ins insLen ctxt src - let tmp = !*ir 32 + let ir = !*ctxt ! !!ir (tmp := AST.ite (compare dst src) dst src) !!ir (dst := tmp) !>ir insLen let private minMaxSD ins insLen ctxt compare = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr64 ins insLen ctxt dst - let src = transOprToExpr64 ins insLen ctxt src - let tmp = !*ir 64 + let ir = !*ctxt ! !!ir (tmp := AST.ite (compare dst src) dst src) !!ir (dst := tmp) !>ir insLen @@ -466,36 +501,37 @@ let minss ins insLen ctxt = let minsd ins insLen ctxt = minMaxSD ins insLen ctxt AST.flt +let private cmppCond ir ins insLen ctxt op3 isDbl c expr1 expr2 = + let imm = + transOprToExpr ir false ins insLen ctxt op3 |> AST.xtlo 8 + .& numI32 0x7 8 + match imm.E with + | Num bv -> + match bv.SmallValue () with + | 0UL -> !!ir (c := expr1 == expr2) + | 1UL -> !!ir (c := AST.flt expr1 expr2) + | 2UL -> !!ir (c := AST.fle expr1 expr2) + | 3UL -> !!ir (c := isNan isDbl expr1 .| isNan isDbl expr2) + | 4UL -> !!ir (c := expr1 != expr2) + | 5UL -> !!ir (c := AST.flt expr1 expr2 |> AST.not) + | 6UL -> !!ir (c := AST.fle expr1 expr2 |> AST.not) + | 7UL -> !!ir (c := (isNan isDbl expr1 .| isNan isDbl expr2) |> AST.not) + | _ -> !!ir (c := AST.b0) + | _ -> Utils.impossible () + let cmpps ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt + ! dst1, AST.xthi 32 dst1 let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 - let imm = transOprToExpr ins insLen ctxt op3 |> AST.xtlo 8 - let isNan expr = - (AST.extract expr 8 23 == AST.num (BitVector.unsignedMax 8)) - .& (AST.xtlo 23 expr != AST.num0 23) - let cmpCond c expr1 expr2 = - !!ir (c := AST.b0) - !!ir (c := AST.ite (imm == AST.num0 8) (expr1 == expr2) c) - !!ir (c := AST.ite (imm == AST.num1 8) (AST.flt expr1 expr2) c) - !!ir (c := AST.ite (imm == numI32 2 8) (AST.fle expr1 expr2) c) - !!ir (c := AST.ite (imm == numI32 3 8) (isNan expr1 .| isNan expr2) c) - !!ir (c := AST.ite (imm == numI32 4 8) (expr1 != expr2) c) - !!ir - (c := AST.ite (imm == numI32 5 8) (AST.flt expr1 expr2 |> AST.not) c) - !!ir - (c := AST.ite (imm == numI32 6 8) (AST.fle expr1 expr2 |> AST.not) c) - !!ir (c := AST.ite (imm == numI32 7 8) - (isNan expr1 .| isNan expr2 |> AST.not) c) let struct (cond1, cond2, cond3, cond4) = tmpVars4 ir 1 - ! src1) - cmpCond cond2 dst1B (AST.xthi 32 src1) - cmpCond cond3 dst2A (AST.xtlo 32 src2) - cmpCond cond4 dst2B (AST.xthi 32 src2) + cmppCond ir ins insLen ctxt op3 false cond1 dst1A (AST.xtlo 32 src1) + cmppCond ir ins insLen ctxt op3 false cond2 dst1B (AST.xthi 32 src1) + cmppCond ir ins insLen ctxt op3 false cond3 dst2A (AST.xtlo 32 src2) + cmppCond ir ins insLen ctxt op3 false cond4 dst2B (AST.xthi 32 src2) !!ir (dst1A := AST.ite cond1 (maxNum 32) (AST.num0 32)) !!ir (dst1B := AST.ite cond2 (maxNum 32) (AST.num0 32)) !!ir (dst2A := AST.ite cond3 (maxNum 32) (AST.num0 32)) @@ -503,57 +539,27 @@ let cmpps ins insLen ctxt = !>ir insLen let cmppd ins insLen ctxt = - let ir = IRBuilder (32) + let ir = !*ctxt + ! AST.xtlo 8 - let isNan expr = - (AST.extract expr 11 52 == AST.num (BitVector.unsignedMax 11)) - .& (AST.xtlo 52 expr != AST.num0 52) - let cmpCond c expr1 expr2 = - !!ir (c := AST.b0) - !!ir (c := AST.ite (imm == AST.num0 8) (expr1 == expr2) c) - !!ir (c := AST.ite (imm == AST.num1 8) (AST.flt expr1 expr2) c) - !!ir (c := AST.ite (imm == numI32 2 8) (AST.fle expr1 expr2) c) - !!ir (c := AST.ite (imm == numI32 3 8) (isNan expr1 .| isNan expr2) c) - !!ir (c := AST.ite (imm == numI32 4 8) (expr1 != expr2) c) - !!ir - (c := AST.ite (imm == numI32 5 8) (AST.flt expr1 expr2 |> AST.not) c) - !!ir - (c := AST.ite (imm == numI32 6 8) (AST.fle expr1 expr2 |> AST.not) c) - !!ir (c := AST.ite (imm == numI32 7 8) - (isNan expr1 .| isNan expr2 |> AST.not) c) + let dst1, dst2 = transOprToExpr128 ir false ins insLen ctxt op1 + let src1, src2 = transOprToExpr128 ir false ins insLen ctxt op2 let struct (cond1, cond2) = tmpVars2 ir 1 - !) (AST.num0 64)) !!ir (dst2 := AST.ite cond2 (maxNum 64) (AST.num0 64)) !>ir insLen let cmpss ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! AST.xtlo 8 - let n num = numI32 num 8 + let dst = transOprToExpr32 ir false ins insLen ctxt dst + let src = transOprToExpr32 ir false ins insLen ctxt src let max32 = maxNum 32 - let isNan expr = - (AST.extract expr 8 23 == AST.num (BitVector.unsignedMax 8)) - .& (AST.xtlo 23 expr != AST.num0 23) - let cond = !*ir 1 - ! AST.not) cond) - !!ir (cond := AST.ite (imm == n 6) (AST.fle dst src |> AST.not) cond) - !!ir (cond := AST.ite (imm == n 7) - ((isNan dst) .| (isNan src) |> AST.not) cond) + let cond = !+ir 1 + cmppCond ir ins insLen ctxt imm false cond dst src !!ir (dst := AST.ite cond max32 (AST.num0 32)) !>ir insLen @@ -561,48 +567,32 @@ let cmpsd (ins: InsInfo) insLen ctxt = match ins.Operands with | NoOperand -> GeneralLifter.cmps ins insLen ctxt | ThreeOperands (dst, src, imm) -> - let ir = IRBuilder (16) - let dst = transOprToExpr64 ins insLen ctxt dst - let src = transOprToExpr64 ins insLen ctxt src - let imm = transOprToExpr ins insLen ctxt imm |> AST.xtlo 8 - let n i = numI32 i 8 - let max64 = maxNum 64 - let isNan expr = - (AST.extract expr 11 52 == AST.num (BitVector.unsignedMax 11)) - .& (AST.xtlo 52 expr != AST.num0 52) - let cond = !*ir 1 + let ir = !*ctxt ! AST.not) cond) - !!ir (cond := AST.ite (imm == n 6) (AST.fle dst src |> AST.not) cond) - !!ir (cond := AST.ite (imm == n 7) - ((isNan dst) .| (isNan src) |> AST.not) cond) + let dst = transOprToExpr64 ir false ins insLen ctxt dst + let src = transOprToExpr64 ir false ins insLen ctxt src + let max64 = maxNum 64 + let cond = !+ir 1 + cmppCond ir ins insLen ctxt imm true cond dst src !!ir (dst := AST.ite cond max64 (AST.num0 64)) !>ir insLen | _ -> raise InvalidOperandException let comiss ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! 23 == AST.num (BitVector.unsignedMax 8)) - .& (AST.xtlo 23 expr != AST.num0 23) - !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + !!ir (AST.cjmp (isNan false opr1 .| isNan false opr2) (AST.name lblNan) (AST.name lblExit)) !!ir (AST.lmark lblNan) !!ir (zf := AST.b1) @@ -612,26 +602,26 @@ let comiss ins insLen ctxt = !!ir (!.ctxt R.OF := AST.b0) !!ir (!.ctxt R.AF := AST.b0) !!ir (!.ctxt R.SF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let comisd ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! 52 == AST.num (BitVector.unsignedMax 11)) - .& (AST.xtlo 52 expr != AST.num0 52) - !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + !!ir (AST.cjmp (isNan true opr1 .| isNan true opr2) (AST.name lblNan) (AST.name lblExit)) !!ir (AST.lmark lblNan) !!ir (zf := AST.b1) @@ -641,26 +631,26 @@ let comisd ins insLen ctxt = !!ir (!.ctxt R.OF := AST.b0) !!ir (!.ctxt R.AF := AST.b0) !!ir (!.ctxt R.SF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let ucomiss ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! 23 == AST.num (BitVector.unsignedMax 8)) - .& (AST.xtlo 23 expr != AST.num0 23) - !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + !!ir (AST.cjmp (isNan false opr1 .| isNan false opr2) (AST.name lblNan) (AST.name lblExit)) !!ir (AST.lmark lblNan) !!ir (zf := AST.b1) @@ -670,26 +660,26 @@ let ucomiss ins insLen ctxt = !!ir (!.ctxt R.OF := AST.b0) !!ir (!.ctxt R.AF := AST.b0) !!ir (!.ctxt R.SF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let ucomisd ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! 52 == AST.num (BitVector.unsignedMax 11)) - .& (AST.xtlo 52 expr != AST.num0 52) - !!ir (AST.cjmp (isNan opr1 .| isNan opr2) + !!ir (AST.cjmp (isNan true opr1 .| isNan true opr2) (AST.name lblNan) (AST.name lblExit)) !!ir (AST.lmark lblNan) !!ir (zf := AST.b1) @@ -699,60 +689,61 @@ let ucomisd ins insLen ctxt = !!ir (!.ctxt R.OF := AST.b0) !!ir (!.ctxt R.AF := AST.b0) !!ir (!.ctxt R.SF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let andps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPand 16 + buildPackedInstr ins insLen ctxt false 32 opPand let andpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPand 16 + buildPackedInstr ins insLen ctxt false 64 opPand let andnps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPandn 8 + buildPackedInstr ins insLen ctxt false 32 opPandn let andnpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPandn 8 + buildPackedInstr ins insLen ctxt false 64 opPandn let orps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPor 16 + buildPackedInstr ins insLen ctxt false 32 opPor let orpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPor 16 + buildPackedInstr ins insLen ctxt false 64 opPor -let private opPxor _ = Array.map2 (.|) +let private opPxor _ = Array.map2 (<+>) let xorps ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPxor 16 + buildPackedInstr ins insLen ctxt false 32 opPxor let xorpd ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPxor 16 + buildPackedInstr ins insLen ctxt false 64 opPxor let shufps ins insLen ctxt = - let ir = IRBuilder (32) + let ir = !*ctxt + ! dst1, AST.xthi 32 dst1 let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 let doShuf cond dst e0 e1 e2 e3 = !!ir (dst := AST.num0 32) - !!ir (dst := AST.ite (cond == AST.num0 2) e0 dst) - !!ir (dst := AST.ite (cond == AST.num1 2) e1 dst) - !!ir (dst := AST.ite (cond == numI32 2 2) e2 dst) - !!ir (dst := AST.ite (cond == numI32 3 2) e3 dst) - let cond1 = AST.xtlo 2 imm - let cond2 = AST.extract imm 2 2 - let cond3 = AST.extract imm 2 4 - let cond4 = AST.extract imm 2 6 + !!ir (dst := AST.ite (cond == AST.num0 8) e0 dst) + !!ir (dst := AST.ite (cond == AST.num1 8) e1 dst) + !!ir (dst := AST.ite (cond == numI32 2 8) e2 dst) + !!ir (dst := AST.ite (cond == numI32 3 8) e3 dst) + let cond shfAmt = + ((AST.xtlo 8 imm) >> (numI32 shfAmt 8)) .& (numI32 0b11 8) let struct (tmp1, tmp2, tmp3, tmp4) = tmpVars4 ir 32 - !ir insLen let shufpd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! imm let cond2 = AST.extract imm 1 1 - ! + !!ir (src1A := dstA) + !!ir (src1B := dstB) + !!ir (src2A := srcA) + !!ir (src2B := srcB) + !!ir (dstA := AST.ite cond1 src1B src1A) + !!ir (dstB := AST.ite cond2 src2B src2A) !>ir insLen let unpckhps ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! dst1, AST.xthi 32 dst1 let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 let src2A, src2B = AST.xtlo 32 src2, AST.xthi 32 src2 - !ir insLen let unpckhpd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src2, _src1 = transOprToExpr128 ins insLen ctxt src + let ir = !*ctxt !ir insLen let unpcklps ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let _src2, src1 = transOprToExpr128 ins insLen ctxt src - let _dst1A, dst1B = AST.xtlo 32 dst1, AST.xthi 32 dst1 - let dst2A, dst2B = AST.xtlo 32 dst2, AST.xthi 32 dst2 - let src1A, src1B = AST.xtlo 32 src1, AST.xthi 32 src1 + let ir = !*ctxt ! + !!ir (tSrc1A := dstA) + !!ir (tSrc1B := dstB) + !!ir (tSrc2A := srcA) + !!ir (dstA := AST.concat (AST.xtlo 32 tSrc2A) (AST.xtlo 32 tSrc1A)) + !!ir (dstB := AST.concat (AST.xthi 32 tSrc2A) (AST.xthi 32 tSrc1A)) !>ir insLen let unpcklpd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let _src2, src1 = transOprToExpr128 ins insLen ctxt src + let ir = !*ctxt !ir insLen let cvtpi2ps ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! src) !!ir (tmp2 := AST.xthi 32 src) - !!ir (AST.xtlo 32 dst := AST.cast CastKind.IntToFloat 32 tmp1) - !!ir (AST.xthi 32 dst := AST.cast CastKind.IntToFloat 32 tmp2) + !!ir (AST.xtlo 32 dst := AST.cast CastKind.SIntToFloat 32 tmp1) + !!ir (AST.xthi 32 dst := AST.cast CastKind.SIntToFloat 32 tmp2) !>ir insLen let cvtdq2pd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! src) !!ir (tmp2 := AST.xthi 32 src) - !!ir (dst1 := AST.cast CastKind.IntToFloat 64 tmp1) - !!ir (dst2 := AST.cast CastKind.IntToFloat 64 tmp2) + !!ir (dst1 := AST.cast CastKind.SIntToFloat 64 tmp1) + !!ir (dst2 := AST.cast CastKind.SIntToFloat 64 tmp2) !>ir insLen let cvtpi2pd ins insLen ctxt = cvtdq2pd ins insLen ctxt let cvtsi2ss ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr64 ins insLen ctxt dst - let src = transOprToExpr ins insLen ctxt src + let ir = !*ctxt ! dst := AST.cast CastKind.IntToFloat 32 src) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src + !!ir (AST.xtlo 32 dst := AST.cast CastKind.SIntToFloat 32 src) !>ir insLen let cvtsi2sd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr64 ins insLen ctxt dst - let src = transOprToExpr ins insLen ctxt src + let ir = !*ctxt ! src) + let struct (dst, src) = getTwoOprs ins + let dst = transOprToExpr64 ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src + !!ir (dst := AST.cast CastKind.SIntToFloat 64 src) !>ir insLen let cvtps2pi ins insLen ctxt rounded = - let ir = IRBuilder (8) + let ir = !*ctxt + ! let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - ! src) !!ir (tmp2 := AST.xthi 32 src) !!ir (AST.xtlo 32 dst := AST.cast castKind 32 tmp1) @@ -881,12 +877,12 @@ let cvtps2pi ins insLen ctxt rounded = !>ir insLen let cvtps2pd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! src) !!ir (tmp2 := AST.xthi 32 src) !!ir (dst1 := AST.cast CastKind.FloatCast 64 tmp1) @@ -894,64 +890,64 @@ let cvtps2pd ins insLen ctxt = !>ir insLen let cvtpd2ps ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src) = getTwoOprs ins - let dst2, dst1 = transOprToExpr128 ins insLen ctxt dst - let src2, src1 = transOprToExpr128 ins insLen ctxt src + let ir = !*ctxt ! dst1 := AST.cast CastKind.FloatCast 32 src1) !!ir (AST.xthi 32 dst1 := AST.cast CastKind.FloatCast 32 src2) !!ir (dst2 := AST.num0 64) !>ir insLen let cvtpd2pi ins insLen ctxt rounded = - let ir = IRBuilder (4) + let ir = !*ctxt + ! dst := AST.cast castKind 32 src1) !!ir (AST.xthi 32 dst := AST.cast castKind 32 src2) !>ir insLen let cvtpd2dq ins insLen ctxt rounded = - let ir = IRBuilder (8) + let ir = !*ctxt + ! dst1 := AST.cast castKind 32 src1) !!ir (AST.xthi 32 dst1 := AST.cast castKind 32 src2) !!ir (dst2 := AST.num0 64) !>ir insLen let cvtdq2ps ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! - ! src1) !!ir (tmp2 := AST.xthi 32 src1) !!ir (tmp3 := AST.xtlo 32 src2) !!ir (tmp4 := AST.xthi 32 src2) - !!ir (AST.xtlo 32 dst1 := AST.cast CastKind.IntToFloat 32 tmp1) - !!ir (AST.xthi 32 dst1 := AST.cast CastKind.IntToFloat 32 tmp2) - !!ir (AST.xtlo 32 dst2 := AST.cast CastKind.IntToFloat 32 tmp3) - !!ir (AST.xthi 32 dst2 := AST.cast CastKind.IntToFloat 32 tmp4) + !!ir (AST.xtlo 32 dst1 := AST.cast CastKind.SIntToFloat 32 tmp1) + !!ir (AST.xthi 32 dst1 := AST.cast CastKind.SIntToFloat 32 tmp2) + !!ir (AST.xtlo 32 dst2 := AST.cast CastKind.SIntToFloat 32 tmp3) + !!ir (AST.xthi 32 dst2 := AST.cast CastKind.SIntToFloat 32 tmp4) !>ir insLen let cvtps2dq ins insLen ctxt rounded = - let ir = IRBuilder (16) + let ir = !*ctxt + ! let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - ! src1) !!ir (tmp2 := AST.xthi 32 src1) !!ir (tmp3 := AST.xtlo 32 src2) @@ -963,14 +959,14 @@ let cvtps2dq ins insLen ctxt rounded = !>ir insLen let cvtss2si ins insLen ctxt rounded = - let ir = IRBuilder (4) + let ir = !*ctxt + ! + let dst = transOprToExpr ir false ins insLen ctxt dst + let src = transOprToExpr32 ir false ins insLen ctxt src + let tmp = !+ir 32 let castKind = if rounded then CastKind.FtoIRound else CastKind.FtoITrunc - ! then !!ir (dst := AST.cast castKind 64 src) else @@ -979,32 +975,32 @@ let cvtss2si ins insLen ctxt rounded = !>ir insLen let cvtss2sd ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr64 ins insLen ctxt dst - let src = transOprToExpr32 ins insLen ctxt src + let ir = !*ctxt ! src) !>ir insLen let cvtsd2ss ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr64 ins insLen ctxt dst - let src = transOprToExpr64 ins insLen ctxt src + let ir = !*ctxt ! dst := AST.cast CastKind.FloatCast 32 src) !>ir insLen let cvtsd2si ins insLen ctxt rounded = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! if is64bit ctxt && oprSize = 64 then !!ir (dst := AST.cast castKind 64 src) else @@ -1012,17 +1008,40 @@ let cvtsd2si ins insLen ctxt rounded = !!ir (dstAssign 32 dst tmp) !>ir insLen +let extractps ins insLen ctxt = + let ir = !*ctxt + ! 2 128 src + let idx = getImmValue imm8 &&& 0b11L |> int + !!ir (dstAssign oprSize dst src[idx]) + !>ir insLen + +let hsubpd ins insLen ctxt = + packedHorizon ins insLen ctxt 64 (opP AST.fsub) + +let hsubps ins insLen ctxt = + packedHorizon ins insLen ctxt 32 (opP AST.fsub) + +let haddpd ins insLen ctxt = + packedHorizon ins insLen ctxt 64 (opP AST.fadd) + +let haddps ins insLen ctxt = + packedHorizon ins insLen ctxt 32 (opP AST.fadd) + let ldmxcsr ins insLen ctxt = - let ir = IRBuilder (4) - let src = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let stmxcsr ins insLen ctxt = - let ir = IRBuilder (4) - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen @@ -1033,121 +1052,168 @@ let private opAveragePackedInt (packSz: int) = AST.extract (dblExt e1 .+ dblExt e2 .+ AST.num1 dblSz) packSz 1 Array.map2 avg -let private opPavgb _ = opAveragePackedInt 8 +let opPavgb _ = opAveragePackedInt 8 let pavgb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPavgb 64 + buildPackedInstr ins insLen ctxt false 8 opPavgb -let private opPavgw _ = opAveragePackedInt 16 +let opPavgw _ = opAveragePackedInt 16 let pavgw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPavgw 32 + buildPackedInstr ins insLen ctxt false 16 opPavgw -let pextrw ins insLen ctxt = - let ir = IRBuilder (8) +let pextrb ins insLen ctxt = + let ir = !*ctxt + ! (* Left Shift *) + let rAmt = numI64 (count % 64L) 64 (* Right Shift *) + let result = + if count < 64 then ((srcB << lAmt) .| (srcA >> rAmt)) .& numU32 0xFFu 64 + else (srcB >> rAmt) .& numU32 0xFFu 64 + |> AST.xtlo 8 + match dst with + | OprReg _ -> !!ir (dstAssign 32 dExpr (AST.zext 32 result)) + | OprMem _ -> !!ir (dExpr := result) + | _ -> raise InvalidOperandException + !>ir insLen + +let pextrd ins insLen ctxt = + let ir = !*ctxt + ! + let srcB, srcA = getPseudoRegVar128 ctxt reg + let count = (count &&& 0b11) (* COUNT[1:0] *) * 32L + let lAmt = numI64 (64L - (count % 64L)) 64 (* Left Shift *) + let rAmt = numI64 (count % 64L) 64 (* Right Shift *) + let result = + if count < 64 then + ((srcB << lAmt) .| (srcA >> rAmt)) .& numU32 0xFFFFFFFFu 64 + else (srcB >> rAmt) .& numU32 0xFFFFFFFFu 64 + !!ir (dstAssign oprSize dst (AST.xtlo oprSize result)) + | _ -> raise InvalidOperandException + !>ir insLen + +let pextrq ins insLen ctxt = + let ir = !*ctxt ! - match Register.getKind reg with - | Register.Kind.MMX -> - let src = transOprToExpr ins insLen ctxt src - let count = count &&& 0b11 (* COUNT[1:0] *) - let sel = !*ir 64 - !!ir (sel := numI64 count 64) - let t = (src >> (sel .* numU32 16u 64)) .& numU32 0xFFFFu 64 - !!ir (dstAssign oprSize dst (AST.xtlo oprSize t)) - | Register.Kind.XMM -> - let srcB, srcA = getPseudoRegVar128 ctxt reg - let count = (count &&& 0b111) (* COUNT[2:0] *) * 16L - let lAmt = numI64 (64L - (count % 64L)) 64 (* Left Shift *) - let rAmt = numI64 (count % 64L) 64 (* Right Shift *) - let result = - if count < 64 then - ((srcB << lAmt) .| (srcA >> rAmt)) .& numU32 0xFFFFu 64 - else (srcB >> rAmt) .& numU32 0xFFFFu 64 - !!ir (dstAssign oprSize dst (AST.xtlo 16 result)) - | _ -> raise InvalidRegisterException + let srcB, srcA = getPseudoRegVar128 ctxt reg + let count = (count &&& 0b1) (* COUNT[0] *) * 64L + let lAmt = numI64 (64L - (count % 64L)) 64 (* Left Shift *) + let rAmt = numI64 (count % 64L) 64 (* Right Shift *) + let result = + if count < 64 then + ((srcB << lAmt) .| (srcA >> rAmt)) + else (srcB >> rAmt) + !!ir (dstAssign oprSize dst (AST.xtlo oprSize result)) | _ -> raise InvalidOperandException !>ir insLen +let pextrw ins insLen ctxt = + let ir = !*ctxt + let oprSize = getOperationSize ins + ! / 16 + let srcSz = + match src with + | OprReg reg -> Register.toRegType reg + | _ -> raise InvalidOperandException + let d = transOprToExpr ir false ins insLen ctxt dst + let src = transOprToArr ir false ins insLen ctxt 16 packNum srcSz src + let idx = getImmValue imm8 |> int + match dst with + | OprMem (_, _, _, 16) -> + let idx = idx &&& 0b111 + !!ir (d := src[idx]) + | _ -> + let idx = idx &&& (Array.length src - 1) + !!ir (dstAssign oprSize d src[idx]) + !>ir insLen + let pinsrw ins insLen ctxt = - let ir = IRBuilder (8) - let struct (dst, src, count) = getThreeOprs ins - let src = transOprToExpr ins insLen ctxt src - let sel = !*ir 64 + let ir = !*ctxt ! + let pNum = 64 / packSz + let struct (dst, src, imm8) = getThreeOprs ins + let src = transOprToExpr ir false ins insLen ctxt src |> AST.xtlo packSz match dst with | OprReg reg -> match Register.getKind reg with | Register.Kind.MMX -> - let dst = transOprToExpr ins insLen ctxt dst - let count = transOprToExpr ins insLen ctxt count - let mask = !*ir 64 - !!ir (sel := count .| numI64 3L 64) - let pos = sel .* numU64 0x10UL 64 - !!ir (mask := (numU64 0xffffUL 64) << pos) - !!ir - (dst := (dst .& (AST.not mask)) .| (AST.zext 64 src << pos .& mask)) + let index = getImmValue imm8 &&& 0b11 |> int + let dst = transOprToArr ir false ins insLen ctxt packSz pNum 64 dst + !!ir (dst[index] := src) | Register.Kind.XMM -> - let dst1, dst2 = transOprToExpr128 ins insLen ctxt dst - let mask = !*ir 64 - let count = getImmValue count - !!ir (sel := numI64 count 64 .| numI64 7L 64) - if count > 3L then - let pos = (sel .- numI32 4 64) .* numI32 16 64 - !!ir (mask := (numU64 0xffffUL 64) << pos) - !!ir (dst1 := (dst1 .& (AST.not mask)) - .| (AST.zext 64 src << pos .& mask)) - else - let pos = sel .* numI32 16 64 - !!ir (mask := (numU64 0xffffUL 64) << pos) - !!ir (dst2 := (dst2 .& (AST.not mask)) - .| (AST.zext 64 src << pos .& mask)) - | _ -> raise InvalidOperandSizeException - | _ -> raise InvalidOperandException + let index = getImmValue imm8 &&& 0b111 |> int + let dst = transOprToArr ir false ins insLen ctxt packSz pNum 128 dst + !!ir (dst[index] := src) + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandSizeException !>ir insLen let private opMaxMinPacked cmp = Array.map2 (fun e1 e2 -> AST.ite (cmp e1 e2) e1 e2) -let private opPmaxub _ = opMaxMinPacked AST.gt +let opPmaxu _ = opMaxMinPacked AST.gt -let pmaxub ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPmaxub 64 +let opPminu _ = opMaxMinPacked AST.lt -let private opPmaxsw _ = opMaxMinPacked AST.sgt +let opPmaxs _ = opMaxMinPacked AST.sgt -let pmaxsw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPmaxsw 32 +let opPmins _ = opMaxMinPacked AST.slt -let private opPmaxsb _ = opMaxMinPacked AST.sgt +let pmaxub ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 8 opPmaxu -let pmaxsb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPmaxsb 64 +let pmaxud ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 32 opPmaxu -let opPminub _ = opMaxMinPacked AST.lt +let pmaxuw ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 16 opPmaxu -let pminub ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPminub 64 +let pmaxsb ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 8 opPmaxs -let private opPminsw _ = opMaxMinPacked AST.slt +let pmaxsd ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 32 opPmaxs -let pminsw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPminsw 32 +let pmaxsw ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 16 opPmaxs -let opPminud _ = opMaxMinPacked AST.lt +let pminub ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 8 opPminu let pminud ins insLen ctxt = - buildPackedInstr ins insLen ctxt 32 opPminud 32 + buildPackedInstr ins insLen ctxt false 32 opPminu -let private opPminsb _ = opMaxMinPacked AST.slt +let pminuw ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 16 opPminu let pminsb ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPminsb 32 + buildPackedInstr ins insLen ctxt false 8 opPmins + +let pminsd ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 32 opPmins + +let pminsw ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 16 opPmins let private mskArrayInit cnt src = Array.init cnt (fun i -> AST.extract src 1 (i * 8 + 7)) @@ -1164,21 +1230,21 @@ let private concatBits (bitExprs: Expr[]) = |> fst let pmovmskb ins insLen ctxt = - let ir = IRBuilder (4) + let ir = !*ctxt + ! r | _ -> raise InvalidOperandException match Register.getKind r with | Register.Kind.MMX -> - let struct (dst, src) = transTwoOprs ins insLen ctxt + let struct (dst, src) = transTwoOprs ir false ins insLen ctxt let srcSize = TypeCheck.typeOf src let cnt = RegType.toByteWidth srcSize let tmps = mskArrayInit cnt src !!ir (dstAssign oprSize dst <| AST.zext oprSize (concatBits tmps)) | Register.Kind.XMM -> - let dst = transOprToExpr ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let dst = transOprToExpr ir false ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ir false ins insLen ctxt src let srcSize = TypeCheck.typeOf srcA let cnt = RegType.toByteWidth srcSize let tmpsA = mskArrayInit cnt srcA @@ -1186,8 +1252,8 @@ let pmovmskb ins insLen ctxt = let tmps = AST.concat (concatBits tmpsB) (concatBits tmpsA) !!ir (dstAssign oprSize dst <| AST.zext oprSize tmps) | Register.Kind.YMM -> - let dst = transOprToExpr ins insLen ctxt dst - let srcD, srcC, srcB, srcA = transOprToExpr256 ins insLen ctxt src + let dst = transOprToExpr ir false ins insLen ctxt dst + let srcD, srcC, srcB, srcA = transOprToExpr256 ir false ins insLen ctxt src let srcSize = TypeCheck.typeOf srcA let cnt = RegType.toByteWidth srcSize let tmpsA = mskArrayInit cnt srcA @@ -1201,25 +1267,116 @@ let pmovmskb ins insLen ctxt = | _ -> raise InvalidOperandException !>ir insLen +let packedMove ir srcSz packSz dstA dstB src isSignExt = + let packNum = int (srcSz / packSz) + let dSz = 128 / packNum + let tDst = Array.init packNum (fun _ -> !+ir dSz) + if isSignExt then + for i in 0 .. packNum - 1 do + !!ir (tDst[i] := AST.sext dSz (AST.extract src packSz (i * (int packSz)))) + else + for i in 0 .. packNum - 1 do + !!ir (tDst[i] := AST.zext dSz (AST.extract src packSz (i * (int packSz)))) + let tDstA, tDstB = tDst |> Array.splitAt (packNum / 2) + !!ir (dstA := tDstA |> AST.concatArr) + !!ir (dstB := tDstB |> AST.concatArr) + +let pmovbw ins insLen ctxt packSz isSignExt = + let ir = !*ctxt + ! + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + packedMove ir 64 packSz dstA dstB srcA isSignExt + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr64 ir false ins insLen ctxt src + packedMove ir 64 packSz dstA dstB src isSignExt + | _ -> raise InvalidOperandException + !>ir insLen + +let pmovbd ins insLen ctxt packSz isSignExt = + let ir = !*ctxt + ! + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + packedMove ir 32 packSz dstA dstB (AST.xtlo 32 srcA) isSignExt + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr32 ir false ins insLen ctxt src + packedMove ir 32 packSz dstA dstB src isSignExt + | _ -> raise InvalidOperandException + !>ir insLen + +let pmovbq ins insLen ctxt packSz isSignExt = + let ir = !*ctxt + ! + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let _, srcA = transOprToExpr128 ir false ins insLen ctxt src + packedMove ir 16 packSz dstA dstB (AST.xtlo 16 srcA) isSignExt + | OprMem _ -> + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let src = transOprToExpr16 ir false ins insLen ctxt src + packedMove ir 16 packSz dstA dstB src isSignExt + | _ -> raise InvalidOperandException + !>ir insLen + let private opPmulhuw _ = opPmul AST.xthi AST.zext 32 16 let pmulhuw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 16 opPmulhuw 32 + buildPackedInstr ins insLen ctxt false 16 opPmulhuw + +let private opPmulld _ = opPmul AST.xtlo AST.sext 32 32 + +let pmulld ins insLen ctxt = + buildPackedInstr ins insLen ctxt false 32 opPmulld -let private opPsadbw _ = - let abs expr = AST.ite (AST.lt expr (AST.num0 8)) (AST.neg expr) (expr) - Array.map2 (fun e1 e2 -> abs (e1 .- e2)) +let private opPsadbw oprSize e1 e2 = + let abs e1 e2 = AST.ite (AST.lt e1 e2) (e2 .- e1) (e1 .- e2) + let temp = Array.map2 abs e1 e2 + let n0 = AST.num0 16 + let inline sum e1 e2 = AST.zext 16 e1 .+ AST.zext 16 e2 + let zeros = Array.init 3 (fun _ -> n0) + match oprSize with + | 64 -> + let res = Array.reduce sum (Array.sub temp 0 8) + Array.append [| res |] zeros + | 128 -> + let res1 = Array.reduce sum (Array.sub temp 0 8) + let res2 = Array.reduce sum (Array.sub temp 8 8) + Array.concat [| [| res1 |]; zeros; [| res2 |]; zeros |] + | _ -> raise InvalidOperandSizeException let psadbw ins insLen ctxt = - buildPackedInstr ins insLen ctxt 8 opPsadbw 64 + let ir = !*ctxt + ! (* SRC Pack size *) + let sPackNum = 64 / sPackSz + let dPackSz = 16 (* DST Pack size *) + let dPackNum = 64 / dPackSz + let struct (dst, src) = getTwoOprs ins + let src1 = transOprToArr ir true ins insLen ctxt sPackSz sPackNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt sPackSz sPackNum oprSize src + let result = opPsadbw oprSize src1 src2 + assignPackedInstr ir false ins insLen ctxt dPackNum oprSize dst result + !>ir insLen let pshufw ins insLen ctxt = - let struct (dst, src, ord) = transThreeOprs ins insLen ctxt + let ir = !*ctxt + ! !*ir 16) + let tmps = Array.init cnt (fun _ -> !+ir 16) let n16 = numI32 16 oprSize let mask2 = numI32 3 16 (* 2-bit mask *) for i in 1 .. cnt do @@ -1232,13 +1389,14 @@ let pshufw ins insLen ctxt = !>ir insLen let pshufd ins insLen ctxt = + let ir = !*ctxt + ! let leftAmt = numI64 (64L - (amount % 64L)) 64 @@ -1248,7 +1406,6 @@ let pshufd ins insLen ctxt = else AST.num0 32 let amount idx = ((ord >>> (idx * 2)) &&& 0b11L) * 32L let struct (tSrcB, tSrcA) = tmpVars2 ir 64 - !ir insLen let pshuflw ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! !*ir 16) + let tmps = Array.init 4 (fun _ -> !+ir 16) let n16 = numI32 16 64 let mask2 = numI32 3 64 (* 2-bit mask *) for i in 1 .. 4 do @@ -1276,13 +1433,13 @@ let pshuflw ins insLen ctxt = !>ir insLen let pshufhw ins insLen ctxt = + let ir = !*ctxt + ! - let ir = IRBuilder (8) - ! !*ir 16) + let tmps = Array.init 4 (fun _ -> !+ir 16) let n16 = numI32 16 64 let mask2 = numI32 3 64 (* 2-bit mask *) for i in 1 .. 4 do @@ -1295,70 +1452,64 @@ let pshufhw ins insLen ctxt = !>ir insLen let pshufb ins insLen ctxt = - let oprSize = getOperationSize ins - let cnt = RegType.toBitWidth oprSize / 8 - let ir = IRBuilder (2 * cnt) + let ir = !*ctxt ! - let n0 = AST.num0 8 + let oprSize = getOperationSize ins + let packSize = 8 + let packNum = 64 / packSize + let allPackNum = oprSize / packSize + let struct (dst, src) = getTwoOprs ins + let src = transOprToArr ir false ins insLen ctxt packSize packNum oprSize src + let struct (mask, n0) = tmpVars2 ir packSize + !!ir (mask := numI32 (int allPackNum - 1) packSize) + !!ir (n0 := AST.num0 packSize) match oprSize with | 64 -> - let struct (dst, src) = transTwoOprs ins insLen ctxt - let tmps = Array.init cnt (fun _ -> !*ir 8) - for i in 0 .. cnt - 1 do - let cond = AST.extract src 1 (i * 8 + 7) - let idx = (AST.extract src 8 (i * 8)) .& mask - let numShift = AST.zext oprSize idx .* numI32 8 oprSize - !!ir - (tmps[i] := - AST.ite cond n0 (AST.xtlo 8 (dst >> numShift))) - done - !!ir (dst := AST.concatArr tmps) + let dst = transOprToExpr ir false ins insLen ctxt dst + let n8 = numI32 8 oprSize + let shuffle src = + let idx = src .& mask + let numShift = AST.zext oprSize idx .* n8 + AST.ite (AST.xthi 1 src) n0 (AST.xtlo packSize (dst >> numShift)) + !!ir (dst := Array.map shuffle src |> AST.concatArr) | 128 -> - let struct (dst, src) = getTwoOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src - let highTmps = Array.init (cnt / 2) (fun _ -> !*ir 8) - let lowTmps = Array.init (cnt / 2) (fun _ -> !*ir 8) - let struct (tDst, tSrc) = tmpVars2 ir 64 - for i in 0 .. cnt - 1 do - !!ir (tSrc := if i < 8 then srcA else srcB) - let cond = AST.extract tSrc 1 (((i * 8) % 64) + 7) - let idx = (AST.extract tSrc 8 ((i * 8) % 64)) .& mask - let numShift = - ((AST.zext 64 idx) .* (numI32 8 64)) .% (numI32 64 64) - !!ir (tDst := AST.ite (idx .< numI32 8 8) dstA dstB) - let temp = AST.xtlo 8 (tDst >> numShift) - if i < 8 then !!ir (lowTmps[i] := AST.ite cond n0 temp) - else !!ir (highTmps[i - 8] := AST.ite cond n0 temp) - done - !!ir (dstA := AST.concatArr lowTmps) - !!ir (dstB := AST.concatArr highTmps) + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let n8 = !+ir 64 + !!ir (n8 := numI32 8 64) + let shuffle src = + let idx = src .& mask + let numShift = ((AST.zext 64 idx) .% n8) .* n8 + let tDst = !+ir 64 + !!ir (tDst := AST.ite (idx .< numI32 8 packSize) dstA dstB) + AST.ite (AST.xthi 1 src) n0 (AST.xtlo packSize (tDst >> numShift)) + let result = Array.map shuffle src + !!ir (dstA := Array.sub result 0 packNum |> AST.concatArr) + !!ir (dstB := Array.sub result packNum packNum |> AST.concatArr) | _ -> raise InvalidOperandSizeException !>ir insLen let movdqa ins insLen ctxt = - buildMove ins insLen ctxt 4 + buildMove ins insLen ctxt let movdqu ins insLen ctxt = - buildMove ins insLen ctxt 4 + buildMove ins insLen ctxt let movq2dq ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let src = transOprToExpr ins insLen ctxt src + let ir = !*ctxt !) !>ir insLen let movdq2q ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst = transOprToExpr ins insLen ctxt dst - let _, srcA = transOprToExpr128 ins insLen ctxt src + let ir = !*ctxt !ir insLen @@ -1367,24 +1518,24 @@ let private opPmuludq _ = Array.map2 (fun e1 e2 -> low32 e1 .* low32 e2) let pmuludq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPmuludq 8 + buildPackedInstr ins insLen ctxt false 64 opPmuludq let paddq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 (opP (.+)) 8 + buildPackedInstr ins insLen ctxt false 64 (opP (.+)) let psubq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPsub 8 + buildPackedInstr ins insLen ctxt false 64 (opP (.-)) let pslldq ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! 15L then 16L * 8L else cnt * 8L let rightAmt = numI64 (64L - (amount % 64L)) 64 let leftAmt = numI64 (amount % 64L) 64 let struct (tDstB, tDstA) = tmpVars2 ir 64 - !ir insLen let psrldq ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! 15L then 16L * 8L else cnt * 8L let rightAmt = numI64 (amount % 64L) 64 let leftAmt = numI64 (64L - (amount % 64L)) 64 let struct (tDstB, tDstA) = tmpVars2 ir 64 - !ir insLen let punpckhqdq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPunpckHigh 8 + buildPackedInstr ins insLen ctxt false 64 opUnpackHighData let punpcklqdq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPunpckLow 8 + buildPackedInstr ins insLen ctxt false 64 opUnpackLowData -let movntq ins insLen ctxt = buildMove ins insLen ctxt 4 +let movntq ins insLen ctxt = buildMove ins insLen ctxt -let movntps ins insLen ctxt = buildMove ins insLen ctxt 4 +let movntps ins insLen ctxt = buildMove ins insLen ctxt -let movntpd ins insLen ctxt = buildMove ins insLen ctxt 4 +let movntpd ins insLen ctxt = buildMove ins insLen ctxt -let movntdq ins insLen ctxt = buildMove ins insLen ctxt 4 +let movntdq ins insLen ctxt = buildMove ins insLen ctxt -let movnti ins insLen ctxt = buildMove ins insLen ctxt 4 +let movnti ins insLen ctxt = buildMove ins insLen ctxt -let lddqu ins insLen ctxt = buildMove ins insLen ctxt 4 +let lddqu ins insLen ctxt = buildMove ins insLen ctxt let movshdup ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! src1) !!ir (tmp2 := AST.xthi 32 src2) !!ir (AST.xtlo 32 dst1 := tmp1) @@ -1455,12 +1606,12 @@ let movshdup ins insLen ctxt = !>ir insLen let movsldup ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - ! src1) !!ir (tmp2 := AST.xtlo 32 src2) !!ir (AST.xtlo 32 dst1 := tmp1) @@ -1470,27 +1621,52 @@ let movsldup ins insLen ctxt = !>ir insLen let movddup ins insLen ctxt = - let ir = IRBuilder (4) - let struct (dst, src) = getTwoOprs ins - let dst1, dst0 = transOprToExpr128 ins insLen ctxt dst - let src = transOprToExpr64 ins insLen ctxt src + let ir = !*ctxt !ir insLen +let packWithSaturation ir packSz src = + let z16 = AST.num0 (packSz / 2) + let z32 = AST.num0 packSz + let f16 = numU32 0xFFFFu (packSz / 2) + let f32 = numU32 0xFFFFu packSz + let tSrc = !+ir packSz + let tmp = !+ir (packSz / 2) + !!ir (tSrc := src) + !!ir (tmp := AST.ite (tSrc ?< z32) z16 (AST.xtlo (packSz / 2) tSrc)) + !!ir (tmp := AST.ite (tSrc ?> f32) f16 tmp) + tmp + +let packusdw ins insLen ctxt = + let ir = !*ctxt + ! / 32 + let struct (dst, src) = getTwoOprs ins + let src1 = transOprToArr ir true ins insLen ctxt 32 packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt 32 packNum oprSize src + let src = Array.append src1 src2 + let result = Array.map (packWithSaturation ir 32) src + assignPackedInstr ir false ins insLen ctxt (packNum * 2) oprSize dst result + !>ir insLen + let palignr ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! let leftAmt = numI64 (64L - (amount % 64L)) 64 - ! -> - let dst = transOprToExpr ins insLen ctxt dst - let src = transOprToExpr ins insLen ctxt src + let dst = transOprToExpr ir false ins insLen ctxt dst + let src = transOprToExpr ir false ins insLen ctxt src let struct (tDst, tSrc) = tmpVars2 ir 64 !!ir (tDst := dst) !!ir (tSrc := src) @@ -1498,8 +1674,8 @@ let palignr ins insLen ctxt = elif amount < 128 then !!ir (dst := tDst >> rightAmt) else !!ir (dst := AST.num0 64) | 128 -> - let dstB, dstA = transOprToExpr128 ins insLen ctxt dst - let srcB, srcA = transOprToExpr128 ins insLen ctxt src + let dstB, dstA = transOprToExpr128 ir false ins insLen ctxt dst + let srcB, srcA = transOprToExpr128 ir false ins insLen ctxt src let struct (tDstB, tDstA, tSrcB, tSrcA) = tmpVars4 ir 64 !!ir (tDstA := dstA) !!ir (tDstB := dstB) @@ -1524,46 +1700,68 @@ let palignr ins insLen ctxt = !>ir insLen let roundsd ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! 10 - let tmp = !*ir 2 + let dst = transOprToExpr64 ir false ins insLen ctxt dst + let src = transOprToExpr64 ir false ins insLen ctxt src + let imm = transOprToExpr ir false ins insLen ctxt imm + let rc = (AST.extract (!.ctxt R.MXCSR) 8 13) .& (numI32 0b11 8) + let tmp = !+ir 8 let cster castKind = AST.cast castKind 64 src - ! 2) rc (AST.xtlo 2 imm)) - !!ir (dst := AST.num0 64) - !!ir (dst := AST.ite (tmp == AST.num0 2) (cster CastKind.FtoIRound) dst) - !!ir (dst := AST.ite (tmp == AST.num1 2) (cster CastKind.FtoIFloor) dst) - !!ir (dst := AST.ite (tmp == numI32 2 2) (cster CastKind.FtoICeil) dst) - !!ir (dst := AST.ite (tmp == numI32 3 2) (cster CastKind.FtoITrunc) dst) + let imm2 = (AST.xtlo 8 imm) .& (numI32 0b11 8) + !!ir (tmp := AST.ite (AST.extract imm 1 2) rc imm2) + !!ir (dst := AST.ite (tmp == AST.num0 8) (cster CastKind.FtoFRound) dst) + !!ir (dst := AST.ite (tmp == AST.num1 8) (cster CastKind.FtoFFloor) dst) + !!ir (dst := AST.ite (tmp == numI32 2 8) (cster CastKind.FtoFCeil) dst) + !!ir (dst := AST.ite (tmp == numI32 3 8) (cster CastKind.FtoFTrunc) dst) !>ir insLen let pinsrb ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + ! let amount = sel * 8L - let t = !*ir 64 + let t = !+ir 64 let expAmt = numI64 (amount % 64L) 64 - ! (AST.xtlo 8 src)) << expAmt) .& mask) - if amount < 64 then !!ir (dstA := (dstA .& (AST.not mask)) .& t) - else !!ir (dstB := (dstB .& (AST.not mask)) .& t) + if amount < 64 then !!ir (dstA := (dstA .& (AST.not mask)) .| t) + else !!ir (dstB := (dstB .& (AST.not mask)) .| t) + !>ir insLen + +let private packedSign ir packSz control inputVal = + let n0 = AST.num0 packSz + let struct (tControl, tInputVal) = tmpVars2 ir packSz + let struct (cond1, cond2) = tmpVars2 ir 1 + !!ir (tControl := control) + !!ir (tInputVal := inputVal) + !!ir (cond1 := tControl ?< n0) + !!ir (cond2 := tControl == n0) + AST.ite cond1 (AST.neg tInputVal) (AST.ite cond2 n0 tInputVal) + +let psign ins insLen ctxt packSz = + let ir = !*ctxt + ! / packSz + let struct (dst, src) = getTwoOprs ins + let srcDst = transOprToArr ir true ins insLen ctxt packSz packNum oprSize dst + let src = transOprToArr ir true ins insLen ctxt packSz packNum oprSize src + let result = Array.map2 (packedSign ir packSz) src srcDst + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result !>ir insLen let ptest ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt + ! - !)) @@ -1574,12 +1772,100 @@ let ptest ins insLen ctxt = !!ir (!.ctxt R.OF := AST.b0) !!ir (!.ctxt R.PF := AST.b0) !!ir (!.ctxt R.SF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen let opPcmpeqq _ = opPcmp 64 (==) let pcmpeqq ins insLen ctxt = - buildPackedInstr ins insLen ctxt 64 opPcmpeqq 8 + buildPackedInstr ins insLen ctxt false 64 opPcmpeqq + +let packedBlend src1 src2 imm = + Array.mapi2 (fun i e1 e2 -> + AST.ite (AST.extract imm 1 (i % 8)) e1 e2) src1 src2 + +let packedVblend src1 src2 (mask: Expr []) = + Array.mapi2 (fun i e1 e2 -> AST.ite (AST.xthi 1 mask[i]) e1 e2) src1 src2 + +let blendpd ins insLen ctxt = + let ir = !*ctxt + ! 0 + let cond2 = AST.extract imm 1 1 + !!ir (dstA := AST.ite cond1 srcA dstA) + !!ir (dstB := AST.ite cond2 srcB dstB) + !>ir insLen + +let blendps ins insLen ctxt = + let ir = !*ctxt + ! / 32 + let struct (dst, src, imm) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt 32 packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt 32 packNum oprSize src + let imm = transOprToExpr ir false ins insLen ctxt imm + let result = packedBlend src2 src1 imm + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + !>ir insLen + +let blendvpd ins insLen ctxt = + let ir = !*ctxt + ! xmm0A + let cond2 = AST.xthi 1 xmm0B + !!ir (dstA := AST.ite cond1 srcA dstA) + !!ir (dstB := AST.ite cond2 srcB dstB) + !>ir insLen + +let blendvps ins insLen ctxt = + let ir = !*ctxt + ! / 32 + let struct (dst, src, xmm0) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt 32 packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt 32 packNum oprSize src + let xmm0 = transOprToArr ir false ins insLen ctxt 32 packNum oprSize xmm0 + let result = packedVblend src2 src1 xmm0 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + !>ir insLen + +let pblendvb ins insLen ctxt = + let ir = !*ctxt + ! / 8 + let struct (dst, src, xmm0) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt 8 packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt 8 packNum oprSize src + let xmm0 = transOprToArr ir false ins insLen ctxt 8 packNum oprSize xmm0 + let result = packedVblend src2 src1 xmm0 + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + !>ir insLen + +let pblendw ins insLen ctxt = + let ir = !*ctxt + ! / 16 + let struct (dst, src, imm) = getThreeOprs ins + let src1 = transOprToArr ir true ins insLen ctxt 16 packNum oprSize dst + let src2 = transOprToArr ir true ins insLen ctxt 16 packNum oprSize src + let imm = transOprToExpr ir false ins insLen ctxt imm + let result = packedBlend src2 src1 imm + assignPackedInstr ir false ins insLen ctxt packNum oprSize dst result + !>ir insLen /// XXX (cleanup required) /// imm8 control byte operation for PCMPESTRI, PCMPESTRM, etc.. @@ -1625,7 +1911,7 @@ and Return = let private getPcmpstrInfo opCode (imm: Expr) = let immByte = match imm.E with - | Num n -> BitVector.getValue n + | Num n -> BitVector.GetValue n | _ -> raise InvalidExprException let agg = match (immByte >>> 2) &&& 3I with | v when v = 0I -> EqualAny @@ -1639,8 +1925,7 @@ let private getPcmpstrInfo opCode (imm: Expr) = | v when v = 2I -> PosMasked | v when v = 3I -> NegMasked | _ -> Utils.impossible () - let size, nElem = - if immByte &&& 1I = 0I then 8, 16u else 16, 8u + let size, nElem = if immByte &&& 1I = 0I then 8, 16u else 16, 8u let len, ret = match opCode with | Opcode.PCMPISTRI | Opcode.VPCMPISTRI -> Implicit, Index @@ -1657,217 +1942,215 @@ let private getPcmpstrInfo opCode (imm: Expr) = Len = len Ret = ret } -let private explicitValidCheck ctrl reg rSz ir = - let tmps = [| for _ in 1u .. ctrl.NumElems -> !*ir 1 |] - let checkNum = numU32 ctrl.NumElems rSz - let rec getValue idx = - let v = AST.lt (numU32 idx rSz) (AST.ite (AST.lt checkNum reg) checkNum reg) - if idx = ctrl.NumElems then () - else !!ir (tmps[int idx] := v) - getValue (idx + 1u) - getValue 0u - tmps - -let private implicitValidCheck ctrl srcB srcA ir = - let unitWidth = RegType.toBitWidth ctrl.PackSize - let tmps = [| for _ in 1u .. ctrl.NumElems -> !*ir 1 |] - let getSrc idx e = AST.extract e ctrl.PackSize (unitWidth * idx) - let rec getValue idx = - if idx = int ctrl.NumElems then () - else - let half = int ctrl.NumElems / 2 - let e, amount = if idx < half then srcA, idx else srcB, idx - half - let v e = tmps[idx - 1] .& (getSrc amount e != AST.num0 ctrl.PackSize) - !!ir (tmps[idx] := v e) - getValue (idx + 1) - !!ir (tmps[0] := AST.b1 .& (getSrc 0 srcA != AST.num0 ctrl.PackSize)) - getValue 1 - tmps - -let private genValidCheck ins insLen ctxt ctrl e1 e2 ir = - let src1B, src1A = transOprToExpr128 ins insLen ctxt e1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt e2 +let private setZFSFOfPCMPSTR ctxt ir ctrl src1 src2 = + let inline checkIfElemIsNull exps = + Array.map (fun e -> (e == AST.num0 ctrl.PackSize)) exps |> Array.reduce (.|) + let inline checkIndexOutOfBounds reg = + let abs = !+ir 32 + let reg = !.ctxt reg + !!ir (abs := AST.ite (AST.xthi 1 reg) (AST.neg reg) reg) + abs .< numU32 ctrl.NumElems 32 match ctrl.Len with - | Implicit -> implicitValidCheck ctrl src1B src1A ir, - implicitValidCheck ctrl src2B src2A ir + | Implicit -> + !!ir (!.ctxt R.ZF := checkIfElemIsNull src2) + !!ir (!.ctxt R.SF := checkIfElemIsNull src1) | Explicit -> - let regSize, ax, dx = - if hasREXW ins.REXPrefix - then 64, !.ctxt R.RAX, !.ctxt R.RDX - else 32, !.ctxt R.EAX, !.ctxt R.EDX - explicitValidCheck ctrl ax regSize ir, - explicitValidCheck ctrl dx regSize ir - -let private genBoolRes ins insLen ctrl ctxt e1 e2 (ck1: Expr []) (ck2: Expr []) - j i cmp = - let src1B, src1A = transOprToExpr128 ins insLen ctxt e1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt e2 - let elemSz = RegType.fromBitWidth <| int ctrl.NumElems - let getSrc s idx = - let unitWidth = RegType.toBitWidth ctrl.PackSize - let amount = unitWidth * idx - let amount = if amount < 64 then amount else amount - 64 - AST.extract s ctrl.PackSize amount - let b = - let e1 = if j < int ctrl.NumElems / 2 then src1A else src1B - let e2 = if i < int ctrl.NumElems / 2 then src2A else src2B - (AST.ite (cmp (getSrc e1 j) (getSrc e2 i)) (AST.num1 elemSz) - (AST.num0 elemSz)) + !!ir (!.ctxt R.ZF := checkIndexOutOfBounds R.EDX) + !!ir (!.ctxt R.SF := checkIndexOutOfBounds R.EAX) + +let private combineBits outSz bitArr = + Array.mapi (fun i b -> AST.zext outSz b << (numI32 i outSz)) bitArr + |> Array.reduce (.|) + +/// Least significant index. +let private leastSign ir expr sz max = + let lblCont = !%ir "Cont" + let lblLoop = !%ir "Loop" + let lblEnd = !%ir "End" + let cond = !+ir 1 + let cnt = !+ir sz + !!ir (cnt := AST.num0 sz) + !!ir (AST.lmark lblLoop) + let max = numI32 max sz + let bit = (AST.xtlo 1 (expr >> cnt)) .& AST.b1 + !!ir (cond := (bit == AST.b0) .& (cnt .< max)) + !!ir (AST.cjmp cond (AST.name lblCont) (AST.name lblEnd)) + !!ir (AST.lmark lblCont) + !!ir (cnt := cnt .+ (AST.num1 sz)) + !!ir (AST.jmp (AST.name lblLoop)) + !!ir (AST.lmark lblEnd) + cnt + +/// Most significant index. +let private mostSign ir expr sz max = + let lblCont = !%ir "Cont" + let lblLoop = !%ir "Loop" + let lblEnd = !%ir "End" + let cond = !+ir 1 + let idx = !+ir sz + !!ir (idx := numI32 (max - 1) sz) + !!ir (AST.lmark lblLoop) + let n0 = AST.num0 sz + let bit = (AST.xtlo 1 (expr >> idx)) .& AST.b1 + !!ir (cond := (bit == AST.b0) .& (idx .> n0)) + !!ir (AST.cjmp cond (AST.name lblCont) (AST.name lblEnd)) + !!ir (AST.lmark lblCont) + !!ir (idx := idx .- (AST.num1 sz)) + !!ir (AST.jmp (AST.name lblLoop)) + !!ir (AST.lmark lblEnd) + idx + +/// override comparisons for invalid characters. +let private overrideIfDataInvalid ir ctrl aInval bInval boolRes = match ctrl.Agg with | EqualAny | Ranges -> - AST.ite (AST.not ck1[j] .& AST.not ck2[i]) (AST.num0 elemSz) - (AST.ite (AST.not ck1[j] .| AST.not ck2[i]) (AST.num0 elemSz) b) + let cond = (AST.not aInval .& bInval) .| (aInval .& AST.not bInval) .| + (aInval .& bInval) + !!ir (boolRes := AST.ite cond AST.b0 boolRes) | EqualEach -> - AST.ite (AST.not ck1[i] .& AST.not ck2[i]) (AST.num1 elemSz) - (AST.ite (AST.not ck1[i] .| AST.not ck2[i]) (AST.num0 elemSz) b) + let cond1 = (AST.not aInval .& bInval) .| (aInval .& AST.not bInval) + let cond2 = aInval .& bInval + !!ir (boolRes := AST.ite cond1 AST.b0 (AST.ite cond2 AST.b1 boolRes)) | EqualOrdered -> - AST.ite (AST.not ck1[j] .& AST.not ck2[i]) (AST.num1 elemSz) - (AST.ite (AST.not ck1[j] .& ck2[i]) (AST.num1 elemSz) - (AST.ite (ck1[j] .& AST.not ck2[i]) (AST.num0 elemSz) b)) + let cond1 = AST.not aInval .& bInval + let cond2 = (aInval .& AST.not bInval) .| (aInval .& bInval) + !!ir (boolRes := AST.ite cond1 AST.b0 (AST.ite cond2 AST.b1 boolRes)) -let private aggOpr ins insLen - ctxt ctrl src1 src2 ck1 ck2 (res1 : Expr []) ir = +let pcmpstr ins insLen ctxt = + let ir = !*ctxt + ! AST.sge - | Signed, _ -> AST.sle - | _, true -> AST.ge - | _, _ -> AST.le + let elemSz = RegType.fromBitWidth nElem + let upperBound = nElem - 1 + let pNum = 64 / packSize + let src1 = transOprToArr ir true ins insLen ctxt packSize pNum oprSz s1 + let src2 = transOprToArr ir true ins insLen ctxt packSize pNum oprSz s2 + let boolRes = Array2D.init nElem nElem (fun _ _ -> !+ir 1) + let n0 = AST.num0 packSize + let regSize, ax, dx = + if hasREXW ins.REXPrefix then 64, !.ctxt R.RAX, !.ctxt R.RDX + else 32, !.ctxt R.EAX, !.ctxt R.EDX + + let struct (aInval, bInval) = tmpVars2 ir 1 + !!ir (aInval := AST.b0) + let (.<=), (.>=) = + if ctrl.Sign = Signed then AST.sle, AST.sge else AST.le, AST.ge + for i in 0 .. upperBound do + !!ir (bInval := AST.b0) + /// invalidate characters after EOS. + match ctrl.Len with + | Implicit -> !!ir (aInval := aInval .| (src1[i] == n0)) + | Explicit -> !!ir (aInval := aInval .| (numI32 i regSize == ax)) + for j in 0 .. upperBound do + /// compare all characters. + if ctrl.Agg = Ranges then + if i % 2 = 0 then !!ir (boolRes[i, j] := src1[i] .<= src2[j]) + else !!ir (boolRes[i, j] := src1[i] .>= src2[j]) + else !!ir (boolRes[i, j] := src1[i] == src2[j]) + + /// invalidate characters after EOS. + match ctrl.Len with + | Implicit -> !!ir (bInval := bInval .| (src2[j] == n0)) + | Explicit -> !!ir (bInval := bInval .| (numI32 j regSize == dx)) + overrideIfDataInvalid ir ctrl aInval bInval boolRes[i, j] + done + done + + let inline initIntRes initVal = Array.iter (fun r -> !!ir (r := initVal)) + let intRes1 = Array.init nElem (fun _ -> !+ir 1) + let intRes2 = Array.init nElem (fun _ -> !+ir 1) + + /// aggregate results. match ctrl.Agg with | EqualAny -> - for j in 0 .. nElem - 1 do - let tRes = [| for _ in 1 .. nElem -> !*ir elemSz |] - let boolRes i = boolRes j i (==) - !!ir (tRes[0] := AST.num0 elemSz .| boolRes 0) - for i in 1 .. nElem - 1 do - !!ir (tRes[i] := tRes[i - 1] .| boolRes i) + initIntRes AST.b0 intRes1 + for i in 0 .. upperBound do + for j in 0 .. upperBound do + !!ir (intRes1[i] := intRes1[i] .| boolRes[j, i]) + done + done + | Ranges -> + initIntRes AST.b0 intRes1 + for i in 0 .. upperBound do + for j in 0 .. 2 .. upperBound do + !!ir (intRes1[i] := intRes1[i] .| (boolRes[j, i] .& boolRes[j + 1, i])) done - !!ir (res1[j] := tRes[nElem - 1] << numI32 j elemSz) done | EqualEach -> - for i in 0 .. nElem - 1 do - let boolRes i = boolRes i i (==) - !!ir (res1[i] := boolRes i << numI32 i elemSz) + initIntRes AST.b0 intRes1 + for i in 0 .. upperBound do + !!ir (intRes1[i] := boolRes[i, i]) done | EqualOrdered -> - for j in 0 .. nElem - 1 do - let tRes = [| for _ in 1 .. nElem -> !*ir elemSz |] - let boolRes k i = boolRes k i (==) - !!ir (tRes[0] := numI32 -1 elemSz .& boolRes j 0) - for i in 1 .. nElem - 1 - j do - let k = i + j - !!ir (tRes[i] := tRes[i - 1] .& boolRes k i) - done - !!ir (res1[j] := tRes[nElem - 1] << numI32 j elemSz) - done - | Ranges -> - for j in 0 .. nElem - 1 do - let tRes = [| for _ in 1 .. nElem -> !*ir elemSz |] - let cmp i = rangesCmp i - let boolRes i = boolRes j i (cmp i) - !!ir (tRes[0] := AST.num0 elemSz .| (boolRes 0 .& boolRes 1)) - for i in 2 .. 2 .. nElem - 1 do - !!ir - (tRes[i] := tRes[i - 1] .| (boolRes i .& boolRes (i + 1))) + initIntRes AST.b1 intRes1 + let mutable k = 0 + for i in 0 .. upperBound do + k <- i + for j in 0 .. upperBound - i do + !!ir (intRes1[i] := intRes1[i] .& boolRes[j, k]) + k <- k + 1 done - !!ir (res1[j] := tRes[nElem - 1] << numI32 j elemSz) done -let private getIntRes2 e ctrInfo (booRes: Expr []) = - let elemSz = RegType.fromBitWidth <| int ctrInfo.NumElems - let elemCnt = ctrInfo.NumElems |> int - match ctrInfo.Polarity with - | PosPolarity | PosMasked -> e - | NegPolarity -> numI32 -1 elemSz <+> e - | NegMasked -> - List.fold (fun acc i -> - let e1 = e .& numI32 (pown 2 i) elemSz - let e2 = (AST.not e) .& numI32 (pown 2 i) elemSz - (AST.ite (booRes[i]) e2 e1) :: acc) [] [0 .. elemCnt - 1] - |> List.reduce (.|) - -let rec private genOutput ctrl e acc i = - let elemSz = RegType.fromBitWidth <| int ctrl.NumElems - let isSmallOut = ctrl.OutSelect = Least - let e' = e >> numI32 i elemSz - let next = if isSmallOut then i - 1 else i + 1 - let cond = if isSmallOut then i = 0 else i = int ctrl.NumElems - 1 - if cond then AST.ite (AST.xtlo 1 e') (numI32 i elemSz) acc - else genOutput ctrl e (AST.ite (AST.xtlo 1 e') (numI32 i elemSz) acc) next - -let private pcmpStrRet (ins: InsInfo) info ctxt intRes2 ir = - let nElem = int info.NumElems - let elemSz = RegType.fromBitWidth <| nElem - match info.Ret with + /// optionally negate results. + initIntRes AST.b0 intRes2 + for i in 0 .. upperBound do + match ctrl.Polarity with + | PosPolarity | PosMasked -> !!ir (intRes2[i] := intRes1[i]) + | NegPolarity (* 0b01 *) -> !!ir (intRes2[i] := AST.not intRes1[i]) + | NegMasked (* 0b11 *) -> + match ctrl.Len with + | Implicit -> + !!ir (bInval := src2[i] == n0) + !!ir (intRes2[i] := AST.ite bInval intRes1[i] (AST.not intRes1[i])) + | Explicit -> + let not = AST.not intRes1[i] + !!ir (intRes2[i] := AST.ite (numI32 i regSize .>= dx) intRes1[i] not) + done + + /// output. + let iRes2 = !+ir elemSz + !!ir (iRes2 := combineBits elemSz intRes2) + match ctrl.Ret with + | Mask -> + let dstB, dstA = getPseudoRegVar128 ctxt R.XMM0 + match ctrl.OutSelect with + | Least (* Bit mask *) -> + let res = !+ir elemSz + !!ir (res := combineBits elemSz intRes2) + !!ir (dstA := AST.zext 64 res) + !!ir (dstB := AST.num0 64) + | Most (* Byte/word mask *) -> + let nFF = numI32 (if ctrl.PackSize = 8 then 0xFF else 0xFFFF) packSize + let res = Array.init nElem (fun _ -> !+ir packSize) + for i in 0 .. upperBound do + !!ir (res[i] := AST.ite intRes2[i] nFF n0) + done + !!ir (dstA := Array.sub res 0 pNum |> AST.concatArr) + !!ir (dstB := Array.sub res pNum pNum |> AST.concatArr) | Index -> let outSz, cx = if hasREXW ins.REXPrefix then 64, R.RCX else 32, R.ECX let cx = !.ctxt cx - let nMaxSz = numI32 nElem elemSz - let idx = if info.OutSelect = Least then nElem - 1 else 0 - let out = AST.zext outSz <| genOutput info intRes2 nMaxSz idx - !!ir (dstAssign outSz cx out) - | Mask -> - let xmmB, xmmA = getPseudoRegVar128 ctxt Register.XMM0 - let loop (acc1, acc2) i = - let src = AST.extract intRes2 1 i - if (i < nElem / 2) then (acc1, (AST.zext info.PackSize src) :: acc2) - else ((AST.zext info.PackSize src) :: acc1, acc2) - if info.OutSelect = Least then - !!ir (xmmA := AST.zext 64 intRes2) - !!ir (xmmB := AST.num0 64) - else let r1, r2 = List.fold loop ([], []) [0 .. nElem - 1] - !!ir (xmmB := AST.concatArr (List.toArray r1)) - !!ir (xmmA := AST.concatArr (List.toArray r2)) - -let private getZSFForPCMPSTR ins insLen ctrl ctxt src1 src2 ir = - let src1B, src1A = transOprToExpr128 ins insLen ctxt src1 - let src2B, src2A = transOprToExpr128 ins insLen ctxt src2 - let getExZSFlag r = - let reg = !.ctxt r - AST.lt (AST.ite (AST.xthi 1 reg) (AST.neg reg) reg) - (numU32 ctrl.NumElems 32) - let rec getImZSFlag acc srcB srcA idx = - let packSz = ctrl.PackSize - let packWidth = RegType.toBitWidth packSz - let half = ctrl.NumElems / 2u |> int - let e, amount = if idx < half then srcA, idx else srcB, idx - half - let v e = e >> numI32 (amount * packWidth) 64 - let next, cond = idx - 1, idx = 0 - if cond then AST.ite (AST.xtlo packSz (v e) == AST.num0 packSz) AST.b1 acc - else let acc = AST.ite (AST.xtlo packSz (v e) == AST.num0 packSz) AST.b1 acc - getImZSFlag acc srcB srcA next - match ctrl.Len with - | Implicit -> - !!ir (!.ctxt R.ZF := - getImZSFlag AST.b0 src2B src2A (ctrl.NumElems - 1u |> int)) - !!ir (!.ctxt R.SF := - getImZSFlag AST.b0 src1B src1A (ctrl.NumElems - 1u |> int)) - | Explicit -> - !!ir (!.ctxt R.ZF := getExZSFlag R.EDX) - !!ir (!.ctxt R.SF := getExZSFlag R.EAX) - -let pcmpstr ins insLen ctxt = - let ir = IRBuilder (64) - ! !*ir elemSz |] - aggOpr ins insLen ctxt ctrl src1 src2 ck1 ck2 res1 ir - !!ir (intRes1 := Array.reduce (.|) res1) - !!ir (intRes2 := getIntRes2 intRes1 ctrl ck2) - pcmpStrRet ins ctrl ctxt intRes2 ir - !!ir (!.ctxt R.CF := intRes2 != AST.num0 elemSz) - getZSFForPCMPSTR ins insLen ctrl ctxt src1 src2 ir - !!ir (!.ctxt R.OF := AST.xtlo 1 intRes2) + let n0 = AST.num0 elemSz + let idx = + match ctrl.OutSelect with + | Least -> leastSign ir iRes2 elemSz nElem + | Most -> mostSign ir iRes2 elemSz nElem + |> AST.zext 32 + let idx = AST.ite (iRes2 == n0) (numI32 nElem 32) idx + !!ir (dstAssign outSz cx idx) + !!ir (!.ctxt R.CF := iRes2 != AST.num0 elemSz) + setZFSFOfPCMPSTR ctxt ir ctrl src1 src2 + !!ir (!.ctxt R.OF := intRes2[0]) !!ir (!.ctxt R.AF := AST.b0) !!ir (!.ctxt R.PF := AST.b0) +#if EMULATION + ctxt.ConditionCodeOp <- ConditionCodeOp.EFlags +#endif !>ir insLen diff --git a/src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt b/src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt index 4fc1ea68..3f530943 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt +++ b/src/FrontEnd/BinLifter/Intel/IntelSupportedOpcodes.txt @@ -522,6 +522,8 @@ INSERTQ INSW /// Call to Interrupt (Interrupt vector specified by immediate byte). INT +/// Call to Interrupt Procedure (Debug trap). +INT1 /// Call to Interrupt (Interrupt 3-trap to debugger). INT3 /// Call to Interrupt (InteInterrupt 4-if overflow flag is 1). @@ -1398,8 +1400,10 @@ TZCNT UCOMISD /// Unordered Compare Scalar Single-Precision FPValues and Set EFLAGS. UCOMISS -/// Undefined instruction. -UD +/// Undefined instruction (Raise invalid opcode exception). +UD0 +/// Undefined Instruction (Raise invalid opcode exception). +UD1 /// Undefined Instruction (Raise invalid opcode exception). UD2 /// Unpack and Interleave High Packed Double-Precision Floating-Point Values. @@ -1516,6 +1520,8 @@ VCVTPD2UDQ VCVTPD2UQQ /// Convert 16-bit FP values to Single-Precision FP values. VCVTPH2PS +/// Conv Packed Single-Precision FP Values to Packed Signed DWord Int Values. +VCVTPS2DQ /// Conv Packed Single-Precision FP Values to Packed Dbl-Precision FP Values. VCVTPS2PD /// Convert Single-Precision FP value to 16-bit FP value. @@ -1598,6 +1604,10 @@ VDIVSD VDIVSS /// Dot Product of BF16 Pairs Accumulated into Packed Single Precision. VDPBF16PS +/// Packed Double-Precision Dot Products. +VDPPD +/// Packed Single-Precision Dot Products. +VDPPS /// Verify a Segment for Reading. VERR /// Verify a Segment for Writing. @@ -1668,6 +1678,14 @@ VFMADD231PS VFMADD231SD /// Fused Multiply-Add of Scalar Single-Precision Floating-Point Values. VFMADD231SS +/// Multiply and Add Packed Double-Precision Floating-Point(Only AMD). +VFMADDPD +/// Multiply and Add Packed Single-Precision Floating-Point(Only AMD). +VFMADDPS +/// Multiply and Add Scalar Double-Precision Floating-Point(Only AMD). +VFMADDSD +/// Multiply and Add Scalar Single-Precision Floating-Point(Only AMD). +VFMADDSS /// Fused Multiply-Alternating Add/Sub of Packed Double-Precision FP Values. VFMADDSUB132PD /// Fused Multiply-Alternating Add/Sub of Packed Single-Precision FP Values. @@ -1846,6 +1864,8 @@ VINSERTI64X4 VINSERTPS /// Load Unaligned Integer 128 Bits. VLDDQU +/// Store Selected Bytes of Double Quadword. +VMASKMOVDQU /// Conditional SIMD Packed Loads and Stores. VMASKMOVPD /// Conditional SIMD Packed Loads and Stores. @@ -1916,6 +1936,8 @@ VMOVMSKPD VMOVMSKPS /// Load Double Quadword Non-Temporal Aligned Hint. VMOVNTDQ +/// Load Double Quadword Non-temporal Aligned. +VMOVNTDQA /// Store Packed Double-Precision FP Values Using Non-Temporal Hint. VMOVNTPD /// Store Packed Single-Precision FP Values Using Non-Temporal Hint. @@ -1934,6 +1956,8 @@ VMOVSS VMOVUPD /// Move Unaligned Packed Single-Precision Floating-Point Values. VMOVUPS +/// Compute Multiple Packed Sums of Absolute Difference. +VMPSADBW /// Load Pointer to Virtual-Machine Control Structure. VMPTRLD /// Store Pointer to Virtual-Machine Control Structure. @@ -2162,8 +2186,10 @@ VPEXPANDQ VPEXPANDW /// Extract Byte. VPEXTRB -/// Extract DWord. +/// Extract Dword. VPEXTRD +/// Extract Qword. +VPEXTRQ /// Extract Word. VPEXTRW /// Gather packed dword values using signed Dword/Qword indices. @@ -2204,6 +2230,8 @@ VPLZCNTQ VPMADD52HUQ /// Packed Multiply of Unsigned 52-bit and Add Low 52-bit Products. VPMADD52LUQ +/// Multiply and Add Packed Signed and Unsigned Bytes. +VPMADDUBSW /// Multiply and Add Packed Integers. VPMADDWD /// Conditional SIMD Integer Packed Loads and Stores. @@ -2672,6 +2700,10 @@ VSUBPS VSUBSD /// Subtract Scalar Single-Precision Floating-Point Values. VSUBSS +/// Packed Bit Test. +VTESTPD +/// Packed Bit Test. +VTESTPS /// Unordered Compare Scalar Double-Precision FP Values and Set EFLAGS. VUCOMISD /// Unordered Compare Scalar Single-Precision FPValues and Set EFLAGS. diff --git a/src/FrontEnd/BinLifter/Intel/IntelTranslationContext.fs b/src/FrontEnd/BinLifter/Intel/IntelTranslationContext.fs new file mode 100644 index 00000000..c00a61d1 --- /dev/null +++ b/src/FrontEnd/BinLifter/Intel/IntelTranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Intel + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for Intel (x86 or x86-64) instructions. +type IntelTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar id pos = + regExprs.GetPseudoRegVar (Register.ofRegID id ) pos diff --git a/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs b/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs index 3eb65952..7d9af538 100644 --- a/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs +++ b/src/FrontEnd/BinLifter/Intel/IntelX87Lifter.fs @@ -34,6 +34,7 @@ open B2R2.FrontEnd.BinLifter.LiftingUtils open B2R2.FrontEnd.BinLifter.Intel open B2R2.FrontEnd.BinLifter.Intel.LiftingUtils +#if !EMULATION let private undefC0 = AST.undef 1 "C0 is undefined." let private undefC1 = AST.undef 1 "C1 is undefined." @@ -52,6 +53,7 @@ let private cflagsUndefined023 ctxt ir = !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif let inline private getFPUPseudoRegVars ctxt r = struct (getPseudoRegVar ctxt r 2, getPseudoRegVar ctxt r 1) @@ -61,18 +63,22 @@ let private updateC1OnLoad ctxt ir = let c1Flag = !.ctxt R.FSWC1 (* Top value has been wrapped around, which means stack overflow in B2R2. *) !!ir (c1Flag := (top == AST.num0 8)) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif let private updateC1OnStore ctxt ir = let top = !.ctxt R.FTOP let c1Flag = !.ctxt R.FSWC1 (* Top value has been wrapped around, which means stack underflow in B2R2. *) !!ir (c1Flag := (top != numI32 7 8)) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif let private moveFPRegtoFPReg regdst regsrc ctxt ir = let struct (dstB, dstA) = getFPUPseudoRegVars ctxt regdst @@ -115,50 +121,70 @@ let private popFPUStack ctxt ir = let inline private getLoadAddressExpr (src: Expr) = match src.E with - | Load (_, _, addr, _) -> struct (addr, TypeCheck.typeOf addr) + | Load (_, _, addr) -> struct (addr, TypeCheck.typeOf addr) | _ -> Utils.impossible () let private castTo80Bit ctxt tmpB tmpA srcExpr ir = let oprSize = TypeCheck.typeOf srcExpr + let zero = AST.num0 oprSize match oprSize with | 32 -> - let tmpSrc = !*ir oprSize + let tmpSrc = !+ir oprSize + let biasedExponent = !+ir 16 let n31 = numI32 31 32 - let n15 = numI32 15 32 + let n15 = numI32 15 16 let n23 = numI32 23 32 let one = numI32 1 32 - let biasDiff = numI32 0x3f80 32 - let sign = AST.xtlo 16 (((tmpSrc >> n31) .& one) << n15) - let exponent = - AST.xtlo 16 (((tmpSrc >> n23) .& (numI32 0xff 32)) .+ biasDiff) - let integerpart = numI64 0x0010000000000000L 64 - let significand = - (AST.zext 64 (tmpSrc .& numI32 0x7fffff 32)) .| integerpart + let biasDiff = numI32 0x3f80 16 + let sign = (AST.xtlo 16 ((tmpSrc >> n31) .& one)) << n15 + let integerpart = numI64 0x8000000000000000L 64 + let significand = (AST.zext 64 (tmpSrc .& numI32 0x7fffff 32)) !!ir (tmpSrc := srcExpr) + !!ir (biasedExponent := + AST.xtlo 16 ((tmpSrc >> n23) .& (numI32 0xff 32))) + let exponent = + AST.ite (biasedExponent == numI32 0 16) (numI32 0 16) + (AST.ite (biasedExponent == numI32 0xff 16) + (numI32 0x7fff 16) + (biasedExponent .+ biasDiff)) !!ir (tmpB := sign .| exponent) - !!ir (tmpA := (significand << numI32 40 64)) + !!ir (tmpA := + AST.ite + (AST.eq tmpSrc zero) + (AST.num0 64) + (integerpart .| (significand << numI32 40 64))) | 64 -> - let tmpSrc = !*ir oprSize + let tmpSrc = !+ir oprSize + let biasedExponent = !+ir 16 let n63 = numI32 63 64 - let n15 = numI32 15 64 + let n15 = numI32 15 16 let n52 = numI32 52 64 let one = numI32 1 64 - let biasDiff = numI32 0x3c00 64 - let sign = AST.xtlo 16 (((tmpSrc >> n63) .& one) << n15) - let exponent = - AST.xtlo 16 (((tmpSrc>> n52) .& (numI32 0x7ff 64)) .+ biasDiff) - let integerpart = numI64 0x0010000000000000L 64 - let significand = tmpSrc .& numI64 0xFFFFFFFFFFFFFL 64 .| integerpart + let biasDiff = numI32 0x3c00 16 + let sign = (AST.xtlo 16 (((tmpSrc >> n63) .& one))) << n15 + let integerpart = numI64 0x8000000000000000L 64 + let significand = tmpSrc .& numI64 0xFFFFFFFFFFFFFL 64 !!ir (tmpSrc := srcExpr) - !!ir (tmpB := sign .| exponent) - !!ir (tmpA := (significand << numI32 11 64)) + !!ir (biasedExponent := + AST.xtlo 16 ((tmpSrc >> n52) .& (numI32 0x7ff 64))) + let exponent = + AST.ite (biasedExponent == numI32 0 16) (numI32 0 16) + (AST.ite (biasedExponent == numI32 0x7ff 16) + (numI32 0x7fff 16) + (biasedExponent .+ biasDiff)) + !!ir (tmpB := sign .| exponent) + !!ir (tmpA := + AST.ite + (AST.eq tmpSrc zero) + (AST.num0 64) + (integerpart .| (significand << numI32 11 64))) | 80 -> match srcExpr.E with - | Load (_, _, addrExpr, _) -> + | Load (_, _, addrExpr) -> let addrSize = TypeCheck.typeOf addrExpr !!ir (tmpB := AST.loadLE 16 (addrExpr .+ numI32 8 addrSize)) !!ir (tmpA := AST.loadLE 64 addrExpr) - | BinOp (_, _, { E = Var (_, r, _, _) }, { E = Var (_, _, _, _)}, _) -> + | BinOp (_, _, { E = Var (_, r, _) }, { E = Var (_)}) -> let reg = Register.pseudoRegToReg (Register.ofRegID r) let struct (srcB, srcA) = getFPUPseudoRegVars ctxt reg !!ir (tmpB := srcB) @@ -167,9 +193,9 @@ let private castTo80Bit ctxt tmpB tmpA srcExpr ir = | _ -> Utils.impossible () let private fpuLoad insLen ctxt oprExpr = - let ir = IRBuilder (64) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let tmpB, tmpA = !*ir 16, !*ir 64 + let tmpB, tmpA = !+ir 16, !+ir 64 !ir insLen let fld ins insLen ctxt = - let oprExpr = transOneOpr ins insLen ctxt - fpuLoad insLen ctxt oprExpr + let ir = !*ctxt + !, !+ir 64 + !?ir (castTo80Bit ctxt tmpB tmpA oprExpr) + !?ir (pushFPUStack ctxt) + !!ir (st0b := tmpB) + !!ir (st0a := tmpA) + !?ir (updateC1OnLoad ctxt) + !>ir insLen let private castFrom80Bit dstExpr dstSize srcB srcA ir = match dstSize with - | 32 -> - let n16 = numI32 16 32 - let sign = (AST.zext 32 srcB .& (numI32 0x8000 32)) << n16 - let biasDiff = numI32 0x3f80 32 - let exponent = AST.zext 32 (srcB .& (numI32 0x7fff 16)) .- biasDiff - let exponent = exponent << numI32 23 32 - let n40 = numI32 40 64 + | 16 -> + let sign = srcB .& (numI32 0x8000 16) + let biasDiff = numI32 0x3ff0 16 + let tmpExp = !+ir 16 + let exp = srcB .& numI32 0x7fff 16 + let computedExp = exp .- biasDiff + let maxExp = numI32 0x1f 16 + let exponent = + AST.ite (exp == AST.num0 16) (AST.num0 16) + (AST.ite (exp == numI32 0x7fff 16) (numI32 0x1f 16) + (AST.ite (computedExp .> maxExp) maxExp computedExp)) + << numI32 10 64 + let n53 = numI32 53 64 let significand = - AST.xtlo 32 ((srcA .& numI64 0x7FFFFFFFFFFFFFFFL 64) >> n40) + AST.xtlo 16 ((srcA .& numI64 0x7FFFFFFFFFFFFFFFL 64) >> n53) + !!ir (tmpExp := computedExp) !!ir (dstExpr := (sign .| exponent .| significand)) + | 32 -> + let n48 = numI32 48 64 + let sign = (AST.zext 64 srcB .& (numI32 0x8000 64)) << n48 + let biasDiff = numI32 0x3c00 64 + let tmpExp = !+ir 64 + let tmpExp2 = !+ir 64 + let exp = srcB .& numI32 0x7fff 16 + let computedExp = AST.zext 64 exp .- biasDiff + let maxExp = numI32 0x7ff 64 + let exponent = + AST.ite (exp == AST.num0 16) (AST.num0 64) + (AST.ite (exp == numI32 0x7fff 16) (numI32 0x7ff 64) + (AST.ite (computedExp .> maxExp) maxExp computedExp)) + << numI32 52 64 + let n11 = numI32 11 64 + let significand = (srcA .& numI64 0x7FFFFFFFFFFFFFFFL 64) >> n11 + !!ir (tmpExp := computedExp) + !!ir (tmpExp2 := (sign .| exponent .| significand)) + !!ir (dstExpr := AST.cast CastKind.FloatCast 32 tmpExp2) | 64 -> let n48 = numI32 48 64 let sign = (AST.zext 64 srcB .& (numI32 0x8000 64)) << n48 let biasDiff = numI32 0x3c00 64 - let exponent = AST.zext 64 (srcB .& (numI32 0x7fff 16)) .- biasDiff - let exponent = exponent << numI32 52 64 + let tmpExp = !+ir 64 + let exp = srcB .& numI32 0x7fff 16 + let computedExp = AST.zext 64 exp .- biasDiff + let maxExp = numI32 0x7ff 64 + let exponent = + AST.ite (exp == AST.num0 16) (AST.num0 64) + (AST.ite (exp == numI32 0x7fff 16) (numI32 0x7ff 64) + (AST.ite (computedExp .> maxExp) maxExp computedExp)) + << numI32 52 64 let n11 = numI32 11 64 let significand = (srcA .& numI64 0x7FFFFFFFFFFFFFFFL 64) >> n11 + !!ir (tmpExp := computedExp) !!ir (dstExpr := (sign .| exponent .| significand)) | 80 -> let struct (addrExpr, addrSize) = getLoadAddressExpr dstExpr @@ -210,7 +279,7 @@ let private castFrom80Bit dstExpr dstSize srcB srcA ir = | _ -> Utils.impossible () let ffst (ins: InsInfo) insLen ctxt doPop = - let ir = IRBuilder (32) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 ! - let oprExpr = transOprToExpr ins insLen ctxt opr + let oprExpr = transOprToExpr ir false ins insLen ctxt opr let oprSize = TypeCheck.typeOf oprExpr !?ir (castFrom80Bit oprExpr oprSize st0b st0a) | _ -> raise InvalidOperandException @@ -228,13 +297,13 @@ let ffst (ins: InsInfo) insLen ctxt doPop = !>ir insLen let fild ins insLen ctxt = - let ir = IRBuilder (32) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let oprExpr = transOneOpr ins insLen ctxt - let tmpB, tmpA = !*ir 16, !*ir 64 + let oprExpr = transOneOpr ir ins insLen ctxt + let tmpB, tmpA = !+ir 16, !+ir 64 ! oprExpr)) + (castTo80Bit ctxt tmpB tmpA (AST.cast CastKind.SIntToFloat 64 oprExpr)) !?ir (pushFPUStack ctxt) !!ir (st0b := tmpB) !!ir (st0a := tmpA) @@ -242,22 +311,25 @@ let fild ins insLen ctxt = !>ir insLen let fist ins insLen ctxt doPop = - let ir = IRBuilder (32) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! (* Rounding Control *) - let num2 = numI32 2 2 + let tmp0 = !+ir oprSize + let rcField = !+ir 8 (* Rounding Control *) + let num2 = numI32 2 8 let cst00 = AST.cast CastKind.FtoIRound oprSize tmp0 let cst01 = AST.cast CastKind.FtoIFloor oprSize tmp0 let cst10 = AST.cast CastKind.FtoICeil oprSize tmp0 let cst11 = AST.cast CastKind.FtoITrunc oprSize tmp0 - ! 10) - !!ir (tmp0 := AST.ite (rcField == AST.num0 2) cst00 cst11) - !!ir (tmp0 := AST.ite (rcField == AST.num1 2) cst01 tmp0) + !!ir (rcField := (AST.zext 8 (AST.extract (!.ctxt R.FCW) 1 10))) + !!ir (rcField := (rcField << AST.num1 8)) + !!ir (rcField := + (rcField .| (AST.zext 8 (AST.extract (!.ctxt R.FCW) 1 11)))) + !!ir (tmp0 := AST.ite (rcField == AST.num0 8) cst00 cst11) + !!ir (tmp0 := AST.ite (rcField == AST.num1 8) cst01 tmp0) !!ir (tmp0 := AST.ite (rcField == num2) cst10 tmp0) !!ir (oprExpr := tmp0) if doPop then !?ir (popFPUStack ctxt) else () @@ -265,25 +337,32 @@ let fist ins insLen ctxt doPop = !>ir insLen let fisttp ins insLen ctxt = - let ir = IRBuilder (32) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! + let tmp1 = !+ir 64 let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - ! st0b st0a) !!ir (oprExpr := AST.cast CastKind.FtoITrunc oprSize tmp1) !?ir (popFPUStack ctxt) !!ir (!.ctxt R.FSWC1 := AST.b0) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif !>ir insLen let private getTwoBCDDigits addrExpr addrSize startPos = let byteValue = AST.loadLE 8 (addrExpr .+ numI32 startPos addrSize) - let d1 = AST.extract byteValue 4 0 |> AST.sext 64 - let d2 = AST.extract byteValue 4 4 |> AST.sext 64 + let d1 = + let msb = AST.extract byteValue 1 3 + (byteValue .& (AST.sext 8 msb .| numI32 0xF0 8)) |> AST.sext 64 + let d2 = + let msb = AST.extract byteValue 1 7 + ((byteValue >> numI32 4 8) .& (AST.sext 8 msb .| numI32 0xF0 8)) + |> AST.sext 64 struct (d1, d2) let private bcdToInt intgr addrExpr addrSize ir = @@ -319,15 +398,15 @@ let private bcdToInt intgr addrExpr addrSize ir = !!ir (AST.xthi 1 intgr := signBit) let fbld ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt + ! - let tmpB, tmpA = !*ir 16, !*ir 64 - ! + let tmpB, tmpA = !+ir 16, !+ir 64 !?ir (bcdToInt intgr addrExpr addrSize) - !?ir (castTo80Bit ctxt tmpB tmpA (AST.cast CastKind.IntToFloat 64 intgr)) + !?ir (castTo80Bit ctxt tmpB tmpA (AST.cast CastKind.SIntToFloat 64 intgr)) !?ir (pushFPUStack ctxt) !!ir (st0b := tmpB) !!ir (st0a := tmpA) @@ -335,15 +414,15 @@ let fbld ins insLen ctxt = !>ir insLen let private storeTwoDigitBCD n10 addrExpr addrSize intgr pos ir = - let d1 = AST.extract (intgr .% n10) 4 0 - let d2 = AST.extract ((intgr ./ n10) .% n10) 4 0 - let ds = AST.concat d2 d1 + let d1 = (AST.xtlo 8 (intgr .% n10)) .& (numI32 0xF 8) + let d2 = (AST.xtlo 8 ((intgr ./ n10) .% n10)) .& (numI32 0xF 8) + let ds = (d2 << (numI32 4 8)) .| d1 !!ir (AST.store Endian.Little (addrExpr .+ numI32 pos addrSize) ds) let private storeBCD addrExpr addrSize intgr ir = let n10 = numI32 10 64 let n100 = numI32 100 64 - let sign = !*ir 1 + let sign = !+ir 1 let signByte = (AST.zext 8 sign) << numI32 7 8 !!ir (sign := AST.xthi 1 intgr) !?ir (storeTwoDigitBCD n10 addrExpr addrSize intgr 0) @@ -366,13 +445,13 @@ let private storeBCD addrExpr addrSize intgr ir = !!ir (AST.store Endian.Little (addrExpr .+ numI32 9 addrSize) signByte) let fbstp ins insLen ctxt = - let ir = IRBuilder (64) - let dst = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! - let intgr = !*ir 64 - ! + let intgr = !+ir 64 !?ir (castFrom80Bit tmp 64 st0b st0a) !!ir (intgr := AST.cast CastKind.FtoIRound 64 tmp) !?ir (storeBCD addrExpr addrSize intgr) @@ -381,10 +460,10 @@ let fbstp ins insLen ctxt = !>ir insLen let fxch (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (16) - let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let tmpB, tmpA = !*ir 16, !*ir 64 + let ir = !*ctxt !, !+ir 64 !!ir (tmpB := st0b) !!ir (tmpA := st0a) let struct (srcB, srcA) = @@ -397,73 +476,133 @@ let fxch (ins: InsInfo) insLen ctxt = !!ir (srcB := tmpB) !!ir (srcA := tmpA) !!ir (!.ctxt R.FSWC1 := AST.b0) +#if !EMULATION !?ir (cflagsUndefined023 ctxt) +#endif !>ir insLen -let private fcmov (ins: InsInfo) insLen ctxt cond = - let ir = IRBuilder (8) +let private fcmov (ins: InsInfo) insLen ctxt ir cond = let srcReg = match ins.Operands with | TwoOperands (_, OprReg reg) -> reg | _ -> raise InvalidOperandException let struct (srcB, srcA) = getFPUPseudoRegVars ctxt srcReg let struct (dstB, dstA) = getFPUPseudoRegVars ctxt R.ST0 - !ir insLen +#endif let fcmove ins insLen ctxt = - !.ctxt R.ZF |> fcmov ins insLen ctxt + let ir = !*ctxt + ! fcmov ins insLen ctxt ir +#else + !.ctxt R.ZF |> fcmov ins insLen ctxt ir +#endif + !>ir insLen + let fcmovne ins insLen ctxt = - !.ctxt R.ZF |> AST.not |> fcmov ins insLen ctxt + let ir = !*ctxt + ! AST.not |> fcmov ins insLen ctxt ir +#else + !.ctxt R.ZF |> AST.not |> fcmov ins insLen ctxt ir +#endif + !>ir insLen let fcmovb ins insLen ctxt = - !.ctxt R.CF |> fcmov ins insLen ctxt + let ir = !*ctxt + ! fcmov ins insLen ctxt ir +#else + !.ctxt R.CF |> fcmov ins insLen ctxt ir +#endif + !>ir insLen let fcmovbe ins insLen ctxt = - (!.ctxt R.CF .| !.ctxt R.ZF) |> fcmov ins insLen ctxt + let ir = !*ctxt + ! fcmov ins insLen ctxt ir +#else + (!.ctxt R.CF .| !.ctxt R.ZF) |> fcmov ins insLen ctxt ir +#endif + !>ir insLen let fcmovnb ins insLen ctxt = - !.ctxt R.CF |> AST.not |> fcmov ins insLen ctxt + let ir = !*ctxt + ! AST.not |> fcmov ins insLen ctxt ir +#else + !.ctxt R.CF |> AST.not |> fcmov ins insLen ctxt ir +#endif + !>ir insLen let fcmovnbe ins insLen ctxt = + let ir = !*ctxt + ! AST.not + let cond2 = getZFLazy ctxt ir |> AST.not +#else let cond1 = !.ctxt R.CF |> AST.not let cond2 = !.ctxt R.ZF |> AST.not - cond1 .& cond2 |> fcmov ins insLen ctxt +#endif + cond1 .& cond2 |> fcmov ins insLen ctxt ir + !>ir insLen let fcmovu ins insLen ctxt = - !.ctxt R.PF |> fcmov ins insLen ctxt + let ir = !*ctxt + ! fcmov ins insLen ctxt ir +#else + !.ctxt R.PF |> fcmov ins insLen ctxt ir +#endif + !>ir insLen let fcmovnu ins insLen ctxt = - !.ctxt R.PF |> AST.not |> fcmov ins insLen ctxt + let ir = !*ctxt + ! AST.not |> fcmov ins insLen ctxt ir +#else + !.ctxt R.PF |> AST.not |> fcmov ins insLen ctxt ir +#endif + !>ir insLen let private fpuFBinOp (ins: InsInfo) insLen ctxt binOp doPop leftToRight = - let ir = IRBuilder (64) + let ir = !*ctxt ! let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let struct (st1b, st1a) = getFPUPseudoRegVars ctxt R.ST1 let struct (tmp0, tmp1) = tmpVars2 ir 64 - let res = !*ir 64 + let res = !+ir 64 !?ir (castFrom80Bit tmp0 64 st0b st0a) !?ir (castFrom80Bit tmp1 64 st1b st1a) if leftToRight then !!ir (res := binOp tmp0 tmp1) else !!ir (res := binOp tmp1 tmp0) !?ir (castTo80Bit ctxt st1b st1a res) - | OneOperand opr -> - let oprExpr = transOneOpr ins insLen ctxt + | OneOperand _ -> + let oprExpr = transOneOpr ir ins insLen ctxt let oprSize = TypeCheck.typeOf oprExpr let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let struct (tmp0, tmp1) = tmpVars2 ir oprSize - let res = !*ir oprSize - !?ir (castFrom80Bit tmp0 oprSize st0b st0a) - !!ir (tmp1 := oprExpr) + let struct (tmp0, tmp1) = tmpVars2 ir 64 + let res = !+ir 64 + !?ir (castFrom80Bit tmp0 64 st0b st0a) + if oprSize = 64 then !!ir (tmp1 := oprExpr) + else !!ir (tmp1 := AST.cast CastKind.FloatCast 64 oprExpr) if leftToRight then !!ir (res := binOp tmp0 tmp1) else !!ir (res := binOp tmp1 tmp0) !?ir (castTo80Bit ctxt st0b st0a res) @@ -471,7 +610,7 @@ let private fpuFBinOp (ins: InsInfo) insLen ctxt binOp doPop leftToRight = let struct (r0B, r0A) = getFPUPseudoRegVars ctxt reg0 let struct (r1B, r1A) = getFPUPseudoRegVars ctxt reg1 let struct (tmp0, tmp1) = tmpVars2 ir 64 - let res = !*ir 64 + let res = !+ir 64 !?ir (castFrom80Bit tmp0 64 r0B r0A) !?ir (castFrom80Bit tmp1 64 r1B r1A) if leftToRight then !!ir (res := binOp tmp0 tmp1) @@ -483,13 +622,13 @@ let private fpuFBinOp (ins: InsInfo) insLen ctxt binOp doPop leftToRight = !>ir insLen let private fpuIntOp ins insLen ctxt binOp leftToRight = - let ir = IRBuilder (8) + let ir = !*ctxt + ! - let res = !*ir 64 - ! oprExpr) + let res = !+ir 64 + !!ir (tmp := AST.cast CastKind.SIntToFloat 64 oprExpr) !?ir (castFrom80Bit dst 64 st0b st0a) if leftToRight then !!ir (res := binOp dst tmp) else !!ir (res := binOp tmp dst) @@ -533,27 +672,69 @@ let fidivr ins insLen ctxt = fpuIntOp ins insLen ctxt AST.fdiv false let inline private castToF64 intexp = - AST.cast CastKind.IntToFloat 64 intexp + AST.cast CastKind.SIntToFloat 64 intexp + +let getExponent isDouble src = + if isDouble then + let numMantissa = numI32 52 64 + let mask = numI32 0x7FF 64 + AST.xtlo 32 ((src >> numMantissa) .& mask) + else + let numMantissa = numI32 23 32 + let mask = numI32 0xff 32 + (src >> numMantissa) .& mask + +let getMantissa isDouble src = + let mask = + if isDouble then numU64 0xfffff_ffffffffUL 64 + else numU64 0x7fffffUL 32 + src .& mask + +let isNan isDouble expr = + let exponent = getExponent isDouble expr + let mantissa = getMantissa isDouble expr + let e = if isDouble then numI32 0x7ff 32 else numI32 0xff 32 + let zero = if isDouble then AST.num0 64 else AST.num0 32 + (exponent == e) .& (mantissa != zero) + +let isInf isDouble expr = + let exponent = getExponent isDouble expr + let mantissa = getMantissa isDouble expr + let e = if isDouble then numI32 0x7ff 32 else numI32 0xff 32 + let zero = if isDouble then AST.num0 64 else AST.num0 32 + (exponent == e) .& (mantissa == zero) + +let isUnordered isDouble expr = isNan isDouble expr .| isInf isDouble expr let fprem _ins insLen ctxt round = - let ir = IRBuilder (32) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let struct (st1b, st1a) = getFPUPseudoRegVars ctxt R.ST1 let caster = if round then CastKind.FtoIRound else CastKind.FtoITrunc - let lblLT64 = ir.NewSymbol "ExpDiffInRange" - let lblGE64 = ir.NewSymbol "ExpDiffOutOfRange" - let lblExit = ir.NewSymbol "Exit" + let lblUnordered = !%ir "Unordered" + let lblOrdered = !%ir "Ordered" + let lblLT64 = !%ir "ExpDiffInRange" + let lblGE64 = !%ir "ExpDiffOutOfRange" + let lblExit = !%ir "Exit" let struct (tmp0, tmp1) = tmpVars2 ir 64 - let expDiff = !*ir 16 + let expDiff = !+ir 16 let expMask = numI32 0x7fff 16 let n64 = numI32 64 16 - let n2 = numI32 2 64 + let n2 = numI32 2 64 |> castToF64 let struct (divres, intres, tmpres, divider) = tmpVars4 ir 64 ! st0b st0a) !?ir (castFrom80Bit tmp1 64 st1b st1a) !!ir (expDiff := (st0b .& expMask) .- (st1b .& expMask)) - !!ir (AST.cjmp (AST.lt expDiff n64) (AST.name lblLT64) (AST.name lblGE64)) + !!ir (AST.cjmp + (isUnordered true tmp0 .| isUnordered true tmp1) + (AST.name lblUnordered) (AST.name lblOrdered)) + !!ir (AST.lmark lblUnordered) + !?ir (castTo80Bit ctxt st0b st0a (AST.ite (isUnordered true tmp0) tmp0 tmp1)) + !!ir (!.ctxt R.FSWC2 := AST.b0) + !!ir (AST.jmp (AST.name lblExit)) + !!ir (AST.lmark lblOrdered) + !!ir (AST.cjmp (AST.slt expDiff n64) (AST.name lblLT64) (AST.name lblGE64)) !!ir (AST.lmark lblLT64) (* D < 64 *) !!ir (divres := AST.fdiv tmp0 tmp1) !!ir (intres := AST.cast caster 64 divres) @@ -577,66 +758,86 @@ let fprem _ins insLen ctxt round = !>ir insLen let fabs _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let struct (st0b, _st0a) = getFPUPseudoRegVars ctxt R.ST0 ! 15 := AST.b0) !!ir (!.ctxt R.FSWC1 := AST.b0) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif !>ir insLen let fchs _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let struct (st0b, _st0a) = getFPUPseudoRegVars ctxt R.ST0 - let tmp = !*ir 1 + let tmp = !+ir 1 ! st0b) !!ir (AST.xthi 1 st0b := AST.not tmp) !!ir (!.ctxt R.FSWC1 := AST.b0) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif !>ir insLen let frndint _ins insLen ctxt = - let ir = IRBuilder (32) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let tmp0 = !*ir 64 - let rcField = !*ir 2 (* Rounding Control *) + let lblOrdered = !%ir "Ordered" + let lblExit = !%ir "Exit" + let tmp0 = !+ir 64 + let rcField = !+ir 8 (* Rounding Control *) let cst00 = AST.cast CastKind.FtoIRound 64 tmp0 let cst01 = AST.cast CastKind.FtoIFloor 64 tmp0 let cst10 = AST.cast CastKind.FtoICeil 64 tmp0 let cst11 = AST.cast CastKind.FtoITrunc 64 tmp0 - let num2 = numI32 2 2 ! st0b st0a) - !!ir (rcField := AST.extract (!.ctxt R.FCW) 2 10) - !!ir (tmp0 := AST.ite (rcField == AST.num0 2) cst00 cst11) - !!ir (tmp0 := AST.ite (rcField == AST.num1 2) cst01 tmp0) - !!ir (tmp0 := AST.ite (rcField == num2) cst10 tmp0) + !!ir (AST.cjmp + (isUnordered true tmp0) + (AST.name lblExit) (AST.name lblOrdered)) + !!ir (AST.lmark lblOrdered) + !!ir (rcField := (AST.zext 8 (AST.extract (!.ctxt R.FCW) 1 11))) + !!ir (rcField := (rcField << AST.num1 8)) + !!ir (rcField := + (rcField .| (AST.zext 8 (AST.extract (!.ctxt R.FCW) 1 10)))) + !!ir (tmp0 := AST.ite (rcField == AST.num0 8) cst00 tmp0) + !!ir (tmp0 := AST.ite (rcField == AST.num1 8) cst01 tmp0) + !!ir (tmp0 := AST.ite (rcField == numI32 2 8) cst10 tmp0) + !!ir (tmp0 := AST.ite (rcField == numI32 3 8) cst11 tmp0) !?ir (castTo80Bit ctxt st0b st0a (castToF64 tmp0)) + !!ir (AST.lmark lblExit) !?ir (updateC1OnStore ctxt) !>ir insLen let fscale _ins insLen ctxt = - let ir = IRBuilder (16) - let struct (tmp0, tmp1, tmp2) = tmpVars3 ir 64 + let ir = !*ctxt + let struct (tmp0, tmp1, tmp2, tmp3) = tmpVars4 ir 64 let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let struct (st1b, st1a) = getFPUPseudoRegVars ctxt R.ST1 + let f2 = numI32 2 64 |> castToF64 ! st0b st0a) !?ir (castFrom80Bit tmp1 64 st1b st1a) - !!ir (tmp2 := numI32 1 64 << (AST.cast CastKind.FtoITrunc 64 tmp1)) - !?ir (castTo80Bit ctxt st0b st0a (AST.fmul tmp1 (castToF64 tmp2))) + !!ir (tmp2 := AST.cast CastKind.FtoITrunc 64 tmp1) + let exp = AST.ite (tmp2 ?>= numI64 0L 64) tmp2 (AST.neg tmp2) + !!ir (tmp3 := AST.fpow f2 (castToF64 exp)) + let v = + AST.ite + (tmp2 ?>= numI64 0L 64) (AST.fmul tmp0 tmp3) (AST.fdiv tmp0 tmp3) + !?ir (castTo80Bit ctxt st0b st0a v) !?ir (updateC1OnStore ctxt) !>ir insLen let fsqrt _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let tmp0 = !*ir 64 + let tmp0 = !+ir 64 ! st0b st0a) !?ir (castTo80Bit ctxt st0b st0a (AST.unop UnOpType.FSQRT tmp0)) @@ -644,18 +845,19 @@ let fsqrt _ins insLen ctxt = !>ir insLen let fxtract _ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let n3fff = numI32 0x3FFF 16 - let tmpB, tmpA = !*ir 16, !*ir 64 - let tmpF = !*ir 64 + let tmpB, tmpA = !+ir 16, !+ir 64 + let tmpF = !+ir 64 !) .| n3fff) !!ir (tmpA := st0a) !!ir (tmpF := castToF64 ((st0b .& numI32 0x7fff 16) .- n3fff)) - !?ir (pushFPUStack ctxt) !?ir (castTo80Bit ctxt st0b st0a tmpF) - !?ir (updateC1OnStore ctxt) + !?ir (pushFPUStack ctxt) + !!ir (st0b := tmpB) + !!ir (st0a := tmpA) !>ir insLen let private prepareTwoOprsForComparison (ins: InsInfo) insLen ctxt ir = @@ -673,7 +875,7 @@ let private prepareTwoOprsForComparison (ins: InsInfo) insLen ctxt ir = !?ir (castFrom80Bit tmp1 64 st1b st1a) | OneOperand (opr) -> let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 - let oprExpr = transOprToExpr ins insLen ctxt opr + let oprExpr = transOprToExpr ir false ins insLen ctxt opr !?ir (castFrom80Bit tmp0 64 st0b st0a) !!ir (tmp1 := AST.cast CastKind.FloatCast 64 oprExpr) | TwoOperands (OprReg r1, OprReg r2) -> @@ -682,60 +884,66 @@ let private prepareTwoOprsForComparison (ins: InsInfo) insLen ctxt ir = !?ir (castFrom80Bit tmp0 64 st0b st0a) !?ir (castFrom80Bit tmp1 64 st1b st1a) | _ -> raise InvalidOperandException - struct (tmp0, tmp1) + if ins.Opcode = Opcode.FUCOM then struct (tmp1, tmp0) else struct (tmp0, tmp1) -let fcom (ins: InsInfo) insLen ctxt nPop unordered = - let ir = IRBuilder (64) +let fcom ins insLen ctxt nPop unordered = + let ir = !*ctxt let c0 = !.ctxt R.FSWC0 let c2 = !.ctxt R.FSWC2 let c3 = !.ctxt R.FSWC3 ! 0 then !?ir (popFPUStack ctxt) else () if nPop = 2 then !?ir (popFPUStack ctxt) else () !>ir insLen let ficom ins insLen ctxt doPop = - let ir = IRBuilder (32) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt + ! - ! st0b st0a) - !!ir (tmp1 := AST.cast CastKind.IntToFloat 64 oprExpr) - !!ir (!.ctxt R.FSWC0 := AST.flt tmp0 tmp1) - !!ir (!.ctxt R.FSWC2 := AST.b0) - !!ir (!.ctxt R.FSWC3 := tmp0 == tmp1) + !!ir (tmp1 := AST.cast CastKind.SIntToFloat 64 oprExpr) + let isNan = isNan true tmp0 .| isNan true tmp1 + !!ir (!.ctxt R.FSWC0 := isNan .| AST.flt tmp0 tmp1) + !!ir (!.ctxt R.FSWC2 := isNan .| AST.b0) + !!ir (!.ctxt R.FSWC3 := isNan .| tmp0 == tmp1) !!ir (!.ctxt R.FSWC1 := AST.b0) if doPop then !?ir (popFPUStack ctxt) else () !>ir insLen let fcomi ins insLen ctxt doPop = - let ir = IRBuilder (64) + let ir = !*ctxt let zf = !.ctxt R.ZF let pf = !.ctxt R.PF let cf = !.ctxt R.CF !ir insLen let ftst _ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let num0V = AST.num0 64 let c0 = !.ctxt R.FSWC0 let c2 = !.ctxt R.FSWC2 let c3 = !.ctxt R.FSWC3 - let tmp = !*ir 64 + let tmp = !+ir 64 ! st0b st0a) !!ir (c0 := AST.flt tmp num0V) @@ -745,38 +953,42 @@ let ftst _ins insLen ctxt = !>ir insLen let fxam _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt + let top = !.ctxt R.FTOP let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let n7fff = numI32 0x7fff 16 let exponent = st0b .& n7fff - let nanCond = (exponent == n7fff) .& (AST.xtlo 62 st0a != AST.num0 62) - let c3Cond1 = (exponent == AST.num0 16) - let isAllZero = (st0a == AST.num0 64) .& (st0b == AST.num0 16) - let c2Cond0 = AST.not (isAllZero .| nanCond) - let c0Cond1 = (exponent == n7fff) + let num = numI64 0x7FFFFFFF_FFFFFFFFL 64 + let isNaN = (exponent == n7fff) .& ((st0a .& num) != AST.num0 64) + let isInf = (exponent == n7fff) .& ((st0a .& num) == AST.num0 64) + let isZero = (st0a == AST.num0 64) .& (exponent == AST.num0 16) + let isEmpty = top == numI32 0 8 + let c3Cond = isZero .| isEmpty + let c2Cond = AST.not (isNaN .| isZero .| isEmpty) + let c0Cond = isNaN .| isInf .| isEmpty ! st0b) - !!ir (!.ctxt R.FSWC3 := c3Cond1) - !!ir (!.ctxt R.FSWC2 := c2Cond0) - !!ir (!.ctxt R.FSWC0 := c0Cond1) + !!ir (!.ctxt R.FSWC3 := c3Cond) + !!ir (!.ctxt R.FSWC2 := c2Cond) + !!ir (!.ctxt R.FSWC0 := c0Cond) !>ir insLen let private checkForTrigFunction unsigned lin lout ir = let maxLimit = numI64 (1L <<< 63) 64 - let maxFloat = AST.cast CastKind.IntToFloat 64 maxLimit + let maxFloat = AST.cast CastKind.SIntToFloat 64 maxLimit !!ir (AST.cjmp (AST.flt unsigned maxFloat) (AST.name lin) (AST.name lout)) let private ftrig _ins insLen ctxt trigFunc = - let ir = IRBuilder (32) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let n7fff = numI32 0x7fff 16 let c0 = !.ctxt R.FSWC0 let c1 = !.ctxt R.FSWC1 let c2 = !.ctxt R.FSWC2 let c3 = !.ctxt R.FSWC3 - let lin = ir.NewSymbol "IsInRange" - let lout = ir.NewSymbol "IsOutOfRange" - let lexit = ir.NewSymbol "Exit" + let lin = !%ir "IsInRange" + let lout = !%ir "IsOutOfRange" + let lexit = !%ir "Exit" let struct (unsigned, signed, tmp) = tmpVars3 ir 64 ! (st0b .& n7fff) st0a) @@ -790,8 +1002,10 @@ let private ftrig _ins insLen ctxt trigFunc = !!ir (AST.lmark lout) !!ir (c2 := AST.b1) !!ir (AST.lmark lexit) +#if !EMULATION !!ir (c0 := undefC0) !!ir (c3 := undefC3) +#endif !!ir (c1:= AST.b0) !>ir insLen @@ -802,15 +1016,15 @@ let fcos ins insLen ctxt = ftrig ins insLen ctxt AST.fcos let fsincos _ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let n7fff = numI32 0x7fff 16 let c0 = !.ctxt R.FSWC0 let c2 = !.ctxt R.FSWC2 let c3 = !.ctxt R.FSWC3 - let lin = ir.NewSymbol "IsInRange" - let lout = ir.NewSymbol "IsOutOfRange" - let lexit = ir.NewSymbol "Exit" + let lin = !%ir "IsInRange" + let lout = !%ir "IsOutOfRange" + let lexit = !%ir "Exit" let struct (unsigned, signed, tmpsin, tmpcos) = tmpVars4 ir 64 ! (st0b .& n7fff) st0a) @@ -827,21 +1041,23 @@ let fsincos _ins insLen ctxt = !!ir (AST.lmark lout) !!ir (c2 := AST.b1) !!ir (AST.lmark lexit) +#if !EMULATION !!ir (c0 := undefC0) !!ir (c3 := undefC3) +#endif !?ir (updateC1OnLoad ctxt) !>ir insLen let fptan _ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let n7fff = numI32 0x7fff 16 let c0 = !.ctxt R.FSWC0 let c2 = !.ctxt R.FSWC2 let c3 = !.ctxt R.FSWC3 - let lin = ir.NewSymbol "IsInRange" - let lout = ir.NewSymbol "IsOutOfRange" - let lexit = ir.NewSymbol "Exit" + let lin = !%ir "IsInRange" + let lout = !%ir "IsOutOfRange" + let lexit = !%ir "Exit" let fone = numI64 0x3ff0000000000000L 64 (* 1.0 *) let struct (unsigned, signed, tmp) = tmpVars3 ir 64 !ir insLen let fpatan _ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let struct (st1b, st1a) = getFPUPseudoRegVars ctxt R.ST1 let struct (tmp0, tmp1, res) = tmpVars3 ir 64 ! st0b st0a) !?ir (castFrom80Bit tmp1 64 st1b st1a) - !!ir (res := AST.fatan (AST.fdiv tmp0 tmp1)) + !!ir (res := AST.fatan (AST.fdiv tmp1 tmp0)) !?ir (castTo80Bit ctxt st1b st1a res) !?ir (popFPUStack ctxt) !?ir (updateC1OnStore ctxt) +#if !EMULATION !?ir (cflagsUndefined023 ctxt) +#endif !>ir insLen let f2xm1 _isn insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let f1 = numI32 1 64 |> castToF64 let f2 = numI32 2 64 |> castToF64 @@ -891,11 +1111,13 @@ let f2xm1 _isn insLen ctxt = !!ir (res := AST.fsub (AST.fpow f2 tmp) f1) !?ir (castTo80Bit ctxt st0b st0a res) !!ir (c1 := AST.b0) +#if !EMULATION !?ir (cflagsUndefined023 ctxt) +#endif !>ir insLen let fyl2x _ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let struct (st1b, st1a) = getFPUPseudoRegVars ctxt R.ST1 let struct (tmp0, tmp1, res) = tmpVars3 ir 64 @@ -907,11 +1129,13 @@ let fyl2x _ins insLen ctxt = !?ir (castTo80Bit ctxt st1b st1a res) !?ir (popFPUStack ctxt) !?ir (updateC1OnStore ctxt) +#if !EMULATION !?ir (cflagsUndefined023 ctxt) +#endif !>ir insLen let fyl2xp1 _ins insLen ctxt = - let ir = IRBuilder (64) + let ir = !*ctxt let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 let struct (st1b, st1a) = getFPUPseudoRegVars ctxt R.ST1 let struct (tmp0, tmp1, res) = tmpVars3 ir 64 @@ -924,7 +1148,9 @@ let fyl2xp1 _ins insLen ctxt = !?ir (castTo80Bit ctxt st1b st1a res) !?ir (popFPUStack ctxt) !?ir (updateC1OnStore ctxt) +#if !EMULATION !?ir (cflagsUndefined023 ctxt) +#endif !>ir insLen let fld1 _ins insLen ctxt = @@ -932,15 +1158,21 @@ let fld1 _ins insLen ctxt = fpuLoad insLen ctxt oprExpr let fldz _ins insLen ctxt = - let oprExpr = AST.num0 64 - fpuLoad insLen ctxt oprExpr + let ir = !*ctxt + let struct (st0b, st0a) = getFPUPseudoRegVars ctxt R.ST0 + !) + !!ir (st0a := AST.num0 64) + !?ir (updateC1OnLoad ctxt) + !>ir insLen let fldpi _ins insLen ctxt = let oprExpr = numU64 4614256656552045848UL 64 fpuLoad insLen ctxt oprExpr let fldl2e _ins insLen ctxt = - let oprExpr = numU64 4599094494223104509UL 64 + let oprExpr = numU64 4609176140021203710UL 64 fpuLoad insLen ctxt oprExpr let fldln2 _ins insLen ctxt = @@ -956,31 +1188,35 @@ let fldlg2 _ins insLen ctxt = fpuLoad insLen ctxt oprExpr let fincstp _ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt let top = !.ctxt R.FTOP !)) !!ir (!.ctxt R.FSWC1 := AST.b0) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif !>ir insLen let fdecstp _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let top = !.ctxt R.FTOP !)) !!ir (!.ctxt R.FSWC1 := AST.b0) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif !>ir insLen let ffree (ins: InsInfo) insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let top = !.ctxt R.FTOP let tagWord = !.ctxt R.FTW let struct (top16, shifter, tagValue) = tmpVars3 ir 16 @@ -1009,62 +1245,70 @@ let private checkFPUExceptions ctxt ir = () let private clearFPU ctxt ir = let cw = numI32 895 16 - let tw = BitVector.maxUInt16 |> AST.num + let tw = BitVector.MaxUInt16 |> AST.num !!ir (!.ctxt R.FCW := cw) !!ir (!.ctxt R.FSW := AST.num0 16) !!ir (!.ctxt R.FTW := tw) let finit _ins insLen ctxt = - let ir = IRBuilder (32) + let ir = !*ctxt !ir insLen let fninit _ins insLen ctxt = - let ir = IRBuilder (16) + let ir = !*ctxt !ir insLen let fclex _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt let stsWrd = !.ctxt R.FSW ! stsWrd := AST.num0 7) + !!ir (stsWrd := stsWrd .& (numI32 0xFF80 16)) !!ir (AST.xthi 1 stsWrd := AST.b0) +#if !EMULATION !!ir (!.ctxt R.FSWC0 := undefC0) !!ir (!.ctxt R.FSWC1 := undefC1) !!ir (!.ctxt R.FSWC2 := undefC2) !!ir (!.ctxt R.FSWC3 := undefC3) +#endif !>ir insLen let fstcw ins insLen ctxt = - let ir = IRBuilder (16) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let fnstcw ins insLen ctxt = - let ir = IRBuilder (8) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let fldcw ins insLen ctxt = - let ir = IRBuilder (8) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let private m14fstenv dstAddr addrSize ctxt ir = @@ -1090,10 +1334,10 @@ let private m28fstenv dstAddr addrSize ctxt ir = !!ir (AST.store Endian.Little (dstAddr .+ numI32 20 addrSize) (!.ctxt R.FDP)) let fnstenv ins insLen ctxt = - let ir = IRBuilder (16) - let dst = transOneOpr ins insLen ctxt - let struct (addrExpr, addrSize) = getLoadAddressExpr dst + let ir = !*ctxt ! -> m14fstenv addrExpr addrSize ctxt ir | 224 -> m28fstenv addrExpr addrSize ctxt ir @@ -1119,10 +1363,10 @@ let private m28fldenv srcAddr addrSize ctxt ir = !!ir (!.ctxt R.FDP := AST.loadLE 64 (srcAddr .+ numI32 20 addrSize)) let fldenv ins insLen ctxt = - let ir = IRBuilder (16) - let src = transOneOpr ins insLen ctxt - let struct (addrExpr, addrSize) = getLoadAddressExpr src + let ir = !*ctxt ! -> m14fldenv addrExpr addrSize ctxt ir | 224 -> m28fldenv addrExpr addrSize ctxt ir @@ -1156,10 +1400,10 @@ let private stSts dstAddr addrSize offset ctxt ir = !!ir (AST.store Endian.Little (dstAddr .+ numI32 (offset + 78) addrSize) stb) let fnsave ins insLen ctxt = - let ir = IRBuilder (32) - let dst = transOneOpr ins insLen ctxt - let struct (addrExpr, addrSize) = getLoadAddressExpr dst + let ir = !*ctxt ! -> m14fstenv addrExpr addrSize ctxt ir @@ -1203,10 +1447,10 @@ let private ldSts srcAddr addrSize offset ctxt ir = !!ir (stb := AST.loadLE 16 (srcAddr .+ numI32 (offset + 78) addrSize)) let frstor ins insLen ctxt = - let ir = IRBuilder (32) - let src = transOneOpr ins insLen ctxt - let struct (addrExpr, addrSize) = getLoadAddressExpr src + let ir = !*ctxt ! -> m14fldenv addrExpr addrSize ctxt ir @@ -1218,23 +1462,27 @@ let frstor ins insLen ctxt = !>ir insLen let fnstsw ins insLen ctxt = - let ir = IRBuilder (8) - let oprExpr = transOneOpr ins insLen ctxt + let ir = !*ctxt !ir insLen let wait _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt !ir insLen let fnop _ins insLen ctxt = - let ir = IRBuilder (8) + let ir = !*ctxt !ir insLen let inline private storeLE addr v = @@ -1325,10 +1573,10 @@ let private fxsaveInternal ctxt dstAddr addrSize is64bit ir = else () let fxsave ins insLen ctxt = - let ir = IRBuilder (128) - let dst = transOneOpr ins insLen ctxt - let struct (addrExpr, addrSize) = getLoadAddressExpr dst + let ir = !*ctxt !)) !>ir insLen @@ -1417,9 +1665,9 @@ let private fxrstoreInternal ctxt srcAddr addrSz is64bit ir = else () let fxrstor ins insLen ctxt = - let ir = IRBuilder (128) - let src = transOneOpr ins insLen ctxt - let struct (addrExpr, addrSize) = getLoadAddressExpr src + let ir = !*ctxt !)) !>ir insLen diff --git a/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj b/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj index 2fd9f6ca..00538ad7 100644 --- a/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj +++ b/src/FrontEnd/BinLifter/MIPS/B2R2.FrontEnd.BinLifter.MIPS.fsproj @@ -9,18 +9,16 @@ - - + - - + - + diff --git a/src/FrontEnd/BinLifter/MIPS/MIPS.fs b/src/FrontEnd/BinLifter/MIPS/MIPS.fs deleted file mode 100644 index 87032bc0..00000000 --- a/src/FrontEnd/BinLifter/MIPS/MIPS.fs +++ /dev/null @@ -1,70 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.MIPS - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for MIPS instructions. -type MIPSTranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for MIPS instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type MIPSParser (isa: ISA) = - inherit Parser () - let wordSize = isa.WordSize - let arch = isa.Arch - let reader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader arch wordSize addr :> Instruction - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader arch wordSize addr :> Instruction - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - MIPSTranslationContext (isa, regexprs) :> TranslationContext, - MIPSRegisterBay (isa.WordSize, regexprs) :> RegisterBay - ) - - let initRegBay isa = - let regexprs = RegExprs (isa.WordSize) - MIPSRegisterBay (isa.WordSize, regexprs) :> RegisterBay - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs b/src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs index 4b7613b1..7b5bb3f0 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSDisasm.fs @@ -76,13 +76,16 @@ let opCodeToString = function | Op.BC3T -> "bc3t" | Op.BC3TL -> "bc3tl" | Op.BEQ -> "beq" + | Op.BEQL -> "beql" | Op.BGEZ -> "bgez" | Op.BGEZAL -> "bgezal" | Op.BGTZ -> "bgtz" | Op.BITSWAP -> "bitswap" | Op.BLEZ -> "blez" | Op.BLTZ -> "bltz" + | Op.BLTZAL -> "bltzal" | Op.BNE -> "bne" + | Op.BNEL -> "bnel" | Op.BREAK -> "break" | Op.C -> "c" | Op.CFC1 -> "cfc1" @@ -90,6 +93,8 @@ let opCodeToString = function | Op.CTC1 -> "ctc1" | Op.CVTD -> "cvt.d" | Op.CVTS -> "cvt.s" + | Op.CVTW -> "cvt.w" + | Op.DADD -> "dadd" | Op.DADDIU -> "daddiu" | Op.DADDU -> "daddu" | Op.DALIGN -> "dalign" @@ -216,7 +221,9 @@ let opCodeToString = function | Op.SWR -> "swr" | Op.SWXC1 -> "swxc1" | Op.SYNC -> "sync" + | Op.SYSCALL -> "syscall" | Op.TEQ -> "teq" + | Op.TEQI -> "teqi" | Op.TRUNCL -> "trunc.l" | Op.TRUNCW -> "trunc.w" | Op.WSBH -> "wsbh" @@ -234,34 +241,39 @@ let inline appendFmt insInfo opcode = | None -> opcode | Some f -> opcode + fmtToString f -let inline buildOpcode ins (builder: DisasmBuilder<_>) = +let inline buildOpcode ins (builder: DisasmBuilder) = let str = opCodeToString ins.Opcode |> appendCond ins |> appendFmt ins builder.Accumulate AsmWordKind.Mnemonic str -let inline relToString pc offset (builder: DisasmBuilder<_>) = +let inline relToString pc offset (builder: DisasmBuilder) = let targetAddr = pc + uint64 offset - builder.Accumulate AsmWordKind.Value (String.u64ToHex targetAddr) + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 targetAddr) -let oprToString insInfo opr delim (builder: DisasmBuilder<_>) = +let inline regToString ins = + match ins.OperationSize with + | 64 -> Register.toString64 + | _ -> Register.toString32 + +let oprToString insInfo opr delim (builder: DisasmBuilder) = match opr with | OpReg reg -> builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Variable (Register.toString reg) + builder.Accumulate AsmWordKind.Variable (regToString insInfo reg) | OpImm imm | OpShiftAmount imm -> builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (String.u64ToHex imm) + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 imm) | OpMem (b, Imm off, _) -> builder.Accumulate AsmWordKind.String delim builder.Accumulate AsmWordKind.Value (off.ToString ("D")) builder.Accumulate AsmWordKind.String "(" - builder.Accumulate AsmWordKind.Variable (Register.toString b) + builder.Accumulate AsmWordKind.Variable (regToString insInfo b) builder.Accumulate AsmWordKind.String ")" | OpMem (b, Reg off, _) -> builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Variable (Register.toString off) + builder.Accumulate AsmWordKind.Variable (regToString insInfo off) builder.Accumulate AsmWordKind.String "(" - builder.Accumulate AsmWordKind.Variable (Register.toString b) + builder.Accumulate AsmWordKind.Variable (regToString insInfo b) builder.Accumulate AsmWordKind.String ")" | OpAddr (Relative offset) -> builder.Accumulate AsmWordKind.String delim @@ -269,7 +281,7 @@ let oprToString insInfo opr delim (builder: DisasmBuilder<_>) = // Never gets matched. Only used in intermediate stage mips assembly parser. | GoToLabel _ -> raise InvalidOperandException -let buildOprs insInfo (builder: DisasmBuilder<_>) = +let buildOprs insInfo (builder: DisasmBuilder) = match insInfo.Operands with | NoOperand -> () | OneOperand opr -> @@ -287,7 +299,7 @@ let buildOprs insInfo (builder: DisasmBuilder<_>) = oprToString insInfo opr3 ", " builder oprToString insInfo opr4 ", " builder -let disasm wordSize insInfo (builder: DisasmBuilder<_>) = +let disasm wordSize insInfo (builder: DisasmBuilder) = if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode insInfo builder buildOprs insInfo builder diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs b/src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs index dd38665c..4e9aa85e 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSHelper.fs @@ -26,16 +26,10 @@ module internal B2R2.FrontEnd.BinLifter.MIPS.Helper open B2R2 open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinLifter.MIPS.Utils +open B2R2.FrontEnd.BinLifter.BitData -let isRel2 arch = arch = Arch.MIPS32R2 || arch = Arch.MIPS64R2 -let isRel6 arch = arch = Arch.MIPS32R6 || arch = Arch.MIPS64R6 -let isMIPS32 arch = arch = Arch.MIPS32R2 || arch = Arch.MIPS32R6 -let isMIPS64 arch = arch = Arch.MIPS64R2 || arch = Arch.MIPS64R6 -let isMIPS32R2 arch = arch = Arch.MIPS32R2 -let isMIPS64R2 arch = arch = Arch.MIPS64R2 -let isMIPS32R6 arch = arch = Arch.MIPS32R6 -let isMIPS64R6 arch = arch = Arch.MIPS64R6 +let isMIPS32 arch = arch = Architecture.MIPS32 +let isMIPS64 arch = arch = Architecture.MIPS64 let getRegister = function | 0x0uy -> R.R0 @@ -127,52 +121,80 @@ let getCondition = function | _ -> raise InvalidConditionException let gprLen = function - | Arch.MIPS32R2 | Arch.MIPS32R6 -> 32 - | Arch.MIPS64R2 | Arch.MIPS64R6 -> 64 - | _ -> failwith "Not Implemented." + | Architecture.MIPS32 -> 32 + | Architecture.MIPS64 -> 64 + | _ -> Utils.impossible () let num9 b = extract b 15u 7u + let num16 b = extract b 15u 0u + let num26 b = extract b 25u 0u + let getRegFrom2521 b = getRegister (extract b 25u 21u |> byte) + let getRegFrom2016 b = getRegister (extract b 20u 16u |> byte) + let getRegFrom1511 b = getRegister (extract b 15u 11u |> byte) + let getFRegFrom2521 b = getFRegister (extract b 25u 21u |> byte) + let getFRegFrom2016 b = getFRegister (extract b 20u 16u |> byte) + let getFRegFrom2018 b = getFRegister (extract b 20u 18u |> byte) + let getFRegFrom1511 b = getFRegister (extract b 15u 11u |> byte) + let getFRegFrom106 b = getFRegister (extract b 10u 6u |> byte) + let getFRegFrom108 b = getFRegister (extract b 10u 8u |> byte) let rs b = getRegFrom2521 b |> OpReg + let rt b = getRegFrom2016 b |> OpReg + let rd b = getRegFrom1511 b |> OpReg let fs b = getFRegFrom1511 b |> OpReg + let ft b = getFRegFrom2016 b |> OpReg + let fd b = getFRegFrom106 b |> OpReg + let fr b = getFRegFrom2521 b |> OpReg -let cc10 b = getFRegFrom108 b |> OpReg // FIXME: Floating Point cond code CC. -let cc20 b = getFRegFrom2018 b |> OpReg // FIXME: Floating Point cond code CC. + +let cc10 b = extract b 10u 8u |> uint64 |> OpImm + +let cc20 b = extract b 20u 18u |> uint64 |> OpImm let sa b = extract b 10u 6u |> uint64 |> OpShiftAmount + let bp b = extract b 7u 6u |> uint64 |> OpImm +let bp64 b = extract b 8u 6u |> uint64 |> OpImm + let hint b = extract b 20u 16u |> uint64 |> OpImm (* FIMXE: hint on page 420 *) + let sel b = extract b 8u 6u |> uint64 |> OpImm (* FIXME: sel on page 432 *) let rel16 b = let off = num16 b |> uint64 <<< 2 |> signExtend 18 64 |> int64 off + 4L |> Relative |> OpAddr + let region b = num26 b <<< 2 |> uint64 |> OpImm (* FIXME: PC-region on page 268 *) + let stype b = extract b 10u 6u |> uint64 |> OpImm (* FIXME: SType Field on page 533 *) + let imm16 b = num16 b |> uint64 |> OpImm + let imm16SignExt b = num16 b |> uint64 |> signExtend 16 64 |> OpImm + let memBaseOff b num accLength = let offset = num b |> uint64 |> signExtend 16 64 |> int64 OpMem (getRegFrom2521 b, Imm offset, accLength) + let memBaseIdx b accLength = OpMem (getRegFrom2521 b, Reg (getRegFrom2016 b), accLength) @@ -180,72 +202,122 @@ let posSize b = let msb = extract b 15u 11u let lsb = extract b 10u 6u lsb |> uint64 |> OpImm, msb + 1u - lsb |> uint64 |> OpImm + let posSize2 b = let msbd = extract b 15u 11u let lsb = extract b 10u 6u lsb |> uint64 |> OpImm, msbd + 1u |> uint64 |> OpImm + let posSize3 b = let msbminus32 = extract b 15u 11u let lsb = extract b 10u 6u lsb |> uint64 |> OpImm, msbminus32 + 33u - lsb |> uint64 |> OpImm + let posSize4 b = let msbminus32 = extract b 15u 11u let lsbminus32 = extract b 10u 6u let pos = lsbminus32 + 32u pos |> uint64 |> OpImm, msbminus32 + 33u - pos |> uint64 |> OpImm + let posSize5 b = let msbdminus32 = extract b 15u 11u let lsb = extract b 10u 6u lsb |> uint64 |> OpImm, msbdminus32 + 33u |> uint64 |> OpImm + let posSize6 b = let msbd = extract b 15u 11u let lsbminus32 = extract b 10u 6u lsbminus32 + 32u |> uint64 |> OpImm, msbd + 1u |> uint64 |> OpImm let getRel16 b = OneOperand (rel16 b) + let getRs b = OneOperand (rs b) + let getRd b = OneOperand (rd b) + let getTarget b = OneOperand (region b) + let getStype b = OneOperand (stype b) + let getRdRs b = TwoOperands (rd b, rs b) + let getRdRtRs b = ThreeOperands (rd b, rt b, rs b) + let getRdRsRt b = ThreeOperands (rd b, rs b, rt b) + let getRsRt b = TwoOperands (rs b, rt b) + let getRdRt b = TwoOperands (rd b, rt b) + let getRtRdSel b = ThreeOperands (rt b, rd b, sel b) -let getRsRtRel16 b = ThreeOperands (rs b, rt b, rel16 b) + +let getRsRtRel16 b = ThreeOperands (rs b, rt b, rel16 b) (* rs, rt, offset *) + let getRsRel16 b = TwoOperands (rs b, rel16 b) + +let getRsImm16s b = TwoOperands (rs b, imm16SignExt b) + let getRtImm16 b = TwoOperands (rt b, imm16 b) + let getRtRsImm16s b = ThreeOperands (rt b, rs b, imm16SignExt b) + let getRtRsImm16 b = ThreeOperands (rt b, rs b, imm16 b) + let getRtMemBaseOff b accLen = TwoOperands (rt b, memBaseOff b num16 accLen) + let getRtMemBaseOff9 b accLen = TwoOperands (rt b, memBaseOff b num9 accLen) + let getFtMemBaseOff b accLen = TwoOperands (ft b, memBaseOff b num16 accLen) + let getHintMemBaseOff b accLen = TwoOperands (hint b, memBaseOff b num16 accLen) + let getHintMemBaseOff9 b accLen = TwoOperands (hint b, memBaseOff b num9 accLen) + let getFdMemBaseIdx b accLen = TwoOperands (fd b, memBaseIdx b accLen) + let getFsMemBaseIdx b accLen = TwoOperands (fs b, memBaseIdx b accLen) + let getHintMemBaseIdx b accLen = TwoOperands (hint b, memBaseIdx b accLen) + let getRdRtSa b = ThreeOperands (rd b, rt b, sa b) + let getRdRsCc b = ThreeOperands (rd b, rs b, cc20 b) + let getRdRsRtBp b = FourOperands (rd b, rs b, rt b, bp b) + +let getRdRsRtBp64 b = FourOperands (rd b, rs b, rt b, bp64 b) + let getRtRsPosSize b = let p, s = posSize b in FourOperands (rt b, rs b, p, s) + let getRtRsPosSize2 b = let p, s = posSize2 b in FourOperands (rt b, rs b, p, s) + let getRtRsPosSize3 b = let p, s = posSize3 b in FourOperands (rt b, rs b, p, s) + let getRtRsPosSize4 b = let p, s = posSize4 b in FourOperands (rt b, rs b, p, s) + let getRtRsPosSize5 b = let p, s = posSize5 b in FourOperands (rt b, rs b, p, s) + let getRtRsPosSize6 b = let p, s = posSize6 b in FourOperands (rt b, rs b, p, s) + let getRtFs b = TwoOperands (rt b, fs b) + let getCcOff b = match extract b 20u 18u with | 0u -> OneOperand (rel16 b) | a -> TwoOperands (a |> uint64 |> OpImm, rel16 b) + let getFsFt b = TwoOperands (fs b, ft b) + let getFdFs b = TwoOperands (fd b, fs b) + let getFdFsRt b = ThreeOperands (fd b, fs b, rt b) + let getFdFsCc b = ThreeOperands (fd b, fs b, cc20 b) + let getCcFsFt b = ThreeOperands (cc10 b, fs b, ft b) + let getFdFsFt b = ThreeOperands (fd b, fs b, ft b) + let getFdFrFsFt b = FourOperands (fd b, fr b, fs b, ft b) // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs b/src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs index 69264d40..5d79ff4d 100755 --- a/src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSInstruction.fs @@ -40,7 +40,7 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = | Opcode.B | Opcode.BAL | Opcode.BEQ | Opcode.BGEZ | Opcode.BGEZAL | Opcode.BGTZ | Opcode.BLEZ | Opcode.BLTZ | Opcode.BNE | Opcode.JALR | Opcode.JALRHB | Opcode.JR | Opcode.JRHB - | Opcode.J | Opcode.JAL -> true + | Opcode.J | Opcode.JAL | Opcode.BC1F | Opcode.BC1T -> true | _ -> false override __.IsModeChanging () = false @@ -62,18 +62,19 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = override __.IsCondBranch () = match __.Info.Opcode with | Opcode.BEQ | Opcode.BLTZ | Opcode.BLEZ | Opcode.BGTZ | Opcode.BGEZ - | Opcode.BGEZAL | Opcode.BNE -> true + | Opcode.BGEZAL | Opcode.BNE | Opcode.BC1F | Opcode.BC1T -> true | _ -> false override __.IsCJmpOnTrue () = match __.Info.Opcode with | Opcode.BEQ | Opcode.BLTZ | Opcode.BLEZ | Opcode.BGTZ | Opcode.BGEZ - | Opcode.BGEZAL -> true + | Opcode.BGEZAL | Opcode.BC1F | Opcode.BC1T -> true | _ -> false override __.IsCall () = match __.Info.Opcode with - | Opcode.BAL | Opcode.BGEZAL | Opcode.JALR | Opcode.JALRHB | Opcode.JAL -> true + | Opcode.BAL | Opcode.BGEZAL | Opcode.JALR | Opcode.JALRHB | Opcode.JAL -> + true | _ -> false override __.IsRET () = @@ -84,13 +85,20 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = | _ -> false | _ -> false - override __.IsInterrupt () = Utils.futureFeature () + override __.IsInterrupt () = + match __.Info.Opcode with + | Opcode.SYSCALL | Opcode.WAIT -> true + | _ -> false - override __.IsExit () = Utils.futureFeature () + override __.IsExit () = + match __.Info.Opcode with + | Opcode.DERET | Opcode.ERET | Opcode.ERETNC -> true + | _ -> false - override __.IsBBLEnd () = // FIXME - __.IsDirectBranch () || - __.IsIndirectBranch () + override __.IsBBLEnd () = + __.IsBranch () + || __.IsInterrupt () + || __.IsExit () override __.DirectBranchTarget (addr: byref) = if __.IsBranch () then @@ -111,7 +119,7 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = else false override __.IndirectTrampolineAddr (_addr: byref) = - if __.IsBranch () then Utils.futureFeature () + if __.IsIndirectBranch () then Utils.futureFeature () else false override __.Immediate (v: byref) = @@ -136,28 +144,28 @@ type MIPSInstruction (addr, numBytes, insInfo, wordSize) = __.Info.Opcode = Opcode.NOP override __.Translate ctxt = - (Lifter.translate __.Info ctxt).ToStmts () + (Lifter.translate __.Info numBytes ctxt).ToStmts () override __.TranslateToList ctxt = - Lifter.translate __.Info ctxt + Lifter.translate __.Info numBytes ctxt - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, wordSize, addr, numBytes) Disasm.disasm wordSize __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, wordSize, addr, numBytes) Disasm.disasm wordSize __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, wordSize, addr, numBytes, 8) Disasm.disasm wordSize __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs b/src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs index 8fa83297..e6f47d33 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSLifter.fs @@ -29,43 +29,107 @@ open B2R2.BinIR open B2R2.BinIR.LowUIR open B2R2.BinIR.LowUIR.AST.InfixOp open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators open B2R2.FrontEnd.BinLifter.LiftingUtils open B2R2.FrontEnd.BinLifter.MIPS let inline getRegVar (ctxt: TranslationContext) name = Register.toRegID name |> ctxt.GetRegVar -let inline private ( + dst := dst (* Prevent setting r0. Our optimizer will remove this anyways. *) + | _ -> + dst := src let transOprToExpr insInfo ctxt = function | OpReg reg -> getRegVar ctxt reg | OpImm imm | OpShiftAmount imm -> numU64 imm ctxt.WordBitSize | OpMem (b, Imm o, sz) -> - AST.loadLE sz (getRegVar ctxt b .+ numI64 o ctxt.WordBitSize) + if ctxt.Endianness = Endian.Little then + AST.loadLE sz (getRegVar ctxt b .+ numI64 o ctxt.WordBitSize) + else AST.loadBE sz (getRegVar ctxt b .+ numI64 o ctxt.WordBitSize) | OpMem (b, Reg o, sz) -> - AST.loadLE sz (getRegVar ctxt b .+ getRegVar ctxt o) + if ctxt.Endianness = Endian.Little then + AST.loadLE sz (getRegVar ctxt b .+ getRegVar ctxt o) + else AST.loadBE sz (getRegVar ctxt b .+ getRegVar ctxt o) | OpAddr (Relative o) -> - numI64 (int64 insInfo.Address + o + int64 insInfo.NumBytes) ctxt.WordBitSize - |> AST.loadLE ctxt.WordBitSize + numI64 (int64 insInfo.Address + o) ctxt.WordBitSize | GoToLabel _ -> raise InvalidOperandException +let private is32Bit (ctxt: TranslationContext) = ctxt.WordBitSize = 32 + +let private transOprToFPConvert (dstFmt: InsInfo) ctxt = function + | OpReg reg -> + if is32Bit ctxt then getRegVar ctxt reg + else + match dstFmt.Fmt with + | Some Fmt.S | Some Fmt.W -> getRegVar ctxt reg |> AST.xtlo 32 + | Some Fmt.D | Some Fmt.L -> getRegVar ctxt reg + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandException + +let private transOprToFP ctxt = function + | OpReg reg -> + if is32Bit ctxt then getRegVar ctxt reg + else getRegVar ctxt reg |> AST.xtlo 32 + | _ -> raise InvalidOperandException + +let private transTwoFP ctxt (o1, o2) = + transOprToFP ctxt o1, transOprToFP ctxt o2 + +let private transThreeFP ctxt (o1, o2, o3) = + transOprToFP ctxt o1, transOprToFP ctxt o2, transOprToFP ctxt o3 + +let private transFourFP ctxt (o1, o2, o3, o4) = + transOprToFP ctxt o1, transOprToFP ctxt o2, transOprToFP ctxt o3, + transOprToFP ctxt o4 + +let transTwoOprFPConvert insInfo ctxt (o1, o2) = + transOprToFPConvert insInfo ctxt o1, transOprToFPConvert insInfo ctxt o2 + +let private transOprToFPPair ctxt = function + | OpReg reg -> + if is32Bit ctxt then + getRegVar ctxt (Register.getFPPairReg reg), getRegVar ctxt reg + else AST.b0, getRegVar ctxt reg + | _ -> raise InvalidOperandException + +let private transOprToFPPairConcat ctxt = function + | OpReg reg -> + if is32Bit ctxt then + AST.concat (getRegVar ctxt (Register.getFPPairReg reg)) + (getRegVar ctxt reg) + else getRegVar ctxt reg + | _ -> raise InvalidOperandException + +let private dstAssignForFP dstB dstA result ctxt ir = + if is32Bit ctxt then + let srcB = AST.xthi 32 result + let srcA = AST.xtlo 32 result + !!ir (dstA := srcA) + !!ir (dstB := srcB) + else + !!ir (dstA := result) + +let private fpneg ir oprSz reg = + let mask = + if oprSz = 32 then numU64 0x80000000UL oprSz + else numU64 0x8000000000000000UL oprSz + !!ir (reg := reg <+> mask) + let transOprToImm = function | OpImm imm | OpShiftAmount imm -> imm | _ -> raise InvalidOperandException +let transOprToImmToInt = function + | OpImm imm + | OpShiftAmount imm -> int imm + | _ -> raise InvalidOperandException + let transOprToBaseOffset ctxt = function | OpMem (b, Imm o, _) -> getRegVar ctxt b .+ numI64 o ctxt.WordBitSize | OpMem (b, Reg o, _) -> getRegVar ctxt b .+ getRegVar ctxt o @@ -102,11 +166,90 @@ let transThreeOprs insInfo ctxt (o1, o2, o3) = transOprToExpr insInfo ctxt o2, transOprToExpr insInfo ctxt o3 -let sideEffects insInfo name = - let builder = IRBuilder (4) - startMark insInfo builder - builder ) + AST.ite (rm == numI32 0 32) + (AST.cast CastKind.FtoIRound oprSz src) // 0 RN + (AST.ite (rm == numI32 1 32) + (AST.cast CastKind.FtoITrunc oprSz src) // 1 RZ + (AST.ite (rm == numI32 2 32) + (AST.cast CastKind.FtoICeil oprSz src) // 2 RP + (AST.cast CastKind.FtoIFloor oprSz src))) // 3 RM + +let private isSNaN32 signalBit nanCheck = + nanCheck .& (signalBit == AST.num0 32) + +let private isSNaN64 signalBit nanCheck = + nanCheck .& (signalBit == AST.num0 64) + +let private isQNaN32 signalBit nanCheck = + nanCheck .& (signalBit != AST.num0 32) + +let private isQNaN64 signalBit nanCheck = + nanCheck .& (signalBit != AST.num0 64) + +let private isNaN oprSz fullExpo mantissa = + match oprSz with + | 32 -> AST.xtlo 1 (fullExpo .& (mantissa != AST.num0 32)) + | 64 -> AST.xtlo 1 (fullExpo .& (mantissa != AST.num0 64)) + | _ -> Utils.impossible () + +let private isSNaN oprSz signalBit isNaN = + match oprSz with + | 32 -> isSNaN32 signalBit isNaN + | 64 -> isSNaN64 signalBit isNaN + | _ -> Utils.impossible () + +let private isQNaN oprSz signalBit isNaN = + match oprSz with + | 32 -> isQNaN32 signalBit isNaN + | 64 -> isQNaN64 signalBit isNaN + | _ -> Utils.impossible () + +let private isInfinity oprSz fullExpo mantissa = + match oprSz with + | 32 -> AST.xtlo 1 (fullExpo .& (mantissa == AST.num0 32)) + | 64 -> AST.xtlo 1 (fullExpo .& (mantissa == AST.num0 64)) + | _ -> Utils.impossible () + +let private isZero oprSz baseExpr = + match oprSz with + | 32 -> + let mask = numU32 0x7fffffffu 32 + AST.eq (baseExpr .& mask) (AST.num0 32) + | 64 -> + let mask = numU64 0x7fffffff_ffffffffUL 64 + AST.eq (baseExpr .& mask) (AST.num0 64) + | _ -> Utils.impossible () + +let private transBigEndianCPU (ctxt: TranslationContext) opSz = + match ctxt.Endianness, opSz with + | Endian.Little, 32 -> AST.num0 32 + | Endian.Big, 32 -> numI32 0b11 32 + | Endian.Little, 64 -> AST.num0 64 + | Endian.Big, 64 -> numI32 0b111 64 + | _ -> raise InvalidOperandException + +let sideEffects insLen ctxt name = + let ir = !*ctxt + !ir insLen let checkOverfolwOnAdd e1 e2 r = let e1High = AST.extract e1 1 31 @@ -114,334 +257,849 @@ let checkOverfolwOnAdd e1 e2 r = let rHigh = AST.extract r 1 31 (e1High == e2High) .& (e1High <+> rHigh) -let notWordValue v = - (AST.xthi 32 v) != AST.sext 32 (AST.extract v 1 31) +let checkOverfolwOnDadd e1 e2 r = + let e1High = AST.extract e1 1 63 + let e2High = AST.extract e2 1 63 + let rHigh = AST.extract r 1 63 + (e1High == e2High) .& (e1High <+> rHigh) -let add insInfo ctxt = - let builder = IRBuilder (8) - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let result = builder.NewTempVar 32 - let cond = checkOverfolwOnAdd rs rt result - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let result = builder.NewTempVar 32 - let cond = notWordValue rs .| notWordValue rt - let cond2 = checkOverfolwOnAdd rs rt result - startMark insInfo builder - builder rs .+ AST.xtlo 32 rt) - builder result) - builder transThreeOprs insInfo ctxt - let result = builder.NewTempVar 32 - startMark insInfo builder - builder + let bit32 = numI64 0x100000000L 64 + let cond = mask64 .- e1 .< e2 + AST.ite cond bit32 (AST.num0 64) + +let private getExponentFull src oprSz = + if oprSz = 32 then + ((src >> numI32 23 32) .& numI32 0xff 32) == numI32 0xff 32 + else + ((src >> numI32 52 64) .& numI32 0x7ff 64) == numI32 0x7ff 64 + +let private getMantissa src oprSz = + if oprSz = 32 then src .& numU32 0x7fffffu 32 + else src .& numU64 0xfffff_ffffffffUL 64 + +let private getSignalBit src oprSz = + if oprSz = 32 then src .& numU32 (1u <<< 22) 32 + else src .& numU64 (1UL <<< 51) 64 + +let private subNormal oprSz src1 src2 result ir = + let struct (qNaNBox, sNaNBox, sqNaNBox, exponent) = tmpVars4 ir 1 + let struct (sign, isNaNCheck) = tmpVars2 ir 1 + let struct (mantissa, signalBit) = tmpVars2 ir oprSz + !!ir (mantissa := getMantissa result oprSz) + !!ir (exponent := getExponentFull result oprSz) + !!ir (signalBit := getSignalBit result oprSz) + !!ir (isNaNCheck := isNaN oprSz exponent mantissa) + !!ir (qNaNBox := isQNaN oprSz signalBit isNaNCheck) + !!ir (sNaNBox := isSNaN oprSz signalBit isNaNCheck) + let mantissa1 = getMantissa src1 oprSz + let mantissa2 = getMantissa src2 oprSz + let infChk = + AST.not (isInfinity oprSz (getExponentFull src1 oprSz) mantissa1 + .| isInfinity oprSz (getExponentFull src2 oprSz) mantissa2) + !!ir (sign := AST.xthi 1 result .& infChk) + !!ir (sqNaNBox := qNaNBox .| sNaNBox) + !!ir (result := + AST.ite sqNaNBox ( + let struct (sNaNVal, negSNaNVal, qNaNVal, negQNaNVal) = + match oprSz with + | 32 -> + struct (numU32 0x7fffffffu 32, numU32 0xffffffffu 32, + numU32 0x7fbfffffu 32, numU32 0xffbfffffu 32) + | _ -> struct (numU64 0x7fffffffffffffffUL 64, + numU64 0xffffffffffffffffUL 64, + numU64 0x7ff7ffffffffffffUL 64, + numU64 0xfff7ffffffffffffUL 64) + let qNaNWithSign = AST.ite sign negQNaNVal qNaNVal + let sNaNWithSign = AST.ite sign negSNaNVal sNaNVal + AST.ite qNaNBox qNaNWithSign (AST.ite sNaNBox sNaNWithSign result)) + result) + +let divNormal oprSz src1 src2 result ir = + let struct (exponent, isNaNCheck, sign) = tmpVars3 ir 1 + let struct (mantissa, signalBit) = tmpVars2 ir oprSz + !!ir (sign := AST.xthi 1 result) + !!ir (mantissa := getMantissa result oprSz) + !!ir (signalBit := getSignalBit result oprSz) + !!ir (exponent := getExponentFull result oprSz) + !!ir (isNaNCheck := isNaN oprSz exponent mantissa) + let src1Zero = src1 == AST.num0 oprSz + let src2Zero = src2 == AST.num0 oprSz + let qNan = isQNaN oprSz signalBit isNaNCheck + let sNan = isSNaN oprSz signalBit isNaNCheck + let struct (sNaNVal, negSNaNVal, qNaNVal, negQNaNVal) = + match oprSz with + | 32 -> + struct (numU32 0x7fffffffu 32, numU32 0xffffffffu 32, + numU32 0x7fbfffffu 32, numU32 0xffbfffffu 32) + | _ -> struct (numU64 0x7fffffffffffffffUL 64, + numU64 0xffffffffffffffffUL 64, + numU64 0x7ff7ffffffffffffUL 64, + numU64 0xfff7ffffffffffffUL 64) + let qNaNWithSign = AST.ite sign negQNaNVal qNaNVal + let sNaNWithSign = AST.ite sign negSNaNVal sNaNVal + !!ir (result := AST.ite (src1Zero .& src2Zero) qNaNVal + (AST.ite qNan qNaNWithSign + (AST.ite sNan sNaNWithSign result))) + +let private normalizeValue oprSz result ir = + let struct (qNaNBox, sNaNBox, infBox, exponent) = tmpVars4 ir 1 + let struct (isNaNCheck, sign) = tmpVars2 ir 1 + !!ir (exponent := getExponentFull result oprSz) + let struct (mantissa, signalBit) = tmpVars2 ir oprSz + !!ir (mantissa := getMantissa result oprSz) + !!ir (isNaNCheck := isNaN oprSz exponent mantissa) + !!ir (signalBit := getSignalBit result oprSz) + !!ir (qNaNBox := isQNaN oprSz signalBit isNaNCheck) + !!ir (sNaNBox := isSNaN oprSz signalBit isNaNCheck) + !!ir (infBox := isInfinity oprSz exponent mantissa) + !!ir (sign := AST.xthi 1 result) + let condBox = qNaNBox .| sNaNBox .| infBox + !!ir (result := + AST.ite condBox ( + let struct (sNaNVal, negSNaNVal, qNaNVal, negQNaNVal) = + match oprSz with + | 32 -> + struct (numU32 0x7fffffffu 32, numU32 0xffffffffu 32, + numU32 0x7fbfffffu 32, numU32 0xffbfffffu 32) + | _ -> struct (numU64 0x7fffffffffffffffUL 64, + numU64 0xffffffffffffffffUL 64, + numU64 0x7ff7ffffffffffffUL 64, + numU64 0xfff7ffffffffffffUL 64) + let struct (pInf, mInf) = + match oprSz with + | 32 -> + struct (numU32 0x7f800000u 32, numU32 0xff800000u 32) + | _ -> struct (numU64 0x7ff0000000000000UL 64, + numU64 0xfff0000000000000UL 64) + let qNanWithSign = AST.ite sign negQNaNVal qNaNVal + let sNanWithSign = AST.ite sign negSNaNVal sNaNVal + let infWithSign = AST.ite sign mInf pInf + AST.ite qNaNBox qNanWithSign (AST.ite sNaNBox sNanWithSign + (AST.ite infBox infWithSign result))) + result) + +let advancePC (ctxt: TranslationContext) ir = + if ctxt.DelayedBranch = InterJmpKind.NotAJmp then + () (* Do nothing, because IEMark will advance PC. *) + else + let nPC = getRegVar ctxt R.NPC + !!ir (AST.interjmp nPC ctxt.DelayedBranch) + ctxt.DelayedBranch <- InterJmpKind.NotAJmp + +let updatePCCond ctxt offset cond kind ir = + let lblTrueCase = !%ir "TrueCase" + let lblFalseCase = !%ir "FalseCase" + let lblEnd = !%ir "End" + let pc = getRegVar ctxt R.PC + let nPC = getRegVar ctxt R.NPC + ctxt.DelayedBranch <- kind + !!ir (AST.cjmp cond (AST.name lblTrueCase) (AST.name lblFalseCase)) + !!ir (AST.lmark lblTrueCase) + !!ir (nPC := offset) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblFalseCase) + !!ir (nPC := pc .+ numI32 8 ctxt.WordBitSize) + !!ir (AST.lmark lblEnd) + +let updateRAPCCond ctxt nAddr offset cond kind ir = + let lblTrueCase = !%ir "TrueCase" + let lblFalseCase = !%ir "FalseCase" + let lblEnd = !%ir "End" + let pc = getRegVar ctxt R.PC + let nPC = getRegVar ctxt R.NPC + ctxt.DelayedBranch <- kind + !!ir (AST.cjmp cond (AST.name lblTrueCase) (AST.name lblFalseCase)) + !!ir (AST.lmark lblTrueCase) + !!ir (nPC := offset) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblFalseCase) + !!ir (nPC := nAddr) + !!ir (AST.lmark lblEnd) + +let private signExtLo64 expr = AST.xtlo 32 expr |> AST.sext 64 + +let private signExtHi64 expr = AST.xthi 32 expr |> AST.sext 64 + +let private getMask size = (1L <<< size) - 1L + +let private shifterLoad fstShf sndShf rRt t1 t2 t3 = + (sndShf (fstShf rRt t1) t1) .| (fstShf t3 t2) + +let private shifterStore fstShf sndShf rRt t1 t2 t3 = + (fstShf (sndShf t3 t2) t2) .| (sndShf rRt t1) + +let private mul64BitReg src1 src2 ir isSign = + let struct (hiSrc1, loSrc1, hiSrc2, loSrc2) = tmpVars4 ir 64 + let struct (tHigh, tLow) = tmpVars2 ir 64 + let struct (src1IsNeg, src2IsNeg, signBit) = tmpVars3 ir 1 + let n32 = numI32 32 64 + let mask32 = numI64 0xFFFFFFFFL 64 + if isSign then + !!ir (src1IsNeg := AST.xthi 1 src1) + !!ir (src2IsNeg := AST.xthi 1 src2) + !!ir (src1 := AST.ite src1IsNeg (AST.neg src1) src1) + !!ir (src2 := AST.ite src2IsNeg (AST.neg src2) src2) + else () + !!ir (hiSrc1 := (src1 >> n32) .& mask32) (* SRC1[63:32] *) + !!ir (loSrc1 := src1 .& mask32) (* SRC1[31:0] *) + !!ir (hiSrc2 := (src2 >> n32) .& mask32) (* SRC2[63:32] *) + !!ir (loSrc2 := src2 .& mask32) (* SRC2[31:0] *) + let pHigh = hiSrc1 .* hiSrc2 + let pMid= (hiSrc1 .* loSrc2) .+ (loSrc1 .* hiSrc2) + let pLow = loSrc1 .* loSrc2 + let overFlowBit = checkOverfolwOnDMul (hiSrc1 .* loSrc2) (loSrc1 .* hiSrc2) + let high = pHigh .+ ((pMid .+ (pLow >> n32)) >> n32) .+ overFlowBit + let low = pLow .+ ((pMid .& mask32) << n32) + if isSign then + !!ir (signBit := src1IsNeg <+> src2IsNeg) + !!ir (tHigh := AST.ite signBit (AST.not high) high) + !!ir (tLow := AST.ite signBit (AST.neg low) low) + else + !!ir (tHigh := high) + !!ir (tLow := low) + struct (tHigh, tLow) + +let abs insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + ! + let fdB, fdA = transOprToFPPair ctxt fd + let fs = transOprToFPPairConcat ctxt fs + fpneg ir 64 fs + dstAssignForFP fdB fdA fs ctxt ir + | _ -> + let fd, fs = transTwoFP ctxt (fd, fs) + fpneg ir 32 fs + !!ir (fd := fs) + advancePC ctxt ir + !>ir insLen + +let private reDupSrc opr1 opr2 expr1 expr2 tmp1 tmp2 ir = + if opr1 = opr2 then + !!ir (tmp1 := expr1) + !!ir (tmp2 := tmp1) + else + !!ir (tmp1 := expr1) + !!ir (tmp2 := expr2) + +let add insInfo insLen ctxt = + let ir = !*ctxt + ! + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let rd, rs, rt = transThreeOprs insInfo ctxt (dst, src1, src2) + let result = if is32Bit ctxt then rs .+ rt else signExtLo64 (rs .+ rt) + let cond = checkOverfolwOnAdd rs rt result + !!ir (AST.cjmp cond (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "int overflow")) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (rd := result) + !!ir (AST.lmark lblEnd) + | Some Fmt.S -> + let fd, fs, ft = transThreeFP ctxt (dst, src1, src2) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 32 + reDupSrc src1 src2 fs ft tSrc1 tSrc2 ir + !!ir (result := AST.fadd tSrc1 tSrc2) + normalizeValue 32 result ir + !!ir (fd := result) + | _ -> + let fdB, fdA = transOprToFPPair ctxt dst + let fs, ft = transFPConcatTwoOprs ctxt (src1, src2) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 64 + reDupSrc src1 src2 fs ft tSrc1 tSrc2 ir + !!ir (result := AST.fadd tSrc1 tSrc2) + normalizeValue 64 result ir + dstAssignForFP fdB fdA result ctxt ir + advancePC ctxt ir + !>ir insLen + +let addiu insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let result = builder.NewTempVar 64 - let cond = notWordValue rs - startMark insInfo builder - builder (AST.xtlo 32 result)) - builder ir insLen + +let addu insInfo insLen ctxt = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen + +let logAnd insInfo insLen ctxt = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let result = builder.NewTempVar 64 - let cond = notWordValue rs .| notWordValue rt - startMark insInfo builder - builder (AST.xtlo 32 result)) - builder transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen -let andi insInfo ctxt = - let builder = IRBuilder (4) +let andi insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen -let aui insInfo ctxt = - let builder = IRBuilder (4) +let aui insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let imm = imm << numI32 16 ctxt.WordBitSize - startMark insInfo builder - builder ir insLen + +let b insInfo insLen ctxt = + let ir = !*ctxt + let nPC = getRegVar ctxt R.NPC let offset = getOneOpr insInfo |> transOneOpr insInfo ctxt - startMark insInfo builder - builder ir insLen -let bal insInfo ctxt = - let builder = IRBuilder (4) +let bal insInfo insLen ctxt = + let ir = !*ctxt let offset = getOneOpr insInfo |> transOneOpr insInfo ctxt let pc = getRegVar ctxt R.PC - startMark insInfo builder - builder ir insLen + +let private fpConditionCode cc ctxt = + let fcsr = getRegVar ctxt R.FCSR + if cc = 0 then (fcsr .& numU32 0x800000u 32) == numU32 0x800000u 32 + else + let num = numU32 0x1000000u 32 << numI32 cc 32 + (fcsr .& num) == num -let beq insInfo ctxt = - let builder = IRBuilder (4) +let bc1f insInfo insLen ctxt = + let ir = !*ctxt + ! + let offset = transOneOpr insInfo ctxt off + let cond = AST.not (fpConditionCode 0 ctxt) + updatePCCond ctxt offset cond InterJmpKind.Base ir + | _ -> + let cc, offset = getTwoOprs insInfo + let offset = transOprToExpr insInfo ctxt offset + let cc = transOprToImmToInt cc + let cond = AST.not (fpConditionCode cc ctxt) + updatePCCond ctxt offset cond InterJmpKind.Base ir + !>ir insLen + +let bc1t insInfo insLen ctxt = + let ir = !*ctxt + ! + let offset = transOneOpr insInfo ctxt off + let cond = fpConditionCode 0 ctxt + updatePCCond ctxt offset cond InterJmpKind.Base ir + | _ -> + let cc, offset = getTwoOprs insInfo + let offset = transOprToExpr insInfo ctxt offset + let cc = transOprToImmToInt cc + let cond = fpConditionCode cc ctxt + updatePCCond ctxt offset cond InterJmpKind.Base ir + !>ir insLen + +let beq insInfo insLen ctxt = + let ir = !*ctxt let rs, rt, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let cond = rs == rt - let fallThrough = - bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder ir insLen + +let blez insInfo insLen ctxt = + let ir = !*ctxt let rs, offset = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let cond = AST.le rs (AST.num0 ctxt.WordBitSize) - let fallThrough = - bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder ir insLen + +let bltz insInfo insLen ctxt = + let ir = !*ctxt + let rs, offset = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let cond = AST.slt rs (AST.num0 ctxt.WordBitSize) + !ir insLen + +let bltzal insInfo insLen ctxt = + let ir = !*ctxt let rs, offset = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let cond = AST.lt rs (AST.num0 ctxt.WordBitSize) - let fallThrough = - bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder ir insLen + +let bgez insInfo insLen ctxt = + let ir = !*ctxt let rs, offset = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let cond = AST.ge rs (AST.num0 ctxt.WordBitSize) - let fallThrough = - bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder ir insLen + +let bgezal insInfo insLen ctxt = + let ir = !*ctxt let rs, offset = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let cond = AST.gt rs (AST.num0 ctxt.WordBitSize) - let fallThrough = - bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder ir insLen + +let bgtz insInfo insLen ctxt = + let ir = !*ctxt + let rs, offset = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let cond = AST.sgt rs (AST.num0 ctxt.WordBitSize) + !ir insLen + +let bne insInfo insLen ctxt = + let ir = !*ctxt let rs, rt, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let cond = rs != rt - let fallThrough = - bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder ir insLen + +let setFPConditionCode ctxt cc tf ir = + let insertBit = AST.xtlo 32 tf + let fcsr = getRegVar ctxt R.FCSR + if cc = 0 then + let shf1 = numI32 23 32 + let mask1 = numU32 0xFF000000u 32 + let mask2 = numU32 0x7FFFFFu 32 + let insertBit = AST.xtlo 32 tf + !!ir (fcsr := (fcsr .& mask1) .| (insertBit << shf1) .| (fcsr .& mask2)) + else + let shf2 = numI32 (24 + cc) 32 + let mask1 = numU32 0xFE000000u 32 << numI32 cc 32 + let mask2 = + (numU32 0xFFFFFFu 32 << numI32 cc 32) .| numU32 0xFFu 32 + !!ir (fcsr := (fcsr .& mask1) .| (insertBit << shf2) .| (fcsr .& mask2)) + +let private getCCondOpr insInfo ctxt = + match insInfo.Operands with + | TwoOperands (fs, ft) -> + let sameReg = fs = ft + match insInfo.Fmt with + | Some Fmt.PS | Some Fmt.D -> + let fs, ft = transFPConcatTwoOprs ctxt (fs, ft) + 64, 0, fs, ft, sameReg + | _ -> + let fs, ft = transTwoFP ctxt (fs, ft) + 32, 0, fs, ft, sameReg + | ThreeOperands (cc, fs, ft) -> + let sameReg = fs = ft + match insInfo.Fmt with + | Some Fmt.PS | Some Fmt.D -> + let cc = transOprToImmToInt cc + let fs, ft = transFPConcatTwoOprs ctxt (fs ,ft) + 64, cc, fs, ft, sameReg + | _ -> + let cc = transOprToImmToInt cc + let fs, ft = transTwoFP ctxt (fs, ft) + 32, cc, fs, ft, sameReg + | _ -> raise InvalidOperandException + +let cCond insInfo insLen ctxt = + let ir = !*ctxt + let oprSz, cc, fs, ft, sameReg = getCCondOpr insInfo ctxt + let num0 = AST.num0 oprSz + let num1 = AST.num1 oprSz + let struct (tFs , tFt, mantissa) = tmpVars3 ir oprSz + let struct (less, equal, unordered, condition) = tmpVars4 ir oprSz + let struct (condNaN, exponent) = tmpVars2 ir 1 + let bit0, bit1, bit2 = + match insInfo.Condition with + | Some Condition.F | Some Condition.SF -> num0, num0, num0 + | Some Condition.UN | Some Condition.NGLE -> num1, num0, num0 + | Some Condition.EQ | Some Condition.SEQ -> num0, num1, num0 + | Some Condition.UEQ | Some Condition.NGL -> num1, num1, num0 + | Some Condition.OLT | Some Condition.LT -> num0, num0, num1 + | Some Condition.ULT | Some Condition.NGE -> num1, num0, num1 + | Some Condition.OLE | Some Condition.LE -> num0, num1, num1 + | Some Condition.ULE | Some Condition.NGT -> num1, num1, num1 + | _ -> raise InvalidOperandException + !> num1) == ((tFt << num1) >> num1) + !!ir (condNaN := + if sameReg then + !!ir (mantissa := getMantissa tFt oprSz) + !!ir (exponent := getExponentFull tFt oprSz) + AST.xtlo 1 (exponent .& (mantissa != AST.num0 oprSz)) + else + let src1Mantissa = getMantissa tFs oprSz + let src2Mantissa = getMantissa tFt oprSz + let src1Exponent = getExponentFull tFs oprSz + let src2Exponent = getExponentFull tFt oprSz + AST.xtlo 1 (src1Exponent .& (src1Mantissa != AST.num0 oprSz)) .| + AST.xtlo 1 (src2Exponent .& (src2Mantissa != AST.num0 oprSz))) + !!ir (less := AST.ite condNaN num0 (AST.ite (AST.flt tFs tFt) num1 num0)) + !!ir (equal := + AST.ite condNaN num0 (AST.ite zeroSameCondWithEqaul num1 num0)) + !!ir (unordered := AST.ite condNaN num1 num0) + !!ir (condition := (bit2 .& less) .| (bit1 .& equal) .| (bit0 .& unordered)) + setFPConditionCode ctxt cc condition ir + advancePC ctxt ir + !>ir insLen + +let ctc1 insInfo insLen ctxt= + let ir = !*ctxt + let rt, _ = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let fcsr = getRegVar ctxt R.FCSR + ! rt) + advancePC ctxt ir + !>ir insLen + +let cfc1 insInfo insLen ctxt= + let ir = !*ctxt + let rt, _ = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let fcsr = getRegVar ctxt R.FCSR + !ir insLen + +let clz insInfo insLen ctxt = + let ir = !*ctxt + let lblLoop = !%ir "Loop" + let lblContinue = !%ir "Continue" + let lblEnd = !%ir "End" let wordSz = ctxt.WordBitSize let rd, rs = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let t = builder.NewTempVar wordSz - let tmp = numI32 (32 - 1) wordSz - startMark insInfo builder - builder > t == AST.num1 wordSz) - (AST.name lblEnd) (AST.name lblContinue)) - builder > t == AST.num1 wordSz + !!ir (AST.cjmp cond1 (AST.name lblEnd) (AST.name lblContinue)) + !!ir (AST.lmark lblContinue) + !!ir (t := t .- AST.num1 wordSz) + let cond2 = t == numI32 -1 wordSz + !!ir (AST.cjmp cond2 (AST.name lblEnd) (AST.name lblLoop)) + !!ir (AST.lmark lblEnd) + !!ir (rd := n31 .- t) + advancePC ctxt ir + !>ir insLen + +let cvtd insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + let fdB, fdA = transOprToFPPair ctxt fd + let result = !+ir 64 + ! + let fs = transOprToFPConvert insInfo ctxt fs + !!ir (result := AST.cast CastKind.SIntToFloat 64 fs) + | Some Fmt.S -> + let fs = transOprToFPConvert insInfo ctxt fs + !!ir (result := AST.cast CastKind.FloatCast 64 fs) + | _ -> + let fs = transOprToFPPairConcat ctxt fs + !!ir (result := AST.cast CastKind.SIntToFloat 64 fs) + normalizeValue 64 result ir + dstAssignForFP fdB fdA result ctxt ir + advancePC ctxt ir + !>ir insLen + +let cvtw insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + let intMax = numI32 0x7fffffff 32 + let intMin = numI32 0x80000000 32 + let exponent = !+ir 1 + ! + let dst, src = transTwoOprFPConvert insInfo ctxt (fd, fs) + !!ir (exponent := getExponentFull src 32) + let mantissa = !+ir 32 + !!ir (mantissa := getMantissa src 32) + let inf = isInfinity 32 exponent mantissa + let nan = isNaN 32 exponent mantissa + dst, src, inf, nan + | _ -> + let dst = transOprToFPConvert insInfo ctxt fd + let src = transOprToFPPairConcat ctxt fs + !!ir (exponent := getExponentFull src 64) + let mantissa = !+ir 64 + !!ir (mantissa := getMantissa src 64) + let inf = isInfinity 64 exponent mantissa + let nan = isNaN 64 exponent mantissa + dst, src, inf, nan + !!ir (dst := roundToInt ctxt src 32) + let outOfRange = AST.sgt dst intMax .| AST.slt dst intMin + !!ir (dst := AST.ite (outOfRange .| inf .| nan) intMax dst) + advancePC ctxt ir + !>ir insLen + +let cvtl insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + let fdB, fdA = transOprToFPPair ctxt fd + let eval = !+ir 64 + let exponent = !+ir 1 + let intMax = numI64 0x7fffffffffffffffL 64 + let intMin = numI64 0x8000000000000000L 64 + ! + let src = transOprToFPConvert insInfo ctxt fs + !!ir (exponent := getExponentFull src 32) + let mantissa = !+ir 32 + !!ir (mantissa := getMantissa src 32) + let inf = isInfinity 32 exponent mantissa + let nan = isNaN 32 exponent mantissa + src, inf, nan + | _ -> + let src = transOprToFPPairConcat ctxt fs + !!ir (exponent := getExponentFull src 64) + let mantissa = !+ir 64 + !!ir (mantissa := getMantissa src 64) + let inf = isInfinity 64 exponent mantissa + let nan = isNaN 64 exponent mantissa + src, inf, nan + !!ir (eval := roundToInt ctxt src 64) + let outOfRange = AST.sgt eval intMax .| AST.slt eval intMin + !!ir (eval := AST.ite (outOfRange .| inf .| nan) intMax eval) + dstAssignForFP fdB fdA eval ctxt ir + advancePC ctxt ir + !>ir insLen + +let cvts insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + let fd = transOprToFPConvert insInfo ctxt fd + let dst = if is32Bit ctxt then fd else AST.xtlo 32 fd + let result = !+ir 32 + ! + let fs = transOprToFPPairConcat ctxt fs + !!ir (result := AST.cast CastKind.SIntToFloat 32 fs) + | Some Fmt.D -> + let fs = transOprToFPPairConcat ctxt fs + !!ir (result := AST.cast CastKind.FloatCast 32 fs) + | _ -> + let fs = transOprToFPConvert insInfo ctxt fs + !!ir (result := AST.cast CastKind.SIntToFloat 32 fs) + normalizeValue 32 result ir + !!ir (dst := result) + advancePC ctxt ir + !>ir insLen + +let dadd insInfo insLen ctxt = + let ir = !*ctxt + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = checkOverfolwOnDadd rs rt (rs .+ rt) + !ir insLen + +let daddu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let result = !+ir 64 + !ir insLen + +let daddiu insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let result = builder.NewTempVar 64 - startMark insInfo builder - builder + !ir insLen + +let dclz insInfo insLen ctxt = + let ir = !*ctxt + let lblLoop = !%ir "Loop" + let lblContinue = !%ir "Continue" + let lblEnd = !%ir "End" let wordSz = ctxt.WordBitSize let rd, rs = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let t = builder.NewTempVar wordSz - let tmp = numI32 (64 - 1) wordSz - startMark insInfo builder - builder > t == AST.num1 wordSz) - (AST.name lblEnd) (AST.name lblContinue)) - builder > t == AST.num1 wordSz) + (AST.name lblEnd) (AST.name lblContinue)) + !!ir (AST.lmark lblContinue) + !!ir (t := t .- AST.num1 wordSz) + !!ir (AST.cjmp (t == numI64 -1 wordSz) + (AST.name lblEnd) (AST.name lblLoop)) + !!ir (AST.lmark lblEnd) + !!ir (rd := n63 .- t) + advancePC ctxt ir + !>ir insLen + +let ddiv insInfo insLen ctxt = + let ir = !*ctxt let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let q = builder.NewTempVar 128 - let r = builder.NewTempVar 128 + let struct (q, r) = tmpVars2 ir 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - let rs = AST.zext 128 rs - let rt = AST.zext 128 rt - builder q) - builder r) - endMark insInfo builder + !ir insLen + +let dmfc1 insInfo insLen ctxt = + let ir = !*ctxt + let rt, fs = getTwoOprs insInfo + let rt = transOprToExpr insInfo ctxt rt + let fs = transOprToFPPairConcat ctxt fs + !ir insLen + +let dmtc1 insInfo insLen ctxt = + let ir = !*ctxt + let rt, fs = getTwoOprs insInfo + let rt = transOprToExpr insInfo ctxt rt + let fsB, fsA = transOprToFPPair ctxt fs + !ir insLen + +let ddivu insInfo insLen ctxt = + let ir = !*ctxt + let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let struct (q, r) = tmpVars2 ir 64 + let hi = getRegVar ctxt R.HI + let lo = getRegVar ctxt R.LO + !ir insLen let checkDEXTPosSize pos size = let posSize = pos + size if 0 <= pos && pos < 32 && 0 < size && size <= 32 && 0 < posSize && posSize <= 63 then () - else raise InvalidOperandException + else raise InvalidOperandException -let dext insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder +let dext insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt let rs = transOprToExpr insInfo ctxt rs - let pos = int32 (transOprToImm pos) - let size = int32 (transOprToImm size) + let pos = transOprToImm pos |> int + let size = transOprToImm size |> int checkDEXTPosSize pos size - let getMask size = (1L <<< size) - 1L let mask = numI64 (getMask size) ctxt.WordBitSize let rs = if pos = 0 then rs else rs >> numI32 pos ctxt.WordBitSize - builder AST.zext 64) + advancePC ctxt ir + !>ir insLen let checkDEXTMPosSize pos size = let posSize = pos + size if 0 <= pos && pos < 32 && 32 < size && size <= 64 && 32 < posSize && posSize <= 64 then () - else raise InvalidOperandException + else raise InvalidOperandException let checkDEXTUPosSize pos size = let posSize = pos + size if 32 <= pos && pos < 64 && 0 < size && size <= 32 && 32 < posSize && posSize <= 64 then () - else raise InvalidOperandException + else raise InvalidOperandException -let dextx insInfo posSizeCheckFn ctxt = - let builder = IRBuilder (16) - startMark insInfo builder +let dextx insInfo insLen posSizeCheckFn ctxt = + let ir = !*ctxt let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt let rs = transOprToExpr insInfo ctxt rs - let pos = int32 (transOprToImm pos) - let sz = int32 (transOprToImm size) + let pos = transOprToImm pos |> int + let sz = transOprToImm size |> int posSizeCheckFn pos sz - if sz = 64 then if rt = rs then () else builder > numI32 pos ctxt.WordBitSize - let rs = if sz = 64 then rs else rs .& numI64 (getMask sz) ctxt.WordBitSize - builder ir insLen let checkINSorExtPosSize pos size = let posSize = pos + size @@ -450,25 +1108,25 @@ let checkINSorExtPosSize pos size = 0 < posSize && posSize <= 32 then () else raise InvalidOperandException -let dins insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder +let dins insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt let rs = transOprToExpr insInfo ctxt rs let pos = int32 (transOprToImm pos) let size = int32 (transOprToImm size) checkINSorExtPosSize pos size + !ir insLen let checkDINSMPosSize pos size = let posSize = pos + size @@ -484,915 +1142,1281 @@ let checkDINSUPosSize pos size = 32 < posSize && posSize <= 64 then () else raise InvalidOperandException -let dinsx insInfo posSizeCheckFn ctxt = - let builder = IRBuilder (16) - startMark insInfo builder +let dinsx insInfo insLen posSizeCheckFn ctxt = + let ir = !*ctxt let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt let rs = transOprToExpr insInfo ctxt rs let pos = int32 (transOprToImm pos) let size = int32 (transOprToImm size) posSizeCheckFn pos size - if size = 64 then if rt = rs then () else builder ir insLen + +let div insInfo insLen ctxt = + let ir = !*ctxt + ! + let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let hi = getRegVar ctxt R.HI + let lo = getRegVar ctxt R.LO + !!ir (rt := AST.ite (rt == numI64 0 ctxt.WordBitSize) + (AST.undef ctxt.WordBitSize "UNPREDICTABLE") rt) + if is32Bit ctxt then + !!ir (lo := + (AST.sext 64 rs ?/ AST.sext 64 rt) |> AST.xtlo 32) + !!ir (hi := + (AST.sext 64 rs ?% AST.sext 64 rt) |> AST.xtlo 32) + else + let mask = numI64 0xFFFFFFFFL 64 + let q = (rs .& mask) ?/ (rt .& mask) + let r = (rs .& mask) ?% (rt .& mask) + !!ir (lo := signExtLo64 q) + !!ir (hi := signExtLo64 r) + | Some Fmt.D -> + let fd, fs, ft = getThreeOprs insInfo + let fdB, fdA = transOprToFPPair ctxt fd + let src1, src2 = transFPConcatTwoOprs ctxt (fs, ft) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 64 + reDupSrc fs ft src1 src2 tSrc1 tSrc2 ir + !!ir (result := AST.fdiv tSrc1 tSrc2) + divNormal 64 tSrc1 tSrc2 result ir + dstAssignForFP fdB fdA result ctxt ir + | _ -> + let fd, fs, ft = getThreeOprs insInfo + let dst, src1, src2 = transThreeFP ctxt (fd, fs, ft) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 32 + reDupSrc fs ft src1 src2 tSrc1 tSrc2 ir + !!ir (result := AST.fdiv tSrc1 tSrc2) + divNormal 32 tSrc1 tSrc2 result ir + !!ir (dst := result) + advancePC ctxt ir + !>ir insLen + +let divu insInfo insLen ctxt = + let ir = !*ctxt let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let q = builder.NewTempVar 64 - let r = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs .| notWordValue rt - let mask = numI64 0xFFFFFFFFL 64 - let rs = rs .& mask - let rt = rt .& mask - builder (AST.xtlo 32 q)) - builder (AST.xtlo 32 r)) - builder + !!ir (extendRs := AST.zext 64 rs) + !!ir (extendRt := AST.zext 64 rt) + !!ir (lo := (extendRs ./ extendRt) |> AST.xtlo 32) + !!ir (hi := (extendRs .% extendRt) |> AST.xtlo 32) else - let rs = AST.zext 64 rs - let rt = AST.zext 64 rt - builder q) - builder r) - endMark insInfo builder - -let dmult insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder - let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = builder.NewTempVar 128 - let hi = getRegVar ctxt R.HI - let lo = getRegVar ctxt R.LO - builder rs) .* (AST.sext 128 rt)) - builder result) - builder result) - endMark insInfo builder - -let dmultu insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder + let struct (maskRs, maskRt) = tmpVars2 ir 64 + let mask = numI64 0xFFFFFFFFL 64 + !!ir (maskRs := rs .& mask) + !!ir (maskRt := rt .& mask) + !!ir (lo := signExtLo64 (maskRs ./ maskRt)) + !!ir (hi := signExtLo64 (maskRs .% maskRt)) + advancePC ctxt ir + !>ir insLen + +let dmul insInfo insLen ctxt isSign = + let ir = !*ctxt let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = builder.NewTempVar 128 + let struct (high, low) = mul64BitReg rs rt ir isSign let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - builder rs) .* (AST.zext 128 rt)) - builder result) - builder result) - endMark insInfo builder - -let drotr insInfo ctxt = - let builder = IRBuilder (4) - let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let drotr insInfo insLen ctxt = + let ir = !*ctxt + let rd, rt, sa = getThreeOprs insInfo + let rd, rt = transTwoOprs insInfo ctxt (rd, rt) + let sa = numU64 (transOprToImm sa) 64 let size = numI32 64 64 - startMark insInfo builder - builder > sa)) - endMark insInfo builder + !> sa)) + advancePC ctxt ir + !>ir insLen -let dsll insInfo ctxt = - let builder = IRBuilder (4) - let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - if sa = AST.num0 ctxt.WordBitSize then builder .+ numI32 32 64 + let size = numI32 64 64 + !> sa)) + advancePC ctxt ir + !>ir insLen -let dsll32 insInfo ctxt = - let builder = IRBuilder (4) +let drotrv insInfo insLen ctxt = + let ir = !*ctxt + let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let sa = !+ir 64 + let size = numI32 64 64 + !) + !!ir (rd := (rt << (size .- sa)) .| (rt >> sa)) + advancePC ctxt ir + !>ir insLen + +let dsra insInfo insLen ctxt = + let ir = !*ctxt let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let sa = sa .+ numI32 32 64 - startMark insInfo builder - builder > sa |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let dsllv insInfo ctxt = - let builder = IRBuilder (4) +let dsrav insInfo insLen ctxt = + let ir = !*ctxt let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder )) - endMark insInfo builder - -let dsra insInfo ctxt = - let builder = IRBuilder (4) - let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - if sa = AST.num0 ctxt.WordBitSize then builder > sa) - endMark insInfo builder + !> (rs .& numI32 63 64) |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let dsra32 insInfo ctxt = - let builder = IRBuilder (4) +let dsra32 insInfo insLen ctxt = + let ir = !*ctxt let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let sa = sa .+ numI32 32 64 - startMark insInfo builder - builder > sa) - endMark insInfo builder + !> sa |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let dsrl insInfo ctxt = - let builder = IRBuilder (4) +let dShiftLeftRight32 insInfo insLen ctxt shf = + let ir = !*ctxt let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - if sa = AST.num0 ctxt.WordBitSize then builder > sa) - endMark insInfo builder + let sa = sa .+ numI32 32 64 + ! AST.zext 64) + advancePC ctxt ir + !>ir insLen -let dsrl32 insInfo ctxt = - let builder = IRBuilder (4) +let dShiftLeftRight insInfo insLen ctxt shf = + let ir = !*ctxt let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let sa = sa .+ numI32 32 64 - startMark insInfo builder - builder > sa) - endMark insInfo builder + ! AST.zext 64) + advancePC ctxt ir + !>ir insLen -let dsrlv insInfo ctxt = - let builder = IRBuilder (16) +let dShiftLeftRightVar insInfo insLen ctxt shf = + let ir = !*ctxt let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder > (rs .& numI32 63 64)) - endMark insInfo builder - -let ins insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder - let rt, rs, pos, size = getFourOprs insInfo - let rt = transOprToExpr insInfo ctxt rt - let rs = transOprToExpr insInfo ctxt rs - let pos = int32 (transOprToImm pos) - let size = int32 (transOprToImm size) - checkINSorExtPosSize pos size - if size = 32 then if rt = rs then () else builder ) |> AST.zext 64) + advancePC ctxt ir + !>ir insLen -let ins64 insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder +let dsubu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let result = !+ir 64 + !ir insLen + +let ins insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt let rs = transOprToExpr insInfo ctxt rs - let pos = int32 (transOprToImm pos) - let size = int32 (transOprToImm size) + let pos = transOprToImm pos |> int + let size = transOprToImm size |> int + let msb = pos + size - 1 + let lsb = pos checkINSorExtPosSize pos size - let posExpr = numI32 pos ctxt.WordBitSize - let getMask size = (1L <<< size) - 1L - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs .| notWordValue rt - builder msb then raise InvalidOperandException else () let mask = numI64 (getMask size) ctxt.WordBitSize - let rs', rt' = if pos = 0 then rs .& mask, rt .& (AST.not mask) - else (rs .& mask) << posExpr, rt .& (AST.not (mask << posExpr)) - builder ir insLen let getJALROprs insInfo ctxt = match insInfo.Operands with - | OneOperand opr -> getRegVar ctxt R.R31, transOprToExpr insInfo ctxt opr + | OneOperand opr -> + struct (getRegVar ctxt R.R31, transOprToExpr insInfo ctxt opr) | TwoOperands (o1, o2) -> - transOprToExpr insInfo ctxt o1, transOprToExpr insInfo ctxt o2 + struct (transOprToExpr insInfo ctxt o1, transOprToExpr insInfo ctxt o2) | _ -> raise InvalidOperandException -let jalr insInfo ctxt = - let builder = IRBuilder (4) - let rd, rs = getJALROprs insInfo ctxt - let r = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo - startMark insInfo builder - builder transOprToExpr insInfo ctxt + ctxt.DelayedBranch <- InterJmpKind.Base + !ir insLen + +let jal insInfo insLen ctxt = + let ir = !*ctxt + let pc = getRegVar ctxt R.PC + let nPC = getRegVar ctxt R.NPC + let lr = getRegVar ctxt R.R31 + let dest = getOneOpr insInfo |> transOprToExpr insInfo ctxt + ctxt.DelayedBranch <- InterJmpKind.IsCall + !ir insLen + +let jalr insInfo insLen ctxt = + let ir = !*ctxt + let pc = getRegVar ctxt R.PC + let nPC = getRegVar ctxt R.NPC + let struct (lr, rs) = getJALROprs insInfo ctxt + ctxt.DelayedBranch <- InterJmpKind.IsCall + !ir insLen + +let jr insInfo insLen ctxt = + let ir = !*ctxt + let nPC = getRegVar ctxt R.NPC let rs = getOneOpr insInfo |> transOneOpr insInfo ctxt - startMark insInfo builder - builder ir insLen -let load insInfo ctxt = - let builder = IRBuilder (4) +let loadSigned insInfo insLen ctxt = + let ir = !*ctxt let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder ir insLen -let loadu insInfo ctxt = - let builder = IRBuilder (4) +let loadUnsigned insInfo insLen ctxt = + let ir = !*ctxt let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder ir insLen -let ext insInfo ctxt = - let builder = IRBuilder (4) - startMark insInfo builder - let rt, rs, pos, size = getFourOprs insInfo - let rt = transOprToExpr insInfo ctxt rt - let rs = transOprToExpr insInfo ctxt rs - let pos = int32 (transOprToImm pos) - let size = int32 (transOprToImm size) - let getMask size = (1L <<< size) - 1L - checkINSorExtPosSize pos size - if size = 32 then if rt = rs then () else builder > numI32 pos ctxt.WordBitSize - builder transTwoOprs insInfo ctxt + !ir insLen + +let sldc1 insInfo insLen ctxt stORld = + let ir = !*ctxt + let ft, mem = getTwoOprs insInfo + let ftB, ftA = transOprToFPPair ctxt ft + let baseOffset = transOprToBaseOffset ctxt mem + let bOff = !+ir ctxt.WordBitSize + let memory = !+ir 64 + ! bOff) + if stORld then + !!ir (AST.loadLE 64 bOff := + if is32Bit ctxt then AST.concat ftB ftA else ftA) + else dstAssignForFP ftB ftA memory ctxt ir + advancePC ctxt ir + !>ir insLen + +let slwc1 insInfo insLen ctxt stORld = + let ir = !*ctxt + let ft, mem = getTwoOprs insInfo + let ft = transOprToFP ctxt ft + let mem = transOprToExpr insInfo ctxt mem + let ft = if is32Bit ctxt then ft else AST.xtlo 32 ft + !ir insLen + +let ext insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, pos, size = getFourOprs insInfo let rt = transOprToExpr insInfo ctxt rt let rs = transOprToExpr insInfo ctxt rs - let pos = int32 (transOprToImm pos) - let size = int32 (transOprToImm size) - let getMask size = (1L <<< size) - 1L + let pos = transOprToImm pos |> int + let size = transOprToImm size |> int + let msbd = size - 1 + let lsb = pos checkINSorExtPosSize pos size - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs - builder > numI32 pos ctxt.WordBitSize - builder 31 then raise InvalidOperandException else () + let rs = if pos = 0 then rs else rs >> numI32 pos ctxt.WordBitSize + !ir insLen + +let lui insInfo insLen ctxt = + let ir = !*ctxt let rt, imm = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - if ctxt.WordBitSize = 64 then - builder (AST.concat (AST.xtlo 16 imm) (AST.num0 16))) - else builder imm) (AST.num0 16)) - endMark insInfo builder - -let madd insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder + ! imm) (AST.num0 16)) + else + !!ir (rt := AST.sext 64 + (AST.concat (AST.xtlo 16 imm) (AST.num0 16))) + advancePC ctxt ir + !>ir insLen + +let mAddSub insInfo insLen ctxt opFn = + let ir = !*ctxt + ! + let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let op = if opFn then AST.add else AST.sub + let result = !+ir 64 + let hi = getRegVar ctxt R.HI + let lo = getRegVar ctxt R.LO + if is32Bit ctxt then + !!ir (result := + op (AST.concat hi lo) (AST.sext 64 rs .* AST.sext 64 rt)) + !!ir (hi := AST.xthi 32 result) + !!ir (lo := AST.xtlo 32 result) + else + let mask = numU32 0xFFFFu 64 + let hilo = AST.concat (AST.xtlo 32 hi) (AST.xtlo 32 lo) + !!ir (result := op hilo ((rs .& mask) .* (rt .& mask))) + !!ir (hi := signExtHi64 result) + !!ir (lo := signExtLo64 result) + | Some Fmt.PS | Some Fmt.D -> + let op = if opFn then AST.fadd else AST.fsub + let fd, fr, fs, ft = getFourOprs insInfo + let fdB, fdA = transOprToFPPair ctxt fd + let fr, fs, ft = transFPConcatThreeOprs ctxt (fr, fs, ft) + let result = op (AST.fmul fs ft) fr + dstAssignForFP fdB fdA result ctxt ir + | _ -> + let op = if opFn then AST.fadd else AST.fsub + let fd, fr, fs, ft = getFourOprs insInfo |> transFourFP ctxt + let result = op (AST.fmul fs ft) fr + !!ir (fd := result) + advancePC ctxt ir + !>ir insLen + +let mAdduSubu insInfo insLen ctxt opFn = + let ir = !*ctxt let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = builder.NewTempVar 64 + let result = !+ir 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs .| notWordValue rt - let hilo = AST.concat (AST.xtlo 32 hi) (AST.xtlo 32 lo) - let mask = numU32 0xFFFFu 64 - builder (AST.xthi 32 result)) - builder (AST.xtlo 32 result)) - builder rs .* AST.zext 64 rt)) + !!ir (hi := AST.xthi 32 result) + !!ir (lo := AST.xtlo 32 result) else - builder rs .* AST.sext 64 rt)) - builder result) - builder result) - endMark insInfo builder - -let mfhi insInfo ctxt = - let builder = IRBuilder (4) + let mask = numU32 0xFFFFu 64 + let hilo = AST.concat (AST.xtlo 32 hi) (AST.xtlo 32 lo) + !!ir (result := op hilo ((rs .& mask) .* (rt .& mask))) + !!ir (hi := AST.xthi 32 result |> AST.zext 64) + !!ir (lo := AST.xtlo 32 result |> AST.zext 64) + advancePC ctxt ir + !>ir insLen + +let mfhi insInfo insLen ctxt = + let ir = !*ctxt let rd = getOneOpr insInfo |> transOneOpr insInfo ctxt - startMark insInfo builder - builder ir insLen -let mflo insInfo ctxt = - let builder = IRBuilder (4) +let mflo insInfo insLen ctxt = + let ir = !*ctxt let rd = getOneOpr insInfo |> transOneOpr insInfo ctxt - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let cond = rt == AST.num0 ctxt.WordBitSize - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let cond = rt != AST.num0 ctxt.WordBitSize - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let result = builder.NewTempVar 64 + !ir insLen + +let mfhc1 insInfo insLen ctxt = + let ir = !*ctxt + let rt, fs = getTwoOprs insInfo + let rt = transOprToExpr insInfo ctxt rt + let fsB, _ = transOprToFPPair ctxt fs + !ir insLen + +let mthc1 insInfo insLen ctxt = + let ir = !*ctxt + let rt, fs = getTwoOprs insInfo + let rt = transOprToExpr insInfo ctxt rt + let fsB, _ = transOprToFPPair ctxt fs + ! rt) + advancePC ctxt ir + !>ir insLen + +let mthi insInfo insLen ctxt = + let ir = !*ctxt + let rs = getOneOpr insInfo |> transOneOpr insInfo ctxt let hi = getRegVar ctxt R.HI + !ir insLen + +let mtlo insInfo insLen ctxt = + let ir = !*ctxt + let rs = getOneOpr insInfo |> transOneOpr insInfo ctxt let lo = getRegVar ctxt R.LO - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs .| notWordValue rt - builder (AST.xtlo 32 result)) - builder rs .* AST.sext 64 rt)) - builder result) - builder ir insLen + +let mfc1 insInfo insLen ctxt = + let ir = !*ctxt + let rt, fs = getTwoOprs insInfo + let rt = transOprToExpr insInfo ctxt rt + let fs = transOprToFP ctxt fs + !ir insLen + +let mov insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + ! + let fd, fs = transTwoFP ctxt (fd, fs) + !!ir (fd := fs) + | Some Fmt.D -> + let fdB, fdA = transOprToFPPair ctxt fd + let fs = transOprToFPPairConcat ctxt fs + let result = !+ir 64 + !!ir (result := fs) + dstAssignForFP fdB fdA result ctxt ir + | _ -> raise InvalidOperandException + advancePC ctxt ir + !>ir insLen + +let movt insInfo insLen ctxt = + let ir = !*ctxt + let dst, src, cc = getThreeOprs insInfo + let cc = transOprToImmToInt cc + let cond = fpConditionCode cc ctxt + ! + let dst, src = transTwoOprs insInfo ctxt (dst, src) + !!ir (dst := AST.ite cond src dst) + | Some Fmt.S -> + let dst, src = transTwoFP ctxt (dst, src) + !!ir (dst := AST.ite cond src dst) + | Some Fmt.D -> + let dstB, dstA = transOprToFPPair ctxt dst + let srcB, srcA = transOprToFPPair ctxt src + !!ir (dstB := AST.ite cond srcB dstB) + !!ir (dstA := AST.ite cond srcA dstA) + | _ -> raise InvalidOperandException + advancePC ctxt ir + !>ir insLen + +let movf insInfo insLen ctxt = + let ir = !*ctxt + let dst, src, cc = getThreeOprs insInfo + let cc = transOprToImmToInt cc + let cond = AST.not (fpConditionCode cc ctxt) + ! + let dst, src = transTwoOprs insInfo ctxt (dst, src) + !!ir (dst := AST.ite cond src dst) + | Some Fmt.S -> + let dst, src = transTwoFP ctxt (dst, src) + !!ir (dst := AST.ite cond src dst) + | Some Fmt.D -> + let dstB, dstA = transOprToFPPair ctxt dst + let srcB, srcA = transOprToFPPair ctxt src + !!ir (dstB := AST.ite cond srcB dstB) + !!ir (dstA := AST.ite cond srcA dstA) + | _ -> raise InvalidOperandException + advancePC ctxt ir + !>ir insLen + +let movzOrn insInfo insLen ctxt opFn = + let ir = !*ctxt + let dst, src, compare = getThreeOprs insInfo + let compare = transOprToExpr insInfo ctxt compare + let cond = opFn compare (AST.num0 ctxt.WordBitSize) + ! + let dst, src = transTwoOprs insInfo ctxt (dst, src) + !!ir (dst := AST.ite cond src dst) + | Some Fmt.S -> + let dst, src = transTwoFP ctxt (dst, src) + !!ir (dst := AST.ite cond src dst) + | Some Fmt.D -> + let dstB, dstA = transOprToFPPair ctxt dst + let src = transOprToFPPairConcat ctxt src + !!ir (dstB := AST.ite cond (AST.xthi 32 src) dstB) + !!ir (dstA := AST.ite cond (AST.xtlo 32 src) dstA) + | _ -> raise InvalidOperandException + advancePC ctxt ir + !>ir insLen + +let mtc1 insInfo insLen ctxt = + let ir = !*ctxt + let rt, fs = getTwoOprs insInfo + let rt = transOprToExpr insInfo ctxt rt + let fs = transOprToFP ctxt fs + ! rt) + advancePC ctxt ir + !>ir insLen + +let mul insInfo insLen ctxt = + let ir = !*ctxt + let dst, src1, src2 = getThreeOprs insInfo + ! + let dst, src1, src2 = transThreeOprs insInfo ctxt (dst, src1, src2) + let hi = getRegVar ctxt R.HI + let lo = getRegVar ctxt R.LO + let result = + if is32Bit ctxt then + (AST.sext 64 src1 .* AST.sext 64 src2) |> AST.xtlo 32 + else signExtLo64 (src1 .* src2) + !!ir (dst := result) + !!ir (hi := AST.undef ctxt.WordBitSize "UNPREDICTABLE") + !!ir (lo := AST.undef ctxt.WordBitSize "UNPREDICTABLE") + | Some Fmt.S -> + let dst, fs, ft = transThreeFP ctxt (dst, src1, src2) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 32 + reDupSrc src1 src2 fs ft tSrc1 tSrc2 ir + !!ir (result := AST.fmul tSrc1 tSrc2) + normalizeValue 32 result ir + !!ir (dst := result) + | Some Fmt.D -> + let dstB, dstA = transOprToFPPair ctxt dst + let fs, ft = transFPConcatTwoOprs ctxt (src1, src2) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 64 + reDupSrc src1 src2 fs ft tSrc1 tSrc2 ir + !!ir (result := AST.fmul tSrc1 tSrc2) + normalizeValue 64 result ir + dstAssignForFP dstB dstA result ctxt ir + | _ -> raise InvalidOperandException + advancePC ctxt ir + !>ir insLen + +let mult insInfo insLen ctxt = + let ir = !*ctxt let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = builder.NewTempVar 64 let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs .| notWordValue rt - let mask = numI64 0xFFFFFFFFL 64 - builder (AST.xtlo 32 result)) - builder (AST.xthi 32 result)) - builder rs .* AST.sext 64 rt)) - builder result) - builder result) - endMark insInfo builder - -let multu insInfo ctxt = - let builder = IRBuilder (16) - startMark insInfo builder - let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - let result = builder.NewTempVar 64 + let mask = numI64 0xFFFFFFFFL 64 + let result = !+ir 64 + ! rs .* AST.sext 64 rt) + result |> AST.xtlo 32, result |> AST.xthi 32 + else + !!ir (result := (rs .& mask) .* (rt .& mask)) + signExtLo64 result, signExtHi64 result + !!ir (lo := low) + !!ir (hi := high) + advancePC ctxt ir + !>ir insLen + +let multu insInfo insLen ctxt = + let ir = !*ctxt + let rs, rt = getTwoOprs insInfo + let src1, src2 = transTwoOprs insInfo ctxt (rs ,rt) + let struct (tRs , tRt) = tmpVars2 ir ctxt.WordBitSize let hi = getRegVar ctxt R.HI let lo = getRegVar ctxt R.LO - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rs .| notWordValue rt - let mask = numI64 0xFFFFFFFFL 64 - builder (AST.xtlo 32 result)) - builder (AST.xthi 32 result)) - builder rs .* AST.zext 64 rt)) - builder result) - builder result) - endMark insInfo builder - -let nop insInfo = - let builder = IRBuilder (4) - startMark insInfo builder - endMark insInfo builder - -let nor insInfo ctxt = - let builder = IRBuilder (4) + let mask = numI64 0xFFFFFFFFL 64 + let result = !+ir 64 + ! tRs .* AST.zext 64 tRt) + result |> AST.xtlo 32, result |> AST.xthi 32 + else + !!ir (result := (tRs .& mask) .* (tRt .& mask)) + signExtLo64 result, signExtHi64 result + !!ir (lo := low) + !!ir (hi := high) + advancePC ctxt ir + !>ir insLen + +let neg insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + ! + let fd, fs = transFPConcatTwoOprs ctxt (fd, fs) + fpneg ir 64 fs + !!ir (fd := fs) + | _ -> + let fd, fs = transTwoFP ctxt (fd, fs) + fpneg ir 32 fs + !!ir (fd := fs) + advancePC ctxt ir + !>ir insLen + +let nop insLen ctxt = + let ir = !*ctxt + !ir insLen + +let nor insInfo insLen ctxt = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen -let logOr insInfo ctxt = - let builder = IRBuilder (4) +let logOr insInfo insLen ctxt = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen -let ori insInfo ctxt = - let builder = IRBuilder (4) +let ori insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen + +let pause insLen ctxt = + let ir = !*ctxt + let llbit = getRegVar ctxt R.LLBit + let lblSpin = !%ir "Spin" + let lblEnd = !%ir "End" + !ir insLen + +let rotr insInfo insLen ctxt = + let ir = !*ctxt let rd, rt, sa = getThreeOprs insInfo let rd, rt = transTwoOprs insInfo ctxt (rd, rt) - let sa = numI32 (int32 (transOprToImm sa)) 32 + let sa = numU64 (transOprToImm sa) 32 let size = numI32 32 32 - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let t1 = builder.NewTempVar 32 - builder rt) - builder ((t1 << (size .- sa)) .| (t1 >> sa))) + !> sa)) else - builder > sa)) - endMark insInfo builder + !!ir (rd := ((AST.xtlo 32 rt << (size .- sa)) .| + (AST.xtlo 32 rt >> sa)) |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let sb insInfo ctxt = - let builder = IRBuilder (4) - let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder rt) - endMark insInfo builder +let rotrv insInfo insLen ctxt = + let ir = !*ctxt + let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let sa = !+ir 32 + let size = numI32 32 32 + ! rs .& numI32 0x1F 32) + if is32Bit ctxt then + !!ir (rd := (rt << (size .- sa)) .| (rt >> sa)) + else + !!ir (rd := ((AST.xtlo 32 rt << (size .- sa)) .| + (AST.xtlo 32 rt >> sa)) |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let sd insInfo ctxt = - let builder = IRBuilder (4) +let store insInfo insLen width ctxt = + let ir = !*ctxt let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder rt) - endMark insInfo builder - -let sdl insInfo ctxt = - let builder = IRBuilder (4) - let rt, mem = getTwoOprs insInfo - let baseOffset = transOprToBaseOffset ctxt mem - let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = builder.NewTempVar 64 - let t2 = builder.NewTempVar 64 - let getMask size = (1L <<< size) - 1L - let mask3 = numI64 (getMask 3) 64 - let vaddr0To2 = baseOffset .& mask3 - let num8 = numI32 8 64 - startMark insInfo builder - builder .- vaddr0To2) .* num8) - builder .+ vaddr0To2) .* num8) - builder > t1) .| ((mem >> t2) << t2)) - endMark insInfo builder - -let sdr insInfo ctxt = - let builder = IRBuilder (4) - let rt, mem = getTwoOprs insInfo - let baseOffset = transOprToBaseOffset ctxt mem - let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = builder.NewTempVar 64 - let t2 = builder.NewTempVar 64 - let getMask size = (1L <<< size) - 1L - let mask3 = numI64 (getMask 3) ctxt.WordBitSize - let vaddr0To2 = baseOffset .& mask3 - let num8 = numI32 8 ctxt.WordBitSize - startMark insInfo builder - builder > t2)) - endMark insInfo builder - -let sh insInfo ctxt = - let builder = IRBuilder (4) + !ir insLen + +let sqrt insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + ! + let fd, fs = transTwoFP ctxt (fd, fs) + let cond = fs == numU32 0x80000000u 32 + !!ir (fd := AST.ite cond (numU32 0x80000000u 32) (AST.fsqrt fs)) + | _ -> + let fdB, fdA = transOprToFPPair ctxt fd + let fs = transOprToFPPairConcat ctxt fs + let cond = fs == numU64 0x8000000000000000UL 64 + let result = + AST.ite cond (numU64 0x8000000000000000UL 64) (AST.fsqrt fs) + dstAssignForFP fdB fdA result ctxt ir + advancePC ctxt ir + !>ir insLen + +let storeConditional insInfo insLen width ctxt = + let ir = !*ctxt + let lblInRMW = !%ir "InRMW" + let lblEnd = !%ir "End" let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder rt) - endMark insInfo builder - -let sw insInfo ctxt = - let builder = IRBuilder (4) - let rt, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder rt) - endMark insInfo builder - -let swl insInfo ctxt = - let builder = IRBuilder (4) + let llbit = getRegVar ctxt R.LLBit + !ir insLen + +let storeLeftRight insInfo insLen ctxt memShf regShf amtOp oprSz = + let ir = !*ctxt let rt, mem = getTwoOprs insInfo let baseOffset = transOprToBaseOffset ctxt mem - let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = builder.NewTempVar 32 - let t2 = builder.NewTempVar 32 - let getMask size = (1L <<< size) - 1L - let mask2 = numI64 (getMask 2) 32 - let baseOffset = if ctxt.WordBitSize = 32 then baseOffset - else AST.xtlo 32 baseOffset - let rt = if ctxt.WordBitSize = 32 then rt else AST.xtlo 32 rt - let vaddr0To2 = baseOffset .& mask2 - let num8 = numI32 8 32 - startMark insInfo builder - builder .- vaddr0To2) .* num8) - builder .+ vaddr0To2) .* num8) - builder > t1) .| ((mem >> t2) << t2)) - endMark insInfo builder - -let swr insInfo ctxt = - let builder = IRBuilder (4) - let rt, mem = getTwoOprs insInfo - let baseOffset = transOprToBaseOffset ctxt mem - let rt, mem = transTwoOprs insInfo ctxt (rt, mem) - let t1 = builder.NewTempVar 32 - let t2 = builder.NewTempVar 32 - let getMask size = (1L <<< size) - 1L - let mask2 = numI64 (getMask 2) 32 - let baseOffset = if ctxt.WordBitSize = 32 then baseOffset - else AST.xtlo 32 baseOffset - let rt = if ctxt.WordBitSize = 32 then rt else AST.xtlo 32 rt - let vaddr0To2 = baseOffset .& mask2 - let num8 = numI32 8 32 - startMark insInfo builder - builder .- vaddr0To2) .* num8) - builder > t2)) - endMark insInfo builder - -let seb insInfo ctxt = - let builder = IRBuilder (16) + let rt = transOprToExpr insInfo ctxt rt + let rRt, baseOffset = + if oprSz = 32 then + if is32Bit ctxt then rt, baseOffset + else AST.xtlo 32 rt, AST.xtlo 32 baseOffset + else rt, baseOffset + let baseOff = !+ir ctxt.WordBitSize + let maskLd = if oprSz = 64 then 0xFFFFFFF8 else 0xFFFFFFFC + let struct (t1, t2, t3, baseMask) = tmpVars4 ir oprSz + let mask = numI32 (((int oprSz) >>> 3) - 1) oprSz + let vaddr0To2 = (baseOff .& mask) <+> (transBigEndianCPU ctxt oprSz) + let baseAddress = AST.loadLE oprSz baseMask + !ir insLen + +let syscall insLen ctxt = + let ir = !*ctxt + !ir insLen + +let seb insInfo insLen ctxt = + let ir = !*ctxt let rd, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rt - builder (AST.extract rt 8 0)) - builder (AST.extract rt 8 0)) - endMark insInfo builder + ! 0)) + advancePC ctxt ir + !>ir insLen -let seh insInfo ctxt = - let builder = IRBuilder (16) +let seh insInfo insLen ctxt = + let ir = !*ctxt let rd, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rt - builder (AST.extract rt 16 0)) - builder 0)) + advancePC ctxt ir + !>ir insLen + +let shiftLeftRight insInfo insLen ctxt shf = + let ir = !*ctxt + let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + ! (AST.extract rt 16 0)) - endMark insInfo builder + let struct (rt, sa) = AST.xtlo 32 rt, AST.xtlo 32 sa + !!ir (rd := shf rt sa |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let sll insInfo ctxt = - let builder = IRBuilder (4) +let sra insInfo insLen ctxt = + let ir = !*ctxt let rd, rt, sa = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let rt = AST.xtlo 32 rt - builder (rt << AST.xtlo 32 sa)) + !> sa |> AST.sext 32) else - builder rt, AST.xtlo 32 sa + !!ir (rd := rt ?>> sa |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let sllv insInfo ctxt = - let builder = IRBuilder (4) +let srav insInfo insLen ctxt = + let ir = !*ctxt let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let mask = numI32 31 32 - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let rt = AST.xtlo 32 rt - builder (rt << (AST.xtlo 32 rs .& mask))) + !> (rs .& mask) |> AST.sext 32) else - builder rt, AST.xtlo 32 rs + !!ir (rd := rt ?>> (rs .& mask) |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let slt insInfo ctxt = - let builder = IRBuilder (4) - let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let cond = AST.lt rs rt - let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let cond = AST.lt rs imm - let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let cond = AST.lt (AST.zext (wordSz * 2) rs) (AST.zext (wordSz * 2) imm) - let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) - startMark insInfo builder - builder transThreeOprs insInfo ctxt - let cond = AST.lt (AST.zext (wordSz * 2) rs) (AST.zext (wordSz * 2) rt) - let rtVal = AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) - startMark insInfo builder - builder - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rt - let t1 = builder.NewTempVar 32 - builder rt) - builder (t1 ?>> sa)) - builder > sa) - endMark insInfo builder - -let srl insInfo ctxt = - let builder = IRBuilder (16) - let rd, rt, sa = getThreeOprs insInfo - let rd, rt = transTwoOprs insInfo ctxt (rd, rt) - let sa = numI32 (int32 (transOprToImm sa)) 32 - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rt - let t1 = builder.NewTempVar 32 - builder rt) - builder (t1 >> sa)) - builder > sa) - endMark insInfo builder - -let srlv insInfo ctxt = - let builder = IRBuilder (16) +let shiftLeftRightVar insInfo insLen ctxt shf = + let ir = !*ctxt let rd, rt, rs = getThreeOprs insInfo |> transThreeOprs insInfo ctxt let mask = numI32 31 32 - startMark insInfo builder - if ctxt.WordBitSize = 64 then - let lblL0 = builder.NewSymbol "L0" - let lblL1 = builder.NewSymbol "L1" - let lblEnd = builder.NewSymbol "End" - let cond = notWordValue rt - let t1 = builder.NewTempVar 32 - builder rt) - builder (t1 >> (AST.xtlo 32 rs .& mask))) - builder > (rs .& mask)) - endMark insInfo builder + let struct (rt, rs) = AST.xtlo 32 rt, AST.xtlo 32 rs + !!ir (rd := shf rt (rs .& mask) |> AST.sext 64) + advancePC ctxt ir + !>ir insLen -let subu insInfo ctxt = - let builder = IRBuilder (4) +let sltAndU insInfo insLen ctxt amtOp = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder ir insLen + +let sltiAndU insInfo insLen ctxt amtOp = + let ir = !*ctxt + let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = amtOp rs imm + let rtVal = + AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) + !ir insLen + +let sub insInfo insLen ctxt = + let ir = !*ctxt + let dst, src1, src2 = getThreeOprs insInfo + ! + let dst, src1, src2 = transThreeOprs insInfo ctxt (dst, src1, src2) + !!ir (dst := src1 .- src2) + | Some Fmt.S -> + let dst, fs, ft = transThreeFP ctxt (dst, src1, src2) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 32 + reDupSrc src1 src2 fs ft tSrc1 tSrc2 ir + !!ir (result := AST.fsub tSrc1 tSrc2) + subNormal 32 tSrc1 tSrc2 result ir + !!ir (dst := result) + | Some Fmt.D -> + let dstB, dstA = transOprToFPPair ctxt dst + let fs, ft = transFPConcatTwoOprs ctxt (src1, src2) + let struct (tSrc1, tSrc2, result) = tmpVars3 ir 64 + reDupSrc src1 src2 fs ft tSrc1 tSrc2 ir + !!ir (result := AST.fsub tSrc1 tSrc2) + subNormal 64 tSrc1 tSrc2 result ir + dstAssignForFP dstB dstA result ctxt ir + | _ -> raise InvalidOperandException + advancePC ctxt ir + !>ir insLen + +let subu insInfo insLen ctxt = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - let cond = notWordValue rs .| notWordValue rt - startMark insInfo builder - builder ir insLen + +let teq insInfo insLen ctxt = + let ir = !*ctxt + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" let rs, rt = getTwoOprs insInfo |> transTwoOprs insInfo ctxt - startMark insInfo builder - builder ir insLen + +let teqi insInfo insLen ctxt = + let ir = !*ctxt + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + let rs, imm = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + !ir insLen + +let truncw insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + let intMax = numI32 0x7fffffff 32 + let intMin = numI32 0x80000000 32 + let exponent = !+ir 1 + let dstTmp = !+ir 32 + ! + let dst, src = transTwoFP ctxt (fd, fs) + !!ir (exponent := getExponentFull src 32) + let mantissa = !+ir 32 + !!ir (mantissa := getMantissa src 32) + let inf = isInfinity 32 exponent mantissa + let nan = isNaN 32 exponent mantissa + dst, src, inf, nan + | _ -> + let dst = transOprToFP ctxt fd + let src = transOprToFPPairConcat ctxt fs + let tSrc = !+ir 64 + !!ir (tSrc := src) + !!ir (exponent := getExponentFull tSrc 64) + let mantissa = !+ir 64 + !!ir (mantissa := getMantissa tSrc 64) + let inf = isInfinity 64 exponent mantissa + let nan = isNaN 64 exponent mantissa + dst, tSrc, inf, nan + !!ir (dst := AST.cast CastKind.FtoITrunc 32 src) + !!ir (dstTmp := dst) + let outOfRange = AST.sgt dstTmp intMax .| AST.slt dstTmp intMin + !!ir (dst := AST.ite (outOfRange .| inf .| nan) intMax dstTmp) + advancePC ctxt ir + !>ir insLen + +let truncl insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + let fdB, fdA = transOprToFPPair ctxt fd + let eval = !+ir 64 + let exponent = !+ir 1 + let intMax = numI64 0x7fffffffffffffffL 64 + let intMin = numI64 0x8000000000000000L 64 + ! + let src = transOprToFP ctxt fs + !!ir (exponent := getExponentFull src 32) + let mantissa = !+ir 32 + !!ir (mantissa := getMantissa src 32) + let inf = isInfinity 32 exponent mantissa + let nan = isNaN 32 exponent mantissa + src, inf, nan + | _ -> + let src = transOprToFPPairConcat ctxt fs + !!ir (exponent := getExponentFull src 64) + let mantissa = !+ir 64 + !!ir (mantissa := getMantissa src 64) + let inf = isInfinity 64 exponent mantissa + let nan = isNaN 64 exponent mantissa + src, inf, nan + !!ir (eval := AST.cast CastKind.FtoITrunc 64 src) + let outOfRange = AST.sgt eval intMax .| AST.slt eval intMin + !!ir (eval := AST.ite (outOfRange .| inf .| nan) intMax eval) + dstAssignForFP fdB fdA eval ctxt ir + advancePC ctxt ir + !>ir insLen + +let logXor insInfo insLen ctxt = + let ir = !*ctxt let rd, rs, rt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder rt) - endMark insInfo builder - -let xori insInfo ctxt = - let builder = IRBuilder (4) + ! rt) + advancePC ctxt ir + !>ir insLen + +let wsbh insInfo insLen ctxt = + let ir = !*ctxt + let dst, src = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let rt = AST.xtlo 32 src + let elements = + Array.init 4 (fun x -> AST.extract rt 8 ((2 + x) % 4 * 8)) |> Array.rev + !ir insLen + +let dsbh insInfo insLen ctxt = + let ir = !*ctxt + let dst, src = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let lo = AST.xtlo 32 src + let hi = AST.xthi 32 src + let hiResult = + Array.init 4 (fun x -> AST.extract hi 8 ((2 + x) % 4 * 8)) |> Array.rev + let lowResult = + Array.init 4 (fun x -> AST.extract lo 8 ((2 + x) % 4 * 8)) |> Array.rev + !ir insLen + +let dshd insInfo insLen ctxt = + let ir = !*ctxt + let dst, src = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let result = + Array.init 4 (fun idx -> AST.extract src 16 (idx * 16)) |> Array.rev + !ir insLen + +let xori insInfo insLen ctxt = + let ir = !*ctxt let rt, rs, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt - startMark insInfo builder - builder imm) - endMark insInfo builder + ! imm) + advancePC ctxt ir + !>ir insLen -let transaui insInfo ctxt = - match insInfo.Operands with - | TwoOperands _ -> lui insInfo ctxt - | ThreeOperands _ -> aui insInfo ctxt - | _ -> raise InvalidOperandException - -let translate insInfo (ctxt: TranslationContext) = +let loadLeftRight insInfo insLen ctxt memShf regShf amtOp oprSz = + let ir = !*ctxt + let rt, mem = getTwoOprs insInfo + let baseOffset = transOprToBaseOffset ctxt mem + let rt = transOprToExpr insInfo ctxt rt + let rRt, baseOffset = + if oprSz = 32 then + if is32Bit ctxt then rt, baseOffset + else AST.xtlo 32 rt, AST.xtlo 32 baseOffset + else rt, baseOffset + let struct (vaddr0To2, t1, t2, t3) = tmpVars4 ir oprSz + let mask = numI32 (((int oprSz) >>> 3) - 1) oprSz + let inline loadBaseAddr oprSz baseOffset = + let maskLoad = if oprSz = 64 then 0xFFFFFFF8 else 0xFFFFFFFC + AST.loadLE oprSz (baseOffset .& numI32 maskLoad oprSz) + ! (transBigEndianCPU ctxt oprSz)) + !!ir (t2 := ((amtOp vaddr0To2 mask) .+ AST.num1 oprSz) .* numI32 8 oprSz) + !!ir (t3 := (amtOp (mask .- vaddr0To2) mask) .* numI32 8 oprSz) + let result = shifterLoad memShf regShf rRt t2 t3 (loadBaseAddr oprSz t1) + !!ir (rt := if is32Bit ctxt then result else result |> AST.sext 64) + advancePC ctxt ir + !>ir insLen + +let recip insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let sz = ctxt.WordBitSize + let fnum = AST.cast CastKind.SIntToFloat sz (AST.num1 sz) + !ir insLen + +let rsqrt insInfo insLen ctxt = + let ir = !*ctxt + let fd, fs = getTwoOprs insInfo + ! + let fd, fs = transTwoFP ctxt (fd, fs) + let fnum = AST.cast CastKind.SIntToFloat 32 (AST.num1 32) + !!ir (fd := AST.fdiv fnum (AST.fsqrt fs)) + | _ -> + let fdB, fdA = transOprToFPPair ctxt fd + let fs = transOprToFPPairConcat ctxt fs + let fnum = AST.cast CastKind.SIntToFloat 64 (AST.num1 64) + let result = AST.fdiv fnum (AST.fsqrt fs) + dstAssignForFP fdB fdA result ctxt ir + advancePC ctxt ir + !>ir insLen + +let translate insInfo insLen (ctxt: TranslationContext) = match insInfo.Opcode with - | Op.ADD when insInfo.Fmt.IsNone && ctxt.WordBitSize = 32 -> - add insInfo ctxt - | Op.ADD when insInfo.Fmt.IsNone -> add64 insInfo ctxt - | Op.ADD -> sideEffects insInfo UnsupportedFP - | Op.ADDIU when ctxt.WordBitSize = 32 -> addiu insInfo ctxt - | Op.ADDIU -> addiu64 insInfo ctxt - | Op.ADDU when ctxt.WordBitSize = 32 -> addu insInfo ctxt - | Op.ADDU -> addu64 insInfo ctxt - | Op.AND -> logAnd insInfo ctxt - | Op.ANDI -> andi insInfo ctxt - | Op.AUI -> transaui insInfo ctxt - | Op.B -> b insInfo ctxt - | Op.BAL -> bal insInfo ctxt - | Op.BC1F | Op.BC1T -> sideEffects insInfo UnsupportedFP - | Op.BEQ -> beq insInfo ctxt - | Op.BGEZ -> bgez insInfo ctxt - | Op.BGTZ -> bgtz insInfo ctxt - | Op.BLEZ -> blez insInfo ctxt - | Op.BLTZ -> bltz insInfo ctxt - | Op.BNE -> bne insInfo ctxt - | Op.C | Op.CFC1 | Op.CTC1 -> sideEffects insInfo UnsupportedFP - | Op.CLZ -> clz insInfo ctxt - | Op.CVTD | Op.CVTS -> sideEffects insInfo UnsupportedFP - | Op.DADDU -> addu insInfo ctxt - | Op.DADDIU -> daddiu insInfo ctxt - | Op.DCLZ -> dclz insInfo ctxt - | Op.DMFC1 | Op.DMTC1 -> sideEffects insInfo UnsupportedFP - | Op.DEXT -> dext insInfo ctxt - | Op.DEXTM -> dextx insInfo checkDEXTMPosSize ctxt - | Op.DEXTU -> dextx insInfo checkDEXTUPosSize ctxt - | Op.DINS -> dins insInfo ctxt - | Op.DINSM -> dinsx insInfo checkDINSMPosSize ctxt - | Op.DINSU -> dinsx insInfo checkDINSUPosSize ctxt - | Op.DIV when insInfo.Fmt.IsSome -> sideEffects insInfo UnsupportedFP - | Op.DIVU when Helper.isRel2 insInfo.Arch -> divu insInfo ctxt - | Op.DDIVU -> ddivu insInfo ctxt - | Op.DMULT -> dmult insInfo ctxt - | Op.DMULTU -> dmultu insInfo ctxt - | Op.DROTR -> drotr insInfo ctxt - | Op.DSLL -> dsll insInfo ctxt - | Op.DSLL32 -> dsll32 insInfo ctxt - | Op.DSLLV -> dsllv insInfo ctxt - | Op.DSRA -> dsra insInfo ctxt - | Op.DSRA32 -> dsra32 insInfo ctxt - | Op.DSRL -> dsrl insInfo ctxt - | Op.DSRL32 -> dsrl32 insInfo ctxt - | Op.DSRLV -> dsrlv insInfo ctxt - | Op.DSUBU -> subu insInfo ctxt - | Op.EHB -> nop insInfo (* FIXME *) - | Op.EXT when ctxt.WordBitSize = 3232 -> ext insInfo ctxt - | Op.EXT -> ext64 insInfo ctxt - | Op.INS when ctxt.WordBitSize = 3232 -> ins insInfo ctxt - | Op.INS -> ins64 insInfo ctxt - | Op.JALR | Op.JALRHB -> jalr insInfo ctxt - | Op.JR | Op.JRHB -> jr insInfo ctxt - | Op.PAUSE -> sideEffects insInfo Delay - | Op.LB | Op.LH | Op.LW | Op.LD -> load insInfo ctxt - | Op.LBU | Op.LHU | Op.LWU -> loadu insInfo ctxt - | Op.LDC1 | Op.LWC1 | Op.SDC1 | Op.SWC1 -> sideEffects insInfo UnsupportedFP - | Op.LUI -> lui insInfo ctxt - | Op.MADD when insInfo.Fmt.IsNone -> madd insInfo ctxt - | Op.MFHI -> mfhi insInfo ctxt - | Op.MFLO -> mflo insInfo ctxt - | Op.MFC1 -> sideEffects insInfo UnsupportedFP - | Op.MOV -> sideEffects insInfo UnsupportedFP - | Op.MOVZ -> movz insInfo ctxt - | Op.MOVN -> movn insInfo ctxt - | Op.MTC1 -> sideEffects insInfo UnsupportedFP - | Op.MUL when insInfo.Fmt.IsNone && Helper.isRel2 insInfo.Arch -> - mul insInfo ctxt - | Op.MUL when insInfo.Fmt.IsSome -> sideEffects insInfo UnsupportedFP - | Op.MULT -> mult insInfo ctxt - | Op.MULTU -> multu insInfo ctxt - | Op.NOP -> nop insInfo - | Op.NOR -> nor insInfo ctxt - | Op.OR -> logOr insInfo ctxt - | Op.ORI -> ori insInfo ctxt - | Op.ROTR -> rotr insInfo ctxt - | Op.SLL -> sll insInfo ctxt - | Op.SLLV -> sllv insInfo ctxt - | Op.SLT -> slt insInfo ctxt - | Op.SLTI -> slti insInfo ctxt - | Op.SLTIU -> sltiu insInfo ctxt - | Op.SLTU -> sltu insInfo ctxt - | Op.SSNOP -> nop insInfo - | Op.SB -> sb insInfo ctxt - | Op.SD -> sd insInfo ctxt - | Op.SEB -> seb insInfo ctxt - | Op.SEH -> seh insInfo ctxt - | Op.SH -> sh insInfo ctxt - | Op.SRA -> sra insInfo ctxt - | Op.SRL -> srl insInfo ctxt - | Op.SRLV -> srlv insInfo ctxt - | Op.SUB when insInfo.Fmt.IsSome -> sideEffects insInfo UnsupportedFP - | Op.SUBU when ctxt.WordBitSize = 32 -> subu insInfo ctxt - | Op.SUBU -> subu64 insInfo ctxt - | Op.SW -> sw insInfo ctxt - | Op.SDL -> sdl insInfo ctxt - | Op.SDR -> sdr insInfo ctxt - | Op.SWL -> swl insInfo ctxt - | Op.SWR -> swr insInfo ctxt - | Op.TEQ -> teq insInfo ctxt - | Op.TRUNCL | Op.TRUNCW -> sideEffects insInfo UnsupportedFP - | Op.XOR -> logXor insInfo ctxt - | Op.XORI -> xori insInfo ctxt - | Op.ABS | Op.BC3F | Op.BC3FL | Op.BC3T | Op.BC3TL | Op.DDIV | Op.DIV - | Op.DROTR32 | Op.DROTRV | Op.DSBH | Op.DSHD | Op.DSRAV | Op.J | Op.JAL - | Op.LDL | Op.LDR | Op.LDXC1 | Op.LWL | Op.LWR | Op.LWXC1 | Op.MADDU - | Op.MFHC1 | Op.MOVF | Op.MOVN | Op.MOVT | Op.MSUB | Op.MTHC1 | Op.MTHI - | Op.MTLO | Op.NEG | Op.ROTRV | Op.SDXC1 | Op.SQRT | Op.SRAV | Op.SWXC1 - | Op.SYNC | Op.TRUNCL | Op.WSBH -> sideEffects insInfo UnsupportedExtension // XXX this is temporary fix + | Op.ABS -> abs insInfo insLen ctxt + | Op.ADD -> add insInfo insLen ctxt + | Op.ADDIU -> addiu insInfo insLen ctxt + | Op.ADDU -> addu insInfo insLen ctxt + | Op.AND -> logAnd insInfo insLen ctxt + | Op.ANDI -> andi insInfo insLen ctxt + | Op.AUI -> aui insInfo insLen ctxt + | Op.B -> b insInfo insLen ctxt + | Op.BAL -> bal insInfo insLen ctxt + | Op.BC1F -> bc1f insInfo insLen ctxt + | Op.BC1T -> bc1t insInfo insLen ctxt + | Op.BEQ | Op.BEQL -> beq insInfo insLen ctxt + | Op.BGEZ -> bgez insInfo insLen ctxt + | Op.BGEZAL -> bgezal insInfo insLen ctxt + | Op.BGTZ -> bgtz insInfo insLen ctxt + | Op.BLEZ -> blez insInfo insLen ctxt + | Op.BLTZ -> bltz insInfo insLen ctxt + | Op.BLTZAL -> bltzal insInfo insLen ctxt + | Op.BNE | Op.BNEL -> bne insInfo insLen ctxt + | Op.BREAK -> sideEffects insLen ctxt Breakpoint + | Op.C -> cCond insInfo insLen ctxt + | Op.CFC1 -> cfc1 insInfo insLen ctxt + | Op.CTC1 -> ctc1 insInfo insLen ctxt + | Op.CLZ -> clz insInfo insLen ctxt + | Op.CVTD -> cvtd insInfo insLen ctxt + | Op.CVTL -> cvtl insInfo insLen ctxt + | Op.CVTS -> cvts insInfo insLen ctxt + | Op.CVTW -> cvtw insInfo insLen ctxt + | Op.DADD -> dadd insInfo insLen ctxt + | Op.DADDU -> daddu insInfo insLen ctxt + | Op.DADDIU -> daddiu insInfo insLen ctxt + | Op.DCLZ -> dclz insInfo insLen ctxt + | Op.DDIV -> ddiv insInfo insLen ctxt + | Op.DMFC1 -> dmfc1 insInfo insLen ctxt + | Op.DMTC1 -> dmtc1 insInfo insLen ctxt + | Op.DEXT -> dext insInfo insLen ctxt + | Op.DEXTM -> dextx insInfo insLen checkDEXTMPosSize ctxt + | Op.DEXTU -> dextx insInfo insLen checkDEXTUPosSize ctxt + | Op.DINS -> dins insInfo insLen ctxt + | Op.DINSM -> dinsx insInfo insLen checkDINSMPosSize ctxt + | Op.DINSU -> dinsx insInfo insLen checkDINSUPosSize ctxt + | Op.DIV -> div insInfo insLen ctxt + | Op.DIVU -> divu insInfo insLen ctxt + | Op.DDIVU -> ddivu insInfo insLen ctxt + | Op.DMULT -> dmul insInfo insLen ctxt true + | Op.DMULTU -> dmul insInfo insLen ctxt false + | Op.DROTR -> drotr insInfo insLen ctxt + | Op.DROTR32 -> drotr32 insInfo insLen ctxt + | Op.DROTRV -> drotrv insInfo insLen ctxt + | Op.DSBH -> dsbh insInfo insLen ctxt + | Op.DSHD -> dshd insInfo insLen ctxt + | Op.DSLL -> dShiftLeftRight insInfo insLen ctxt (<<) + | Op.DSLL32 -> dShiftLeftRight32 insInfo insLen ctxt (<<) + | Op.DSLLV -> dShiftLeftRightVar insInfo insLen ctxt (<<) + | Op.DSRA -> dsra insInfo insLen ctxt + | Op.DSRAV -> dsrav insInfo insLen ctxt + | Op.DSRA32 -> dsra32 insInfo insLen ctxt + | Op.DSRL -> dShiftLeftRight insInfo insLen ctxt (>>) + | Op.DSRL32 -> dShiftLeftRight32 insInfo insLen ctxt (>>) + | Op.DSRLV -> dShiftLeftRightVar insInfo insLen ctxt (>>) + | Op.DSUBU -> dsubu insInfo insLen ctxt + | Op.EHB -> nop insLen ctxt + | Op.EXT -> ext insInfo insLen ctxt + | Op.INS -> ins insInfo insLen ctxt + | Op.J -> j insInfo insLen ctxt + | Op.JAL -> jal insInfo insLen ctxt + | Op.JALR | Op.JALRHB -> jalr insInfo insLen ctxt + | Op.JR | Op.JRHB -> jr insInfo insLen ctxt + | Op.LD | Op.LB | Op.LH | Op.LW -> loadSigned insInfo insLen ctxt + | Op.LBU | Op.LHU | Op.LWU -> loadUnsigned insInfo insLen ctxt + | Op.LL | Op.LLD -> loadLinked insInfo insLen ctxt + | Op.SDC1 | Op.SDXC1 -> sldc1 insInfo insLen ctxt true + | Op.LDC1 | Op.LDXC1 -> sldc1 insInfo insLen ctxt false + | Op.SWC1 | Op.SWXC1 -> slwc1 insInfo insLen ctxt true + | Op.LWC1 | Op.LWXC1 -> slwc1 insInfo insLen ctxt false + | Op.LUI -> lui insInfo insLen ctxt + | Op.LDL -> loadLeftRight insInfo insLen ctxt (<<) (>>) (.&) 64 + | Op.LDR -> loadLeftRight insInfo insLen ctxt (>>) (<<) (<+>) 64 + | Op.LWL -> loadLeftRight insInfo insLen ctxt (<<) (>>) (.&) 32 + | Op.LWR -> loadLeftRight insInfo insLen ctxt (>>) (<<) (<+>) 32 + | Op.MADD -> mAddSub insInfo insLen ctxt true + | Op.MADDU -> mAdduSubu insInfo insLen ctxt true + | Op.MFHI -> mfhi insInfo insLen ctxt + | Op.MFLO -> mflo insInfo insLen ctxt + | Op.MFHC1 -> mfhc1 insInfo insLen ctxt + | Op.MTHC1 -> mthc1 insInfo insLen ctxt + | Op.MTHI -> mthi insInfo insLen ctxt + | Op.MTLO -> mtlo insInfo insLen ctxt + | Op.MFC1 -> mfc1 insInfo insLen ctxt + | Op.MOV -> mov insInfo insLen ctxt + | Op.MOVT -> movt insInfo insLen ctxt + | Op.MOVF -> movf insInfo insLen ctxt + | Op.MOVZ -> movzOrn insInfo insLen ctxt (==) + | Op.MOVN -> movzOrn insInfo insLen ctxt (!=) + | Op.MSUB -> mAddSub insInfo insLen ctxt false + | Op.MSUBU -> mAdduSubu insInfo insLen ctxt false + | Op.MTC1 -> mtc1 insInfo insLen ctxt + | Op.MUL -> mul insInfo insLen ctxt + | Op.MULT -> mult insInfo insLen ctxt + | Op.MULTU -> multu insInfo insLen ctxt + | Op.NEG -> neg insInfo insLen ctxt + | Op.NOP -> nop insLen ctxt + | Op.NOR -> nor insInfo insLen ctxt + | Op.OR -> logOr insInfo insLen ctxt + | Op.ORI -> ori insInfo insLen ctxt + | Op.PAUSE -> pause insLen ctxt + | Op.PREF | Op.PREFE | Op.PREFX -> nop insLen ctxt + | Op.RDHWR -> sideEffects insLen ctxt ProcessorID + | Op.ROTR -> rotr insInfo insLen ctxt + | Op.ROTRV -> rotrv insInfo insLen ctxt + | Op.RECIP -> recip insInfo insLen ctxt + | Op.RSQRT -> rsqrt insInfo insLen ctxt + | Op.SLL -> shiftLeftRight insInfo insLen ctxt (<<) + | Op.SLLV -> shiftLeftRightVar insInfo insLen ctxt (<<) + | Op.SLT -> sltAndU insInfo insLen ctxt (?<) + | Op.SLTU -> sltAndU insInfo insLen ctxt (.<) + | Op.SLTI -> sltiAndU insInfo insLen ctxt (?<) + | Op.SLTIU -> sltiAndU insInfo insLen ctxt (.<) + | Op.SSNOP -> nop insLen ctxt + | Op.SB -> store insInfo insLen 8 ctxt + | Op.SC -> storeConditional insInfo insLen 32 ctxt + | Op.SCD -> storeConditional insInfo insLen 64 ctxt + | Op.SD -> store insInfo insLen 64 ctxt + | Op.SEB -> seb insInfo insLen ctxt + | Op.SEH -> seh insInfo insLen ctxt + | Op.SH -> store insInfo insLen 16 ctxt + | Op.SQRT -> sqrt insInfo insLen ctxt + | Op.SRA -> sra insInfo insLen ctxt + | Op.SRAV -> srav insInfo insLen ctxt + | Op.SRL -> shiftLeftRight insInfo insLen ctxt (>>) + | Op.SRLV -> shiftLeftRightVar insInfo insLen ctxt (>>) + | Op.SUB -> sub insInfo insLen ctxt + | Op.SUBU -> subu insInfo insLen ctxt + | Op.SW -> store insInfo insLen 32 ctxt + | Op.SDL -> storeLeftRight insInfo insLen ctxt (<<) (>>) (.&) 64 + | Op.SDR -> storeLeftRight insInfo insLen ctxt (>>) (<<) (<+>) 64 + | Op.SWL -> storeLeftRight insInfo insLen ctxt (<<) (>>) (.&) 32 + | Op.SWR -> storeLeftRight insInfo insLen ctxt (>>) (<<) (<+>) 32 + | Op.SYNC | Op.SYNCI -> nop insLen ctxt + | Op.SYSCALL -> syscall insLen ctxt + | Op.TEQ -> teq insInfo insLen ctxt + | Op.TEQI -> teqi insInfo insLen ctxt + | Op.TRUNCW -> truncw insInfo insLen ctxt + | Op.TRUNCL -> truncl insInfo insLen ctxt + | Op.XOR -> logXor insInfo insLen ctxt + | Op.XORI -> xori insInfo insLen ctxt + | Op.WSBH -> wsbh insInfo insLen ctxt + | Op.BC3F | Op.BC3FL | Op.BC3T | Op.BC3TL -> + sideEffects insLen ctxt UnsupportedExtension // XXX this is a temporary fix | o -> #if DEBUG eprintfn "%A" o diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSParser.fs b/src/FrontEnd/BinLifter/MIPS/MIPSParser.fs index 581596ff..b56d50e2 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSParser.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSParser.fs @@ -22,529 +22,27 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.MIPS.Parser +namespace B2R2.FrontEnd.BinLifter.MIPS open System open B2R2 -open B2R2.FrontEnd.BinLifter.MIPS.Helper -open B2R2.FrontEnd.BinLifter.MIPS.Utils +open B2R2.FrontEnd.BinLifter -/// Check encoded field value -let nd binary target = pickBit binary 17u = target -let tf binary target = pickBit binary 16u = target -let ztf binary target = extract binary 17u 16u (* 0:tf *) = target -let cc binary target = extract binary 10u 8u = target -let chk10to0 binary target = extract binary 10u 0u = target -let chk10to6 binary target = extract binary 10u 6u = target -let chk15to6 binary target = extract binary 15u 6u = target -let chk15to11 binary target = extract binary 15u 11u = target -let chk20to6 binary target = extract binary 20u 6u = target -let chk20to16 binary target = extract binary 20u 16u = target -let chk25to11 binary target = extract binary 25u 11u = target -let chk25to21 binary target = extract binary 25u 21u = target +/// Parser for MIPS instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type MIPSParser (isa: ISA) = + let wordSize = isa.WordSize + let arch = isa.Arch + let reader = BinReader.Init isa.Endian -let parseNOP binary = - match extract binary 10u 6u with - | 0u -> Op.NOP, None, None, NoOperand - | 1u -> Op.SSNOP, None, None, NoOperand - | 3u -> Op.EHB, None, None, NoOperand - | 5u -> Op.PAUSE, None, None, NoOperand - | _ -> failwith "Not Implemented." + interface IInstructionParsable with + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader arch wordSize addr :> Instruction -let parseSLL binary = - match extract binary 25u 11u with - | 0u -> parseNOP binary - | _ when extract binary 25u 21u = 0u -> Op.SLL, None, None, getRdRtSa binary - | _ -> failwith "Not Implemented." + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader arch wordSize addr :> Instruction -let parseJALR binary = - match extract binary 15u 11u, pickBit binary 10u with - | 0u, 0u -> Op.JR, None, None, getRs binary - | 31u, 0u -> Op.JALR, None, None, getRs binary - | 31u, 1u -> Op.JALRHB, None, None, getRs binary - | _, 0u -> Op.JALR, None, None, getRdRs binary - | _, 1u -> Op.JALRHB, None, None, getRdRs binary - | _ -> failwith "Not Implemented." + member __.MaxInstructionSize = 4 -let parseJR binary = - match pickBit binary 10u with - | 0u -> Op.JR, None, None, getRs binary - | _ -> Op.JRHB, None, None, getRs binary - -let parseDIVU arch binary = - match extract binary 15u 11u, extract binary 10u 6u with - | 0u, 0u -> Op.DIVU, None, None, getRsRt binary - | _, 0b00010u when isMIPS32R6 arch -> Op.DIVU, None, None, getRdRsRt binary - | _ -> failwith "Not Implemented." - -let parseR2CLZ binary = - match extract binary 10u 6u with - | 0u -> Op.CLZ, None, None, getRdRs binary - | _ -> failwith "Not Implemented." - -let parseR6CLZ binary = - match extract binary 20u 16u with - | 0u -> Op.CLZ, None, None, getRdRs binary - | _ -> failwith "Not Implemented." - -let parseMFHI arch binary = - match isRel2 arch, extract binary 25u 16u, extract binary 10u 6u with - | true, 0u, 0u -> Op.MFHI, None, None, getRd binary - | false, _, 1u -> parseR6CLZ binary - | _ -> failwith "Not Implemented." - -let parseR2DCLZ binary = - match extract binary 10u 6u with - | 0u -> Op.DCLZ, None, None, getRdRs binary - | _ -> failwith "Not Implemented." - -let parseR6DCLZ binary = - match extract binary 20u 16u with - | 0u -> Op.DCLZ, None, None, getRdRs binary - | _ -> failwith "Not Implemented." - -let parseMFLO arch binary = - match isRel2 arch, extract binary 25u 16u, extract binary 10u 6u with - | true, 0u, 0u -> Op.MFLO, None, None, getRd binary - | false, _, 1u -> parseR6DCLZ binary - | _ -> failwith "Not Implemented." - -/// Table A.3 MIPS64 SEPCIAL Opcode Encoding of Function Field -let parseSPECIAL arch bin = - match extract bin 5u 0u with - | 0b000000u -> parseSLL bin - | 0b000001u when chk10to6 bin 0u && ztf bin 0b00u && isRel2 arch -> - Op.MOVF, None, None, getRdRsCc bin - | 0b000001u when chk10to6 bin 0u && ztf bin 0b01u && isRel2 arch -> - Op.MOVT, None, None, getRdRsCc bin - | 0b000010u when chk25to21 bin 0u -> Op.SRL, None, None, getRdRtSa bin - | 0b000010u when chk25to21 bin 1u -> Op.ROTR, None, None, getRdRtSa bin - | 0b000011u when chk25to21 bin 0u -> Op.SRA, None, None, getRdRtSa bin - | 0b000100u when chk10to6 bin 0u -> Op.SLLV, None, None, getRdRtRs bin - | 0b000101u -> failwith "LSA" - | 0b000110u when chk10to6 bin 0u -> Op.SRLV, None, None, getRdRtRs bin - | 0b000110u when chk10to6 bin 1u && isRel2 arch -> - Op.ROTRV, None, None, getRdRtRs bin - | 0b000111u when chk10to6 bin 0u -> Op.SRAV, None, None, getRdRtRs bin - | 0b001000u -> parseJR bin - | 0b001001u -> parseJALR bin - | 0b001010u when chk10to6 bin 0u -> Op.MOVZ, None, None, getRdRsRt bin - | 0b001011u when chk10to6 bin 0u -> Op.MOVN, None, None, getRdRsRt bin - | 0b001101u -> Op.BREAK, None, None, NoOperand - | 0b001111u when chk25to11 bin 0u -> Op.SYNC, None, None, getStype bin - | 0b010000u -> parseMFHI arch bin - | 0b010001u when isRel2 arch && chk20to6 bin 0u -> - Op.MTHI, None, None, getRs bin - | 0b010010u -> parseMFLO arch bin - | 0b010011u when isRel2 arch && chk20to6 bin 0u -> - Op.MTLO, None, None, getRs bin - | 0b010100u when chk10to6 bin 0u && isMIPS64 arch -> - Op.DSLLV, None, None, getRdRtRs bin - | 0b010110u when chk10to6 bin 0u && isMIPS64 arch -> - Op.DSRLV, None, None, getRdRtRs bin - | 0b010110u when chk10to6 bin 1u && isMIPS64R2 arch -> - Op.DROTRV, None, None, getRdRtRs bin - | 0b010111u when chk10to6 bin 0u && isMIPS64 arch -> - Op.DSRAV, None, None, getRdRtRs bin - | 0b011000u when chk15to6 bin 0u && isRel2 arch -> - Op.MULT, None, None, getRsRt bin - | 0b011001u when chk15to6 bin 0u -> Op.MULTU, None, None, getRsRt bin - | 0b011010u when chk15to6 bin 0u -> Op.DIV, None, None, getRsRt bin - | 0b011011u -> parseDIVU arch bin - | 0b011100u when chk15to6 bin 0u && isMIPS64R2 arch -> - Op.DMULT, None, None, getRsRt bin - | 0b011101u when chk15to6 bin 0u && isMIPS64R2 arch -> - Op.DMULTU, None, None, getRsRt bin - | 0b011110u when chk15to6 bin 0u && isMIPS64R2 arch -> - Op.DDIV, None, None, getRsRt bin - | 0b011111u when chk15to6 bin 0u && isMIPS64R2 arch -> - Op.DDIVU, None, None, getRsRt bin - | 0b100000u when chk10to6 bin 0u -> Op.ADD, None, None, getRdRsRt bin - | 0b100001u when chk10to6 bin 0u -> Op.ADDU, None, None, getRdRsRt bin - | 0b100011u when chk10to6 bin 0u -> Op.SUBU, None, None, getRdRsRt bin - | 0b100100u when chk10to6 bin 0u -> Op.AND, None, None, getRdRsRt bin - | 0b100101u when chk10to6 bin 0u -> Op.OR, None, None, getRdRsRt bin - | 0b100110u when chk10to6 bin 0u -> Op.XOR, None, None, getRdRsRt bin - | 0b100111u when chk10to6 bin 0u -> Op.NOR, None, None, getRdRsRt bin - | 0b101010u when chk10to6 bin 0u -> Op.SLT, None, None, getRdRsRt bin - | 0b101011u when chk10to6 bin 0u -> Op.SLTU, None, None, getRdRsRt bin - | 0b101101u when chk10to6 bin 0u && isMIPS64 arch -> - Op.DADDU, None, None, getRdRsRt bin - | 0b101111u when chk10to6 bin 0u && isMIPS64 arch -> - Op.DSUBU, None, None, getRdRsRt bin - | 0b110100u -> Op.TEQ, None, None, getRsRt bin - | 0b111000u when chk25to21 bin 0u && isMIPS64 arch -> - Op.DSLL, None, None, getRdRtSa bin - | 0b111010u when chk25to21 bin 0u && isMIPS64 arch -> - Op.DSRL, None, None, getRdRtSa bin - | 0b111010u when chk25to21 bin 1u && isMIPS64R2 arch -> - Op.DROTR, None, None, getRdRtSa bin - | 0b111011u when chk25to21 bin 0u && isMIPS64 arch -> - Op.DSRA, None, None, getRdRtSa bin - | 0b111100u when chk25to21 bin 0u && isMIPS64 arch -> - Op.DSLL32, None, None, getRdRtSa bin - | 0b111110u when chk25to21 bin 0u && isMIPS64 arch -> - Op.DSRL32, None, None, getRdRtSa bin - | 0b111110u when chk25to21 bin 1u && isMIPS64R2 arch -> - Op.DROTR32, None, None, getRdRtSa bin - | 0b111111u when chk25to21 bin 0u && isMIPS64 arch -> - Op.DSRA32, None, None, getRdRtSa bin - | _ -> failwith "Not Implemented." - -let parseBAL arch binary = - match extract binary 25u 21u with - | 0u -> Op.BAL, None, None, getRel16 binary - | _ when isMIPS32R2 arch -> Op.BGEZAL, None, None, getRsRel16 binary - | _ -> failwith "Not Implemented." - -/// Table A.4 MIPS64 REGIMM Encoding of rt Field -let parseREGIMM arch binary = - match extract binary 20u 16u with - | 0b00000u -> Op.BLTZ, None, None, getRsRel16 binary - | 0b00001u -> Op.BGEZ, None, None, getRsRel16 binary - | 0b10001u -> parseBAL arch binary - | _ -> failwith "Not Implemented." - -/// Table A.5 MIPS64 SEPCIAL2 Encoding of Function Field -let parseSPECIAL2 arch bin = - match extract bin 5u 0u with - | 0b000000u when isRel2 arch && chk15to6 bin 0u -> - Op.MADD, None, None, getRsRt bin - | 0b000001u when isRel2 arch && chk15to6 bin 0u -> - Op.MADDU, None, None, getRsRt bin - | 0b000010u when isRel2 arch && chk10to6 bin 0u -> - Op.MUL, None, None, getRdRsRt bin - | 0b000100u when isRel2 arch && chk15to6 bin 0u -> - Op.MSUB, None, None, getRsRt bin - | 0b000101u when isRel2 arch && chk15to6 bin 0u -> - Op.MSUBU, None, None, getRsRt bin - | 0b100000u -> parseR2CLZ bin - | 0b100100u when isMIPS64 arch -> parseR2DCLZ bin - | _ -> failwith "Not Implemented." - -let parseSignExt arch binary = - match extract binary 25u 21u, extract binary 10u 8u, extract binary 7u 6u with - | 0u, 0u, 0u when isMIPS32R6 arch -> Op.BITSWAP, None, None, getRdRt binary - | 0u, 0u, 0u when isMIPS64R6 arch -> Op.DBITSWAP, None, None, getRdRt binary - | _, 0b10u, _ when isMIPS32R6 arch -> Op.ALIGN, None, None, getRdRsRtBp binary - | _, 0b10u, _ when isMIPS64R6 arch -> - Op.DALIGN, None, None, getRdRsRtBp binary - | 0u, 0b100u, 0u -> Op.SEB, None, None, getRdRt binary - | 0u, 0b110u, 0u -> Op.SEH, None, None, getRdRt binary - | 0u, 0u, 0b10u when isRel2 arch -> - Op.WSBH, None, None, getRdRt binary - | _ -> failwith "Not Implemented." - -/// Table A.6 MIPS64 SEPCIAL3 Encoding of Function Field for Release of the -/// Architecture -let parseSPECIAL3 arch binary = - match extract binary 5u 0u with - | 0b000000u -> Op.EXT, None, None, getRtRsPosSize2 binary - | 0b000001u when isMIPS64R2 arch -> - Op.DEXTM, None, None, getRtRsPosSize5 binary - | 0b000010u when isMIPS64R2 arch -> - Op.DEXTU, None, None, getRtRsPosSize6 binary - | 0b000011u when isMIPS64R2 arch -> - Op.DEXT, None, None, getRtRsPosSize2 binary - | 0b000100u -> Op.INS, None, None, getRtRsPosSize binary - | 0b000101u when isMIPS64R2 arch -> - Op.DINSM, None, None, getRtRsPosSize3 binary - | 0b000110u when isMIPS64R2 arch -> - Op.DINSU, None, None, getRtRsPosSize4 binary - | 0b000111u when isMIPS64R2 arch -> - Op.DINS, None, None, getRtRsPosSize binary - | 0b100000u -> parseSignExt arch binary - | 0b100100u when chk25to21 binary 0u && isMIPS64R2 arch (* DBSHFL *) -> - match extract binary 10u 6u with - | 0b00010u -> Op.DSBH, None, None, getRdRt binary - | 0b00101u -> Op.DSHD, None, None, getRdRt binary - | _ -> failwith "Not Implemented." - | 0b100110u when pickBit binary 6u = 0u && isRel6 arch -> - Op.SC, None, None, getRtMemBaseOff9 binary 32 - | 0b100111u when pickBit binary 6u = 0u && isRel6 arch -> - Op.SCD, None, None, getRtMemBaseOff9 binary 64 - | 0b110101u when pickBit binary 6u = 0u && isRel6 arch -> - Op.PREF, None, None, getHintMemBaseOff9 binary 32 - | 0b110110u when pickBit binary 6u = 0u && isRel6 arch -> - Op.LL, None, None, getRtMemBaseOff9 binary 32 - | 0b110111u when pickBit binary 6u = 0u && isMIPS64R6 arch -> - Op.LL, None, None, getRtMemBaseOff9 binary 64 - | 0b111011u when extract binary 10u 9u = 0u -> - Op.RDHWR, None, None, getRtRdSel binary - | _ -> failwith "Not Implemented." - -/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 -/// on page 70, 93 -let parseBEQ binary = - match extract binary 25u 16u with - | 0u -> Op.B, None, None, getRel16 binary - | _ -> Op.BEQ, None, None, getRsRtRel16 binary - -/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 -/// on page 58, 295 -let parseLUIAUI arch binary = - match extract binary 25u 21u with - | 0u when isRel6 arch -> Op.AUI, None, None, getRtImm16 binary - | 0u -> Op.LUI, None, None, getRtImm16 binary - | _ -> Op.AUI, None, None, getRtRsImm16s binary - -/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 -/// on page 89, 94, 105 -let parsePOP06 binary = - match extract binary 20u 16u with - | 0u -> Op.BLEZ, None, None, getRsRel16 binary - | _ -> failwith "Not Implemented." - -/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 -/// on page 89, 94, 105 -let parsePOP07 binary = - match extract binary 20u 16u with - | 0u -> Op.BGTZ, None, None, getRsRel16 binary - | _ -> failwith "Not Implemented." - -/// Table A.18 MIPS64 COP1 Encoding of Function Field When rs=S, Revision 6.06 -let parseCOP1WhenRsS arch binary = - match extract binary 5u 0u with - | 0b000000u -> Op.ADD, None, Some Fmt.S, getFdFsFt binary - | 0b000001u -> Op.SUB, None, Some Fmt.S, getFdFsFt binary - | 0b000010u -> Op.MUL, None, Some Fmt.S, getFdFsFt binary - | 0b000011u -> Op.DIV, None, Some Fmt.S, getFdFsFt binary - | 0b000100u -> Op.SQRT, None, Some Fmt.S, getFdFs binary - | 0b000101u -> Op.ABS, None, Some Fmt.S, getFdFs binary - | 0b000110u when chk20to16 binary 0u -> - Op.MOV, None, Some Fmt.S, getFdFs binary - | 0b000111u when chk20to16 binary 0u -> - Op.NEG, None, Some Fmt.S, getFdFs binary - | 0b001001u when chk20to16 binary 0u -> - Op.TRUNCL, None, Some Fmt.S, getFdFs binary - | 0b001101u when chk20to16 binary 0u -> - Op.TRUNCW, None, Some Fmt.S, getFdFs binary - | 0b010001u when ztf binary 0b00u && isRel2 arch -> - Op.MOVF, None, Some Fmt.S, getFdFsCc binary - | 0b010001u when ztf binary 0b01u && isRel2 arch -> - Op.MOVT, None, Some Fmt.S, getFdFsCc binary - | 0b010010u when isRel2 arch -> Op.MOVZ, None, Some Fmt.S, getFdFsRt binary - | 0b010011u when isRel2 arch -> Op.MOVN, None, Some Fmt.S, getFdFsRt binary - | 0b010101u -> Op.RECIP, None, Some Fmt.S, getFdFs binary - | 0b010110u -> Op.RSQRT, None, Some Fmt.S, getFdFs binary - | 0b100001u when chk20to16 binary 0u -> - Op.CVTD, None, Some Fmt.S, getFdFs binary - | b when b &&& 0b110000u = 0b110000u && isRel2 arch -> - let oprFn = if cc binary 0u then getFsFt else getCcFsFt - let cond = getCondition (extract binary 3u 0u) |> Some - Op.C, cond, Some Fmt.S, oprFn binary - | _ -> failwith "Not Implemented." - -/// Table A.19 MIPS64 COP1 Encoding of Function Field When rs=D, Revision 6.06 -let parseCOP1WhenRsD arch binary = - match extract binary 5u 0u with - | 0b000000u -> Op.ADD, None, Some Fmt.D, getFdFsFt binary - | 0b000001u -> Op.SUB, None, Some Fmt.D, getFdFsFt binary - | 0b000010u -> Op.MUL, None, Some Fmt.D, getFdFsFt binary - | 0b000011u -> Op.DIV, None, Some Fmt.D, getFdFsFt binary - | 0b000100u -> Op.SQRT, None, Some Fmt.D, getFdFs binary - | 0b000101u -> Op.ABS, None, Some Fmt.D, getFdFs binary - | 0b000110u when chk20to16 binary 0u -> - Op.MOV, None, Some Fmt.D, getFdFs binary - | 0b000111u when chk20to16 binary 0u -> - Op.NEG, None, Some Fmt.D, getFdFs binary - | 0b001001u when chk20to16 binary 0u -> - Op.TRUNCL, None, Some Fmt.D, getFdFs binary - | 0b001101u when chk20to16 binary 0u -> - Op.TRUNCW, None, Some Fmt.D, getFdFs binary - | 0b010001u when ztf binary 0b00u && isRel2 arch -> - Op.MOVF, None, Some Fmt.D, getFdFsCc binary - | 0b010001u when ztf binary 0b01u && isRel2 arch -> - Op.MOVT, None, Some Fmt.D, getFdFsCc binary - | 0b010010u when isRel2 arch -> Op.MOVZ, None, Some Fmt.D, getFdFsRt binary - | 0b010011u when isRel2 arch -> Op.MOVN, None, Some Fmt.D, getFdFsRt binary - | 0b010101u -> Op.RECIP, None, Some Fmt.D, getFdFs binary - | 0b010110u -> Op.RSQRT, None, Some Fmt.D, getFdFs binary - | 0b100000u when chk20to16 binary 0u -> - Op.CVTS, None, Some Fmt.D, getFdFs binary - | b when b &&& 0b110000u = 0b110000u && isRel2 arch -> - let oprFn = if cc binary 0u then getFsFt else getCcFsFt - let cond = getCondition (extract binary 3u 0u) |> Some - Op.C, cond, Some Fmt.D, oprFn binary - | _ -> failwith "Not Implemented." - -/// Table A.20 MIPS64 COP1 Encoding of Function Field When rs=W or L, -/// Revision 6.06 -let parseCOP1WhenRsW _arch binary = - match extract binary 5u 0u with - | 0b100000u when chk20to16 binary 0u -> - Op.CVTS, None, Some Fmt.W, getFdFs binary - | 0b100001u when chk20to16 binary 0u -> - Op.CVTD, None, Some Fmt.W, getFdFs binary - | _ -> failwith "Not Implemented." - -/// Table A.20 MIPS64 COP1 Encoding of Function Field When rs=W or L, -/// Revision 6.06 -let parseCOP1WhenRsL _arch binary = - match extract binary 5u 0u with - | 0b100000u when chk20to16 binary 0u -> - Op.CVTS, None, Some Fmt.L, getFdFs binary - | 0b100001u when chk20to16 binary 0u -> - Op.CVTD, None, Some Fmt.L, getFdFs binary - | _ -> failwith "Not Implemented." - -let parseCOP1 arch binary = - match extract binary 25u 21u with - | 0b00000u when chk10to0 binary 0u -> Op.MFC1, None, None, getRtFs binary - | 0b00001u when chk10to0 binary 0u && isMIPS64 arch -> - Op.DMFC1, None, None, getRtFs binary - | 0b00010u when chk10to0 binary 0u -> Op.CFC1, None, None, getRtFs binary - | 0b00011u when chk10to0 binary 0u && isRel2 arch -> - Op.MFHC1, None, None, getRtFs binary - | 0b00100u when chk10to0 binary 0u -> Op.MTC1, None, None, getRtFs binary - | 0b00101u when chk10to0 binary 0u -> Op.DMTC1, None, None, getRtFs binary - | 0b00110u when chk10to0 binary 0u -> Op.CTC1, None, None, getRtFs binary - | 0b00111u when chk10to0 binary 0u && isRel2 arch -> - Op.MTHC1, None, None, getRtFs binary - | 0b01000u when nd binary 0u && tf binary 0u -> - Op.BC1F, None, None, getCcOff binary - | 0b01000u when nd binary 0u && tf binary 1u -> - Op.BC1T, None, None, getCcOff binary - | 0b10000u -> parseCOP1WhenRsS arch binary - | 0b10001u -> parseCOP1WhenRsD arch binary - | 0b10100u -> parseCOP1WhenRsW arch binary - | 0b10101u -> parseCOP1WhenRsL arch binary - | _ -> failwith "Not Implemented." - -/// Table A.24 MIPS64 COP1X6R1 Encoding of Function Field on page 588, -/// Revision 6.06. -let parseCOP1X arch binary = - match extract binary 5u 0u with - | 0b000000u when chk15to11 binary 0u && isRel2 arch -> - Op.LWXC1, None, None, getFdMemBaseIdx binary 32 - | 0b000001u when chk15to11 binary 0u && isRel2 arch -> - Op.LDXC1, None, None, getFdMemBaseIdx binary 64 - | 0b001000u when chk10to6 binary 0u && isRel2 arch -> - Op.SWXC1, None, None, getFsMemBaseIdx binary 32 - | 0b001001u when chk10to6 binary 0u && isRel2 arch -> - Op.SDXC1, None, None, getFsMemBaseIdx binary 64 - | 0b001111u when chk10to6 binary 0u && isRel2 arch -> - Op.PREFX, None, None, getHintMemBaseIdx binary 32 - | 0b100000u when isRel2 arch -> Op.MADD, None, Some Fmt.S, getFdFrFsFt binary - | 0b100001u when isRel2 arch -> Op.MADD, None, Some Fmt.D, getFdFrFsFt binary - | 0b100110u when isRel2 arch -> - Op.MADD, None, Some Fmt.PS, getFdFrFsFt binary - | 0b101000u when isRel2 arch -> Op.MSUB, None, Some Fmt.S, getFdFrFsFt binary - | 0b101001u when isRel2 arch -> Op.MSUB, None, Some Fmt.D, getFdFrFsFt binary - | 0b101110u when isRel2 arch -> - Op.MSUB, None, Some Fmt.PS, getFdFrFsFt binary - | 0b110000u when isRel2 arch -> Op.NMADD, None, Some Fmt.S, getFdFrFsFt binary - | 0b110001u when isRel2 arch -> Op.NMADD, None, Some Fmt.D, getFdFrFsFt binary - | 0b110110u when isRel2 arch -> - Op.NMADD, None, Some Fmt.PS, getFdFrFsFt binary - | _ -> failwith "Not Implemented." - -/// The MIPS64 Instrecutin Set Reference Manual, MD00087, Revision 6.06 -/// Table A.2 MIPS64 Encoding of the Opcode Field -let parseOpcodeField arch binary = - match extract binary 31u 26u with - | 0b000000u -> parseSPECIAL arch binary - | 0b000001u -> parseREGIMM arch binary - | 0b000010u -> Op.J, None, None, getTarget binary - | 0b000011u -> Op.JAL, None, None, getTarget binary - | 0b000100u -> parseBEQ binary - | 0b000101u -> Op.BNE, None, None, getRsRtRel16 binary - | 0b000110u -> parsePOP06 binary - | 0b000111u -> parsePOP07 binary - | 0b001000u -> failwith "ADDI/POP10" - | 0b001001u -> Op.ADDIU, None, None, getRtRsImm16s binary - | 0b001010u -> Op.SLTI, None, None, getRtRsImm16s binary - | 0b001011u -> Op.SLTIU, None, None, getRtRsImm16s binary - | 0b001100u -> Op.ANDI, None, None, getRtRsImm16 binary - | 0b001101u -> Op.ORI, None, None, getRtRsImm16 binary - | 0b001110u -> Op.XORI, None, None, getRtRsImm16 binary - | 0b001111u -> parseLUIAUI arch binary - | 0b010000u -> failwith "COP0" - | 0b010001u -> parseCOP1 arch binary - | 0b010010u -> failwith "COP2" - | 0b010011u -> parseCOP1X arch binary - | 0b010100u -> failwith "BEQL" - | 0b010101u -> failwith "BNEL" - | 0b010110u -> failwith "BLEZL/POP26" - | 0b010111u -> failwith "BGTZL/POP27" - | 0b011000u -> failwith "DADDI/POP30" - | 0b011001u when isMIPS64 arch -> Op.DADDIU, None, None, getRtRsImm16s binary - | 0b011010u when isMIPS64R2 arch -> - Op.LDL, None, None, getRtMemBaseOff binary 64 - | 0b011011u when isMIPS64R2 arch -> - Op.LDR, None, None, getRtMemBaseOff binary 64 - | 0b011100u -> parseSPECIAL2 arch binary - | 0b011101u -> failwith "JALX/DAUI" - | 0b011110u -> failwith "MSA" - | 0b011111u -> parseSPECIAL3 arch binary - | 0b100000u -> Op.LB, None, None, getRtMemBaseOff binary 8 - | 0b100001u -> Op.LH, None, None, getRtMemBaseOff binary 16 - | 0b100010u when isRel2 arch -> - Op.LWL, None, None, getRtMemBaseOff binary 32 - | 0b100011u -> Op.LW, None, None, getRtMemBaseOff binary 32 - | 0b100100u -> Op.LBU, None, None, getRtMemBaseOff binary 8 - | 0b100101u -> Op.LHU, None, None, getRtMemBaseOff binary 16 - | 0b100110u when isRel2 arch -> - Op.LWR, None, None, getRtMemBaseOff binary 32 - | 0b100111u when isMIPS64 arch -> - Op.LWU, None, None, getRtMemBaseOff binary 32 - | 0b101000u -> Op.SB, None, None, getRtMemBaseOff binary 8 - | 0b101001u -> Op.SH, None, None, getRtMemBaseOff binary 16 - | 0b101010u when isRel2 arch -> - Op.SWL, None, None, getRtMemBaseOff binary 32 - | 0b101011u -> Op.SW, None, None, getRtMemBaseOff binary 32 - | 0b101100u when isMIPS64R2 arch -> - Op.SDL, None, None, getRtMemBaseOff binary 64 - | 0b101101u when isMIPS64R2 arch -> - Op.SDR, None, None, getRtMemBaseOff binary 64 - | 0b101110u when isRel2 arch -> - Op.SWR, None, None, getRtMemBaseOff binary 32 - | 0b101111u -> failwith "CACHE" - | 0b110000u when isRel2 arch (* pre-Release 6 *) -> - Op.LL, None, None, getRtMemBaseOff binary 32 - | 0b110001u -> Op.LWC1, None, None, getFtMemBaseOff binary 32 - | 0b110010u -> failwith "LWC2" - | 0b110011u when isRel2 arch (* pre-Release 6 *) -> - Op.PREF, None, None, getHintMemBaseOff binary 32 - | 0b110100u when isMIPS64R2 arch (* MIPS64 pre-Release 6 *) -> - Op.LLD, None, None, getRtMemBaseOff binary 64 - | 0b110101u -> Op.LDC1, None, None, getFtMemBaseOff binary 64 - | 0b110110u -> failwith "LDC2/BEQZC/JIC/POP66" - | 0b110111u when isMIPS64 arch -> - Op.LD, None, None, getRtMemBaseOff binary 64 - | 0b111000u when isRel2 arch (* pre-Release 6 *) -> - Op.SC, None, None, getRtMemBaseOff binary 32 - | 0b111001u -> Op.SWC1, None, None, getFtMemBaseOff binary 32 - | 0b111010u -> failwith "SWC2/BALC" - | 0b111011u -> failwith "PCREL" - | 0b111100u when isRel2 arch (* pre-Release 6 *) -> - Op.SCD, None, None, getRtMemBaseOff binary 64 - | 0b111101u -> Op.SDC1, None, None, getFtMemBaseOff binary 64 - | 0b111110u -> failwith "SDC2/BNEZC/JIALC/POP76" - | 0b111111u when isMIPS64 arch -> - Op.SD, None, None, getRtMemBaseOff binary 64 - | _ -> failwith "Not Implemented." - -let getOperationSize opcode wordSz = - match opcode with - | Op.SB -> 8 - | Op.SH -> 16 - | Op.SW -> 32 - | Op.SD -> 64 - | _ -> WordSize.toRegType wordSz - -let parse (span: ReadOnlySpan) (reader: IBinReader) arch wordSize addr = - let bin = reader.ReadUInt32 (span, 0) - let opcode, cond, fmt, operands = parseOpcodeField arch bin - let insInfo = - { Address = addr - NumBytes = 4u - Condition = cond - Fmt = fmt - Opcode = opcode - Operands = operands - OperationSize = getOperationSize opcode wordSize - Arch = arch } - MIPSInstruction (addr, 4u, insInfo, wordSize) - -// vim: set tw=80 sts=2 sw=2: + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSParsingMain.fs b/src/FrontEnd/BinLifter/MIPS/MIPSParsingMain.fs new file mode 100644 index 00000000..2328d42b --- /dev/null +++ b/src/FrontEnd/BinLifter/MIPS/MIPSParsingMain.fs @@ -0,0 +1,661 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.MIPS.ParsingMain + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData +open B2R2.FrontEnd.BinLifter.MIPS.Helper + +let parseNOP binary = + match extract binary 10u 6u with + | 0u -> Op.NOP, None, None, NoOperand + | 1u -> Op.SSNOP, None, None, NoOperand + | 3u -> Op.EHB, None, None, NoOperand + | 5u -> Op.PAUSE, None, None, NoOperand + | _ -> raise ParsingFailureException + +let parseSLL binary = + match extract binary 25u 11u with + | 0u -> parseNOP binary + | _ when extract binary 25u 21u = 0u -> Op.SLL, None, None, getRdRtSa binary + | _ -> raise ParsingFailureException + +let parseJALR binary = + match extract binary 15u 11u, pickBit binary 10u with + | 0u, 0u -> Op.JR, None, None, getRs binary + | 31u, 0u -> Op.JALR, None, None, getRs binary + | 31u, 1u -> Op.JALRHB, None, None, getRs binary + | _, 0u -> Op.JALR, None, None, getRdRs binary + | _, 1u -> Op.JALRHB, None, None, getRdRs binary + | _ -> raise ParsingFailureException + +let parseJR binary = + match pickBit binary 10u with + | 0u -> Op.JR, None, None, getRs binary + | _ -> Op.JRHB, None, None, getRs binary + +let parseDIVU binary = + match extract binary 15u 11u, extract binary 10u 6u with + | 0u, 0u -> Op.DIVU, None, None, getRsRt binary + | _, 0b00010u -> Op.DIVU, None, None, getRdRsRt binary + | _ -> raise ParsingFailureException + +let parseR2CLZ binary = + match extract binary 10u 6u with + | 0u -> Op.CLZ, None, None, getRdRs binary + | _ -> raise ParsingFailureException + +let parseR6CLZ binary = + match extract binary 20u 16u with + | 0u -> Op.CLZ, None, None, getRdRs binary + | _ -> raise ParsingFailureException + +let parseMFHI binary = + match extract binary 25u 16u, extract binary 10u 6u with + | 0u, 0u -> Op.MFHI, None, None, getRd binary + | _, 1u -> parseR6CLZ binary + | _ -> raise ParsingFailureException + +let parseR2DCLZ binary = + match extract binary 10u 6u with + | 0u -> Op.DCLZ, None, None, getRdRs binary + | _ -> raise ParsingFailureException + +let parseR6DCLZ binary = + match extract binary 20u 16u with + | 0u -> Op.DCLZ, None, None, getRdRs binary + | _ -> raise ParsingFailureException + +let parseMFLO binary = + match extract binary 25u 16u, extract binary 10u 6u with + | 0u, 0u -> Op.MFLO, None, None, getRd binary + | _, 1u -> parseR6DCLZ binary + | _ -> raise ParsingFailureException + +/// Table A.3 MIPS64 SEPCIAL Opcode Encoding of Function Field +let parseSPECIAL bin = + let b25to21 = extract bin 25u 21u + let b20to6 = extract bin 20u 6u + let b15to6 = extract bin 15u 6u + let b10to6 = extract bin 10u 6u + match extract bin 5u 0u with + | 0b000000u -> parseSLL bin + | 0b000001u -> + if b10to6 = 0u then + let ztf = extract bin 17u 16u + if ztf = 0b00u then Op.MOVF, None, None, getRdRsCc bin + elif ztf = 0b01u then Op.MOVT, None, None, getRdRsCc bin + else raise ParsingFailureException + else raise ParsingFailureException + | 0b000010u -> + if b25to21 = 0u then Op.SRL, None, None, getRdRtSa bin + elif b25to21 = 1u then Op.ROTR, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b000011u -> + if b25to21 = 0u then Op.SRA, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b000100u -> + if b10to6 = 0u then Op.SLLV, None, None, getRdRtRs bin + else raise ParsingFailureException + | 0b000101u -> failwith "LSA" // TODO + | 0b000110u -> + if b10to6 = 0u then Op.SRLV, None, None, getRdRtRs bin + elif b10to6 = 1u then Op.ROTRV, None, None, getRdRtRs bin + else raise ParsingFailureException + | 0b000111u -> + if b10to6 = 0u then Op.SRAV, None, None, getRdRtRs bin + else raise ParsingFailureException + | 0b001000u -> parseJR bin + | 0b001001u -> parseJALR bin + | 0b001010u -> + if b10to6 = 0u then Op.MOVZ, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b001011u -> + if b10to6 = 0u then Op.MOVN, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b001100u -> Op.SYSCALL, None, None, NoOperand + | 0b001101u -> Op.BREAK, None, None, NoOperand + | 0b001111u -> + if extract bin 25u 11u = 0u then Op.SYNC, None, None, getStype bin + else raise ParsingFailureException + | 0b010000u -> parseMFHI bin + | 0b010001u -> + if b20to6 = 0u then Op.MTHI, None, None, getRs bin + else raise ParsingFailureException + | 0b010010u -> parseMFLO bin + | 0b010011u -> + if b20to6 = 0u then Op.MTLO, None, None, getRs bin + else raise ParsingFailureException + | 0b010100u -> + if b10to6 = 0u then Op.DSLLV, None, None, getRdRtRs bin + else raise ParsingFailureException + | 0b010110u -> + if b10to6 = 0u then Op.DSRLV, None, None, getRdRtRs bin + elif b10to6 = 1u then Op.DROTRV, None, None, getRdRtRs bin + else raise ParsingFailureException + | 0b010111u -> + if b10to6 = 0u then Op.DSRAV, None, None, getRdRtRs bin + else raise ParsingFailureException + | 0b011000u -> + if b15to6 = 0u then Op.MULT, None, None, getRsRt bin + else raise ParsingFailureException + | 0b011001u -> + if b15to6 = 0u then Op.MULTU, None, None, getRsRt bin + else raise ParsingFailureException + | 0b011010u -> + if b15to6 = 0u then Op.DIV, None, None, getRsRt bin + else raise ParsingFailureException + | 0b011011u -> parseDIVU bin + | 0b011100u -> + if b15to6 = 0u then Op.DMULT, None, None, getRsRt bin + else raise ParsingFailureException + | 0b011101u -> + if b15to6 = 0u then Op.DMULTU, None, None, getRsRt bin + else raise ParsingFailureException + | 0b011110u -> + if b15to6 = 0u then Op.DDIV, None, None, getRsRt bin + else raise ParsingFailureException + | 0b011111u -> + if b15to6 = 0u then Op.DDIVU, None, None, getRsRt bin + else raise ParsingFailureException + | 0b100000u -> + if b10to6 = 0u then Op.ADD, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b101100u -> + if b10to6 = 0u then Op.DADD, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b100001u -> + if b10to6 = 0u then Op.ADDU, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b100011u -> + if b10to6 = 0u then Op.SUBU, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b100100u -> + if b10to6 = 0u then Op.AND, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b100101u -> + if b10to6 = 0u then Op.OR, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b100110u -> + if b10to6 = 0u then Op.XOR, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b100111u -> + if b10to6 = 0u then Op.NOR, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b101010u -> + if b10to6 = 0u then Op.SLT, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b101011u -> + if b10to6 = 0u then Op.SLTU, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b101101u -> + if b10to6 = 0u then Op.DADDU, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b101111u -> + if b10to6 = 0u then Op.DSUBU, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b110100u -> Op.TEQ, None, None, getRsRt bin + | 0b111000u -> + if b25to21 = 0u then Op.DSLL, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b111010u -> + if b25to21 = 0u then Op.DSRL, None, None, getRdRtSa bin + elif b25to21 = 1u then Op.DROTR, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b111011u -> + if b25to21 = 0u then Op.DSRA, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b111100u -> + if b25to21 = 0u then Op.DSLL32, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b111110u -> + if b25to21 = 0u then Op.DSRL32, None, None, getRdRtSa bin + elif b25to21 = 1u then Op.DROTR32, None, None, getRdRtSa bin + else raise ParsingFailureException + | 0b111111u -> + if b25to21 = 0u then Op.DSRA32, None, None, getRdRtSa bin + else raise ParsingFailureException + | _ -> raise ParsingFailureException + +let parseBAL binary = + match extract binary 25u 21u with + | 0u -> Op.BAL, None, None, getRel16 binary + | _ -> Op.BGEZAL, None, None, getRsRel16 binary + +/// Table A.4 MIPS64 REGIMM Encoding of rt Field +let parseREGIMM binary = + match extract binary 20u 16u with + | 0b00000u -> Op.BLTZ, None, None, getRsRel16 binary + | 0b00001u -> Op.BGEZ, None, None, getRsRel16 binary + | 0b01100u -> Op.TEQI, None, None, getRsImm16s binary + | 0b10000u -> Op.BLTZAL, None, None, getRsRel16 binary + | 0b10001u -> parseBAL binary + | _ -> raise ParsingFailureException + +/// Table A.5 MIPS64 SEPCIAL2 Encoding of Function Field +let parseSPECIAL2 bin = + let b15to6 = extract bin 15u 6u + let b10to6 = extract bin 10u 6u + match extract bin 5u 0u with + | 0b000000u -> + if b15to6 = 0u then Op.MADD, None, None, getRsRt bin + else raise ParsingFailureException + | 0b000001u -> + if b15to6 = 0u then Op.MADDU, None, None, getRsRt bin + else raise ParsingFailureException + | 0b000010u -> + if b10to6 = 0u then Op.MUL, None, None, getRdRsRt bin + else raise ParsingFailureException + | 0b000100u -> + if b15to6 = 0u then Op.MSUB, None, None, getRsRt bin + else raise ParsingFailureException + | 0b000101u -> + if b15to6 = 0u then Op.MSUBU, None, None, getRsRt bin + else raise ParsingFailureException + | 0b100000u -> parseR2CLZ bin + | 0b100100u -> parseR2DCLZ bin + | _ -> raise ParsingFailureException + +/// Table A.13 MIPS64 BSHFL and DBSHFL Encoding of sa Field +let parseBSHFL binary = + let b25to21 = extract binary 25u 21u + match extract binary 10u 6u with + | 0b000000u -> + if b25to21 = 0u then Op.BITSWAP, None, None, getRdRt binary + else raise ParsingFailureException + | 0b00010u -> + if b25to21 = 0u then Op.WSBH, None, None, getRdRt binary + else raise ParsingFailureException + | b when b &&& 0b11100u = 0b01000u (* 0b010xx *) -> + Op.ALIGN, None, None, getRdRsRtBp binary + | 0b10000u -> + if b25to21 = 0u then Op.SEB, None, None, getRdRt binary + else raise ParsingFailureException + | 0b11000u -> + if b25to21 = 0u then Op.SEH, None, None, getRdRt binary + else raise ParsingFailureException + | _ -> raise ParsingFailureException + +let parseDBSHFL binary = + let b25to21 = extract binary 25u 21u + match extract binary 10u 6u with + | 0b000000u -> + if b25to21 = 0u then Op.DBITSWAP, None, None, getRdRt binary + else raise ParsingFailureException + | 0b00010u -> + if b25to21 = 0u then Op.DSBH, None, None, getRdRt binary + else raise ParsingFailureException + | b when b &&& 0b11000u = 0b01000u (* 0b01xxx *) -> + Op.DALIGN, None, None, getRdRsRtBp64 binary + | 0b00101u -> + if b25to21 = 0u then Op.DSHD, None, None, getRdRt binary + else raise ParsingFailureException + | _ -> raise ParsingFailureException + +/// Table A.6 MIPS64 SEPCIAL3 Encoding of Function Field for Release of the +/// Architecture +let parseSPECIAL3 binary = + let b6 = pickBit binary 6u + match extract binary 5u 0u with + | 0b000000u -> Op.EXT, None, None, getRtRsPosSize2 binary + | 0b000001u -> Op.DEXTM, None, None, getRtRsPosSize5 binary + | 0b000010u -> Op.DEXTU, None, None, getRtRsPosSize6 binary + | 0b000011u -> Op.DEXT, None, None, getRtRsPosSize2 binary + | 0b000100u -> Op.INS, None, None, getRtRsPosSize binary + | 0b000101u -> Op.DINSM, None, None, getRtRsPosSize3 binary + | 0b000110u -> Op.DINSU, None, None, getRtRsPosSize4 binary + | 0b000111u -> Op.DINS, None, None, getRtRsPosSize binary + | 0b100000u (* BSHFL *) -> parseBSHFL binary + | 0b100100u (* DBSHFL *) -> parseDBSHFL binary + | 0b100110u -> + if b6 = 0u then Op.SC, None, None, getRtMemBaseOff9 binary 32 + else raise ParsingFailureException + | 0b100111u -> + if b6 = 0u then Op.SCD, None, None, getRtMemBaseOff9 binary 64 + else raise ParsingFailureException + | 0b110101u -> + if b6 = 0u then Op.PREF, None, None, getHintMemBaseOff9 binary 32 + else raise ParsingFailureException + | 0b110110u -> + if b6 = 0u then Op.LL, None, None, getRtMemBaseOff9 binary 32 + else raise ParsingFailureException + | 0b110111u -> + if b6 = 0u then Op.LL, None, None, getRtMemBaseOff9 binary 64 + else raise ParsingFailureException + | 0b111011u -> + if extract binary 10u 9u = 0u then Op.RDHWR, None, None, getRtRdSel binary + else raise ParsingFailureException + | _ -> raise ParsingFailureException + +/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 +/// on page 70, 93 +let parseBEQ binary = + match extract binary 25u 16u with + | 0u -> Op.B, None, None, getRel16 binary + | _ -> Op.BEQ, None, None, getRsRtRel16 binary + +/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 +/// on page 58, 295 +let parseLUIAUI binary = + match extract binary 25u 21u with + | 0u -> Op.LUI, None, None, getRtImm16 binary + | _ -> Op.AUI, None, None, getRtRsImm16s binary + +/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 +/// on page 89, 94, 105 +let parsePOP06 binary = + match extract binary 20u 16u with + | 0u -> Op.BLEZ, None, None, getRsRel16 binary + | _ -> raise ParsingFailureException + +/// The MIPS64 Instruction Set Reference Manual, Revision 6.06 +/// on page 89, 94, 105 +let parsePOP07 binary = + match extract binary 20u 16u with + | 0u -> Op.BGTZ, None, None, getRsRel16 binary + | _ -> raise ParsingFailureException + +/// Table A.18 MIPS64 COP1 Encoding of Function Field When rs=S, Revision 6.06 +let parseCOP1WhenRsS binary = + let b20to16 = extract binary 20u 16u + let b17to16 = extract binary 17u 16u (* 0:tf *) + match extract binary 5u 0u with + | 0b000000u -> Op.ADD, None, Some Fmt.S, getFdFsFt binary + | 0b000001u -> Op.SUB, None, Some Fmt.S, getFdFsFt binary + | 0b000010u -> Op.MUL, None, Some Fmt.S, getFdFsFt binary + | 0b000011u -> Op.DIV, None, Some Fmt.S, getFdFsFt binary + | 0b000100u -> Op.SQRT, None, Some Fmt.S, getFdFs binary + | 0b000101u -> Op.ABS, None, Some Fmt.S, getFdFs binary + | 0b000110u -> + if b20to16 = 0u then Op.MOV, None, Some Fmt.S, getFdFs binary + else raise ParsingFailureException + | 0b000111u -> + if b20to16 = 0u then Op.NEG, None, Some Fmt.S, getFdFs binary + else raise ParsingFailureException + | 0b001001u -> + if b20to16 = 0u then Op.TRUNCL, None, Some Fmt.S, getFdFs binary + else raise ParsingFailureException + | 0b001101u -> + if b20to16 = 0u then Op.TRUNCW, None, Some Fmt.S, getFdFs binary + else raise ParsingFailureException + | 0b010001u -> + if b17to16 = 0b00u then Op.MOVF, None, Some Fmt.S, getFdFsCc binary + elif b17to16 = 0b01u then Op.MOVT, None, Some Fmt.S, getFdFsCc binary + else raise ParsingFailureException + | 0b010010u -> Op.MOVZ, None, Some Fmt.S, getFdFsRt binary + | 0b010011u -> Op.MOVN, None, Some Fmt.S, getFdFsRt binary + | 0b010101u -> Op.RECIP, None, Some Fmt.S, getFdFs binary + | 0b010110u -> Op.RSQRT, None, Some Fmt.S, getFdFs binary + | 0b100001u -> + if b20to16 = 0u then Op.CVTD, None, Some Fmt.S, getFdFs binary + else raise ParsingFailureException + | b when b &&& 0b110000u = 0b110000u -> + let cc = extract binary 10u 8u + let oprFn = if cc = 0u then getFsFt else getCcFsFt + let cond = getCondition (extract binary 3u 0u) |> Some + Op.C, cond, Some Fmt.S, oprFn binary + | _ -> raise ParsingFailureException + +/// Table A.19 MIPS64 COP1 Encoding of Function Field When rs=D, Revision 6.06 +let parseCOP1WhenRsD binary = + let b20to16 = extract binary 20u 16u + let b17to16 = extract binary 17u 16u (* 0:tf *) + match extract binary 5u 0u with + | 0b000000u -> Op.ADD, None, Some Fmt.D, getFdFsFt binary + | 0b000001u -> Op.SUB, None, Some Fmt.D, getFdFsFt binary + | 0b000010u -> Op.MUL, None, Some Fmt.D, getFdFsFt binary + | 0b000011u -> Op.DIV, None, Some Fmt.D, getFdFsFt binary + | 0b000100u -> Op.SQRT, None, Some Fmt.D, getFdFs binary + | 0b000101u -> Op.ABS, None, Some Fmt.D, getFdFs binary + | 0b000110u -> + if b20to16 = 0u then Op.MOV, None, Some Fmt.D, getFdFs binary + else raise ParsingFailureException + | 0b000111u -> + if b20to16 = 0u then Op.NEG, None, Some Fmt.D, getFdFs binary + else raise ParsingFailureException + | 0b001001u -> + if b20to16 = 0u then Op.TRUNCL, None, Some Fmt.D, getFdFs binary + else raise ParsingFailureException + | 0b001101u -> + if b20to16 = 0u then Op.TRUNCW, None, Some Fmt.D, getFdFs binary + else raise ParsingFailureException + | 0b010001u -> + if b17to16 = 0b00u then Op.MOVF, None, Some Fmt.D, getFdFsCc binary + elif b17to16 = 0b01u then Op.MOVT, None, Some Fmt.D, getFdFsCc binary + else raise ParsingFailureException + | 0b010010u -> Op.MOVZ, None, Some Fmt.D, getFdFsRt binary + | 0b010011u -> Op.MOVN, None, Some Fmt.D, getFdFsRt binary + | 0b010101u -> Op.RECIP, None, Some Fmt.D, getFdFs binary + | 0b010110u -> Op.RSQRT, None, Some Fmt.D, getFdFs binary + | 0b100000u -> + if b20to16 = 0u then Op.CVTS, None, Some Fmt.D, getFdFs binary + else raise ParsingFailureException + | b when b &&& 0b110000u = 0b110000u -> + let cc = extract binary 10u 8u + let oprFn = if cc = 0u then getFsFt else getCcFsFt + let cond = getCondition (extract binary 3u 0u) |> Some + Op.C, cond, Some Fmt.D, oprFn binary + | _ -> raise ParsingFailureException + +/// Table A.20 MIPS64 COP1 Encoding of Function Field When rs=W or L, +/// Revision 6.06 +let parseCOP1WhenRsW binary = + let b20to16 = extract binary 20u 16u + match extract binary 5u 0u with + | 0b100000u -> + if b20to16 = 0u then Op.CVTS, None, Some Fmt.W, getFdFs binary + else raise ParsingFailureException + | 0b100001u -> + if b20to16 = 0u then Op.CVTD, None, Some Fmt.W, getFdFs binary + else raise ParsingFailureException + | _ -> raise ParsingFailureException + +/// Table A.20 MIPS64 COP1 Encoding of Function Field When rs=W or L, +/// Revision 6.06 +let parseCOP1WhenRsL binary = + let b20to16 = extract binary 20u 16u + match extract binary 5u 0u with + | 0b100000u -> + if b20to16 = 0u then Op.CVTS, None, Some Fmt.L, getFdFs binary + else raise ParsingFailureException + | 0b100001u -> + if b20to16 = 0u then Op.CVTD, None, Some Fmt.L, getFdFs binary + else raise ParsingFailureException + | _ -> raise ParsingFailureException + +let parseCOP1 arch binary = + let b10to0 = extract binary 10u 0u + let b17to16 = extract binary 17u 16u (* nd:tf *) + match extract binary 25u 21u with + | 0b00000u -> + if b10to0 = 0u then Op.MFC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00001u -> + if b10to0 = 0u then Op.DMFC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00010u -> + if b10to0 = 0u then Op.CFC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00011u -> + if b10to0 = 0u then Op.MFHC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00100u -> + if b10to0 = 0u then Op.MTC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00101u -> + if b10to0 = 0u then Op.DMTC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00110u -> + if b10to0 = 0u then Op.CTC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b00111u -> + if b10to0 = 0u then Op.MTHC1, None, None, getRtFs binary + else raise ParsingFailureException + | 0b01000u -> + if b17to16 = 0b00u then Op.BC1F, None, None, getCcOff binary + elif b17to16 = 0b01u then Op.BC1T, None, None, getCcOff binary + else raise ParsingFailureException + | 0b10000u -> parseCOP1WhenRsS binary + | 0b10001u -> parseCOP1WhenRsD binary + | 0b10100u -> parseCOP1WhenRsW binary + | 0b10101u -> parseCOP1WhenRsL binary + | _ -> raise ParsingFailureException + +/// Table A.24 MIPS64 COP1X6R1 Encoding of Function Field on page 588, +/// Revision 6.06. +let parseCOP1X binary = + let b15to11 = extract binary 15u 11u + let b10to6 = extract binary 10u 6u + match extract binary 5u 0u with + | 0b000000u -> + if b15to11 = 0u then Op.LWXC1, None, None, getFdMemBaseIdx binary 32 + else raise ParsingFailureException + | 0b000001u -> + let b15to11 = extract binary 15u 11u + if b15to11 = 0u then Op.LDXC1, None, None, getFdMemBaseIdx binary 64 + else raise ParsingFailureException + | 0b001000u -> + if b10to6 = 0u then Op.SWXC1, None, None, getFsMemBaseIdx binary 32 + else raise ParsingFailureException + | 0b001001u -> + if b10to6 = 0u then Op.SDXC1, None, None, getFsMemBaseIdx binary 64 + else raise ParsingFailureException + | 0b001111u -> + if b10to6 = 0u then Op.PREFX, None, None, getHintMemBaseIdx binary 32 + else raise ParsingFailureException + | 0b100000u -> Op.MADD, None, Some Fmt.S, getFdFrFsFt binary + | 0b100001u -> Op.MADD, None, Some Fmt.D, getFdFrFsFt binary + | 0b100110u -> Op.MADD, None, Some Fmt.PS, getFdFrFsFt binary + | 0b101000u -> Op.MSUB, None, Some Fmt.S, getFdFrFsFt binary + | 0b101001u -> Op.MSUB, None, Some Fmt.D, getFdFrFsFt binary + | 0b101110u -> Op.MSUB, None, Some Fmt.PS, getFdFrFsFt binary + | 0b110000u -> Op.NMADD, None, Some Fmt.S, getFdFrFsFt binary + | 0b110001u -> Op.NMADD, None, Some Fmt.D, getFdFrFsFt binary + | 0b110110u -> Op.NMADD, None, Some Fmt.PS, getFdFrFsFt binary + | _ -> raise ParsingFailureException + +/// The MIPS64 Instrecutin Set Reference Manual, MD00087, Revision 6.06 +/// Table A.2 MIPS64 Encoding of the Opcode Field +let parseOpcodeField arch binary wordSize = + match extract binary 31u 26u with + | 0b000000u -> parseSPECIAL binary + | 0b000001u -> parseREGIMM binary + | 0b000010u -> Op.J, None, None, getTarget binary + | 0b000011u -> Op.JAL, None, None, getTarget binary + | 0b000100u -> parseBEQ binary + | 0b000101u -> Op.BNE, None, None, getRsRtRel16 binary + | 0b000110u -> parsePOP06 binary + | 0b000111u -> parsePOP07 binary + | 0b001000u -> failwith "ADDI/POP10" + | 0b001001u -> Op.ADDIU, None, None, getRtRsImm16s binary + | 0b001010u -> Op.SLTI, None, None, getRtRsImm16s binary + | 0b001011u -> Op.SLTIU, None, None, getRtRsImm16s binary + | 0b001100u -> Op.ANDI, None, None, getRtRsImm16 binary + | 0b001101u -> Op.ORI, None, None, getRtRsImm16 binary + | 0b001110u -> Op.XORI, None, None, getRtRsImm16 binary + | 0b001111u -> parseLUIAUI binary + | 0b010000u -> failwith "COP0" + | 0b010001u -> parseCOP1 arch binary + | 0b010010u -> failwith "COP2" + | 0b010011u -> parseCOP1X binary + | 0b010100u -> Op.BEQL, None, None, getRsRtRel16 binary + | 0b010101u -> Op.BNEL, None, None, getRsRtRel16 binary + | 0b010110u -> failwith "BLEZL/POP26" + | 0b010111u -> failwith "BGTZL/POP27" + | 0b011000u -> failwith "DADDI/POP30" + | 0b011001u -> Op.DADDIU, None, None, getRtRsImm16s binary + | 0b011010u -> Op.LDL, None, None, getRtMemBaseOff binary 64 + | 0b011011u -> Op.LDR, None, None, getRtMemBaseOff binary 64 + | 0b011100u -> parseSPECIAL2 binary + | 0b011101u -> failwith "JALX/DAUI" + | 0b011110u -> failwith "MSA" + | 0b011111u -> parseSPECIAL3 binary + | 0b100000u -> Op.LB, None, None, getRtMemBaseOff binary 8 + | 0b100001u -> Op.LH, None, None, getRtMemBaseOff binary 16 + | 0b100010u -> Op.LWL, None, None, getRtMemBaseOff binary 32 + | 0b100011u -> Op.LW, None, None, getRtMemBaseOff binary 32 + | 0b100100u -> Op.LBU, None, None, getRtMemBaseOff binary 8 + | 0b100101u -> Op.LHU, None, None, getRtMemBaseOff binary 16 + | 0b100110u -> Op.LWR, None, None, getRtMemBaseOff binary 32 + | 0b100111u -> Op.LWU, None, None, getRtMemBaseOff binary 32 + | 0b101000u -> Op.SB, None, None, getRtMemBaseOff binary 8 + | 0b101001u -> Op.SH, None, None, getRtMemBaseOff binary 16 + | 0b101010u -> Op.SWL, None, None, getRtMemBaseOff binary 32 + | 0b101011u -> Op.SW, None, None, getRtMemBaseOff binary 32 + | 0b101100u -> Op.SDL, None, None, getRtMemBaseOff binary 64 + | 0b101101u -> Op.SDR, None, None, getRtMemBaseOff binary 64 + | 0b101110u -> Op.SWR, None, None, getRtMemBaseOff binary 32 + | 0b101111u -> failwith "CACHE" + | 0b110000u (* pre-Release 6 *) -> + Op.LL, None, None, getRtMemBaseOff binary 32 + | 0b110001u -> Op.LWC1, None, None, getFtMemBaseOff binary 32 + | 0b110010u -> failwith "LWC2" + | 0b110011u (* pre-Release 6 *) -> + Op.PREF, None, None, getHintMemBaseOff binary 32 + | 0b110100u (* MIPS64 pre-Release 6 *) -> + Op.LLD, None, None, getRtMemBaseOff binary 64 + | 0b110101u -> + Op.LDC1, None, None, getFtMemBaseOff binary (WordSize.toRegType wordSize) + | 0b110110u -> failwith "LDC2/BEQZC/JIC/POP66" + | 0b110111u -> Op.LD, None, None, getRtMemBaseOff binary 64 + | 0b111000u (* pre-Release 6 *) -> + Op.SC, None, None, getRtMemBaseOff binary 32 + | 0b111001u -> Op.SWC1, None, None, getFtMemBaseOff binary 32 + | 0b111010u -> failwith "SWC2/BALC" + | 0b111011u -> failwith "PCREL" + | 0b111100u (* pre-Release 6 *) -> + Op.SCD, None, None, getRtMemBaseOff binary 64 + | 0b111101u -> + Op.SDC1, None, None, getFtMemBaseOff binary (WordSize.toRegType wordSize) + | 0b111110u -> failwith "SDC2/BNEZC/JIALC/POP76" + | 0b111111u -> + Op.SD, None, None, getRtMemBaseOff binary 64 + | _ -> raise ParsingFailureException + +let getOperationSize opcode wordSz = + match opcode with + | Op.SB -> 8 + | Op.SH -> 16 + | Op.SW -> 32 + | Op.SD -> 64 + | _ -> WordSize.toRegType wordSz + +let parse (span: ReadOnlySpan) (reader: IBinReader) arch wordSize addr = + let bin = reader.ReadUInt32 (span, 0) + let opcode, cond, fmt, operands = parseOpcodeField arch bin wordSize + let insInfo = + { Address = addr + NumBytes = 4u + Condition = cond + Fmt = fmt + Opcode = opcode + Operands = operands + OperationSize = getOperationSize opcode wordSize + Arch = arch } + MIPSInstruction (addr, 4u, insInfo, wordSize) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs index 44246e18..fb85817c 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegExprs.fs @@ -26,9 +26,10 @@ namespace B2R2.FrontEnd.BinLifter.MIPS open B2R2 open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinLifter -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (MIPSRegisterSet.singleton t) +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name (* Registers *) let regType = WordSize.toRegType wordSize @@ -102,12 +103,19 @@ type internal RegExprs (wordSize) = member val HI = var regType (Register.toRegID Register.HI) "HI" with get member val LO = var regType (Register.toRegID Register.LO) "LO" with get member val PC = AST.pcvar regType "PC" with get + member val NextPC = var regType (Register.toRegID Register.NPC) "nPC" with get + member val LLBit = + var 1 (Register.toRegID Register.LLBit) "LLBit" with get + member val FCSR = var 32 (Register.toRegID Register.FCSR) "FCSR" with get + member val FIR = var 32 (Register.toRegID Register.FIR) "FIR" with get member __.GetRegVar (name) = match name with | R.HI -> __.HI | R.LO -> __.LO | R.PC -> __.PC + | R.NPC -> __.NextPC + | R.LLBit -> __.LLBit | R.R0 -> __.R0 | R.R1 -> __.R1 | R.R2 -> __.R2 @@ -172,6 +180,8 @@ type internal RegExprs (wordSize) = | R.F29 -> __.F29 | R.F30 -> __.F30 | R.F31 -> __.F31 - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | R.FCSR -> __.FCSR + | R.FIR -> __.FIR + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs index f4cd7dcc..24ebb8c5 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegister.fs @@ -163,6 +163,15 @@ type Register = | LO = 0x101 /// Program Counter. | PC = 0x102 + /// Pseudo register for the next PC (nPC). + | NPC = 0x103 + /// Pseudo register for LLBit. This is used to store the actual LLBit value + /// from the CPU after an exception. + | LLBit = 0x104 + /// Floating Point Control and Status Register. + | FCSR = 0x105 + /// Floating Point Implementation Register. + | FIR = 0x106 /// Shortcut for Register type. type internal R = Register @@ -176,40 +185,44 @@ module Register = let inline toRegID (reg: Register) = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create - let ofString (str: string) = - match str.ToLower () with + let ofString wordSize (str: string) = + match str.ToLowerInvariant () with | "r0" -> R.R0 - | "r1" -> R.R1 - | "r2" -> R.R2 - | "r3" -> R.R3 - | "r4" -> R.R4 - | "r5" -> R.R5 - | "r6" -> R.R6 - | "r7" -> R.R7 - | "r8" -> R.R8 - | "r9" -> R.R9 - | "r10" -> R.R10 - | "r11" -> R.R11 - | "r12" -> R.R12 - | "r13" -> R.R13 - | "r14" -> R.R14 - | "r15" -> R.R15 - | "r16" -> R.R16 - | "r17" -> R.R17 - | "r18" -> R.R18 - | "r19" -> R.R19 - | "r20" -> R.R20 - | "r21" -> R.R21 - | "r22" -> R.R22 - | "r23" -> R.R23 - | "r24" -> R.R24 - | "r25" -> R.R25 - | "r26" -> R.R26 - | "r27" -> R.R27 - | "r28" -> R.R28 - | "r29" -> R.R29 - | "r30" -> R.R30 - | "r31" -> R.R31 + | "r1" | "at" -> R.R1 + | "r2" | "v0" -> R.R2 + | "r3" | "v1" -> R.R3 + | "r4" | "a0" -> R.R4 + | "r5" | "a1" -> R.R5 + | "r6" | "a2" -> R.R6 + | "r7" | "a3" -> R.R7 + | "r8" | "a4" -> R.R8 + | "r9" | "a5" -> R.R9 + | "r10" | "a6" -> R.R10 + | "r11" | "a7" -> R.R11 + | "t0" -> if wordSize = WordSize.Bit32 then R.R8 else R.R12 + | "t1" -> if wordSize = WordSize.Bit32 then R.R9 else R.R13 + | "t2" -> if wordSize = WordSize.Bit32 then R.R10 else R.R14 + | "t3" -> if wordSize = WordSize.Bit32 then R.R11 else R.R15 + | "r12" | "t4" -> R.R12 + | "r13" | "t5" -> R.R13 + | "r14" | "t6" -> R.R14 + | "r15" | "t7" -> R.R15 + | "r16" | "s0" -> R.R16 + | "r17" | "s1" -> R.R17 + | "r18" | "s2" -> R.R18 + | "r19" | "s3" -> R.R19 + | "r20" | "s4" -> R.R20 + | "r21" | "s5" -> R.R21 + | "r22" | "s6" -> R.R22 + | "r23" | "s7" -> R.R23 + | "r24" | "t8" -> R.R24 + | "r25" | "t9" -> R.R25 + | "r26" | "k0" -> R.R26 + | "r27" | "k1" -> R.R27 + | "r28" | "gp" -> R.R28 + | "r29" | "sp" -> R.R29 + | "r30" | "fp" -> R.R30 + | "r31" | "ra" -> R.R31 | "f0" -> R.F0 | "f1" -> R.F1 | "f2" -> R.F2 @@ -245,9 +258,12 @@ module Register = | "hi" -> R.HI | "lo" -> R.LO | "pc" -> R.PC + | "llbit" -> R.LLBit + | "fcsr" -> R.FCSR + | "fir" -> R.FIR | _ -> Utils.impossible () - let toString = function + let toString32 = function | R.R0 -> "r0" | R.R1 -> "at" | R.R2 -> "v0" @@ -315,4 +331,99 @@ module Register = | R.HI -> "hi" | R.LO -> "lo" | R.PC -> "pc" + | R.LLBit -> "LLBit" + | R.FCSR -> "fcsr" + | R.FIR -> "fir" + | _ -> Utils.impossible () + + let toString64 = function + | R.R0 -> "r0" + | R.R1 -> "at" + | R.R2 -> "v0" + | R.R3 -> "v1" + | R.R4 -> "a0" + | R.R5 -> "a1" + | R.R6 -> "a2" + | R.R7 -> "a3" + | R.R8 -> "a4" + | R.R9 -> "a5" + | R.R10 -> "a6" + | R.R11 -> "a7" + | R.R12 -> "t0" + | R.R13 -> "t1" + | R.R14 -> "t2" + | R.R15 -> "t3" + | R.R16 -> "s0" + | R.R17 -> "s1" + | R.R18 -> "s2" + | R.R19 -> "s3" + | R.R20 -> "s4" + | R.R21 -> "s5" + | R.R22 -> "s6" + | R.R23 -> "s7" + | R.R24 -> "t8" + | R.R25 -> "t9" + | R.R26 -> "k0" + | R.R27 -> "k1" + | R.R28 -> "gp" + | R.R29 -> "sp" + | R.R30 -> "s8" + | R.R31 -> "ra" + | R.F0 -> "f0" + | R.F1 -> "f1" + | R.F2 -> "f2" + | R.F3 -> "f3" + | R.F4 -> "f4" + | R.F5 -> "f5" + | R.F6 -> "f6" + | R.F7 -> "f7" + | R.F8 -> "f8" + | R.F9 -> "f9" + | R.F10 -> "f10" + | R.F11 -> "f11" + | R.F12 -> "f12" + | R.F13 -> "f13" + | R.F14 -> "f14" + | R.F15 -> "f15" + | R.F16 -> "f16" + | R.F17 -> "f17" + | R.F18 -> "f18" + | R.F19 -> "f19" + | R.F20 -> "f20" + | R.F21 -> "f21" + | R.F22 -> "f22" + | R.F23 -> "f23" + | R.F24 -> "f24" + | R.F25 -> "f25" + | R.F26 -> "f26" + | R.F27 -> "f27" + | R.F28 -> "f28" + | R.F29 -> "f29" + | R.F30 -> "f30" + | R.F31 -> "f31" + | R.HI -> "hi" + | R.LO -> "lo" + | R.PC -> "pc" + | R.LLBit -> "LLBit" + | R.FCSR -> "fcsr" + | R.FIR -> "fir" + | _ -> Utils.impossible () + + let getFPPairReg = function + | R.F0 -> R.F1 + | R.F2 -> R.F3 + | R.F4 -> R.F5 + | R.F6 -> R.F7 + | R.F8 -> R.F9 + | R.F10 -> R.F11 + | R.F12 -> R.F13 + | R.F14 -> R.F15 + | R.F16 -> R.F17 + | R.F18 -> R.F19 + | R.F20 -> R.F21 + | R.F22 -> R.F23 + | R.F24 -> R.F25 + | R.F26 -> R.F27 + | R.F28 -> R.F29 + | R.F30 -> R.F31 | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSRegisterBay.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterBay.fs deleted file mode 100644 index aceefc77..00000000 --- a/src/FrontEnd/BinLifter/MIPS/MIPSRegisterBay.fs +++ /dev/null @@ -1,161 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.MIPS - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR.LowUIR - -type MIPSRegisterBay internal (wordSize, R: RegExprs) = - inherit RegisterBay () - - override __.GetAllRegExprs () = - [ R.HI; R.LO; R.PC; R.R0; R.R1; R.R2; R.R3; R.R4; R.R5; R.R6; R.R7; R.R8; - R.R9; R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.R16; R.R17; R.R18; - R.R19; R.R20; R.R21; R.R22; R.R23; R.R24; R.R25; R.R26; R.R27; R.R28; - R.R29; R.R30; R.R31; R.F0; R.F1; R.F2; R.F3; R.F4; R.F5; R.F6; R.F7; R.F8; - R.F9; R.F10; R.F11; R.F12; R.F13; R.F14; R.F15; R.F16; R.F17; R.F18; - R.F19; R.F20; R.F21; R.F22; R.F23; R.F24; R.F25; R.F26; R.F27; R.F28; - R.F29; R.F30; R.F31 ] - - override __.GetAllRegNames () = - __.GetAllRegExprs () - |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) - - override __.GetGeneralRegExprs () = - [ R.HI; R.LO; R.PC; R.R0; R.R1; R.R2; R.R3; R.R4; R.R5; R.R6; R.R7; R.R8; - R.R9; R.R10; R.R11; R.R12; R.R13; R.R14; R.R15; R.R16; R.R17; R.R18; - R.R19; R.R20; R.R21; R.R22; R.R23; R.R24; R.R25; R.R26; R.R27; R.R28; - R.R29; R.R30; R.R31 ] - - override __.RegIDFromRegExpr (e) = - match e.E with - | Var (_,id, _,_) -> id - | PCVar (_, _) -> Register.toRegID Register.PC - | _ -> failwith "not a register expression" - - override __.RegIDToRegExpr (id) = - Register.ofRegID id |> R.GetRegVar - - override __.StrToRegExpr s = - match s with - | "HI" -> R.HI - | "LO" -> R.LO - | "PC" -> R.PC - | "R0" -> R.R0 - | "R1" -> R.R1 - | "R2" -> R.R2 - | "R3" -> R.R3 - | "R4" -> R.R4 - | "R5" -> R.R5 - | "R6" -> R.R6 - | "R7" -> R.R7 - | "R8" -> R.R8 - | "R9" -> R.R9 - | "R10" -> R.R10 - | "R11" -> R.R11 - | "R12" -> R.R12 - | "R13" -> R.R13 - | "R14" -> R.R14 - | "R15" -> R.R15 - | "R16" -> R.R16 - | "R17" -> R.R17 - | "R18" -> R.R18 - | "R19" -> R.R19 - | "R20" -> R.R20 - | "R21" -> R.R21 - | "R22" -> R.R22 - | "R23" -> R.R23 - | "R24" -> R.R24 - | "R25" -> R.R25 - | "R26" -> R.R26 - | "R27" -> R.R27 - | "R28" -> R.R28 - | "R29" -> R.R29 - | "R30" -> R.R30 - | "R31" -> R.R31 - | "F0" -> R.F0 - | "F1" -> R.F1 - | "F2" -> R.F2 - | "F3" -> R.F3 - | "F4" -> R.F4 - | "F5" -> R.F5 - | "F6" -> R.F6 - | "F7" -> R.F7 - | "F8" -> R.F8 - | "F9" -> R.F9 - | "F10" -> R.F10 - | "F11"-> R.F11 - | "F12" -> R.F12 - | "F13" -> R.F13 - | "F14" -> R.F14 - | "F15" -> R.F15 - | "F16" -> R.F16 - | "F17" -> R.F17 - | "F18" -> R.F18 - | "F19" -> R.F19 - | "F20" -> R.F20 - | "F21" -> R.F21 - | "F22" -> R.F22 - | "F23" -> R.F23 - | "F24" -> R.F24 - | "F25" -> R.F25 - | "F26" -> R.F26 - | "F27" -> R.F27 - | "F28" -> R.F28 - | "F29" -> R.F29 - | "F30" -> R.F30 - | "F31" -> R.F31 - | _ -> raise UnhandledRegExprException - - override __.RegIDFromString str = - Register.ofString str |> Register.toRegID - - override __.RegIDToString rid = - Register.ofRegID rid |> Register.toString - - override __.RegIDToRegType _rid = - WordSize.toRegType wordSize - - override __.GetRegisterAliases rid = - [| rid |] - - override __.ProgramCounter = - Register.PC |> Register.toRegID - - override __.StackPointer = - Register.R29 |> Register.toRegID |> Some - - override __.FramePointer = - Register.R30 |> Register.toRegID |> Some - - override __.IsProgramCounter regid = - __.ProgramCounter = regid - - override __.IsStackPointer regid = - (__.StackPointer |> Option.get) = regid - - override __.IsFramePointer regid = - (__.FramePointer |> Option.get) = regid diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSRegisterFactory.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterFactory.fs new file mode 100644 index 00000000..455b92c6 --- /dev/null +++ b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterFactory.fs @@ -0,0 +1,96 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.MIPS + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type MIPSRegisterFactory (wordSize, r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + [ r.HI; r.LO; r.PC; r.R0; r.R1; r.R2; r.R3; r.R4; r.R5; r.R6; r.R7; r.R8; + r.R9; r.R10; r.R11; r.R12; r.R13; r.R14; r.R15; r.R16; r.R17; r.R18; + r.R19; r.R20; r.R21; r.R22; r.R23; r.R24; r.R25; r.R26; r.R27; r.R28; + r.R29; r.R30; r.R31; r.F0; r.F1; r.F2; r.F3; r.F4; r.F5; r.F6; r.F7; r.F8; + r.F9; r.F10; r.F11; r.F12; r.F13; r.F14; r.F15; r.F16; r.F17; r.F18; + r.F19; r.F20; r.F21; r.F22; r.F23; r.F24; r.F25; r.F26; r.F27; r.F28; + r.F29; r.F30; r.F31 ] + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + [ r.HI; r.LO; r.PC; r.R0; r.R1; r.R2; r.R3; r.R4; r.R5; r.R6; r.R7; r.R8; + r.R9; r.R10; r.R11; r.R12; r.R13; r.R14; r.R15; r.R16; r.R17; r.R18; + r.R19; r.R20; r.R21; r.R22; r.R23; r.R24; r.R25; r.R26; r.R27; r.R28; + r.R29; r.R30; r.R31 ] + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_, id, _) -> id + | PCVar _ -> Register.toRegID Register.PC + | _ -> raise InvalidRegisterException + + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> r.GetRegVar + + override __.StrToRegExpr str = + Register.ofString wordSize str |> Register.toRegID |> __.RegIDToRegExpr + + override __.RegIDFromString str = + Register.ofString wordSize str |> Register.toRegID + + override __.RegIDToString rid = + if wordSize = WordSize.Bit32 then + Register.ofRegID rid |> Register.toString32 + else + Register.ofRegID rid |> Register.toString64 + + override __.RegIDToRegType _rid = + WordSize.toRegType wordSize + + override __.GetRegisterAliases rid = + [| rid |] + + override __.ProgramCounter = + Register.PC |> Register.toRegID + + override __.StackPointer = + Register.R29 |> Register.toRegID |> Some + + override __.FramePointer = + Register.R30 |> Register.toRegID |> Some + + override __.IsProgramCounter regid = + __.ProgramCounter = regid + + override __.IsStackPointer regid = + (__.StackPointer |> Option.get) = regid + + override __.IsFramePointer regid = + (__.FramePointer |> Option.get) = regid diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSRegisterSet.fs b/src/FrontEnd/BinLifter/MIPS/MIPSRegisterSet.fs deleted file mode 100644 index 2ccf700e..00000000 --- a/src/FrontEnd/BinLifter/MIPS/MIPSRegisterSet.fs +++ /dev/null @@ -1,194 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.MIPS - -open B2R2 - -module private RegisterSetLiteral = - let [] ArrLen = 2 - -open RegisterSetLiteral - -type MIPSRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = MIPSRegisterSet (RegisterSet.MakeInternalBitArray ArrLen, Set.empty) - - override __.Tag = RegisterSetTag.MIPS - - override __.ArrSize = ArrLen - - override __.New arr s = new MIPSRegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | R.R0 -> 0 - | R.R1 -> 1 - | R.R2 -> 2 - | R.R3 -> 3 - | R.R4 -> 4 - | R.R5 -> 5 - | R.R6 -> 6 - | R.R7 -> 7 - | R.R8 -> 8 - | R.R9 -> 9 - | R.R10 -> 10 - | R.R11 -> 11 - | R.R12 -> 12 - | R.R13 -> 13 - | R.R14 -> 14 - | R.R15 -> 15 - | R.R16 -> 16 - | R.R17 -> 17 - | R.R18 -> 18 - | R.R19 -> 19 - | R.R20 -> 20 - | R.R21 -> 21 - | R.R22 -> 22 - | R.R23 -> 23 - | R.R24 -> 24 - | R.R25 -> 25 - | R.R26 -> 26 - | R.R27 -> 27 - | R.R28 -> 28 - | R.R29 -> 29 - | R.R30 -> 30 - | R.R31 -> 31 - | R.F0 -> 32 - | R.F1 -> 33 - | R.F2 -> 34 - | R.F3 -> 35 - | R.F4 -> 36 - | R.F5 -> 37 - | R.F6 -> 38 - | R.F7 -> 39 - | R.F8 -> 40 - | R.F9 -> 41 - | R.F10 -> 42 - | R.F11 -> 43 - | R.F12 -> 44 - | R.F13 -> 45 - | R.F14 -> 46 - | R.F15 -> 47 - | R.F16 -> 48 - | R.F17 -> 49 - | R.F18 -> 50 - | R.F19 -> 51 - | R.F20 -> 52 - | R.F21 -> 53 - | R.F22 -> 54 - | R.F23 -> 55 - | R.F24 -> 56 - | R.F25 -> 57 - | R.F26 -> 58 - | R.F27 -> 59 - | R.F28 -> 60 - | R.F29 -> 61 - | R.F30 -> 62 - | R.F31 -> 63 - | R.HI -> 64 - | R.LO -> 65 - | R.PC -> 66 - | _ -> -1 - - override __.IndexToRegID index = - match index with - | 0 -> R.R0 - | 1 -> R.R1 - | 2 -> R.R2 - | 3 -> R.R3 - | 4 -> R.R4 - | 5 -> R.R5 - | 6 -> R.R6 - | 7 -> R.R7 - | 8 -> R.R8 - | 9 -> R.R9 - | 10 -> R.R10 - | 11 -> R.R11 - | 12 -> R.R12 - | 13 -> R.R13 - | 14 -> R.R14 - | 15 -> R.R15 - | 16 -> R.R16 - | 17 -> R.R17 - | 18 -> R.R18 - | 19 -> R.R19 - | 20 -> R.R20 - | 21 -> R.R21 - | 22 -> R.R22 - | 23 -> R.R23 - | 24 -> R.R24 - | 25 -> R.R25 - | 26 -> R.R26 - | 27 -> R.R27 - | 28 -> R.R28 - | 29 -> R.R29 - | 30 -> R.R30 - | 31 -> R.R31 - | 32 -> R.F0 - | 33 -> R.F1 - | 34 -> R.F2 - | 35 -> R.F3 - | 36 -> R.F4 - | 37 -> R.F5 - | 38 -> R.F6 - | 39 -> R.F7 - | 40 -> R.F8 - | 41 -> R.F9 - | 42 -> R.F10 - | 43 -> R.F11 - | 44 -> R.F12 - | 45 -> R.F13 - | 46 -> R.F14 - | 47 -> R.F15 - | 48 -> R.F16 - | 49 -> R.F17 - | 50 -> R.F18 - | 51 -> R.F19 - | 52 -> R.F20 - | 53 -> R.F21 - | 54 -> R.F22 - | 55 -> R.F23 - | 56 -> R.F24 - | 57 -> R.F25 - | 58 -> R.F26 - | 59 -> R.F27 - | 60 -> R.F28 - | 61 -> R.F29 - | 62 -> R.F30 - | 63 -> R.F31 - | 64 -> R.HI - | 65 -> R.LO - | 66 -> R.PC - | _ -> Utils.impossible () - |> Register.toRegID - - override __.ToString () = - sprintf "MIPSRegisterSet<%x, %x>" __.BitArray[0] __.BitArray[1] - -[] -module MIPSRegisterSet = - let singleton rid = MIPSRegisterSet().Add(rid) - let empty = MIPSRegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSTranslationContext.fs b/src/FrontEnd/BinLifter/MIPS/MIPSTranslationContext.fs new file mode 100644 index 00000000..631c7e26 --- /dev/null +++ b/src/FrontEnd/BinLifter/MIPS/MIPSTranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.MIPS + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for MIPS instructions. +type MIPSTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs (isa.WordSize) + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs b/src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs index 2a01cda2..ba0e4d40 100644 --- a/src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs +++ b/src/FrontEnd/BinLifter/MIPS/MIPSTypes.fs @@ -750,6 +750,8 @@ type Opcode = | XORI = 326 /// Invalid Opcode. | InvalOP = 327 + /// Add Dword. + | DADD = 328 type internal Op = Opcode @@ -770,6 +772,18 @@ and Base = Register and AccessLength = RegType and Label = string +type RoundMode = + // Round to Nearest, ties to Even + | RNE + // Round towards Zero + | RTZ + // Round Down + | RDN + // Round Up + | RUP + // Round to Nearest, ties to Max Magnitude + | RMM + type Operands = | NoOperand | OneOperand of Operand @@ -798,7 +812,7 @@ type InsInfo = { /// Operation Size. OperationSize: RegType /// Mips architecture. - Arch: Arch + Arch: Architecture } with override __.GetHashCode () = diff --git a/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs b/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs index 9c1be9dc..54bca0d9 100644 --- a/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs +++ b/src/FrontEnd/BinLifter/Optimizer/ConstantFolding.fs @@ -37,72 +37,73 @@ type Context = { let private concretizeUnOp unopType bv = match unopType with - | UnOpType.NEG -> BitVector.neg bv - | UnOpType.NOT -> BitVector.bnot bv - | UnOpType.FSQRT -> BitVector.fsqrt bv - | UnOpType.FCOS -> BitVector.fcos bv - | UnOpType.FSIN -> BitVector.fsin bv - | UnOpType.FTAN -> BitVector.ftan bv - | UnOpType.FATAN -> BitVector.fatan bv + | UnOpType.NEG -> BitVector.Neg bv + | UnOpType.NOT -> BitVector.BNot bv + | UnOpType.FSQRT -> BitVector.FSqrt bv + | UnOpType.FCOS -> BitVector.FCos bv + | UnOpType.FSIN -> BitVector.FSin bv + | UnOpType.FTAN -> BitVector.FTan bv + | UnOpType.FATAN -> BitVector.FAtan bv | _ -> Utils.impossible () let private concretizeBinOp binopType bv1 bv2 = match binopType with - | BinOpType.ADD -> BitVector.add bv1 bv2 - | BinOpType.SUB -> BitVector.sub bv1 bv2 - | BinOpType.MUL -> BitVector.mul bv1 bv2 - | BinOpType.DIV -> BitVector.div bv1 bv2 - | BinOpType.SDIV -> BitVector.sdiv bv1 bv2 - | BinOpType.MOD -> BitVector.modulo bv1 bv2 - | BinOpType.SMOD -> BitVector.smodulo bv1 bv2 - | BinOpType.SHL -> BitVector.shl bv1 bv2 - | BinOpType.SHR -> BitVector.shr bv1 bv2 - | BinOpType.SAR -> BitVector.sar bv1 bv2 - | BinOpType.AND -> BitVector.band bv1 bv2 - | BinOpType.OR -> BitVector.bor bv1 bv2 - | BinOpType.XOR -> BitVector.bxor bv1 bv2 - | BinOpType.CONCAT -> BitVector.concat bv1 bv2 - | BinOpType.FADD -> BitVector.fadd bv1 bv2 - | BinOpType.FSUB -> BitVector.fsub bv1 bv2 - | BinOpType.FMUL -> BitVector.fmul bv1 bv2 - | BinOpType.FDIV -> BitVector.fdiv bv1 bv2 - | BinOpType.FPOW -> BitVector.fpow bv1 bv2 - | BinOpType.FLOG -> BitVector.flog bv1 bv2 + | BinOpType.ADD -> BitVector.Add (bv1, bv2) + | BinOpType.SUB -> BitVector.Sub (bv1, bv2) + | BinOpType.MUL -> BitVector.Mul (bv1, bv2) + | BinOpType.DIV -> BitVector.Div (bv1, bv2) + | BinOpType.SDIV -> BitVector.SDiv (bv1, bv2) + | BinOpType.MOD -> BitVector.Modulo (bv1, bv2) + | BinOpType.SMOD -> BitVector.SModulo (bv1, bv2) + | BinOpType.SHL -> BitVector.Shl (bv1, bv2) + | BinOpType.SHR -> BitVector.Shr (bv1, bv2) + | BinOpType.SAR -> BitVector.Sar (bv1, bv2) + | BinOpType.AND -> BitVector.BAnd (bv1, bv2) + | BinOpType.OR -> BitVector.BOr (bv1, bv2) + | BinOpType.XOR -> BitVector.BXor (bv1, bv2) + | BinOpType.CONCAT -> BitVector.Concat (bv1, bv2) + | BinOpType.FADD -> BitVector.FAdd (bv1, bv2) + | BinOpType.FSUB -> BitVector.FSub (bv1, bv2) + | BinOpType.FMUL -> BitVector.FMul (bv1, bv2) + | BinOpType.FDIV -> BitVector.FDiv (bv1, bv2) + | BinOpType.FPOW -> BitVector.FPow (bv1, bv2) + | BinOpType.FLOG -> BitVector.FLog (bv1, bv2) | _ -> Utils.impossible () let private concretizeRelOp relopType bv1 bv2 = match relopType with - | RelOpType.EQ -> BitVector.eq bv1 bv2 - | RelOpType.NEQ -> BitVector.neq bv1 bv2 - | RelOpType.GT -> BitVector.gt bv1 bv2 - | RelOpType.GE -> BitVector.ge bv1 bv2 - | RelOpType.SGT -> BitVector.sgt bv1 bv2 - | RelOpType.SGE -> BitVector.sge bv1 bv2 - | RelOpType.LT -> BitVector.lt bv1 bv2 - | RelOpType.LE -> BitVector.le bv1 bv2 - | RelOpType.SLT -> BitVector.slt bv1 bv2 - | RelOpType.SLE -> BitVector.sle bv1 bv2 - | RelOpType.FGT -> BitVector.fgt bv1 bv2 - | RelOpType.FGE -> BitVector.fge bv1 bv2 - | RelOpType.FLT -> BitVector.flt bv1 bv2 - | RelOpType.FLE -> BitVector.fle bv1 bv2 + | RelOpType.EQ -> BitVector.Eq (bv1, bv2) + | RelOpType.NEQ -> BitVector.Neq (bv1, bv2) + | RelOpType.GT -> BitVector.Gt (bv1, bv2) + | RelOpType.GE -> BitVector.Ge (bv1, bv2) + | RelOpType.SGT -> BitVector.SGt (bv1, bv2) + | RelOpType.SGE -> BitVector.SGe (bv1, bv2) + | RelOpType.LT -> BitVector.Lt (bv1, bv2) + | RelOpType.LE -> BitVector.Le (bv1, bv2) + | RelOpType.SLT -> BitVector.SLt (bv1, bv2) + | RelOpType.SLE -> BitVector.SLe (bv1, bv2) + | RelOpType.FGT -> BitVector.FGt (bv1, bv2) + | RelOpType.FGE -> BitVector.FGe (bv1, bv2) + | RelOpType.FLT -> BitVector.FLt (bv1, bv2) + | RelOpType.FLE -> BitVector.FLe (bv1, bv2) | _ -> Utils.impossible () let private concretizeCast castType rt bv = match castType with - | CastKind.SignExt -> BitVector.sext bv rt - | CastKind.ZeroExt -> BitVector.zext bv rt - | CastKind.IntToFloat -> BitVector.itof bv rt - | CastKind.FtoIRound -> BitVector.ftoiround bv rt - | CastKind.FtoICeil -> BitVector.ftoiceil bv rt - | CastKind.FtoIFloor -> BitVector.ftoifloor bv rt - | CastKind.FtoITrunc -> BitVector.ftoitrunc bv rt - | CastKind.FloatCast -> BitVector.fcast bv rt + | CastKind.SignExt -> BitVector.SExt (bv, rt) + | CastKind.ZeroExt -> BitVector.ZExt (bv, rt) + | CastKind.SIntToFloat -> BitVector.Itof (bv, rt, true) + | CastKind.UIntToFloat -> BitVector.Itof (bv, rt, false) + | CastKind.FtoIRound -> BitVector.FtoiRound (bv, rt) + | CastKind.FtoICeil -> BitVector.FtoiCeil (bv, rt) + | CastKind.FtoIFloor -> BitVector.FtoiFloor (bv, rt) + | CastKind.FtoITrunc -> BitVector.FtoiTrunc (bv, rt) + | CastKind.FloatCast -> BitVector.FCast (bv, rt) | _ -> Utils.impossible () let rec replace ctxt expr = match expr.E with - | Var (_, name, _, _) -> + | Var (_, name, _) -> match ctxt.VarMap.TryGetValue name with | true, e -> struct (true, e) | _ -> struct (false, expr) @@ -110,24 +111,24 @@ let rec replace ctxt expr = match ctxt.TempVarMap.TryGetValue name with | (true, e) -> struct (true, e) | _ -> struct (false, expr) - | UnOp (t, e, _) -> + | UnOp (t, e) -> let struct (changed, e) = replace ctxt e if changed then match e.E with | Num bv -> struct (true, AST.num <| concretizeUnOp t bv) | _ -> struct (true, AST.unop t e) else struct (false, expr) - | BinOp (BinOpType.ADD, _, e, { E = Num bv }, _) - | BinOp (BinOpType.ADD, _, { E = Num bv }, e, _) - when BitVector.isZero bv -> + | BinOp (BinOpType.ADD, _, e, { E = Num bv }) + | BinOp (BinOpType.ADD, _, { E = Num bv }, e) + when BitVector.IsZero bv -> let struct (changed, e') = replace ctxt e if changed then struct (true, e') else struct (true, e) - | BinOp (BinOpType.MUL, _, e, { E = Num bv }, _) - | BinOp (BinOpType.MUL, _, { E = Num bv }, e, _) - when BitVector.isOne bv -> + | BinOp (BinOpType.MUL, _, e, { E = Num bv }) + | BinOp (BinOpType.MUL, _, { E = Num bv }, e) + when BitVector.IsOne bv -> let struct (changed, e') = replace ctxt e if changed then struct (true, e') else struct (true, e) - | BinOp (t, _, e1, e2, _) -> + | BinOp (t, _, e1, e2) -> let struct (changed1, e1) = replace ctxt e1 let struct (changed2, e2) = replace ctxt e2 match e1.E, e2.E with @@ -135,7 +136,7 @@ let rec replace ctxt expr = | _ -> if changed1 || changed2 then struct (true, AST.binop t e1 e2) else struct (false, expr) - | RelOp (t, e1, e2, _) -> + | RelOp (t, e1, e2) -> let struct (changed1, e1) = replace ctxt e1 let struct (changed2, e2) = replace ctxt e2 match e1.E, e2.E with @@ -143,41 +144,41 @@ let rec replace ctxt expr = | _ -> if changed1 || changed2 then struct (true, AST.relop t e1 e2) else struct (false, expr) - | Load (endian, rt, e, _) -> + | Load (endian, rt, e) -> let struct (changed, e') = replace ctxt e if changed then struct (true, AST.load endian rt e') else struct (false, expr) - | Ite (cond, e1, e2, _) -> + | Ite (cond, e1, e2) -> let struct (changed0, cond) = replace ctxt cond let struct (changed1, e1) = replace ctxt e1 let struct (changed2, e2) = replace ctxt e2 if changed0 || changed1 || changed2 then match cond.E with | Num bv -> - if BitVector.isTrue bv then struct (true, e1) + if BitVector.IsTrue bv then struct (true, e1) else struct (false, e2) | _ -> struct (true, AST.ite cond e1 e2) else struct (false, expr) - | Cast (kind, rt, e, _) -> + | Cast (kind, rt, e) -> let struct (changed, e) = replace ctxt e if changed then match e.E with | Num bv -> struct (true, AST.num <| concretizeCast kind rt bv) | _ -> struct (true, AST.cast kind rt e) else struct (false, expr) - | Extract (e, rt, pos, _) -> + | Extract (e, rt, pos) -> let struct (changed, e) = replace ctxt e if changed then match e.E with - | Num bv -> struct (true, AST.num <| BitVector.extract bv rt pos) + | Num bv -> struct (true, AST.num <| BitVector.Extract (bv, rt, pos)) | _ -> struct (true, AST.extract e rt pos) else struct (false, expr) | _ -> struct (false, expr) let updateContextAtDef ctxt dst src = match dst.E, src.E with - | Var (_, r, _, _), Num _ -> ctxt.VarMap.TryAdd (r, src) |> ignore - | Var (_, r, _, _), _ -> ctxt.VarMap.Remove (r) |> ignore + | Var (_, r, _), Num _ -> ctxt.VarMap.TryAdd (r, src) |> ignore + | Var (_, r, _), _ -> ctxt.VarMap.Remove (r) |> ignore | TempVar (_, n), Num _ -> ctxt.TempVarMap.TryAdd (n, src) |> ignore | TempVar (_, n), _ -> ctxt.TempVarMap.Remove (n) |> ignore | _ -> () @@ -201,7 +202,7 @@ let rec optimizeLoop (stmts: Stmt []) idx ctxt = if c0 || c1 || c2 then stmts[idx] <- match cond.E with - | Num n when BitVector.isOne n -> AST.interjmp e1 InterJmpKind.Base + | Num n when BitVector.IsOne n -> AST.interjmp e1 InterJmpKind.Base | Num _ -> AST.interjmp e2 InterJmpKind.Base | _ -> AST.intercjmp cond e1 e2 else () @@ -217,7 +218,7 @@ let rec optimizeLoop (stmts: Stmt []) idx ctxt = if c0 || c1 || c2 then stmts[idx] <- match cond.E with - | Num (n) when BitVector.isOne n -> AST.jmp e1 + | Num (n) when BitVector.IsOne n -> AST.jmp e1 | Num (_) -> AST.jmp e2 | _ -> AST.cjmp cond e1 e2 else () @@ -229,7 +230,7 @@ let rec optimizeLoop (stmts: Stmt []) idx ctxt = | _ -> rhs updateContextAtDef ctxt lhs rhs optimizeLoop stmts (idx + 1) ctxt - | ISMark _ | IEMark _ | SideEffect _ -> + | ISMark _ | IEMark _ | ExternalCall _ | SideEffect _ -> optimizeLoop stmts (idx + 1) ctxt else stmts diff --git a/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs b/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs index 2cac1357..c9a741ef 100644 --- a/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs +++ b/src/FrontEnd/BinLifter/Optimizer/DeadCodeElimination.fs @@ -25,57 +25,19 @@ [] module B2R2.FrontEnd.BinLifter.DeadCodeElimination +open System.Collections.Generic open B2R2 open B2R2.BinIR.LowUIR type DeadCodeRemovalContext = { UseRegisters: RegisterSet OutRegisters: RegisterSet - UseTempVar: Set - OutTempVar: Set - IsLastBlock: bool + UseTempVar: HashSet + OutTempVar: HashSet + mutable IsLastBlock: bool } -let emptyCtxt = - { UseRegisters = RegisterSet.empty - OutRegisters = RegisterSet.empty - UseTempVar = Set.empty - OutTempVar= Set.empty - IsLastBlock = false } - -let removeUse n ctxt = - { ctxt with UseRegisters = RegisterSet.remove n ctxt.UseRegisters } - -let removeTempUse n ctxt = - { ctxt with UseTempVar = Set.remove n ctxt.UseTempVar } - -let updateUse ei ctxt = - { ctxt with UseTempVar = Set.union ei.TempVarsUsed ctxt.UseTempVar - UseRegisters = RegisterSet.union ei.VarsUsed ctxt.UseRegisters } - -let updateUse2 ei1 ei2 ctxt = - { ctxt with - UseTempVar = Set.union ei1.TempVarsUsed ctxt.UseTempVar - |> Set.union ei2.TempVarsUsed - UseRegisters = RegisterSet.union ei1.VarsUsed ctxt.UseRegisters - |> RegisterSet.union ei2.VarsUsed } - -let updateUse3 ei1 ei2 ei3 ctxt = - { ctxt with - UseTempVar = Set.union ei1.TempVarsUsed ctxt.UseTempVar - |> Set.union ei2.TempVarsUsed - |> Set.union ei3.TempVarsUsed - UseRegisters = RegisterSet.union ei1.VarsUsed ctxt.UseRegisters - |> RegisterSet.union ei2.VarsUsed - |> RegisterSet.union ei3.VarsUsed } - -let updateOut rs ctxt = - { ctxt with OutRegisters = RegisterSet.union rs ctxt.OutRegisters } - -let updateTempOut n ctxt = - { ctxt with OutTempVar = Set.add n ctxt.OutTempVar } - -let rec createLoop (outs: Stmt []) (ins: Stmt []) (used: bool []) iIdx oIdx = +let rec createLoop (outs: Stmt[]) (ins: Stmt[]) (used: bool[]) iIdx oIdx = if oIdx < outs.Length then if used[iIdx] then outs[oIdx] <- ins[iIdx] @@ -83,65 +45,69 @@ let rec createLoop (outs: Stmt []) (ins: Stmt []) (used: bool []) iIdx oIdx = else createLoop outs ins used (iIdx + 1) oIdx else outs -let createReducedStmts (stmts: Stmt []) reducedLen (used: bool []) = +let createReducedStmts (stmts: Stmt[]) reducedLen (used: bool[]) = createLoop (Array.zeroCreate reducedLen) stmts used 0 0 -let rec optimizeLoop (stmts: Stmt []) (used: bool []) idx len ctxt = +let rec optimizeLoop (stmts: Stmt[]) (used: bool[]) idx len ctxt = if idx >= 0 then match stmts[idx].S with | Store (_, e1, e2) -> - let ei1 = AST.getExprInfo e1 - let ei2 = AST.getExprInfo e2 - optimizeLoop stmts used (idx - 1) len (updateUse2 ei1 ei2 ctxt) + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e1 + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e2 + optimizeLoop stmts used (idx - 1) len ctxt | InterJmp (e, _) -> - let ei = AST.getExprInfo e - optimizeLoop stmts used (idx - 1) len (updateUse ei ctxt) + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e + optimizeLoop stmts used (idx - 1) len ctxt | InterCJmp (e, e1, e2) -> - let ei = AST.getExprInfo e - let ei1 = AST.getExprInfo e1 - let ei2 = AST.getExprInfo e2 - optimizeLoop stmts used (idx - 1) len (updateUse3 ei ei1 ei2 ctxt) + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e1 + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e2 + optimizeLoop stmts used (idx - 1) len ctxt | Jmp e -> - let ei = AST.getExprInfo e - optimizeLoop stmts used (idx - 1) len (updateUse ei ctxt) + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e + optimizeLoop stmts used (idx - 1) len ctxt | CJmp (e, e1, e2) -> - let ei = AST.getExprInfo e - let ei1 = AST.getExprInfo e1 - let ei2 = AST.getExprInfo e2 - optimizeLoop stmts used (idx - 1) len (updateUse3 ei ei1 ei2 ctxt) + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e1 + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e2 + optimizeLoop stmts used (idx - 1) len ctxt | Put (v, e) when v = e -> used[idx] <- false optimizeLoop stmts used (idx - 1) (len - 1) ctxt - | Put ({ E = Var (_, rid, _, rs) }, rhs) -> - let isUsed = RegisterSet.exist rid ctxt.UseRegisters - let ctxt = if isUsed then removeUse rid ctxt else ctxt - if not isUsed && RegisterSet.exist rid ctxt.OutRegisters then + | Put ({ E = Var (_, rid, _) }, rhs) -> + let isUsed = ctxt.UseRegisters.Contains (int rid) + if isUsed then ctxt.UseRegisters.Remove (int rid) else () + if not isUsed && ctxt.OutRegisters.Contains (int rid) then used[idx] <- false optimizeLoop stmts used (idx - 1) (len - 1) ctxt else - let ctxt = updateOut rs ctxt - let ctxt = updateUse (AST.getExprInfo rhs) ctxt + ctxt.OutRegisters.Add (int rid) + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar rhs optimizeLoop stmts used (idx - 1) len ctxt | Put ({ E = TempVar (_, n) }, rhs) -> - let isUsed = Set.contains n ctxt.UseTempVar - let ctxt = if isUsed then removeTempUse n ctxt else ctxt - if not isUsed && (ctxt.IsLastBlock || Set.contains n ctxt.OutTempVar) then + let isUsed = ctxt.UseTempVar.Contains n + if isUsed then ctxt.UseTempVar.Remove n |> ignore else () + if not isUsed && (ctxt.IsLastBlock || ctxt.OutTempVar.Contains n) then used[idx] <- false optimizeLoop stmts used (idx - 1) (len - 1) ctxt else - let ctxt = updateTempOut n ctxt - let ctxt = updateUse (AST.getExprInfo rhs) ctxt + ctxt.OutTempVar.Add n |> ignore + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar rhs optimizeLoop stmts used (idx - 1) len ctxt - | SideEffect (BinIR.SideEffect.ExternalCall expr) -> - let ctxt = updateUse (AST.getExprInfo expr) ctxt + | ExternalCall (e) -> + AST.updateAllVarsUses ctxt.UseRegisters ctxt.UseTempVar e optimizeLoop stmts used (idx - 1) len ctxt | LMark _ -> - optimizeLoop stmts used (idx - 1) len { ctxt with IsLastBlock = false } + ctxt.IsLastBlock <- false + optimizeLoop stmts used (idx - 1) len ctxt | ISMark _ -> - optimizeLoop stmts used (idx - 1) len { ctxt with IsLastBlock = false } + ctxt.IsLastBlock <- false + optimizeLoop stmts used (idx - 1) len ctxt | IEMark _ -> - optimizeLoop stmts used (idx - 1) len { ctxt with IsLastBlock = true } - | _ -> optimizeLoop stmts used (idx - 1) len ctxt + ctxt.IsLastBlock <- true + optimizeLoop stmts used (idx - 1) len ctxt + | _ -> + optimizeLoop stmts used (idx - 1) len ctxt else createReducedStmts stmts len used /// Assuming that the stmts are localized, i.e., those stmts represent a basic @@ -149,4 +115,10 @@ let rec optimizeLoop (stmts: Stmt []) (used: bool []) idx len ctxt = let optimize (stmts: Stmt []) = let used = Array.init stmts.Length (fun _ -> true) let len = stmts.Length - optimizeLoop stmts used (len - 1) len emptyCtxt + let ctxt = + { UseRegisters = RegisterSet () + OutRegisters = RegisterSet () + UseTempVar = HashSet () + OutTempVar= HashSet () + IsLastBlock = false } + optimizeLoop stmts used (len - 1) len ctxt diff --git a/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs b/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs index 3bbf535f..9951319f 100644 --- a/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs +++ b/src/FrontEnd/BinLifter/Optimizer/LocalOptimizer.fs @@ -40,7 +40,7 @@ module private Localizer = else List.rev (stmts :: acc) |> List.toArray let breakIntoBlocks (stmts: Stmt []) = - if Array.length stmts = 0 then [| stmts |] + if Array.isEmpty stmts then [| stmts |] else breakByMark [] stmts 1 /// Intra-block local IR optimizer. @@ -59,7 +59,5 @@ type LocalOptimizer = static member Optimize stmts = LocalOptimizer.TrimIEMark stmts |> breakIntoBlocks - |> Array.map (fun stmts -> - ConstantFolding.optimize stmts - |> DeadCodeElimination.optimize) - |> Array.concat + |> Array.collect + (ConstantFolding.optimize >> DeadCodeElimination.optimize) diff --git a/src/FrontEnd/BinLifter/PARISC/B2R2.FrontEnd.BinLifter.PARISC.fsproj b/src/FrontEnd/BinLifter/PARISC/B2R2.FrontEnd.BinLifter.PARISC.fsproj new file mode 100644 index 00000000..c264ff14 --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/B2R2.FrontEnd.BinLifter.PARISC.fsproj @@ -0,0 +1,28 @@ + + + LICENSE.md + b2r2-240x240.png + README.md + B2R2 PARISC frontend. + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MiddleEnd/ConcEval/EvalUtils.fs b/src/FrontEnd/BinLifter/PARISC/PARISCDisasm.fs similarity index 92% rename from src/MiddleEnd/ConcEval/EvalUtils.fs rename to src/FrontEnd/BinLifter/PARISC/PARISCDisasm.fs index e9cbf7aa..773838eb 100644 --- a/src/MiddleEnd/ConcEval/EvalUtils.fs +++ b/src/FrontEnd/BinLifter/PARISC/PARISCDisasm.fs @@ -22,8 +22,6 @@ SOFTWARE. *) -module internal B2R2.MiddleEnd.ConcEval.EvalUtils +module B2R2.FrontEnd.BinLifter.PARISC.Disasm -open B2R2 - -let tr = BitVector.one 1 +// TODO Implement disasm logic diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCInstruction.fs b/src/FrontEnd/BinLifter/PARISC/PARISCInstruction.fs new file mode 100644 index 00000000..087b1b7f --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCInstruction.fs @@ -0,0 +1,101 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PARISC + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// The internal representation for a PARISC instruction used by our +/// disassembler and lifter. +type PARISCInstruction (addr, numBytes, insInfo) = + inherit Instruction (addr, numBytes, WordSize.Bit32) + + /// Basic instruction information. + member val Info: InsInfo = insInfo + + override __.IsBranch () = + match __.Info.Opcode with + | _ -> false + + override __.IsModeChanging () = false + + member __.HasConcJmpTarget () = Utils.futureFeature () + + override __.IsDirectBranch () = + __.IsBranch () && __.HasConcJmpTarget () + + override __.IsIndirectBranch () = + __.IsBranch () && (not <| __.HasConcJmpTarget ()) + + override __.IsCondBranch () = Utils.futureFeature () + + override __.IsCJmpOnTrue () = Utils.futureFeature () + + override __.IsCall () = Utils.futureFeature () + + override __.IsRET () = Utils.futureFeature () + + override __.IsInterrupt () = Utils.futureFeature () + + override __.IsExit () = Utils.futureFeature () + + override __.IsBBLEnd () = + __.IsDirectBranch () || + __.IsIndirectBranch () + + override __.DirectBranchTarget (_addr: byref) = Utils.futureFeature () + + override __.IndirectTrampolineAddr (_addr: byref) = + Utils.futureFeature () + + override __.Immediate (_v: byref) = Utils.futureFeature () + + override __.GetNextInstrAddrs () = Utils.futureFeature () + + override __.InterruptNum (_num: byref) = Utils.futureFeature () + + override __.IsNop () = Utils.futureFeature () + + override __.Translate ctxt = + Utils.futureFeature () + + override __.TranslateToList ctxt = + Utils.futureFeature () + + override __.Disasm (showAddr, _) = + Utils.futureFeature () + + override __.Disasm () = + Utils.futureFeature () + + override __.Decompose (showAddr) = + Utils.futureFeature () + + override __.IsInlinedAssembly () = false + + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCLifter.fs b/src/FrontEnd/BinLifter/PARISC/PARISCLifter.fs new file mode 100644 index 00000000..69a5ddf5 --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCLifter.fs @@ -0,0 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.PARISC.Lifter + +// TODO diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCParser.fs b/src/FrontEnd/BinLifter/PARISC/PARISCParser.fs new file mode 100644 index 00000000..1598c01f --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCParser.fs @@ -0,0 +1,46 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PARISC + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Parser for PARISC instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type PARISC64Parser (isa: ISA) = + let wordSize = int isa.WordSize + let reader = BinReader.Init isa.Endian + + interface IInstructionParsable with + member __.Parse (span: ByteSpan, addr: Addr) = + Utils.futureFeature (): Instruction + + member __.Parse (bs: byte[], addr: Addr) = + Utils.futureFeature (): Instruction + + member __.MaxInstructionSize = 4 + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/MiddleEnd/BinGraph.Tests/Types.fs b/src/FrontEnd/BinLifter/PARISC/PARISCParsingMain.fs similarity index 85% rename from src/MiddleEnd/BinGraph.Tests/Types.fs rename to src/FrontEnd/BinLifter/PARISC/PARISCParsingMain.fs index 6393e1a5..ee9f64b1 100644 --- a/src/MiddleEnd/BinGraph.Tests/Types.fs +++ b/src/FrontEnd/BinLifter/PARISC/PARISCParsingMain.fs @@ -22,11 +22,11 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.BinGraph.Tests +module internal B2R2.FrontEnd.BinLifter.PARISC.ParsingMain -open B2R2.MiddleEnd.BinGraph +open B2R2 -type V (v, range) = - inherit RangedVertexData (range) - member __.Val : int = v - override __.ToString () = v.ToString () +let parse (span: ByteSpan) (reader: IBinReader) wordSize addr = + Utils.futureFeature () + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64Parser.fs b/src/FrontEnd/BinLifter/PARISC/PARISCRegExprs.fs similarity index 82% rename from src/FrontEnd/BinLifter/Sparc64/Sparc64Parser.fs rename to src/FrontEnd/BinLifter/PARISC/PARISCRegExprs.fs index 49d2569b..0290120b 100644 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64Parser.fs +++ b/src/FrontEnd/BinLifter/PARISC/PARISCRegExprs.fs @@ -22,15 +22,13 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.Sparc64.Parser +namespace B2R2.FrontEnd.BinLifter.PARISC open B2R2 open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingUtils +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp -let parse (span: ByteSpan) (reader: IBinReader) addr = - let bin = reader.ReadUInt32 (span, 0) - let insInfo = - { Address = addr } - Sparc64Instruction (addr, insInfo) - -// vim: set tw=80 sts=2 sw=2: +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCRegister.fs b/src/FrontEnd/BinLifter/PARISC/PARISCRegister.fs new file mode 100644 index 00000000..f959a1a9 --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCRegister.fs @@ -0,0 +1,158 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PARISC + +open B2R2 + +type Register = + | GR0 = 0x0 + | GR1 = 0x1 + | GR2 = 0x2 + | GR3 = 0x3 + | GR4 = 0x4 + | GR5 = 0x5 + | GR6 = 0x6 + | GR7 = 0x7 + | GR8 = 0x8 + | GR9 = 0x9 + | GR10 = 0xA + | GR11 = 0xB + | GR12 = 0xC + | GR13 = 0xD + | GR14 = 0xE + | GR15 = 0xF + | GR16 = 0x10 + | GR17 = 0x11 + | GR18 = 0x12 + | GR19 = 0x13 + | GR20 = 0x14 + | GR21 = 0x15 + | GR22 = 0x16 + | GR23 = 0x17 + | GR24 = 0x18 + | GR25 = 0x19 + | GR26 = 0x1A + | GR27 = 0x1B + | GR28 = 0x1C + | GR29 = 0x1D + | GR30 = 0x1E + | GR31 = 0x1F + | SR0 = 0x20 + | SR1 = 0x21 + | SR2 = 0x22 + | SR3 = 0x23 + | SR4 = 0x24 + | SR5 = 0x25 + | SR6 = 0x26 + | SR7 = 0x27 + | IAOQ_Front = 0x28 + | IAOQ_Back = 0x29 + | IASQ_Front = 0x2A + | IASQ_Back = 0x2B + | PSW = 0x2C + | CR0 = 0x2D + | CR1 = 0x2E + | CR2 = 0x2F + | CR3 = 0x30 + | CR4 = 0x31 + | CR5 = 0x32 + | CR6 = 0x33 + | CR7 = 0x34 + | CR8 = 0x35 + | CR9 = 0x36 + | CR10 = 0x37 + | CR11 = 0x38 + | CR12 = 0x39 + | CR13 = 0x3A + | CR14 = 0x3B + | CR15 = 0x3C + | CR16 = 0x3D + | CR17 = 0x3E + | CR18 = 0x3F + | CR19 = 0x40 + | CR20 = 0x41 + | CR21 = 0x42 + | CR22 = 0x43 + | CR23 = 0x44 + | CR24 = 0x45 + | CR25 = 0x46 + | CR26 = 0x47 + | CR27 = 0x48 + | CR28 = 0x49 + | CR29 = 0x4A + | CR30 = 0x4B + | CR31 = 0x4C + | FPR0 = 0x4D + | FPR1 = 0x4E + | FPR2 = 0x4F + | FPR3 = 0x50 + | FPR4 = 0x51 + | FPR5 = 0x52 + | FPR6 = 0x53 + | FPR7 = 0x54 + | FPR8 = 0x55 + | FPR9 = 0x56 + | FPR10 = 0x57 + | FPR11 = 0x58 + | FPR12 = 0x59 + | FPR13 = 0x5A + | FPR14 = 0x5B + | FPR15 = 0x5C + | FPR16 = 0x5D + | FPR17 = 0x5E + | FPR18 = 0x5F + | FPR19 = 0x60 + | FPR20 = 0x61 + | FPR21 = 0x62 + | FPR22 = 0x63 + | FPR23 = 0x64 + | FPR24 = 0x65 + | FPR25 = 0x66 + | FPR26 = 0x67 + | FPR27 = 0x68 + | FPR28 = 0x69 + | FPR29 = 0x6A + | FPR30 = 0x6B + | FPR31 = 0x6C + +/// Shortcut for Register type. +type internal R = Register + +/// This module exposes several useful functions to handle s390/s390x +/// registers. +[] +module Register = + let inline ofRegID (n: RegisterID): Register = + int n |> LanguagePrimitives.EnumOfValue + + let inline toRegID (reg: Register) = + LanguagePrimitives.EnumToValue (reg) |> RegisterID.create + + let ofString (str: string) = + match str.ToLowerInvariant () with + | _ -> Utils.impossible () + + let toRegType wordSize = function + | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCRegisterFactory.fs b/src/FrontEnd/BinLifter/PARISC/PARISCRegisterFactory.fs new file mode 100644 index 00000000..de63aa1c --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCRegisterFactory.fs @@ -0,0 +1,81 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PARISC + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type PARISC64RegisterFactory (wordSize, r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + Utils.futureFeature () + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + Utils.futureFeature () + + override __.RegIDFromRegExpr (e) = + Utils.futureFeature () + + override __.RegIDToRegExpr (id) = + Utils.futureFeature () + + override __.StrToRegExpr s = + Utils.futureFeature () + + override __.RegIDFromString str = + Utils.futureFeature () + + override __.RegIDToString rid = + Utils.futureFeature () + + override __.RegIDToRegType rid = + Utils.futureFeature () + + override __.GetRegisterAliases _rid = + Utils.futureFeature () + + override __.ProgramCounter = + Utils.futureFeature () + + override __.StackPointer = + Utils.futureFeature () + + override __.FramePointer = + Utils.futureFeature () + + override __.IsProgramCounter rid = + Utils.futureFeature () + + override __.IsStackPointer rid = + Utils.futureFeature () + + override __.IsFramePointer rid = + Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCTranslationContext.fs b/src/FrontEnd/BinLifter/PARISC/PARISCTranslationContext.fs new file mode 100644 index 00000000..baca8c9d --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCTranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PARISC + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for PARISC instructions. +type PARISCTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Utils.futureFeature () + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/PARISC/PARISCTypes.fs b/src/FrontEnd/BinLifter/PARISC/PARISCTypes.fs new file mode 100644 index 00000000..c2f47709 --- /dev/null +++ b/src/FrontEnd/BinLifter/PARISC/PARISCTypes.fs @@ -0,0 +1,82 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PARISC + +open B2R2 +open System.Runtime.CompilerServices + +[] +do () + +/// +/// PARISC opcodes. This type should be generated using +/// scripts/genOpcode.fsx from the `PARISC64SupportedOpcode.txt` +/// file. +/// +type Opcode = + | MyOp = 0 // FIXME + +type internal Op = Opcode + +type Operand = + | MyOpr // FIXME + +type Operands = + | NoOperand + | OneOperand of Operand + | TwoOperands of Operand * Operand + +/// Basic information obtained by parsing a PARISC instruction. +[] +type InsInfo = { + /// Address. + Address: Addr + /// Instruction length. + NumBytes: uint32 + /// Opcode. + Opcode: Opcode + /// Operands. + Operands: Operands + /// Operation Size. + OperationSize: RegType +} +with + override __.GetHashCode () = + hash (__.Address, + __.NumBytes, + __.Opcode, + __.Operands, + __.OperationSize) + override __.Equals (i) = + match i with + | :? InsInfo as i -> + i.Address = __.Address + && i.NumBytes = __.NumBytes + && i.Opcode = __.Opcode + && i.Operands = __.Operands + && i.OperationSize = __.OperationSize + | _ -> false + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Sparc64/README.md b/src/FrontEnd/BinLifter/PARISC/README.md similarity index 57% rename from src/FrontEnd/BinLifter/Sparc64/README.md rename to src/FrontEnd/BinLifter/PARISC/README.md index 71347322..7206bd00 100644 --- a/src/FrontEnd/BinLifter/Sparc64/README.md +++ b/src/FrontEnd/BinLifter/PARISC/README.md @@ -1,4 +1,4 @@ -# B2R2.FrontEnd.BinLifter.Sparc64 +# B2R2.FrontEnd.BinLifter.PARISC ### B2R2? @@ -6,6 +6,6 @@ B2R2 is a binary analysis and reversing framework written purely in F#. Since it does not rely on any native (unmanaged) code, it is readily usable in any platform or OS that .NET runs on. -### B2R2.FrontEnd.BinLifter.Sparc64 Package? +### B2R2.FrontEnd.BinLifter.PARISC Package? -`B2R2.FrontEnd.BinLifter.Sparc64` includes Sparc64 parsers and lifters. +`B2R2.FrontEnd.BinLifter.PARISC` includes PARISC parsers and lifters. diff --git a/src/FrontEnd/BinLifter/PPC32/B2R2.FrontEnd.BinLifter.PPC32.fsproj b/src/FrontEnd/BinLifter/PPC32/B2R2.FrontEnd.BinLifter.PPC32.fsproj index d6a48fb7..2645b052 100644 --- a/src/FrontEnd/BinLifter/PPC32/B2R2.FrontEnd.BinLifter.PPC32.fsproj +++ b/src/FrontEnd/BinLifter/PPC32/B2R2.FrontEnd.BinLifter.PPC32.fsproj @@ -9,14 +9,16 @@ - - + + + + - + diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32.fs b/src/FrontEnd/BinLifter/PPC32/PPC32.fs deleted file mode 100644 index a5a116fa..00000000 --- a/src/FrontEnd/BinLifter/PPC32/PPC32.fs +++ /dev/null @@ -1,65 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.PPC32 - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for PPC32 instructions. -type PPC32TranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for PPC32 instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type PPC32Parser (isa: ISA) = - inherit Parser () - - let reader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader addr :> Instruction - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader addr :> Instruction - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - PPC32TranslationContext (isa, regexprs) :> TranslationContext, - PPC32RegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32Disasm.fs b/src/FrontEnd/BinLifter/PPC32/PPC32Disasm.fs index 27aef939..e24a4423 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32Disasm.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32Disasm.fs @@ -26,6 +26,8 @@ module B2R2.FrontEnd.BinLifter.PPC32.Disasm open B2R2 open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData +open B2R2.FrontEnd.BinLifter.PPC32.OperandHelper let opCodeToString = function | Op.ADD -> "add" @@ -262,18 +264,24 @@ let opCodeToString = function | Op.FNMADDS -> "fnmadds" | Op.FNMADDSdot -> "fnmadds." | Op.TWLGT -> "twlgt" - | Op.TWLLT -> "twllt" - | Op.TWLNL -> "twlnl" + | Op.TWLLE -> "twlle" + | Op.TWGE -> "twge" | Op.TWGT -> "twgt" + | Op.TWLE -> "twle" | Op.TWLT -> "twlt" + | Op.TWLLT -> "twllt" + | Op.TWLNL -> "twlnl" | Op.TWNE -> "twne" | Op.TWI -> "twi" | Op.TWLGTI -> "twlgti" + | Op.TWLLEI -> "twllei" | Op.TWLLTI -> "twllti" | Op.TWEQI -> "tweqi" | Op.TWLNLI -> "twlnli" + | Op.TWGEI -> "twgei" | Op.TWGTI -> "twgti" | Op.TWLTI -> "twlti" + | Op.TWLEI -> "twlei" | Op.TWNEI -> "twnei" | Op.MULLI -> "mulli" | Op.SUBFIC -> "subfic" @@ -318,7 +326,7 @@ let opCodeToString = function | Op.STFDU -> "stfdu" | Op.ORI -> "ori" | Op.NOP -> "nop" - | Op.ORIS -> "opis" + | Op.ORIS -> "oris" | Op.XORI -> "xori" | Op.XORIS -> "xoris" | Op.ANDIdot -> "andi." @@ -462,55 +470,307 @@ let opCodeToString = function | Op.BCTR -> "bctr" | Op.BCTRL -> "bctrl" | Op.MR -> "mr" + | Op.BTLRL -> "btlrl" + | Op.BFLRL -> "bflrl" + | Op.BTCTRL -> "btctrl" + | Op.CLRRWI -> "clrrwi" + | Op.LWSYNC -> "lwsync" | _ -> Utils.impossible () -let inline buildOpcode ins (builder: DisasmBuilder<_>) = +let condToString = function + | Condition.LT -> "lt" + | Condition.LE -> "le" + | Condition.EQ -> "eq" + | Condition.GE -> "ge" + | Condition.GT -> "gt" + | Condition.NL -> "nl" + | Condition.NE -> "ne" + | Condition.NG -> "ng" + | Condition.SO -> "so" + | Condition.NS -> "ns" + | Condition.UN -> "un" + | Condition.NU -> "nu" + | _ -> raise ParsingFailureException + +let inline buildOpcode ins (builder: DisasmBuilder) = let str = opCodeToString ins.Opcode builder.Accumulate AsmWordKind.Mnemonic str -let oprToString opr delim (builder: DisasmBuilder<_>) = +let inline relToString pc offset (builder: DisasmBuilder) = + let targetAddr = pc + uint64 offset + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 targetAddr) + +let inline getCond bi = + match extract bi 1u 0u with + | 0b00u -> Condition.LT + | 0b01u -> Condition.GT + | 0b10u -> Condition.EQ + | _ (* 11 *) -> Condition.SO + +let oprToString insInfo opr delim (builder: DisasmBuilder) = match opr with - | OpReg reg -> + | OprReg reg -> builder.Accumulate AsmWordKind.String delim builder.Accumulate AsmWordKind.Variable (Register.toString reg) - | Immediate imm -> - builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (String.u64ToHex imm) - | Branch bi -> - builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (String.u64ToHex bi) - | ImmOp (imm, reg) -> + | OprMem (imm, reg) -> builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (String.u64ToHex imm) + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 imm) builder.Accumulate AsmWordKind.String "(" builder.Accumulate AsmWordKind.Variable (Register.toString reg) builder.Accumulate AsmWordKind.String ")" + | OprImm imm -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 imm) + | OprAddr addr -> + builder.Accumulate AsmWordKind.String delim + relToString insInfo.Address addr builder + | OprBI imm -> + let cr = extract imm 4u 2u |> getCondRegister + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (HexString.ofUInt32 4u) + builder.Accumulate AsmWordKind.String " * " + builder.Accumulate AsmWordKind.Variable (Register.toString cr) + builder.Accumulate AsmWordKind.String " + " + builder.Accumulate AsmWordKind.String (condToString (getCond imm)) let buildOprs insInfo builder = match insInfo.Operands with | NoOperand -> () | OneOperand opr -> - oprToString opr " " builder + oprToString insInfo opr " " builder | TwoOperands (opr1, opr2) -> - oprToString opr1 " " builder - oprToString opr2 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder | ThreeOperands (opr1, opr2, opr3) -> - oprToString opr1 " " builder - oprToString opr2 ", " builder - oprToString opr3 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder | FourOperands (opr1, opr2, opr3, opr4) -> - oprToString opr1 " " builder - oprToString opr2 ", " builder - oprToString opr3 ", " builder - oprToString opr4 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder + oprToString insInfo opr4 ", " builder | FiveOperands (opr1, opr2, opr3, opr4, opr5) -> - oprToString opr1 " " builder - oprToString opr2 ", " builder - oprToString opr3 ", " builder - oprToString opr4 ", " builder - oprToString opr5 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder + oprToString insInfo opr4 ", " builder + oprToString insInfo opr5 ", " builder + +let buildSimpleMnemonic opcode bi addr insInfo (builder: DisasmBuilder) = + let cr = extract bi 4u 2u |> getCondRegister + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) + builder.Accumulate AsmWordKind.String " " + builder.Accumulate AsmWordKind.Variable (Register.toString cr) + builder.Accumulate AsmWordKind.String ", " + relToString insInfo.Address addr builder + +let buildCrMnemonic opcode bi (builder: DisasmBuilder) = + let cr = extract bi 4u 2u |> getCondRegister + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) + builder.Accumulate AsmWordKind.String " " + builder.Accumulate AsmWordKind.Variable (Register.toString cr) + +let buildTargetMnemonic opcode addr insInfo (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) + builder.Accumulate AsmWordKind.String " " + relToString insInfo.Address addr builder + +let buildRotateMnemonic opcode ra rs n (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString opcode) + builder.Accumulate AsmWordKind.String " " + builder.Accumulate AsmWordKind.Variable (Register.toString ra) + builder.Accumulate AsmWordKind.String ", " + builder.Accumulate AsmWordKind.Variable (Register.toString rs) + builder.Accumulate AsmWordKind.String ", " + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 n) + +let buildBC insInfo builder = + match insInfo.Operands with + | ThreeOperands (OprImm bo , OprBI bi, OprAddr addr) -> + let bibit = bi % 4u + match bo, bi, bibit with + | 16UL, 0u, _ -> buildTargetMnemonic Op.BDNZ addr insInfo builder + | 12UL, _ , 0u -> buildTargetMnemonic Op.BLT addr insInfo builder + | 12UL, _ , 1u -> buildSimpleMnemonic Op.BGT bi addr insInfo builder + | 12UL, _ , 2u -> buildSimpleMnemonic Op.BEQ bi addr insInfo builder + | 12UL, _ , 3u -> buildSimpleMnemonic Op.BSO bi addr insInfo builder + | 4UL, _ , 0u -> buildSimpleMnemonic Op.BGE bi addr insInfo builder + | 4UL, _ , 1u -> buildSimpleMnemonic Op.BLE bi addr insInfo builder + | 4UL, _ , 2u -> buildSimpleMnemonic Op.BNE bi addr insInfo builder + | 4UL, _, 3u -> buildSimpleMnemonic Op.BNS bi addr insInfo builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCA insInfo builder = + match insInfo.Operands with + | ThreeOperands (OprImm bo , OprBI bi, OprAddr addr) -> + let bibit = bi % 4u + match bo, bibit with + | 12UL, 0u -> buildSimpleMnemonic Op.BLTA bi addr insInfo builder + | 12UL, 1u -> buildSimpleMnemonic Op.BGTA bi addr insInfo builder + | 12UL, 2u -> buildSimpleMnemonic Op.BEQA bi addr insInfo builder + | 12UL, 3u -> buildSimpleMnemonic Op.BSOA bi addr insInfo builder + | 4UL, 0u -> buildSimpleMnemonic Op.BGEA bi addr insInfo builder + | 4UL, 1u -> buildSimpleMnemonic Op.BLEA bi addr insInfo builder + | 4UL, 2u -> buildSimpleMnemonic Op.BNEA bi addr insInfo builder + | 4UL, 3u -> buildSimpleMnemonic Op.BNSA bi addr insInfo builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCL insInfo builder = + match insInfo.Operands with + | ThreeOperands (OprImm bo , OprBI bi, OprAddr addr) -> + let bibit = bi % 4u + match bo, bibit with + | 12UL, 0u -> buildSimpleMnemonic Op.BLTA bi addr insInfo builder + | 12UL, 1u -> buildSimpleMnemonic Op.BGTA bi addr insInfo builder + | 12UL, 2u -> buildSimpleMnemonic Op.BEQA bi addr insInfo builder + | 12UL, 3u -> buildSimpleMnemonic Op.BSOA bi addr insInfo builder + | 4UL, 0u -> buildSimpleMnemonic Op.BGEA bi addr insInfo builder + | 4UL, 1u -> buildSimpleMnemonic Op.BLEA bi addr insInfo builder + | 4UL, 2u -> buildSimpleMnemonic Op.BNEA bi addr insInfo builder + | 4UL, 3u -> buildSimpleMnemonic Op.BNSA bi addr insInfo builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCLA insInfo builder = + match insInfo.Operands with + | ThreeOperands (OprImm bo , OprBI bi, OprAddr addr) -> + let bibit = bi % 4u + match bo, bibit with + | 12uL, 0u -> buildSimpleMnemonic Op.BLTLA bi addr insInfo builder + | 12UL, 1u -> buildSimpleMnemonic Op.BGTLA bi addr insInfo builder + | 12UL, 2u -> buildSimpleMnemonic Op.BEQLA bi addr insInfo builder + | 12UL, 3u -> buildSimpleMnemonic Op.BSOLA bi addr insInfo builder + | 4UL, 0u -> buildSimpleMnemonic Op.BGELA bi addr insInfo builder + | 4UL, 1u -> buildSimpleMnemonic Op.BLELA bi addr insInfo builder + | 4UL, 2u -> buildSimpleMnemonic Op.BNELA bi addr insInfo builder + | 4UL, 3u -> buildSimpleMnemonic Op.BNSLA bi addr insInfo builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCLR insInfo (builder: DisasmBuilder) = + match insInfo.Operands with + | TwoOperands (OprImm bo , OprBI bi) -> + let bibit = bi % 4u + match bo, bibit with + | 20uL, 0u -> + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString Op.BLR) + | 12UL, 0u -> buildCrMnemonic Op.BLTLR bi builder + | 12UL, 1u -> buildCrMnemonic Op.BGTLR bi builder + | 12UL, 2u -> buildCrMnemonic Op.BEQLR bi builder + | 12UL, 3u -> buildCrMnemonic Op.BSOLR bi builder + | 4UL, 0u -> buildCrMnemonic Op.BGELR bi builder + | 4UL, 1u -> buildCrMnemonic Op.BLELR bi builder + | 4UL, 2u -> buildCrMnemonic Op.BNELR bi builder + | 4UL, 3u -> buildCrMnemonic Op.BNSLR bi builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCLRL insInfo (builder: DisasmBuilder) = + match insInfo.Operands with + | TwoOperands (OprImm bo , OprBI bi) -> + match bo, bi with + | 12UL, 0u -> buildCrMnemonic Op.BLTLRL bi builder + | 12UL, 1u -> buildCrMnemonic Op.BGTLRL bi builder + | 12UL, 2u -> buildCrMnemonic Op.BEQLRL bi builder + | 12UL, 3u -> buildCrMnemonic Op.BSOLRL bi builder + | 4UL, 0u -> buildCrMnemonic Op.BGELRL bi builder + | 4UL, 1u -> buildCrMnemonic Op.BLELRL bi builder + | 4UL, 2u -> buildCrMnemonic Op.BNELRL bi builder + | 4UL, 3u -> buildCrMnemonic Op.BNSLRL bi builder + | 20UL, 0u -> + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString Op.BLRL) + | 16UL, 0u -> + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString Op.BDNZLRL) + | 18UL, 0u -> + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString Op.BDZLRL) + | 8UL, _ -> buildCrMnemonic Op.BDNZTLRL bi builder + | 0UL, _ -> buildCrMnemonic Op.BDNZFLRL bi builder + | 10UL, _ -> buildCrMnemonic Op.BDZTLRL bi builder + | 2UL, _ -> buildCrMnemonic Op.BDZFLRL bi builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCCTR insInfo builder = + match insInfo.Operands with + | TwoOperands (OprImm bo , OprBI bi) -> + let bibit = bi % 4u + match bo, bibit with + | 12UL, 0u -> buildCrMnemonic Op.BLTCTR bi builder + | 12UL, 1u -> buildCrMnemonic Op.BGTCTR bi builder + | 12UL, 2u -> buildCrMnemonic Op.BEQCTR bi builder + | 12UL, 3u -> buildCrMnemonic Op.BSOCTR bi builder + | 4UL, 0u -> buildCrMnemonic Op.BGECTR bi builder + | 4UL, 1u -> buildCrMnemonic Op.BLECTR bi builder + | 4UL, 2u -> buildCrMnemonic Op.BNECTR bi builder + | 4UL, 3u -> buildCrMnemonic Op.BNSCTR bi builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildBCCTRL insInfo builder = + match insInfo.Operands with + | TwoOperands (OprImm bo , OprBI bi) -> + let bibit = bi % 4u + match bo, bibit with + | 12UL, 0u -> buildCrMnemonic Op.BLTCTRL bi builder + | 12UL, 1u -> buildCrMnemonic Op.BGTCTRL bi builder + | 12UL, 2u -> buildCrMnemonic Op.BEQCTRL bi builder + | 12UL, 3u -> buildCrMnemonic Op.BSOCTRL bi builder + | 4UL, 0u -> buildCrMnemonic Op.BGECTRL bi builder + | 4UL, 1u -> buildCrMnemonic Op.BLECTRL bi builder + | 4UL, 2u -> buildCrMnemonic Op.BNECTRL bi builder + | 4UL, 3u -> buildCrMnemonic Op.BNSCTRL bi builder + | 20UL, 0u -> + builder.Accumulate AsmWordKind.Mnemonic (opCodeToString Op.BCTRL) + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException + +let buildRLWINM insInfo builder = + match insInfo.Operands with + | FiveOperands (OprReg ra, OprReg rs, OprImm sh, OprImm mb, OprImm me) -> + match sh, mb, me with + | _ , 0UL, 31UL -> buildRotateMnemonic Op.ROTLWI ra rs sh builder + | n1, 0UL, n2 when n2 = (31UL - n1) -> + buildRotateMnemonic Op.SLWI ra rs sh builder + | n1, n2, 31UL when n1 = (32UL - n2) -> + buildRotateMnemonic Op.SRWI ra rs mb builder + | 0UL, _ , 31UL -> buildRotateMnemonic Op.CLRLWI ra rs mb builder + | 0UL, 0UL, n -> buildRotateMnemonic Op.CLRRWI ra rs (31UL - me) builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder + | _ -> raise ParsingFailureException -let disasm insInfo (builder: DisasmBuilder<_>) = +let disasm insInfo (builder: DisasmBuilder) = if builder.ShowAddr then builder.AccumulateAddr () else () - buildOpcode insInfo builder - buildOprs insInfo builder + match insInfo.Opcode with + | Op.BC -> buildBC insInfo builder + | Op.BCA -> buildBCA insInfo builder + | Op.BCL -> buildBCL insInfo builder + | Op.BCLA -> buildBCLA insInfo builder + | Op.BCLR -> buildBCLR insInfo builder + | Op.BCLRL -> buildBCLRL insInfo builder + | Op.BCCTR -> buildBCCTR insInfo builder + | Op.BCCTRL -> buildBCCTRL insInfo builder + | Op.RLWINM -> buildRLWINM insInfo builder + | _ -> + buildOpcode insInfo builder + buildOprs insInfo builder diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32Instruction.fs b/src/FrontEnd/BinLifter/PPC32/PPC32Instruction.fs index 358459a2..6b9e83d5 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32Instruction.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32Instruction.fs @@ -78,27 +78,28 @@ type PPC32Instruction (addr, numBytes, insInfo) = override __.IsNop () = Utils.futureFeature () - override __.Translate _ctxt = Utils.futureFeature () + override __.Translate ctxt = + (Lifter.translate __.Info numBytes ctxt).ToStmts () - override __.TranslateToList _ctxt = Utils.futureFeature () + override __.TranslateToList ctxt = Lifter.translate __.Info numBytes ctxt - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32Lifter.fs b/src/FrontEnd/BinLifter/PPC32/PPC32Lifter.fs new file mode 100644 index 00000000..af2ed2e1 --- /dev/null +++ b/src/FrontEnd/BinLifter/PPC32/PPC32Lifter.fs @@ -0,0 +1,2459 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.PPC32.Lifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.LiftingUtils +open B2R2.FrontEnd.BinLifter.PPC32 +open B2R2.FrontEnd.BinLifter.PPC32.OperandHelper + +let inline ( !. ) (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let getOneOpr (ins: InsInfo) = + match ins.Operands with + | OneOperand o -> o + | _ -> raise InvalidOperandException + +let getTwoOprs (ins: InsInfo) = + match ins.Operands with + | TwoOperands (o1, o2) -> struct (o1, o2) + | _ -> raise InvalidOperandException + +let getThreeOprs (ins: InsInfo) = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> struct (o1, o2, o3) + | _ -> raise InvalidOperandException + +let getExtMask mb me = + let struct (mb, me) = + match mb.E, me.E with + | Num b, Num m -> struct (b.SmallValue () |> int, m.SmallValue () |> int) + | _ -> raise InvalidExprException + let allOnes = System.UInt32.MaxValue + let mask = + if mb = me + 1 then allOnes + elif me = 31 then allOnes >>> mb + else + let v = (allOnes >>> mb) ^^^ (allOnes >>> (me + 1)) + if mb > me then ~~~v else v + numU32 mask 32 + +let rotateLeft rs sh = (rs << sh) .| (rs >> ((numI32 32 32) .- sh)) + +let loadNative (ctxt: TranslationContext) rt addr = + match ctxt.Endianness with + | Endian.Big -> AST.loadBE rt addr + | Endian.Little -> AST.loadLE rt addr + | _ -> raise InvalidEndianException + +/// Operand of the form d(rA) where the EA is (rA|0) + d. +let transEAWithOffset opr (ctxt: TranslationContext) = + match opr with + | OprMem (d, R.R0) -> numI32 d ctxt.WordBitSize + | OprMem (d, b) -> !.ctxt b .+ numI32 d ctxt.WordBitSize + | _ -> raise InvalidOperandException + +/// Operand of the form d(rA) where the EA is rA + d. rA is updated with EA. +let transEAWithOffsetForUpdate opr (ctxt: TranslationContext) = + match opr with + | OprMem (d, b) -> + let rA = !.ctxt b + struct (rA .+ numI32 d ctxt.WordBitSize, rA) + | _ -> raise InvalidOperandException + +/// Operands of the form "rA, rB" where the EA is (rA|0) + rB. +let transEAWithIndexReg rA rB (ctxt: TranslationContext) = + match rA, rB with + | OprReg R.R0, OprReg rB -> !.ctxt rB + | OprReg reg, OprReg rB -> !.ctxt reg .+ !.ctxt rB + | _ -> raise InvalidOpcodeException + +/// Operands of the form "rA, rB" where the EA is rA + rB, and rA is updated. +let transEAWithIndexRegForUpdate rA rB (ctxt: TranslationContext) = + match rA, rB with + | OprReg rA, OprReg rB -> + let rA = !.ctxt rA + struct (rA .+ !.ctxt rB, rA) + | _ -> raise InvalidOpcodeException + +let transOpr (ctxt: TranslationContext) = function + | OprReg reg -> !.ctxt reg + | OprMem (d, b) -> (* FIXME *) + loadNative ctxt 32 (!.ctxt b .+ numI32 d ctxt.WordBitSize) + | OprImm imm -> numU64 imm ctxt.WordBitSize + | OprAddr addr -> + numI64 (int64 addr) ctxt.WordBitSize + | OprBI bi -> getCRbitRegister bi |> !.ctxt + +let transOneOpr (ins: InsInfo) ctxt = + match ins.Operands with + | OneOperand o -> transOpr ctxt o + | _ -> raise InvalidOperandException + +let transTwoOprs (ins: InsInfo) ctxt = + match ins.Operands with + | TwoOperands (o1, o2) -> + struct (transOpr ctxt o1, transOpr ctxt o2) + | _ -> raise InvalidOperandException + +let transThreeOprs (ins: InsInfo) ctxt = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> + struct (transOpr ctxt o1, + transOpr ctxt o2, + transOpr ctxt o3) + | _ -> raise InvalidOperandException + +let transFourOprs (ins: InsInfo) ctxt = + match ins.Operands with + | FourOperands (o1, o2, o3, o4) -> + struct (transOpr ctxt o1, + transOpr ctxt o2, + transOpr ctxt o3, + transOpr ctxt o4) + | _ -> raise InvalidOperandException + +let transFiveOprs (ins: InsInfo) ctxt = + match ins.Operands with + | FiveOperands (o1, o2, o3, o4, o5) -> + struct (transOpr ctxt o1, + transOpr ctxt o2, + transOpr ctxt o3, + transOpr ctxt o4, + transOpr ctxt o5) + | _ -> raise InvalidOperandException + +let transCRxToExpr ctxt reg = + match reg with + | R.CR0 -> !.ctxt R.CR0_0, !.ctxt R.CR0_1, !.ctxt R.CR0_2, !.ctxt R.CR0_3 + | R.CR1 -> !.ctxt R.CR1_0, !.ctxt R.CR1_1, !.ctxt R.CR1_2, !.ctxt R.CR1_3 + | R.CR2 -> !.ctxt R.CR2_0, !.ctxt R.CR2_1, !.ctxt R.CR2_2, !.ctxt R.CR2_3 + | R.CR3 -> !.ctxt R.CR3_0, !.ctxt R.CR3_1, !.ctxt R.CR3_2, !.ctxt R.CR3_3 + | R.CR4 -> !.ctxt R.CR4_0, !.ctxt R.CR4_1, !.ctxt R.CR4_2, !.ctxt R.CR4_3 + | R.CR5 -> !.ctxt R.CR5_0, !.ctxt R.CR5_1, !.ctxt R.CR5_2, !.ctxt R.CR5_3 + | R.CR6 -> !.ctxt R.CR6_0, !.ctxt R.CR6_1, !.ctxt R.CR6_2, !.ctxt R.CR6_3 + | R.CR7 -> !.ctxt R.CR7_0, !.ctxt R.CR7_1, !.ctxt R.CR7_2, !.ctxt R.CR7_3 + | _ -> raise InvalidOperandException + +let transCmpOprs (ins: InsInfo) ctxt = + match ins.Operands with + | ThreeOperands (OprReg o1, o2, o3) -> + struct (transCRxToExpr ctxt o1, + transOpr ctxt o2, + transOpr ctxt o3) + + | FourOperands (OprReg o1, _ , o3, o4) -> + struct (transCRxToExpr ctxt o1, + transOpr ctxt o3, + transOpr ctxt o4) + | _ -> raise InvalidOperandException + +let transCondOneOpr (ins: InsInfo) ctxt = + match ins.Operands with + | OneOperand (OprReg o) -> + transCRxToExpr ctxt o + | _ -> raise InvalidOperandException + +let transCondTwoOprs (ins: InsInfo) ctxt = + match ins.Operands with + | TwoOperands (OprReg o1, OprReg o2) -> + struct (transCRxToExpr ctxt o1, transCRxToExpr ctxt o2) + | _ -> raise InvalidOperandException + +let transCondThreeOprs (ins: InsInfo) ctxt = + match ins.Operands with + | ThreeOperands (OprReg o1, OprReg o2, OprReg o3) -> + struct (transCRxToExpr ctxt o1, + transCRxToExpr ctxt o2, + transCRxToExpr ctxt o3) + | _ -> raise InvalidOperandException + +let transBranchTwoOprs (ins: InsInfo) ctxt = + match ins.Operands with + | TwoOperands (OprImm o1, OprBI o2) -> + struct (uint32 o1, getCRbitRegister o2 |> !.ctxt) + | _ -> raise InvalidOperandException + +let transBranchThreeOprs (ins: InsInfo) ctxt = + match ins.Operands with + | ThreeOperands (OprImm o1, OprBI o2, OprAddr o3) -> + struct (uint32 o1, + getCRbitRegister o2 |> !.ctxt, + numI64 (int64 o3) ctxt.WordBitSize) + | _ -> raise InvalidOperandException + +let getCRRegValue ir cr ctxt = + !!ir (cr := numI32 0 32) + for i in 0 .. 31 do + let crbit = uint32 (31 - i) |> getCRbitRegister |> !.ctxt + !!ir (AST.extract cr 1 i := crbit) + +let getImmValue = function + | OprImm imm -> uint32 imm + | OprBI imm -> imm + | _ -> raise InvalidOperandException + +let getSPRReg ctxt imm = + match uint32 imm with + | 1u -> !.ctxt R.XER + | 8u -> !.ctxt R.LR + | 9u -> !.ctxt R.CTR + | 287u -> !.ctxt R.PVR + | 18u | 19u | 22u | 25u | 26u | 27u | 272u | 273u | 274u | 275u | 282u | 528u + | 529u | 530u | 531u | 532u | 533u | 534u | 535u | 536u | 537u | 538u | 539u + | 540u | 541u | 542u | 543u | 1013u -> raise UnhandledRegExprException + | _ -> raise InvalidOperandException + +let floatingNeg ir dst src rt = + let sign = (AST.xthi 1 src <+> (AST.b1)) + let tmp = !+ir rt + !!ir (tmp := src) + !!ir (AST.xthi 1 tmp := sign) + !!ir (dst := tmp) + +let roundingToCastInt ctxt ir frd frb = + let fpscr = !.ctxt R.FPSCR + let rnA = AST.extract fpscr 1 1 + let rnB = AST.extract fpscr 1 0 + let lblRN0 = !%ir "RN0x" + let lblRN1 = !%ir "RN1x" + let lblEnd = !%ir "End" + !!ir (AST.cjmp rnA (AST.name lblRN1) (AST.name lblRN0)) + !!ir (AST.lmark lblRN0) + !!ir (frd := AST.ite rnB (AST.cast CastKind.FtoITrunc 64 frb) + (AST.cast CastKind.FtoIRound 64 frb)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblRN1) + !!ir (frd := AST.ite rnB (AST.cast CastKind.FtoIFloor 64 frb) + (AST.cast CastKind.FtoICeil 64 frb)) + !!ir (AST.lmark lblEnd) + +let setCR0Reg ctxt ir result = + let xerSO = AST.xthi 1 (!.ctxt R.XER) + let cr0LT = !.ctxt R.CR0_0 + let cr0GT = !.ctxt R.CR0_1 + let cr0EQ = !.ctxt R.CR0_2 + let cr0SO = !.ctxt R.CR0_3 + !!ir (cr0LT := result ?< AST.num0 32) + !!ir (cr0GT := result ?> AST.num0 32) + !!ir (cr0EQ := result == AST.num0 32) + !!ir (cr0SO := xerSO) + +let setCR1Reg ctxt ir = + let fpscr = !.ctxt R.FPSCR + let cr1FX = !.ctxt R.CR1_0 + let cr1FEX = !.ctxt R.CR1_1 + let cr1VX = !.ctxt R.CR1_2 + let cr1OX = !.ctxt R.CR1_3 + !!ir (cr1FX := AST.extract fpscr 1 31) + !!ir (cr1FEX := AST.extract fpscr 1 30) + !!ir (cr1VX := AST.extract fpscr 1 29) + !!ir (cr1OX := AST.extract fpscr 1 28) + +let isDenormailized frx = + let exponent = (frx >> numI32 52 64) .& numI32 0x7FF 64 + let fraction = frx .& numU64 0xfffff_ffffffffUL 64 + let zero = AST.num0 64 + AST.xtlo 1 ((exponent == zero) .& (fraction != zero)) + +let setFPRF ctxt ir result = + let fpscr = !.ctxt R.FPSCR + let c = AST.extract fpscr 1 16 + let fl = AST.extract fpscr 1 15 + let fg = AST.extract fpscr 1 14 + let fe = AST.extract fpscr 1 13 + let fu = AST.extract fpscr 1 12 + let nzero = numU64 0x8000000000000000UL 64 + !!ir (c := IEEE754Double.isNaN result + .| isDenormailized result + .| AST.eq result nzero) + !!ir (fl := AST.flt result (AST.num0 64)) + !!ir (fg := AST.fgt result (AST.num0 64)) + !!ir (fe := AST.eq (result << AST.num1 64) (AST.num0 64)) + !!ir (fu := IEEE754Double.isNaN result .| IEEE754Double.isInfinity result) + +let setCarryOut ctxt res ir = + let xerCA = AST.extract (!.ctxt R.XER) 1 29 + !!ir (xerCA := AST.extract res 1 32) + +let setCRRegValue ir cr ctxt = + for i in 0 .. 31 do + let crbit = uint32 (31 - i) |> getCRbitRegister |> !.ctxt + !!ir (crbit := AST.extract cr 1 i) + +let isAddSubOV ctxt expA expB result ir = + let struct (checkOF, t1, t2) = tmpVars3 ir 1 + let xerSO = AST.extract (!.ctxt R.XER) 1 31 + let xerOV = AST.extract (!.ctxt R.XER) 1 30 + let e1High = AST.xthi 1 expA + let e2High = AST.xthi 1 expB + let rHigh = AST.xthi 1 result + !!ir (t1 := e1High) + !!ir (t2 := rHigh) + !!ir (checkOF := (t1 == e2High) .& (t1 <+> t2)) + !!ir (xerOV := checkOF) + !!ir (xerSO := checkOF .& xerSO) + +let isMulOV ctxt expA expB ir = + let checkOF = !+ir 1 + let maxValue = numI32 0x7FFFFFFF 32 + let minValue = numI32 0x80000000 32 + let xerSO = AST.extract (!.ctxt R.XER) 1 31 + let xerOV = AST.extract (!.ctxt R.XER) 1 30 + let cond1 = (expA ?> maxValue ?/ expB) + let cond2 = (expA ?< minValue ?/ expB) + !!ir (checkOF := AST.ite (expB == AST.num0 32) AST.b0 (cond1 .| cond2)) + !!ir (xerOV := checkOF) + !!ir (xerSO := checkOF .& xerSO) + +let isSignedDivOV ctxt expA expB ir = + let checkOF = !+ir 1 + let minValue = numI32 0x80000000 32 + let xerSO = AST.extract (!.ctxt R.XER) 1 31 + let xerOV = AST.extract (!.ctxt R.XER) 1 30 + let cond = (expA == minValue) .& (expB == (numI32 0xFFFFFFFF 32)) + !!ir (checkOF := AST.ite (expB == AST.num0 32) AST.b0 cond) + !!ir (xerOV := checkOF) + !!ir (xerSO := checkOF .& xerSO) + +let isUnsignedDivOV ctxt expA expB ir = + let checkOF = !+ir 1 + let maxValue = numU32 0xFFFFFFFFu 32 + let xerSO = AST.extract (!.ctxt R.XER) 1 31 + let xerOV = AST.extract (!.ctxt R.XER) 1 30 + let cond = (expA ./ expB) .> maxValue + !!ir (checkOF := AST.ite (expB == AST.num0 32) AST.b0 cond) + !!ir (xerOV := checkOF) + !!ir (xerSO := checkOF .& xerSO) + +let sideEffects insLen ctxt name = + let ir = !*ctxt + !ir insLen + +let add ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + let struct (t1, t2) = tmpVars2 ir 32 + !ir insLen + +let addc ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! src1) + !!ir (t2 := AST.zext 64 src2) + !!ir (t3 := t1 .+ t2) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let adde ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let xerCA = AST.zext 64 (AST.extract (!.ctxt R.XER) 1 29) + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! src1) + !!ir (t2 := AST.zext 64 src2) + !!ir (t3 := t1 .+ t2 .+ xerCA) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let addi ins insLen ctxt = + let struct (dst, src1, simm) = transThreeOprs ins ctxt + let cond = src1 == AST.num0 32 + let ir = !*ctxt + !ir insLen + +let addic ins insLen updateCond ctxt = + let struct (dst, src1, simm) = transThreeOprs ins ctxt + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! src1) + !!ir (t2 := AST.zext 64 simm) + !!ir (t3 := t1 .+ t2) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let addis ins insLen ctxt = + let struct (dst, src1, simm) = transThreeOprs ins ctxt + let cond = src1 == AST.num0 32 + let simm = AST.concat (AST.xtlo 16 simm) (AST.num0 16) + let ir = !*ctxt + !ir insLen + +let addme ins insLen updateCond ovCond ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let xerCA = AST.zext 64 (AST.extract (!.ctxt R.XER) 1 29) + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! src) + !!ir (t2 := xerCA) + !!ir (t3 := t1 .+ t2 .- AST.num1 64) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let addze ins insLen updateCond ovCond ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let xerCA = AST.zext 64 (AST.extract (!.ctxt R.XER) 1 29) + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! src) + !!ir (t2 := xerCA) + !!ir (t3 := t1 .+ t2) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let andx ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let andc ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let andidot ins insLen ctxt = + let struct (dst, src, uimm) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let andisdot ins insLen ctxt = + let struct (dst, src, uimm) = transThreeOprs ins ctxt + let uimm = uimm << numI32 16 32 + let ir = !*ctxt + !ir insLen + +let b ins insLen ctxt lk = + let addr = transOneOpr ins ctxt + let ir = !*ctxt + let lr = !.ctxt R.LR + ! .+ numI32 4 32) + !!ir (AST.interjmp addr InterJmpKind.Base) + !>ir insLen + +let bc ins insLen ctxt aa lk = + let struct (bo, cr, addr) = transBranchThreeOprs ins ctxt + let ir = !*ctxt + let lr = !.ctxt R.LR + let ctr = !.ctxt R.CTR + let bo0 = numU32 ((bo >>> 4) &&& 1u) 1 + let bo1 = numU32 ((bo >>> 3) &&& 1u) 1 + let bo2 = numU32 ((bo >>> 2) &&& 1u) 1 + let bo3 = numU32 ((bo >>> 1) &&& 1u) 1 + let ctrOk = !+ir 1 + let condOk = !+ir 1 + let cia = numU64 ins.Address 32 + let nia = cia .+ numI32 4 32 + let temp = !+ir 32 + !>> 2) &&& 1u = 1u) then ctr else (ctr .- AST.num1 32)) + !!ir (ctrOk := bo2 .| ((ctr != AST.num0 32) <+> bo3)) + !!ir (condOk := bo0 .| (cr <+> AST.not bo1)) + if aa then !!ir (temp := AST.ite (ctrOk .& condOk) addr nia) + else !!ir (temp := AST.ite (ctrOk .& condOk) (cia .+ addr) nia) + !!ir (AST.interjmp temp InterJmpKind.Base) + !>ir insLen + +let bclr ins insLen ctxt lk = + let struct (bo, cr) = transBranchTwoOprs ins ctxt + let ir = !*ctxt + let lr = !.ctxt R.LR + let ctr = !.ctxt R.CTR + let bo0 = numU32 ((bo >>> 4) &&& 1u) 1 + let bo1 = numU32 ((bo >>> 3) &&& 1u) 1 + let bo2 = numU32 ((bo >>> 2) &&& 1u) 1 + let bo3 = numU32 ((bo >>> 1) &&& 1u) 1 + let ctrOk = !+ir 1 + let condOk = !+ir 1 + let cia = numU64 ins.Address 32 + let nia = cia .+ numI32 4 32 + let temp = !+ir 32 + !>> 2) &&& 1u = 1u) then ctr else (ctr .- AST.num1 32)) + !!ir (ctrOk := bo2 .| ((ctr != AST.num0 32) <+> bo3)) + !!ir (condOk := bo0 .| (cr <+> AST.not bo1)) + !!ir (temp := AST.ite (ctrOk .& condOk) (lr .& numI32 0xfffffffc 32) nia) + if lk then !!ir (lr := AST.ite (ctrOk .& condOk) nia lr) + !!ir (AST.interjmp temp InterJmpKind.Base) + !>ir insLen + +let bcctr ins insLen ctxt lk = + let struct (bo, cr) = transBranchTwoOprs ins ctxt + let ir = !*ctxt + let lr = !.ctxt R.LR + let ctr = !.ctxt R.CTR + let bo0 = numU32 ((bo >>> 4) &&& 1u) 1 + let bo1 = numU32 ((bo >>> 3) &&& 1u) 1 + let condOk = !+ir 1 + let cia = numU64 ins.Address 32 + let nia = cia .+ numI32 4 32 + let temp = !+ir 32 + ! AST.not bo1)) + !!ir (temp := AST.ite condOk (ctr .& numI32 0xfffffffc 32) nia) + if lk then !!ir (lr := AST.ite condOk nia lr) + !!ir (AST.interjmp temp InterJmpKind.Base) + !>ir insLen + +let cmp ins insLen ctxt = + let struct ((crf0, crf1, crf2, crf3), ra, rb) = transCmpOprs ins ctxt + let cond1 = ra ?< rb + let cond2 = ra ?> rb + let xer = !.ctxt R.XER + let ir = !*ctxt + ! xer) + !>ir insLen + +let cmpl ins insLen ctxt = + let struct ((crf0, crf1, crf2, crf3), ra, rb) = transCmpOprs ins ctxt + let cond1 = ra .< rb + let cond2 = ra .> rb + let xer = !.ctxt R.XER + let ir = !*ctxt + ! xer) + !>ir insLen + +let cmpli ins insLen ctxt = + let struct ((crf0, crf1, crf2, crf3), ra, uimm) = transCmpOprs ins ctxt + let cond1 = ra .< uimm + let cond2 = ra .> uimm + let xer = !.ctxt R.XER + let ir = !*ctxt + ! xer) + !>ir insLen + +let cntlzw ins insLen updateCond ctxt = + let struct (ra, rs) = transTwoOprs ins ctxt + let ir = !*ctxt + let mask1 = numI32 0x55555555 32 + let mask2 = numI32 0x33333333 32 + let mask3 = numI32 0x0f0f0f0f 32 + ! + !!ir (x := rs) + !!ir (x := x .| (x >> numI32 1 32)) + !!ir (x := x .| (x >> numI32 2 32)) + !!ir (x := x .| (x >> numI32 4 32)) + !!ir (x := x .| (x >> numI32 8 32)) + !!ir (x := x .| (x >> numI32 16 32)) + !!ir (x := x .- ((x >> numI32 1 32) .& mask1)) + !!ir (x := ((x >> numI32 2 32) .& mask2) .+ (x .& mask2)) + !!ir (x := ((x >> numI32 4 32) .+ x) .& mask3) + !!ir (x := x .+ (x >> numI32 8 32)) + !!ir (x := x .+ (x >> numI32 16 32)) + !!ir (ra := numI32 32 32 .- (x .& numI32 63 32)) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let crclr ins insLen ctxt = + let crbd = transOneOpr ins ctxt + let ir = !*ctxt + !ir insLen + +let cror ins insLen ctxt = + let struct (crbD, crbA, crbB) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let crorc ins insLen ctxt = + let struct (crbD, crbA, crbB) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let creqv ins insLen ctxt = + let struct (crbD, crbA, crbB) = transThreeOprs ins ctxt + let ir = !*ctxt + ! AST.not(crbB)) + !>ir insLen + +let crset ins insLen ctxt = + let crbD = transOneOpr ins ctxt + let ir = !*ctxt + ! AST.not(crbD)) + !>ir insLen + +let crnand ins insLen ctxt = + let struct (crbD, crbA, crbB) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let crnor ins insLen ctxt = + let struct (crbD, crbA, crbB) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let crnot ins insLen ctxt = + let struct (crbD, crbA) = transTwoOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let crxor ins insLen ctxt = + let struct (crbD, crbA, crbB) = transThreeOprs ins ctxt + let ir = !*ctxt + ! crbB) + !>ir insLen + +let divw ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !) dst (src1 ?/ src2)) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let divwu ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !) dst (src1 ./ src2)) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let extsb ins insLen updateCond ctxt = + let struct (ra, rs) = transTwoOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 8 + ! rs) + !!ir (ra := AST.sext 32 tmp) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let extsh ins insLen updateCond ctxt = + let struct (ra, rs) = transTwoOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 16 + ! rs) + !!ir (ra := AST.sext 32 tmp) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let eqvx ins insLen updateCond ctxt = + let struct (ra, rs, rb) = transThreeOprs ins ctxt + let ir = !*ctxt + ! rb)) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let fabs ins insLen updateCond ctxt = + let struct (frd, frb) = transTwoOprs ins ctxt + let ir = !*ctxt + !) + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fAddOrSub ins insLen updateCond isDouble fnOp ctxt = + let struct (frd, fra, frb) = transThreeOprs ins ctxt + let ir = !*ctxt + ! fra + let frb = AST.cast CastKind.FloatCast 32 frb + !!ir (frd := AST.cast CastKind.FloatCast 64 (fnOp fra frb)) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fadd ins insLen updateCond isDouble ctxt = + fAddOrSub ins insLen updateCond isDouble AST.fadd ctxt + +let fcmp ins insLen ctxt isOrdered = + let struct ((crf0, crf1, crf2, crf3), fra, frb) = transCmpOprs ins ctxt + let fpscr = !.ctxt R.FPSCR + let vxsnan = AST.extract fpscr 1 24 + let vxvc = AST.extract fpscr 1 19 + let fl = AST.extract fpscr 1 15 + let fg = AST.extract fpscr 1 14 + let fe = AST.extract fpscr 1 13 + let fu = AST.extract fpscr 1 12 + let ve = AST.extract fpscr 1 7 + let cond1 = AST.flt fra frb + let cond2 = AST.fgt fra frb + let cond3 = (IEEE754Double.isSNaN fra) .| (IEEE754Double.isSNaN frb) + let cond4 = (IEEE754Double.isQNaN fra) .| (IEEE754Double.isQNaN frb) + let ir = !*ctxt + let nanFlag = !+ir 1 + let lblNan = !%ir "NaN" + let lblRegular = !%ir "Regular" + let lblEnd = !%ir "End" + !ir insLen + +let fcmpo ins insLen ctxt = + fcmp ins insLen ctxt true + +let fcmpu ins insLen ctxt = + fcmp ins insLen ctxt false + +let fdiv ins insLen updateCond isDouble ctxt = + let struct (frd, fra, frb) = transThreeOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 32 + ! fra + let frbS = AST.cast CastKind.FloatCast 32 frb + !!ir (tmp := AST.fdiv fraS frbS) + !!ir (frd := AST.cast CastKind.FloatCast 64 tmp) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let frsp ins insLen updateCond ctxt = + let ir = !*ctxt + let struct (frd, frb) = transTwoOprs ins ctxt + ! frb + !!ir (frd := AST.cast CastKind.FloatCast 64 single) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fsub ins insLen updateCond isDouble ctxt = + fAddOrSub ins insLen updateCond isDouble AST.fsub ctxt + +let fsqrt ins insLen updateCond isDouble ctxt = + let ir = !*ctxt + let struct (frd, frb) = transTwoOprs ins ctxt + let tmp = !+ir 32 + ! frb + !!ir (tmp := AST.fsqrt frbS) + !!ir (frd := AST.cast CastKind.FloatCast 64 tmp) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fctiw ins insLen updateCond ctxt = + let ir = !*ctxt + let tmp = !+ir 64 + let struct (frd, frb) = transTwoOprs ins ctxt + !ir insLen + +let fctiwz ins insLen updateCond ctxt = + let ir = !*ctxt + let intMaxInFloat = numU64 0x41dfffffffc00000uL 64 + let intMinInFloat = numU64 0xc1e0000000000000uL 64 + let intMax = numU64 0x7fffffffUL 64 + let intMin = numU64 0x80000000UL 64 + let struct (frd, frb) = transTwoOprs ins ctxt + ! frb) + !!ir (frd := AST.ite (IEEE754Double.isNaN frb) intMin frd) + !!ir (frd := AST.ite (AST.fle frb intMinInFloat) intMin frd) + !!ir (frd := AST.ite (AST.fge frb intMaxInFloat) intMax frd) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fmadd ins insLen updateCond isDouble ctxt = + let struct (frd, fra, frc, frb) = transFourOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 32 + ! fra + let frbS = AST.cast CastKind.FloatCast 32 frb + let frcS = AST.cast CastKind.FloatCast 32 frc + !!ir (tmp := AST.fadd (AST.fmul fraS frcS) frbS) + !!ir (frd := AST.cast CastKind.FloatCast 64 tmp) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fmr ins insLen updateCond ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let fmsub ins insLen updateCond isDouble ctxt = + let struct (frd, fra, frc, frb) = transFourOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 32 + ! fra + let frbS = AST.cast CastKind.FloatCast 32 frb + let frcS = AST.cast CastKind.FloatCast 32 frc + !!ir (tmp := AST.fsub (AST.fmul fraS frcS) frbS) + !!ir (frd := AST.cast CastKind.FloatCast 64 tmp) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fmul ins insLen updateCond isDouble ctxt = + let struct (frd, fra, frb) = transThreeOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 32 + ! fra + let frbS = AST.cast CastKind.FloatCast 32 frb + !!ir (tmp := AST.fmul fraS frbS) + !!ir (frd := AST.cast CastKind.FloatCast 64 tmp) + setFPRF ctxt ir frd + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fnabs ins insLen updateCond ctxt = + let struct (frd, frb) = transTwoOprs ins ctxt + let ir = !*ctxt + !) + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fneg ins insLen updateCond ctxt = + let struct (frd, frb) = transTwoOprs ins ctxt + let ir = !*ctxt + ! + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fnmadd ins insLen updateCond isDouble ctxt = + let struct (frd, fra, frc, frb) = transFourOprs ins ctxt + let ir = !*ctxt + ! + !!ir (res := (AST.fadd (AST.fmul fra frc) frb)) + floatingNeg ir frd res 64 + else + let res = !+ir 32 + let nres = !+ir 32 + let fraS = AST.cast CastKind.FloatCast 32 fra + let frcS = AST.cast CastKind.FloatCast 32 frc + let frbS = AST.cast CastKind.FloatCast 32 frb + !!ir (res := (AST.fadd (AST.fmul fraS frcS) frbS)) + floatingNeg ir nres res 32 + !!ir (frd := AST.cast CastKind.FloatCast 64 nres) + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fnmsub ins insLen updateCond isDouble ctxt = + let struct (frd, fra, frc, frb) = transFourOprs ins ctxt + let ir = !*ctxt + ! + !!ir (res := (AST.fsub (AST.fmul fra frc) frb)) + floatingNeg ir frd res 64 + else + let res = !+ir 32 + let nres = !+ir 32 + let fraS = AST.cast CastKind.FloatCast 32 fra + let frcS = AST.cast CastKind.FloatCast 32 frc + let frbS = AST.cast CastKind.FloatCast 32 frb + !!ir (res := (AST.fadd (AST.fmul fraS frcS) frbS)) + floatingNeg ir nres res 32 + !!ir (frd := AST.cast CastKind.FloatCast 64 nres) + if updateCond then setCR1Reg ctxt ir else () + !>ir insLen + +let fsel ins insLen updateCond ctxt = + let struct(frd, fra, frc, frb) = transFourOprs ins ctxt + let ir = !*ctxt + let cond = AST.fge fra (AST.num0 64) + !ir insLen + +let lbz ins insLen (ctxt: TranslationContext) = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let dst = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 8 tmpEA)) + !>ir insLen + +let lbzu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let rd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 8 tmpEA)) + !!ir (ra := tmpEA) + !>ir insLen + +let lbzux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let struct (ea, ra) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 8 tmpEA)) + !!ir (ra := tmpEA) + !>ir insLen + +let lbzx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 8 tmpEA)) + !>ir insLen + +let lfd ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let dst = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !>ir insLen + +let lfdu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let dst = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !!ir (ra := tmpEA) + !>ir insLen + +let lfdux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let dst = transOpr ctxt o1 + let struct (ea, ra) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !!ir (ra := tmpEA) + !>ir insLen + +let lfdx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let dst = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !>ir insLen + +let lfs ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let dst = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + let v = loadNative ctxt 32 tmpEA + ! v) + !>ir insLen + +let lfsu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let frd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + let v = loadNative ctxt 32 tmpEA + ! v) + !!ir (ra := tmpEA) + !>ir insLen + +let lfsux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let frd = transOpr ctxt o1 + let struct (ea, ra) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + let v = loadNative ctxt 32 tmpEA + ! v) + !!ir (ra := tmpEA) + !>ir insLen + +let lfsx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let frd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + let v = loadNative ctxt 32 tmpEA + ! v) + !>ir insLen + +let lha ins insLen (ctxt: TranslationContext) = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let rd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !>ir insLen + +let lhau ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let rd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !!ir (ra := tmpEA) + !>ir insLen + +let lhaux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let struct (ea, ra) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !!ir (ra := tmpEA) + !>ir insLen + +let lhax ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !>ir insLen + +let lhbrx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + let tmpMem = !+ir 16 + let revtmp = !+ir 16 + ! tmpEA) + !!ir (AST.xthi 8 revtmp := AST.xtlo 8 tmpMem) + !!ir (AST.xtlo 8 revtmp := AST.xthi 8 tmpMem) + !!ir (rd := AST.zext 32 revtmp) + !>ir insLen + +let lhz ins insLen (ctxt: TranslationContext) = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let rd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !>ir insLen + +let lhzu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let rd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !!ir (ra := ea) + !>ir insLen + +let lhzux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !!ir (rA := tmpEA) + !>ir insLen + +let lhzx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! (loadNative ctxt 16 tmpEA)) + !>ir insLen + +let li ins insLen ctxt = + let struct (dst, simm) = transTwoOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let lis ins insLen ctxt = + let struct (dst, simm) = transTwoOprs ins ctxt + let simm = AST.concat (AST.xtlo 16 simm) (AST.num0 16) + let ir = !*ctxt + !ir insLen + +let lwarx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + !) + !!ir (rd := loadNative ctxt 32 tmpEA) + !>ir insLen + +let lwbrx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + let tmpMem = !+ir 32 + ! tmpEA) + !!ir (AST.extract rd 8 0 := AST.extract tmpMem 8 24) + !!ir (AST.extract rd 8 8 := AST.extract tmpMem 8 16) + !!ir (AST.extract rd 8 16 := AST.extract tmpMem 8 8) + !!ir (AST.extract rd 8 24 := AST.extract tmpMem 8 0) + !>ir insLen + +let lwz ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let dst = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !>ir insLen + +let lwzu ins insLen ctxt = + let struct (o1 , o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let rd = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !!ir (ra := tmpEA) + !>ir insLen + +let lwzux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let struct (ea, ra) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !!ir (ra := tmpEA) + !>ir insLen + +let lwzx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rd = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA) + !>ir insLen + +let mcrf ins insLen ctxt = + let struct ((crd0, crd1, crd2, crd3), + (crs0, crs1, crs2, crs3)) = transCondTwoOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let mcrxr ins insLen ctxt = + let crd0, crd1, crd2, crd3 = transCondOneOpr ins ctxt + let ir = !*ctxt + let xer = !.ctxt R.XER + ! 31) + !!ir (crd1 := AST.extract xer 1 30) + !!ir (crd2 := AST.extract xer 1 29) + !!ir (crd3 := AST.extract xer 1 28) + !!ir (xer := xer .& numI32 0x0fffffff 32) + !>ir insLen + +let mfcr ins insLen ctxt = + let dst = transOneOpr ins ctxt + let ir = !*ctxt + let cr = !+ir 32 + !ir insLen + +let mfctr ins insLen ctxt = + let dst = transOneOpr ins ctxt + let ctr = !.ctxt R.CTR + let ir = !*ctxt + !ir insLen + +let mffs ins insLen ctxt = + let dst = transOneOpr ins ctxt + let fpscr = !.ctxt R.FPSCR + let ir = !*ctxt + ! fpscr) + !>ir insLen + +let mflr ins insLen ctxt = + let dst = transOneOpr ins ctxt + let lr = !.ctxt R.LR + let ir = !*ctxt + !ir insLen + +let mfspr ins insLen ctxt = + let struct (dst, spr) = + match ins.Operands with + | TwoOperands (o1, OprImm o2) -> + transOpr ctxt o1, getSPRReg ctxt o2 + | _ -> raise InvalidOperandException + let ir = !*ctxt + !ir insLen + +let mfxer ins insLen ctxt = + let dst = transOneOpr ins ctxt + let xer = !.ctxt R.XER + let ir = !*ctxt + !ir insLen + +let mr ins insLen ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let mtctr ins insLen ctxt = + let src = transOneOpr ins ctxt + let ctr = !.ctxt R.CTR + let ir = !*ctxt + !ir insLen + +let mtfsfi ins insLen updateCond ctxt = + let struct (crfd, imm) = getTwoOprs ins + let crfd = crfd |> getImmValue |> int + let pos = 4 * (7 - crfd) + let imm = transOpr ctxt imm + let fpscr = !.ctxt R.FPSCR + let ir = !*ctxt + ! 31 := AST.extract imm 1 3) + !!ir (AST.extract fpscr 1 28 := AST.extract imm 1 0) + else + !!ir (AST.extract fpscr 1 (pos + 3) := AST.extract imm 1 3) + !!ir (AST.extract fpscr 1 (pos + 2) := AST.extract imm 1 2) + !!ir (AST.extract fpscr 1 (pos+ 1) := AST.extract imm 1 1) + !!ir (AST.extract fpscr 1 pos := AST.extract imm 1 0) + !>ir insLen + +let mtspr ins insLen ctxt = + let struct (spr, rs) = + match ins.Operands with + | TwoOperands (OprImm o1, o2) -> + getSPRReg ctxt o1, transOpr ctxt o2 + | _ -> raise InvalidOperandException + let ir = !*ctxt + !ir insLen + +let private crmMask ir crm = + let tCrm = Array.init 4 (fun _ -> !+ir 8) + for i in 0..3 do + let cond1 = AST.extract crm 1 (i * 2) + let cond2 = AST.extract crm 1 (i * 2 + 1) + !!ir (tCrm[i] := + AST.ite cond1 (AST.ite cond2 (numI32 0xff 8)(numI32 0xf 8)) + (AST.ite cond2 (numI32 0xf0 8) (AST.num0 8))) + tCrm |> AST.concatArr + +let mtcrf ins insLen ctxt = + let struct (crm, rs) = transTwoOprs ins ctxt + let ir = !*ctxt + let mask = !+ir 32 + let cr = !+ir 32 + !ir insLen + +let mtlr ins insLen ctxt = + let src = transOneOpr ins ctxt + let lr = !.ctxt R.LR + let ir = !*ctxt + !ir insLen + +let mtfsb0 ins insLen updateCond ctxt = + let crbD = getOneOpr ins |> getImmValue |> int + let fpscr = !.ctxt R.FPSCR + let ir = !*ctxt + ! 1 && crbD <> 2 then + !!ir (AST.extract fpscr 1 (31 - crbD) := AST.b0) + if updateCond then setCR1Reg ctxt ir else () + (* Affected: FX *) + !>ir insLen + +let mtfsb1 ins insLen updateCond ctxt = + let crbD = getOneOpr ins |> getImmValue |> int + let fpscr = !.ctxt R.FPSCR + let ir = !*ctxt + ! 1 && crbD <> 2 then + !!ir (AST.extract fpscr 1 (31 - crbD) := AST.b1) + if updateCond then setCR1Reg ctxt ir else () + (* Affected: FX *) + !>ir insLen + +let mtfsf ins insLen ctxt = + let struct (fm, frB) = getTwoOprs ins + let frB = transOpr ctxt frB + let fm = BitVector.OfUInt32 (getImmValue fm) 32 |> AST.num + let fpscr = !.ctxt R.FPSCR + let ir = !*ctxt + ! frB .& fm) + !>ir insLen + +let mtxer ins insLen ctxt = + let src = transOneOpr ins ctxt + let xer = !.ctxt R.XER + let ir = !*ctxt + !ir insLen + +let mulhw ins insLen updateCond ctxt = + let struct (dst, ra, rb) = transThreeOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 64 + ! ra) .* (AST.sext 64 rb)) + !!ir (dst := AST.xthi 32 tmp) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let mulhwu ins insLen updateCond ctxt = + let struct (dst, ra, rb) = transThreeOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 64 + ! ra) .* (AST.zext 64 rb)) + !!ir (dst := AST.xthi 32 tmp) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let mulli ins insLen ctxt = + let struct (dst, ra, simm) = transThreeOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 64 + ! ra) .* (AST.sext 64 simm)) + !!ir (dst := AST.xtlo 32 tmp) + !>ir insLen + +let mullw ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + let tmp = !+ir 64 + ! src1) .* (AST.sext 64 src2)) + !!ir (dst := AST.xtlo 32 tmp) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let nand ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let neg ins insLen updateCond ovCond ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let ir = !*ctxt + let struct (t1, t2) = tmpVars2 ir 32 + !) + !!ir (dst := t1 .+ t2) + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let nor ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let nop insLen ctxt = + let ir = !*ctxt + !ir insLen + +let orx ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let orc ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + !ir insLen + +let ori ins insLen ctxt = + let struct (dst, src, uimm) = transThreeOprs ins ctxt + let uimm = AST.zext 32 (AST.xtlo 16 uimm) + let ir = !*ctxt + !ir insLen + +let oris ins insLen ctxt = + let struct (dst, src, uimm) = transThreeOprs ins ctxt + let uimm = AST.concat (AST.xtlo 16 uimm) (AST.num0 16) + let ir = !*ctxt + !ir insLen + +let rlwinm ins insLen updateCond ctxt = + let struct (ra, rs, sh, mb, me) = transFiveOprs ins ctxt + let ir = !*ctxt + let rol = !+ir 32 + !ir insLen + +let rlwimi ins insLen updateCond ctxt = + let struct (ra, rs, sh, mb, me) = transFiveOprs ins ctxt + let ir = !*ctxt + let m = getExtMask mb me + let rol = rotateLeft rs sh + !ir insLen + +let rlwnm ins insLen updateCond ctxt = + let struct (ra, rs, rb, mb, me) = transFiveOprs ins ctxt + let ir = !*ctxt + let rol = !+ir 32 + !) + !!ir (ra := rol .& (getExtMask mb me)) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let rotlw ins insLen ctxt = + let struct (ra, rs, rb) = transThreeOprs ins ctxt + let ir = !*ctxt + let n = rb .& numI32 0x1f 32 + let rol = rotateLeft rs n + !ir insLen + +let slw ins insLen updateCond ctxt = + let struct (dst, rs, rb) = transThreeOprs ins ctxt + let ir = !*ctxt + let n = !+ir 32 + !) + let z = AST.num0 32 + let cond1 = rb .& numI32 0x20 32 == z + !!ir (dst := AST.ite cond1 (rs << n) (numI32 0 32)) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let sraw ins insLen updateCond ctxt = + let struct (ra, rs, rb) = transThreeOprs ins ctxt + let xerCA = AST.extract (!.ctxt R.XER) 1 29 + let z = AST.num0 32 + let cond1 = rb .& numI32 0x20 32 == z + let ir = !*ctxt + let n = !+ir 32 + !) + !!ir (ra := AST.ite cond1 (rs ?>> n) (rs ?>> numI32 31 32)) + let cond2 = ra ?< z + let cond3 = (rs .& ((AST.num1 32 << n) .- AST.num1 32)) == z + !!ir (xerCA := AST.ite cond2 (AST.ite cond3 AST.b0 AST.b1) AST.b0) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let srawi ins insLen updateCond ctxt = + let struct (ra, rs, sh) = transThreeOprs ins ctxt + let xerCA = AST.extract (!.ctxt R.XER) 1 29 + let z = AST.num0 32 + let ir = !*ctxt + !> sh) + let cond1 = ra ?< z + let cond2 = (rs .& ((AST.num1 32 << sh) .- AST.num1 32)) == z + !!ir (xerCA := AST.ite cond1 (AST.ite cond2 AST.b0 AST.b1) AST.b0) + if updateCond then setCR0Reg ctxt ir ra else () + !>ir insLen + +let srw ins insLen updateCond ctxt = + let struct (dst, rs, rb) = transThreeOprs ins ctxt + let ir = !*ctxt + let n = !+ir 32 + !) + let z = AST.num0 32 + let cond1 = rb .& numI32 0x20 32 == z + !!ir (dst := AST.ite cond1 (rs >> n) (numI32 0 32)) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let stb ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let src = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 8 src) + !>ir insLen + +let stbx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 8 rs) + !>ir insLen + +let stbu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let src = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 8 src) + !!ir (ra := tmpEA) + !>ir insLen + +let stbux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 8 rs) + !!ir (rA := tmpEA) + !>ir insLen + +let stfd ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let frs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := frs) + !>ir insLen + +let stfdx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let ea = transEAWithIndexReg o2 o3 ctxt + let frs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := frs) + !>ir insLen + +let stfdu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let frs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := frs) + !!ir (ra := tmpEA) + !>ir insLen + +let stfdux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let frs = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := frs) + !!ir (rA := tmpEA) + !>ir insLen + +let stfiwx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let frs = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 32 frs) + !!ir (rA := tmpEA) + !>ir insLen + +let stfs ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let frs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.cast CastKind.FloatCast 32 frs) + !>ir insLen + +let stfsx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let ea = transEAWithIndexReg o2 o3 ctxt + let frs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.cast CastKind.FloatCast 32 frs) + !>ir insLen + +let stfsu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let frs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.cast CastKind.FloatCast 32 frs) + !!ir (ra := tmpEA) + !>ir insLen + +let stfsux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let frs = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.cast CastKind.FloatCast 32 frs) + !!ir (rA := tmpEA) + !>ir insLen + +let sth ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let src = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 16 src) + !>ir insLen + +let sthbrx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let revtmp = !+ir 16 + ! 0) (AST.extract rs 8 8)) + !!ir (loadNative ctxt 16 ea := revtmp) + !>ir insLen + +let sthx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 16 rs) + !>ir insLen + +let sthu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let rs = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 16 rs) + !!ir (ra := tmpEA) + !>ir insLen + +let sthux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := AST.xtlo 16 rs) + !!ir (rA := tmpEA) + !>ir insLen + +let stw ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let ea = transEAWithOffset o2 ctxt + let src = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := src) + !>ir insLen + +let stwbrx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + let revtmp = !+ir 32 + ! 0:= AST.extract rs 8 24) + !!ir (AST.extract revtmp 8 8:= AST.extract rs 8 16) + !!ir (AST.extract revtmp 8 16:= AST.extract rs 8 8) + !!ir (AST.extract revtmp 8 24:= AST.extract rs 8 0) + !!ir (loadNative ctxt 32 tmpEA := revtmp) + !>ir insLen + +let stwcxdot ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let res = !.ctxt R.RES + let xerSO = AST.xthi 1 (!.ctxt R.XER) + let cr0LT = !.ctxt R.CR0_0 + let cr0GT = !.ctxt R.CR0_1 + let cr0EQ = !.ctxt R.CR0_2 + let cr0SO = !.ctxt R.CR0_3 + let ir = !*ctxt + ! + !!ir (tmpEA := ea) + !!ir (AST.extCall <| AST.app "IsReserved" [tmpEA] 32) + !!ir (AST.cjmp (res == AST.b1) (AST.name lblRes) (AST.name lblNoRes)) + !!ir (AST.lmark lblRes) + !!ir (loadNative ctxt 32 tmpEA := rs) + !!ir (res := AST.b0) + !!ir (cr0EQ := AST.b1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblNoRes) + !!ir (cr0EQ := AST.b0) + !!ir (AST.lmark lblEnd) + !!ir (cr0LT := AST.b0) + !!ir (cr0GT := AST.b0) + !!ir (cr0SO := xerSO) + !>ir insLen + +let stwu ins insLen ctxt = + let struct (o1, o2) = getTwoOprs ins + let struct (ea, ra) = transEAWithOffsetForUpdate o2 ctxt + let src = transOpr ctxt o1 + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := src) + !!ir (ra := tmpEA) + !>ir insLen + +let stwux ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let struct (ea, rA) = transEAWithIndexRegForUpdate o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := rs) + !!ir (rA := tmpEA) + !>ir insLen + +let stwx ins insLen ctxt = + let struct (o1, o2, o3) = getThreeOprs ins + let rs = transOpr ctxt o1 + let ea = transEAWithIndexReg o2 o3 ctxt + let ir = !*ctxt + let tmpEA = !+ir 32 + ! tmpEA := rs) + !>ir insLen + +let subf ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let one = AST.num1 32 + let ir = !*ctxt + let struct (t1, t2) = tmpVars2 ir 32 + !ir insLen + +let subfc ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let one = AST.num1 64 + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! (AST.not src1)) + !!ir (t2 := AST.zext 64 src2) + !!ir (t3 := t1 .+ t2 .+ one) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let subfe ins insLen updateCond ovCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let xerCA = AST.zext 64 (AST.extract (!.ctxt R.XER) 1 29) + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! (AST.not src1)) + !!ir (t2 := AST.zext 64 src2) + !!ir (t3 := t1 .+ t2 .+ xerCA) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let subfic ins insLen ctxt = + let struct (dst, src1, simm) = transThreeOprs ins ctxt + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! (AST.not src1)) + !!ir (t2 := AST.zext 64 simm) + !!ir (t3 := t1 .+ t2 .+ AST.num1 64) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + !>ir insLen + +let subfme ins insLen updateCond ovCond ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let xerCA = AST.zext 64 (AST.extract (!.ctxt R.XER) 1 29) + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + let minusone = AST.num (BitVector.OfUInt32 0xffffffffu 64) + ! (AST.not src)) + !!ir (t2 := xerCA) + !!ir (t3 := t1 .+ t2 .+ minusone) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let subfze ins insLen updateCond ovCond ctxt = + let struct (dst, src) = transTwoOprs ins ctxt + let xerCA = AST.zext 64 (AST.extract (!.ctxt R.XER) 1 29) + let ir = !*ctxt + let struct (t1, t2, t3) = tmpVars3 ir 64 + ! (AST.not src)) + !!ir (t2 := xerCA) + !!ir (t3 := t1 .+ t2) + !!ir (dst := AST.xtlo 32 t3) + setCarryOut ctxt t3 ir + if ovCond then isAddSubOV ctxt t1 t2 dst ir else () + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let trap insLen ctxt = + let ir = !*ctxt + !ir insLen + +let trapCond ins insLen cmpOp ctxt = + let struct (ra, rb) = transTwoOprs ins ctxt + let ir = !*ctxt + let lblTrap = !%ir "Trap" + let lblEnd = !%ir "End" + !ir insLen + +let xor ins insLen updateCond ctxt = + let struct (dst, src1, src2) = transThreeOprs ins ctxt + let ir = !*ctxt + ! src2)) + if updateCond then setCR0Reg ctxt ir dst else () + !>ir insLen + +let xori ins insLen ctxt = + let struct (dst, src, uimm) = transThreeOprs ins ctxt + let uimm = AST.zext 32 (AST.xtlo 16 uimm) + let ir = !*ctxt + ! uimm) + !>ir insLen + +let xoris ins insLen ctxt = + let struct (dst, src, uimm) = transThreeOprs ins ctxt + let uimm = AST.concat (AST.xtlo 16 uimm) (AST.num0 16) + let ir = !*ctxt + ! uimm) + !>ir insLen + +/// Translate IR. +let translate (ins: InsInfo) insLen (ctxt: TranslationContext) = + match ins.Opcode with + | Op.ADD -> add ins insLen false false ctxt + | Op.ADDdot -> add ins insLen true false ctxt + | Op.ADDO -> add ins insLen false true ctxt + | Op.ADDOdot -> add ins insLen true true ctxt + | Op.ADDC -> addc ins insLen false false ctxt + | Op.ADDCdot -> addc ins insLen true false ctxt + | Op.ADDCO -> add ins insLen false true ctxt + | Op.ADDCOdot -> add ins insLen true true ctxt + | Op.ADDE -> adde ins insLen false false ctxt + | Op.ADDEdot -> adde ins insLen true false ctxt + | Op.ADDEO -> adde ins insLen false true ctxt + | Op.ADDEOdot -> adde ins insLen true true ctxt + | Op.ADDI -> addi ins insLen ctxt + | Op.ADDIC -> addic ins insLen false ctxt + | Op.ADDICdot -> addic ins insLen true ctxt + | Op.ADDIS -> addis ins insLen ctxt + | Op.ADDME -> addme ins insLen false false ctxt + | Op.ADDMEdot -> addme ins insLen true false ctxt + | Op.ADDMEO -> addme ins insLen false true ctxt + | Op.ADDMEOdot -> addme ins insLen true true ctxt + | Op.ADDZE -> addze ins insLen false false ctxt + | Op.ADDZEdot -> addze ins insLen true false ctxt + | Op.ADDZEO -> addze ins insLen false true ctxt + | Op.ADDZEOdot -> addze ins insLen true true ctxt + | Op.AND -> andx ins insLen false ctxt + | Op.ANDdot -> andx ins insLen true ctxt + | Op.ANDC -> andc ins insLen false ctxt + | Op.ANDCdot -> andc ins insLen true ctxt + | Op.ANDIdot -> andidot ins insLen ctxt + | Op.ANDISdot -> andisdot ins insLen ctxt + | Op.B -> b ins insLen ctxt false + | Op.BA -> b ins insLen ctxt false + | Op.BL -> b ins insLen ctxt true + | Op.BLA -> b ins insLen ctxt true + | Op.BC -> bc ins insLen ctxt false false + | Op.BCA -> bc ins insLen ctxt true false + | Op.BCL -> bc ins insLen ctxt false true + | Op.BCLA -> bc ins insLen ctxt true true + | Op.BCCTR -> bcctr ins insLen ctxt false + | Op.BCCTRL -> bcctr ins insLen ctxt true + | Op.BCLR -> bclr ins insLen ctxt false + | Op.BCLRL -> bclr ins insLen ctxt true + | Op.CMPI | Op.CMPL | Op.CMPLI -> raise InvalidOperandException (* invaild *) + | Op.CMP -> cmp ins insLen ctxt + | Op.CMPW -> cmp ins insLen ctxt + | Op.CMPLW -> cmpl ins insLen ctxt + | Op.CMPLWI -> cmpli ins insLen ctxt + | Op.CMPWI -> cmp ins insLen ctxt + | Op.CNTLZW -> cntlzw ins insLen false ctxt + | Op.CNTLZWdot -> cntlzw ins insLen true ctxt + | Op.CRCLR -> crclr ins insLen ctxt + | Op.CREQV -> creqv ins insLen ctxt + | Op.CRXOR -> crxor ins insLen ctxt + | Op.CROR -> cror ins insLen ctxt + | Op.CRORC -> crorc ins insLen ctxt + | Op.CRSET -> crset ins insLen ctxt + | Op.CRNOR -> crnor ins insLen ctxt + | Op.CRNOT -> crnot ins insLen ctxt + | Op.DCBT -> nop insLen ctxt + | Op.DCBTST -> nop insLen ctxt + | Op.DIVW -> divw ins insLen false true ctxt + | Op.DIVWdot -> divw ins insLen false false ctxt + | Op.DIVWO -> divw ins insLen true true ctxt + | Op.DIVWOdot -> divw ins insLen true false ctxt + | Op.DIVWU -> divwu ins insLen false true ctxt + | Op.DIVWUdot -> divwu ins insLen false false ctxt + | Op.DIVWUO -> divwu ins insLen true true ctxt + | Op.DIVWUOdot -> divwu ins insLen true false ctxt + | Op.EXTSB -> extsb ins insLen false ctxt + | Op.EXTSBdot -> extsb ins insLen true ctxt + | Op.EXTSH -> extsh ins insLen false ctxt + | Op.EXTSHdot -> extsh ins insLen true ctxt + | Op.EIEIO -> nop insLen ctxt + | Op.EQV -> eqvx ins insLen false ctxt + | Op.EQVdot -> eqvx ins insLen true ctxt + | Op.FABS -> fabs ins insLen false ctxt + | Op.FABSdot -> fabs ins insLen true ctxt + | Op.FADD -> fadd ins insLen false true ctxt + | Op.FADDS -> fadd ins insLen false false ctxt + | Op.FADDdot -> fadd ins insLen true true ctxt + | Op.FADDSdot -> fadd ins insLen true false ctxt + | Op.FCTIW -> fctiw ins insLen false ctxt + | Op.FCTIWdot -> fctiw ins insLen true ctxt + | Op.FCTIWZ -> fctiwz ins insLen false ctxt + | Op.FCTIWZdot -> fctiwz ins insLen true ctxt + | Op.FCMPO -> fcmpo ins insLen ctxt + | Op.FCMPU -> fcmpu ins insLen ctxt + | Op.FDIV -> fdiv ins insLen false true ctxt + | Op.FDIVS -> fdiv ins insLen false false ctxt + | Op.FDIVdot -> fdiv ins insLen true true ctxt + | Op.FDIVSdot -> fdiv ins insLen true false ctxt + | Op.FRSP -> frsp ins insLen false ctxt + | Op.FRSPdot -> frsp ins insLen true ctxt + | Op.FMADD -> fmadd ins insLen false true ctxt + | Op.FMADDS -> fmadd ins insLen false false ctxt + | Op.FMADDdot -> fmadd ins insLen true true ctxt + | Op.FMADDSdot -> fmadd ins insLen true false ctxt + | Op.FMR -> fmr ins insLen false ctxt + | Op.FMRdot -> fmr ins insLen true ctxt + | Op.FMSUB -> fmsub ins insLen false true ctxt + | Op.FMSUBS -> fmsub ins insLen false false ctxt + | Op.FMSUBdot -> fmsub ins insLen true true ctxt + | Op.FMSUBSdot -> fmsub ins insLen true false ctxt + | Op.FMUL -> fmul ins insLen false true ctxt + | Op.FMULS -> fmul ins insLen false false ctxt + | Op.FMULdot -> fmul ins insLen true true ctxt + | Op.FMULSdot -> fmul ins insLen true false ctxt + | Op.FNABS -> fnabs ins insLen false ctxt + | Op.FNABSdot -> fnabs ins insLen true ctxt + | Op.FNEG -> fneg ins insLen false ctxt + | Op.FNEGdot -> fneg ins insLen true ctxt + | Op.FNMADD -> fnmadd ins insLen false true ctxt + | Op.FNMADDdot -> fnmadd ins insLen true true ctxt + | Op.FNMADDS -> fnmadd ins insLen false false ctxt + | Op.FNMADDSdot -> fnmadd ins insLen true false ctxt + | Op.FNMSUB -> fnmsub ins insLen false true ctxt + | Op.FNMSUBdot -> fnmsub ins insLen true true ctxt + | Op.FNMSUBS -> fnmsub ins insLen false false ctxt + | Op.FNMSUBSdot -> fnmsub ins insLen true false ctxt + | Op.FSEL -> fsel ins insLen false ctxt + | Op.FSELdot -> fsel ins insLen true ctxt + | Op.FSUB -> fsub ins insLen false true ctxt + | Op.FSUBS -> fsub ins insLen false false ctxt + | Op.FSUBdot -> fsub ins insLen true true ctxt + | Op.FSUBSdot -> fsub ins insLen true false ctxt + | Op.FSQRT -> fsqrt ins insLen false true ctxt + | Op.FSQRTS -> fsqrt ins insLen false false ctxt + | Op.FSQRTdot -> fsqrt ins insLen true true ctxt + | Op.FSQRTSdot -> fsqrt ins insLen true false ctxt + | Op.ISYNC | Op.LWSYNC | Op.SYNC -> nop insLen ctxt + | Op.LBZ -> lbz ins insLen ctxt + | Op.LBZU -> lbzu ins insLen ctxt + | Op.LBZUX -> lbzux ins insLen ctxt + | Op.LBZX -> lbzx ins insLen ctxt + | Op.LFD -> lfd ins insLen ctxt + | Op.LFDU -> lfdu ins insLen ctxt + | Op.LFDUX -> lfdux ins insLen ctxt + | Op.LFDX -> lfdx ins insLen ctxt + | Op.LFS -> lfs ins insLen ctxt + | Op.LFSU -> lfsu ins insLen ctxt + | Op.LFSUX -> lfsux ins insLen ctxt + | Op.LFSX -> lfsx ins insLen ctxt + | Op.LHA -> lha ins insLen ctxt + | Op.LHAU -> lhau ins insLen ctxt + | Op.LHAUX ->lhaux ins insLen ctxt + | Op.LHAX -> lhax ins insLen ctxt + | Op.LHBRX -> lhbrx ins insLen ctxt + | Op.LHZ -> lhz ins insLen ctxt + | Op.LHZU -> lhzu ins insLen ctxt + | Op.LHZUX ->lhzux ins insLen ctxt + | Op.LHZX -> lhzx ins insLen ctxt + | Op.LI -> li ins insLen ctxt + | Op.LIS -> lis ins insLen ctxt + | Op.LWARX -> lwarx ins insLen ctxt + | Op.LWBRX -> lwbrx ins insLen ctxt + | Op.LWZ -> lwz ins insLen ctxt + | Op.LWZU -> lwzu ins insLen ctxt + | Op.LWZUX -> lwzux ins insLen ctxt + | Op.LWZX -> lwzx ins insLen ctxt + | Op.MCRF -> mcrf ins insLen ctxt + | Op.MCRXR -> mcrxr ins insLen ctxt + | Op.MFCR -> mfcr ins insLen ctxt + | Op.MFSPR -> mfspr ins insLen ctxt + | Op.MFCTR -> mfctr ins insLen ctxt + | Op.MFFS -> mffs ins insLen ctxt + | Op.MFLR -> mflr ins insLen ctxt + | Op.MFXER -> mfxer ins insLen ctxt + | Op.MR -> mr ins insLen ctxt + | Op.MTCTR -> mtctr ins insLen ctxt + | Op.MTCRF -> mtcrf ins insLen ctxt + | Op.MTFSFI -> mtfsfi ins insLen false ctxt + | Op.MTFSFIdot -> mtfsfi ins insLen true ctxt + | Op.MTSPR -> mtspr ins insLen ctxt + | Op.MTFSB0 -> mtfsb0 ins insLen false ctxt + | Op.MTFSB0dot -> mtfsb0 ins insLen true ctxt + | Op.MTFSB1 -> mtfsb1 ins insLen false ctxt + | Op.MTFSB1dot -> mtfsb1 ins insLen true ctxt + | Op.MTFSF -> mtfsf ins insLen ctxt + | Op.MTLR -> mtlr ins insLen ctxt + | Op.MTXER -> mtxer ins insLen ctxt + | Op.MULHW -> mulhw ins insLen false ctxt + | Op.MULHWU -> mulhwu ins insLen false ctxt + | Op.MULHWUdot -> mulhwu ins insLen true ctxt + | Op.MULLI -> mulli ins insLen ctxt + | Op.MULLW -> mullw ins insLen false false ctxt + | Op.MULLWdot -> mullw ins insLen true false ctxt + | Op.MULLWO -> mullw ins insLen false true ctxt + | Op.MULLWOdot -> mullw ins insLen true true ctxt + | Op.NAND -> nand ins insLen false ctxt + | Op.NANDdot -> nand ins insLen true ctxt + | Op.NEG -> neg ins insLen false false ctxt + | Op.NEGdot -> neg ins insLen true false ctxt + | Op.NEGO -> neg ins insLen false true ctxt + | Op.NEGOdot -> neg ins insLen true true ctxt + | Op.NOR -> nor ins insLen false ctxt + | Op.NORdot -> nor ins insLen true ctxt + | Op.NOP -> nop insLen ctxt + | Op.ORC -> orc ins insLen false ctxt + | Op.ORCdot -> orc ins insLen true ctxt + | Op.OR -> orx ins insLen false ctxt + | Op.ORdot -> orx ins insLen true ctxt + | Op.ORI -> ori ins insLen ctxt + | Op.ORIS -> oris ins insLen ctxt + | Op.RLWIMI -> rlwimi ins insLen false ctxt + | Op.RLWIMIdot -> rlwimi ins insLen true ctxt + | Op.RLWINM -> rlwinm ins insLen false ctxt + | Op.RLWINMdot -> rlwinm ins insLen true ctxt + | Op.RLWNM -> rlwnm ins insLen false ctxt + | Op.RLWNMdot -> rlwnm ins insLen true ctxt + | Op.ROTLW -> rotlw ins insLen ctxt + | Op.SC -> sideEffects insLen ctxt SysCall + | Op.SLW -> slw ins insLen false ctxt + | Op.SLWdot -> slw ins insLen true ctxt + | Op.SRAW -> sraw ins insLen false ctxt + | Op.SRAWdot -> sraw ins insLen true ctxt + | Op.SRAWI -> srawi ins insLen false ctxt + | Op.SRAWIdot -> srawi ins insLen true ctxt + | Op.SRW -> srw ins insLen false ctxt + | Op.SRWdot -> srw ins insLen true ctxt + | Op.STB -> stb ins insLen ctxt + | Op.STBU -> stbu ins insLen ctxt + | Op.STBX -> stbx ins insLen ctxt + | Op.STBUX -> stbux ins insLen ctxt + | Op.STFD -> stfd ins insLen ctxt + | Op.STFDX -> stfdx ins insLen ctxt + | Op.STFDU -> stfdu ins insLen ctxt + | Op.STFDUX -> stfdux ins insLen ctxt + | Op.STFIWX -> stfiwx ins insLen ctxt + | Op.STFS -> stfs ins insLen ctxt + | Op.STFSX -> stfsx ins insLen ctxt + | Op.STFSU -> stfsu ins insLen ctxt + | Op.STFSUX -> stfsux ins insLen ctxt + | Op.STH -> sth ins insLen ctxt + | Op.STHBRX -> sthbrx ins insLen ctxt + | Op.STHU -> sthu ins insLen ctxt + | Op.STHX -> sthx ins insLen ctxt + | Op.STHUX -> sthux ins insLen ctxt + | Op.STW -> stw ins insLen ctxt + | Op.STWBRX -> stwbrx ins insLen ctxt + | Op.STWCXdot -> stwcxdot ins insLen ctxt + | Op.STWU -> stwu ins insLen ctxt + | Op.STWUX -> stwux ins insLen ctxt + | Op.STWX -> stwx ins insLen ctxt + | Op.SUBF -> subf ins insLen false false ctxt + | Op.SUBFdot -> subf ins insLen true false ctxt + | Op.SUBFO -> subf ins insLen false true ctxt + | Op.SUBFOdot -> subf ins insLen true true ctxt + | Op.SUBFC -> subfc ins insLen false false ctxt + | Op.SUBFCdot -> subfc ins insLen true false ctxt + | Op.SUBFCO -> subfc ins insLen false true ctxt + | Op.SUBFCOdot -> subfc ins insLen true true ctxt + | Op.SUBFE -> subfe ins insLen false false ctxt + | Op.SUBFEdot -> subfe ins insLen true false ctxt + | Op.SUBFEO -> subfe ins insLen false true ctxt + | Op.SUBFEOdot -> subfe ins insLen true true ctxt + | Op.SUBFIC -> subfic ins insLen ctxt + | Op.SUBFME -> subfme ins insLen false false ctxt + | Op.SUBFMEdot -> subfme ins insLen true false ctxt + | Op.SUBFMEO -> subfme ins insLen false true ctxt + | Op.SUBFMEOdot -> subfme ins insLen true true ctxt + | Op.SUBFZE -> subfze ins insLen false false ctxt + | Op.SUBFZEdot -> subfze ins insLen true false ctxt + | Op.SUBFZEO -> subfze ins insLen false true ctxt + | Op.SUBFZEOdot -> subfze ins insLen true true ctxt + | Op.TRAP | Op.TWI -> trap insLen ctxt + | Op.TWLT -> trapCond ins insLen (AST.slt) ctxt + | Op.TWLE -> trapCond ins insLen (AST.sle) ctxt + | Op.TWEQ -> trapCond ins insLen (AST.eq) ctxt + | Op.TWGE -> trapCond ins insLen (AST.sge) ctxt + | Op.TWGT -> trapCond ins insLen (AST.sgt) ctxt + | Op.TWNE -> trapCond ins insLen (AST.neq) ctxt + | Op.TWLLT -> trapCond ins insLen (AST.lt) ctxt + | Op.TWLLE -> trapCond ins insLen (AST.le) ctxt + | Op.TWLNL -> trapCond ins insLen (AST.ge) ctxt + | Op.TWLGT -> trapCond ins insLen (AST.gt) ctxt + | Op.TWLTI -> trapCond ins insLen (AST.slt) ctxt + | Op.TWLEI -> trapCond ins insLen (AST.sle) ctxt + | Op.TWEQI -> trapCond ins insLen (AST.eq) ctxt + | Op.TWGEI -> trapCond ins insLen (AST.sge) ctxt + | Op.TWGTI -> trapCond ins insLen (AST.sgt) ctxt + | Op.TWNEI -> trapCond ins insLen (AST.neq) ctxt + | Op.TWLLTI -> trapCond ins insLen (AST.lt) ctxt + | Op.TWLLEI -> trapCond ins insLen (AST.le) ctxt + | Op.TWLNLI -> trapCond ins insLen (AST.ge) ctxt + | Op.TWLGTI -> trapCond ins insLen (AST.gt) ctxt + | Op.XOR -> xor ins insLen false ctxt + | Op.XORdot -> xor ins insLen true ctxt + | Op.XORI -> xori ins insLen ctxt + | Op.XORIS -> xoris ins insLen ctxt + | o -> +#if DEBUG + eprintfn "%A" o +#endif + raise <| NotImplementedIRException (Disasm.opCodeToString o) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/MiddleEnd/DataFlow/UVValue.fs b/src/FrontEnd/BinLifter/PPC32/PPC32OperandHelper.fs similarity index 59% rename from src/MiddleEnd/DataFlow/UVValue.fs rename to src/FrontEnd/BinLifter/PPC32/PPC32OperandHelper.fs index 1f42e372..7e3bf33d 100644 --- a/src/MiddleEnd/DataFlow/UVValue.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32OperandHelper.fs @@ -1,4 +1,4 @@ -(* +(* B2R2 - the Next-Generation Reversing Platform Copyright (c) SoftSec Lab. @ KAIST, since 2016 @@ -22,35 +22,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *) -namespace B2R2.MiddleEnd.DataFlow - -open B2R2 -open B2R2.BinIR.SSA - -type UntouchedTag = - | RegisterTag of Variable - | MemoryTag of Addr - -/// Untouched value propagation value. -type UVValue = - /// Touched means the value is redefined. - | Touched - /// This value is never defined within the function. - | Untouched of UntouchedTag - | Undef - -module UVValue = - - let goingUp fromV toV = - match fromV, toV with - | Untouched _, Undef - | Touched, Undef - | Touched, Untouched _ -> true - | _ -> false - - let meet c1 c2 = - match c1, c2 with - | Undef, c | c, Undef -> c - | Untouched t1, Untouched t2 when t1 = t2 -> c1 - | Untouched _, Untouched _ -> Touched - | _ -> Touched +module internal B2R2.FrontEnd.BinLifter.PPC32.OperandHelper + +let getRegister (n: uint32): Register = + n |> int |> LanguagePrimitives.EnumOfValue + +let getFPRegister (n: uint32): Register = + n + 0x20u |> int |> LanguagePrimitives.EnumOfValue + +let getCondRegister (n: uint32): Register = + n + 0x40u |> int |> LanguagePrimitives.EnumOfValue + +/// Used to specify a CR bit. +let getCRbitRegister (n: uint32): Register = + n + 0x48u |> int |> LanguagePrimitives.EnumOfValue + +/// Used to specify in the FPSCR. +let getFPSCRBit (bin: uint32) = bin |> uint64 |> OprImm + +let getSegRegister (bin: uint32) = bin |> uint64 |> OprImm + +/// UISA SPR Encodings for mfspr. +let getSPRegister (bin: uint32) = bin |> uint64 |> OprImm + +let getTBRRegister (bin: uint32) = bin |> uint64 |> OprImm + diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32Parser.fs b/src/FrontEnd/BinLifter/PPC32/PPC32Parser.fs index 9f5fad6d..4aa875a9 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32Parser.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32Parser.fs @@ -22,2698 +22,25 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.PPC32.Parser +namespace B2R2.FrontEnd.BinLifter.PPC32 +open System open B2R2 open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinLifter.BitData -let getRegister = function - | 0b00000u -> R.R0 - | 0b00001u -> R.R1 - | 0b00010u -> R.R2 - | 0b00011u -> R.R3 - | 0b00100u -> R.R4 - | 0b00101u -> R.R5 - | 0b00110u -> R.R6 - | 0b00111u -> R.R7 - | 0b01000u -> R.R8 - | 0b01001u -> R.R9 - | 0b01010u -> R.R10 - | 0b01011u -> R.R11 - | 0b01100u -> R.R12 - | 0b01101u -> R.R13 - | 0b01110u -> R.R14 - | 0b01111u -> R.R15 - | 0b10000u -> R.R16 - | 0b10001u -> R.R17 - | 0b10010u -> R.R18 - | 0b10011u -> R.R19 - | 0b10100u -> R.R20 - | 0b10101u -> R.R21 - | 0b10110u -> R.R22 - | 0b10111u -> R.R23 - | 0b11000u -> R.R24 - | 0b11001u -> R.R25 - | 0b11010u -> R.R26 - | 0b11011u -> R.R27 - | 0b11100u -> R.R28 - | 0b11101u -> R.R29 - | 0b11110u -> R.R30 - | 0b11111u -> R.R31 - | _ -> raise ParsingFailureException +/// Parser for PPC32 instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type PPC32Parser (isa: ISA) = + let reader = BinReader.Init isa.Endian -let getFPRegister = function - | 0b00000u -> F.F0 - | 0b00001u -> F.F1 - | 0b00010u -> F.F2 - | 0b00011u -> F.F3 - | 0b00100u -> F.F4 - | 0b00101u -> F.F5 - | 0b00110u -> F.F6 - | 0b00111u -> F.F7 - | 0b01000u -> F.F8 - | 0b01001u -> F.F9 - | 0b01010u -> F.F10 - | 0b01011u -> F.F11 - | 0b01100u -> F.F12 - | 0b01101u -> F.F13 - | 0b01110u -> F.F14 - | 0b01111u -> F.F15 - | 0b10000u -> F.F16 - | 0b10001u -> F.F17 - | 0b10010u -> F.F18 - | 0b10011u -> F.F19 - | 0b10100u -> F.F20 - | 0b10101u -> F.F21 - | 0b10110u -> F.F22 - | 0b10111u -> F.F23 - | 0b11000u -> F.F24 - | 0b11001u -> F.F25 - | 0b11010u -> F.F26 - | 0b11011u -> F.F27 - | 0b11100u -> F.F28 - | 0b11101u -> F.F29 - | 0b11110u -> F.F30 - | 0b11111u -> F.F31 - | _ -> raise ParsingFailureException + interface IInstructionParsable with + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader addr :> Instruction -let getCondRegister = function - | 0b000u -> CR.CR0 - | 0b001u -> CR.CR1 - | 0b010u -> CR.CR2 - | 0b011u -> CR.CR3 - | 0b100u -> CR.CR4 - | 0b101u -> CR.CR5 - | 0b110u -> CR.CR6 - | 0b111u -> CR.CR7 - | _ -> raise ParsingFailureException + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader addr :> Instruction -let getCRM bin = bin |> uint64 |> Immediate + member __.MaxInstructionSize = 4 -let getSegRegister bin = bin |> uint64 |> Immediate - -let getSPRegister bin = bin |> uint64 |> Immediate - -let getTBRRegister bin = bin |> uint64 |> Immediate - -let getFPSCRegister bin = bin |> uint64 |> Immediate - -let getFM bin = bin |> uint64 |> Immediate - -let parseTWI bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let value = extract bin 15u 0u |> uint64 |> Immediate - match extract bin 25u 21u with - /// twlgti ra,value = twi 1,ra,value - | 0x1u -> struct (Op.TWLGTI, TwoOperands (ra, value)) - /// twllti ra,value = twi 2,ra,value - | 0x2u -> struct (Op.TWLLTI, TwoOperands (ra, value)) - /// tweqi ra,value = twi 4,ra,value - | 0x4u -> struct (Op.TWEQI, TwoOperands (ra, value)) - /// twlnli ra,value = twi 5,ra,value - | 0x5u -> struct (Op.TWLNLI, TwoOperands (ra, value)) - /// twgti ra,value = twi 8,ra,value - | 0x8u -> struct (Op.TWGTI, TwoOperands (ra, value)) - /// twlti ra,value = twi 16,ra,value - | 0x10u -> struct (Op.TWLTI, TwoOperands (ra, value)) - /// twnei ra,value = twi 24,ra,value - | 0x18u -> struct (Op.TWNEI, TwoOperands (ra, value)) - (* twllei ra,value = twlngi ra, value = twi 6,ra,value - twgei ra,value = twlgei ra, value = twnli ra, value = twi 12,ra,value - twlei ra,value = twngi ra, value = twi 20,ra,value *) - | _ -> - let tO = extract bin 25u 21u |> uint64 |> Immediate - struct (Op.TWI, ThreeOperands (tO, ra, value)) - -let parseMULLI bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let simm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.MULLI, ThreeOperands (rd, ra, simm)) - -let parseSUBFIC bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let simm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.SUBFIC, ThreeOperands (rd, ra, simm)) - -let parseCMPLI bin = - match pickBit bin 22u with - | 0b0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - match pickBit bin 21u with - /// cmplwi crfd,ra,uimm = cmpli crfd,0,ra,uimm - | 0b0u -> struct (Op.CMPLWI, ThreeOperands (crfd, ra, uimm)) - | _ -> struct (Op.CMPLI, FourOperands (crfd, Immediate 1UL, ra, uimm)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCMPI bin = - match pickBit bin 22u with - | 0b0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let simm = extract bin 15u 0u |> uint64 |> Immediate - match pickBit bin 21u with - /// cmpwl crfd,ra,uimm = cmpl crfd,0,ra,uimm - | 0b0u -> struct (Op.CMPWI, ThreeOperands (crfd, ra, simm)) - | _ -> struct (Op.CMPI, FourOperands (crfd, Immediate 1UL, ra, simm)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseADDIC bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let value = extract bin 15u 0u |> uint64 |> Immediate - /// subic rd,ra,value = addic rd,ra,-value - struct (Op.ADDIC, ThreeOperands (rd, ra, value)) - -let parseADDICdot bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let value = extract bin 15u 0u |> uint64 |> Immediate - /// subic. rd,ra,value = addic. rd,ra,-value - struct (Op.ADDICdot, ThreeOperands (rd, ra, value)) - -let parseADDI bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let value = extract bin 15u 0u |> uint64 |> Immediate - match extract bin 20u 16u with - | 0b0u -> struct (Op.LI, TwoOperands (rd, value)) - /// subi rd,ra,value = addi rd,ra,-value - | _ -> - let ra = getRegister (extract bin 20u 16u) |> OpReg - struct (Op.ADDI, ThreeOperands (rd, ra, value)) - -let parseADDIS bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let value = extract bin 15u 0u |> uint64 |> Immediate - match extract bin 20u 16u with - | 0b0u -> struct (Op.LIS, TwoOperands (rd, value)) - /// subis rd,ra,value = addis rd,ra,-value - | _ -> - let ra = getRegister (extract bin 20u 16u) |> OpReg - struct (Op.ADDIS, ThreeOperands (rd, ra, value)) - -let parseBCx bin = - let bd = extract bin 15u 2u |> uint64 |> Immediate - match extract bin 1u 0u (* AA:LK *) with - | 0b00u -> - match extract bin 25u 21u with - /// bdnzf bi,target = bc 0,bi,target - | 0x0u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZF, TwoOperands (bi, bd)) - /// bdzf bi,target = bc 2,bi,target - | 0x2u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZF, TwoOperands (bi, bd)) - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bf 0,target = bnl 0,target = bge target = bc 4,0,target - | 0b00u -> struct (Op.BGE, OneOperand bd) - /// bf 1,target = bng 0,target = ble target = bc 4,1,target - | 0b01u -> struct (Op.BLE, OneOperand bd) - /// bf 2,target = bne target = bc 4,2,target - | 0b10u -> struct (Op.BNE, OneOperand bd) - /// bf 3,target = bnu 0,target = bns target = bc 4,3,target - | _ (* 1 *) -> struct (Op.BNS, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - (* bf 4*crs,target = bnl crs,target = bge crs,target - = bc 4,4*crs,target *) - | 0b00u -> struct (Op.BGE, TwoOperands (crs, bd)) - (* bf 4*crs+1,target = bng crs,target = ble crs,target - = bc 4,4*crs+1,target *) - | 0b01u -> struct (Op.BLE, TwoOperands (crs, bd)) - /// bf 4*crs+2,target = bne crs,target = bc 4,4*crs+2,target - | 0b10u -> struct (Op.BNE, TwoOperands (crs, bd)) - (* bf 4*crs+3,target = bnu crs,target = bns crs,target - = bc 4,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BNS, TwoOperands (crs, bd)) - /// bdnzt bi,target = bc 8,bi,target - | 0x8u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZT, TwoOperands (bi, bd)) - /// bdzt bi,target = bc 10,bi,target - | 0xAu -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZT, TwoOperands (bi, bd)) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bt 0,target = blt target = bc 12,0,target - | 0b00u -> struct (Op.BLT, OneOperand bd) - /// bt 1,0 = bgt target = bc 12,1,target - | 0b01u -> struct (Op.BGT, OneOperand bd) - /// bt 2,0 = beq target = bc 12,2,target - | 0b10u -> struct (Op.BEQ, OneOperand bd) - /// bt 3,0 = bun 0,target = bso target = bc 12,3,target - | _ (* 1 *) -> struct (Op.BSO, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// bt 4*crs,target = blt crs,target = bc 12,4*crs,target - | 0b00u -> struct (Op.BLT, TwoOperands (crs, bd)) - /// bt 4*crs+1,target = bgt crs,target = bc 12,4*crs+1,target - | 0b01u -> struct (Op.BGT, TwoOperands (crs, bd)) - /// bt 4*crs+2,target = beq crs,target = bc 12,4*crs+2,target - | 0b10u -> struct (Op.BEQ, TwoOperands (crs, bd)) - (* bt 4*crs+3,target = bun crs,target = bso crs,target - = bc 12,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BSO, TwoOperands (crs, bd)) - | 0x10u -> - match extract bin 20u 16u with - /// bdnz target = bc 16,0,target - | 0b0u -> struct (Op.BDNZ, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BC, ThreeOperands (bo, bi, bd)) - | 0x12u -> - match extract bin 20u 16u with - /// bdz target = bc 18,0,target - | 0b0u -> struct (Op.BDZ, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BC, ThreeOperands (bo, bi, bd)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BC, ThreeOperands (bo, bi, bd)) - | 0b01u -> - match extract bin 25u 21u with - /// bdnzfl bi,target = bcl 0,bi,target - | 0x0u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZFL, TwoOperands (bi, bd)) - /// bdzfl bi,target = bcl 2,bi,target - | 0x2u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZFL, TwoOperands (bi, bd)) - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bfl 0,target = bnll 0,target = bgel target = bcl 4,0,target - | 0b00u -> struct (Op.BGEL, OneOperand bd) - /// bfl 1,0 = bngl 0,target = blel target = bcl 4,1,target - | 0b01u -> struct (Op.BLEL, OneOperand bd) - /// bfl 2,0 = bnel target = bcl 4,2,target - | 0b10u -> struct (Op.BNEL, OneOperand bd) - /// bfl 3,0 = bnul 0,target = bnsl target = bcl 4,3,target - | _ (* 1 *) -> struct (Op.BNSL, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - (* bfl 4*crs,target = bnll crs,target = bgel crs,target - = bcl 4,4*crs,target *) - | 0b00u -> struct (Op.BGEL, TwoOperands (crs, bd)) - (* bfl 4*crs+1,target = bngl crs,target = blel crs,target - = bcl 4,4*crs+1,target *) - | 0b01u -> struct (Op.BLEL, TwoOperands (crs, bd)) - /// bfl 4*crs+2,target = bnel crs,target = bcl 4,4*crs+2,target - | 0b10u -> struct (Op.BNEL, TwoOperands (crs, bd)) - (*bfl 4*crs+3,target = bnul crs,target = bnsl crs,target - = bcl 4,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BNSL, TwoOperands (crs, bd)) - /// bdnztl bi,target = bc 8,bi,target - | 0x8u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZTL, TwoOperands (bi, bd)) - /// bdztl bi,target = bc 10,bi,target - | 0xAu -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZTL, TwoOperands (bi, bd)) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// btl 0,target = bltl target = bcl 12,0,target - | 0b00u -> struct (Op.BLTL, OneOperand bd) - /// btl 1,target = bgtl target = bcl 12,1,target - | 0b01u -> struct (Op.BGTL, OneOperand bd) - /// btl 2,target = beql target = bcl 12,2,target - | 0b10u -> struct (Op.BEQL, OneOperand bd) - /// btl 3,target = bunl 0,target = bsol target = bcl 12,3,target - | _ (* 1 *) -> struct (Op.BSOL, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// btl 4*crs,target = bltl crs,target = bcl 12,4*crs,target - | 0b00u -> struct (Op.BLTL, TwoOperands (crs, bd)) - /// btl 4*crs+1,target = bgtl crs,target = bcl 12,4*crs+1,target - | 0b01u -> struct (Op.BGTL, TwoOperands (crs, bd)) - /// btl 4*crs+2,target = beql crs,target = bcl 12,4*crs+2,target - | 0b10u -> struct (Op.BEQL, TwoOperands (crs, bd)) - (* btl 4*crs+3,target = bunl crs,target = bsol crs,target - = bcl 12,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BSOL, TwoOperands (crs, bd)) - | 0x10u -> - match extract bin 20u 16u with - /// bdnzl target = bcl 16,0,target - | 0b0u -> struct (Op.BDNZL, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCL, ThreeOperands (bo, bi, bd)) - | 0x12u -> - match extract bin 20u 16u with - /// bdzl target = bcl 18,0,target - | 0b0u -> struct (Op.BDZL, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCL, ThreeOperands (bo, bi, bd)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCL, ThreeOperands (bo, bi, bd)) - | 0b10u -> - match extract bin 25u 21u with - /// bdnzfa bi,target = bca 0,bi,target0 - | 0x0u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZFA, TwoOperands (bi, bd)) - /// bdzfa bi,target = bca 2,bi,target - | 0x2u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZFA, TwoOperands (bi, bd)) - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bfa 0,target = bnla 0,target = bgea target = bca 4,0,target - | 0b00u -> struct (Op.BGEA, OneOperand bd) - /// bfa 1,target = bnga 0,target = blea target = bca 4,1,target - | 0b01u -> struct (Op.BLEA, OneOperand bd) - /// bfa 2,target = bnea target = bca 4,2,target - | 0b10u -> struct (Op.BNEA, OneOperand bd) - /// bfa 3,target = bnua 0,target = bnsa target = bca 4,3,target - | _ (* 1 *) -> struct (Op.BNSA, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - (* bfa 4*crs,target = bnla crs,target = bgea crs,target - = bca 4,4*crs,target *) - | 0b00u -> struct (Op.BGEA, TwoOperands (crs, bd)) - (* bfa 4*crs+1,target = bnga crs,target = blea crs,target - = bca 4,4*crs+1,target *) - | 0b01u -> struct (Op.BLEA, TwoOperands (crs, bd)) - /// bfa 4*crs+2,target = bnea crs,target = bca 4,4*crs+2,target - | 0b10u -> struct (Op.BNEA, TwoOperands (crs, bd)) - (* bfa 4*crs+3,target = bnua crs,target = bnsa crs,target - = bca 4,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BNSA, TwoOperands (crs, bd)) - /// bdnzta bi,target = bc 8,bi,target - | 0x8u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZTA, TwoOperands (bi, bd)) - /// bdzta bi,target = bc 10,bi,target - | 0xAu -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZTA, TwoOperands (bi, bd)) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bta 0,target = blta target = bca 12,0,target - | 0b00u -> struct (Op.BLTA, OneOperand bd) - /// bta 1,target = bgta target = bca 12,1,target - | 0b01u -> struct (Op.BGTA, OneOperand bd) - /// bta 2,target = beqa target = bca 12,2,target - | 0b10u -> struct (Op.BEQA, OneOperand bd) - /// bta 3,target = buna 0,target = bsoa target = bca 12,3,target - | _ (* 1 *) -> struct (Op.BSOA, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// bta 4*crs,target = blta crs,target = bca 12,4*crs,target - | 0b00u -> struct (Op.BLTA, TwoOperands (crs, bd)) - /// bta 4*crs+1,target = bgta crs,target = bca 12,4*crs+1,target - | 0b01u -> struct (Op.BGTA, TwoOperands (crs, bd)) - /// bta 4*crs+2,target = beqa crs,target = bca 12,4*crs+2,target - | 0b10u -> struct (Op.BEQA, TwoOperands (crs, bd)) - (* bta 4*crs+3,target = buna crs,target = bsoa crs,target - = bca 12,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BSOA, TwoOperands (crs, bd)) - | 0x10u -> - match extract bin 20u 16u with - /// bdnza target = bca 16,0,target - | 0b0u -> struct (Op.BDNZA, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCA, ThreeOperands (bo, bi, bd)) - | 0x12u -> - match extract bin 20u 16u with - /// bdza target = bca 18,0,target - | 0b0u -> struct (Op.BDZA, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCA, ThreeOperands (bo, bi, bd)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCA, ThreeOperands (bo, bi, bd)) - | _ (* 11 *) -> - match extract bin 25u 21u with - /// bdnzfla bi,target = bcla 0,bi,target - | 0x0u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZFLA, TwoOperands (bi, bd)) - /// bdzfla bi,target = bcla 2,bi,target - | 0x2u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZFLA, TwoOperands (bi, bd)) - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bfla 0,target = bnlla 0,target = bgela target = bcla 4,0,target - | 0b00u -> struct (Op.BGELA, OneOperand bd) - /// bfla 1,target = bngla 0,target = blela target = bcla 4,1,target - | 0b01u -> struct (Op.BLELA, OneOperand bd) - /// bfla 2,target = bnela target = bcla 4,2,target - | 0b10u -> struct (Op.BNELA, OneOperand bd) - /// bfla 3,target = bnula 0,target = bnsla target = bcla 4,3,target - | _ (* 1 *) -> struct (Op.BNSLA, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - (* bfla 4*crs,target = bnlla crs,target = bgela crs,target - = bcla 4,4*crs,target *) - | 0b00u -> struct (Op.BGELA, TwoOperands (crs, bd)) - (* bfla 4*crs+1,target = bngla crs,target = blela crs,target - = bcla 4,4*crs+1,target *) - | 0b01u -> struct (Op.BLELA, TwoOperands (crs, bd)) - /// bfla 4*crs+2,target = bnela crs,target = bcla 4,4*crs+2,target - | 0b10u -> struct (Op.BNELA, TwoOperands (crs, bd)) - (* bfla 4*crs+3,target = bnula crs,target = bnsla crs,target - = bcla 4,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BNSLA, TwoOperands (crs, bd)) - /// bdnztla bi,target = bc 8,bi,target - | 0x8u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZTLA, TwoOperands (bi, bd)) - /// bdztla bi,target = bc 10,bi,target - | 0xAu -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZTLA, TwoOperands (bi, bd)) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// btla 0,target = bltla target = bcla 12,0,target - | 0b00u -> struct (Op.BLTLA, OneOperand bd) - /// btla 1,target = bgtla target = bcla 12,1,target - | 0b01u -> struct (Op.BGTLA, OneOperand bd) - /// btla 2,target = beqla target = bcla 12,2,target - | 0b10u -> struct (Op.BEQLA, OneOperand bd) - /// btla 3,target = bunla crs,target = bsola target = bcla 12,3,target - | _ (* 1 *) -> struct (Op.BSOLA, OneOperand bd) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// btla 4*crs,target = bltla crs,target = bcla 12,4*crs,target - | 0b00u -> struct (Op.BLTLA, TwoOperands (crs, bd)) - /// btla 4*crs+1,target = bgtla crs,target = bcla 12,4*crs+1,target - | 0b01u -> struct (Op.BGTLA, TwoOperands (crs, bd)) - /// btla 4*crs+2,target = beqla crs,target = bcla 12,4*crs+2,target - | 0b10u -> struct (Op.BEQLA, TwoOperands (crs, bd)) - (* btla 4*crs+3,target = bunla crs,target = bsola crs,target - = bcla 12,4*crs+3,target *) - | _ (* 1 *) -> struct (Op.BSOLA, TwoOperands (crs, bd)) - | 0x10u -> - match extract bin 20u 16u with - /// bdnzla target = bcLA 16,0,target - | 0b0u -> struct (Op.BDNZLA, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLA, ThreeOperands (bo, bi, bd)) - | 0x12u -> - match extract bin 20u 16u with - /// bdzla target = bcLA 18,0,target - | 0b0u -> struct (Op.BDZLA, OneOperand bd) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLA, ThreeOperands (bo, bi, bd)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLA, ThreeOperands (bo, bi, bd)) - -let parseSC bin = - match pickBit bin 1u with - | 0b1u -> struct (Op.SC, NoOperand) - | _ -> raise ParsingFailureException - -let parseBx bin = - let li = extract bin 25u 2u |> uint64 |> Immediate - match extract bin 1u 0u (* AA:LK *) with - | 0b00u -> struct (Op.B, OneOperand li) - | 0b01u -> struct (Op.BL, OneOperand li) - | 0b10u -> struct (Op.BA, OneOperand li) - | _ (* 11 *) -> struct (Op.BLA, OneOperand li) - -let parseMCRF bin = - match pickBit bin 0u with - | 0b0u when concat (extract bin 22u 21u) (extract bin 17u 11u) 2 = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let crfs = getCondRegister (extract bin 20u 18u) |> OpReg - struct (Op.MCRF, TwoOperands (crfd, crfs)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseBCLRx bin = - match pickBit bin 0u with - | 0b0u when extract bin 15u 11u = 0u -> - match extract bin 25u 21u with - /// bdnzflr bi = bclr 0,bi - | 0x0u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZFLR, OneOperand bi) - /// bdzflr bi = bclr 2,bi - | 0x2u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZFLR, OneOperand bi) - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bflr 0 = bnllr 0 = bgelr = bclr 4,0 - | 0b00u -> struct (Op.BGELR, NoOperand) - /// bflr 1 = bnglr 0 = blelr = bclr 4,1 - | 0b01u -> struct (Op.BLELR, NoOperand) - /// bflr 2 = bnelr = bclr 4,2 - | 0b10u -> struct (Op.BNELR, NoOperand) - /// bflr 3 = bnulr 0 = bnslr = bclr 4,3 - | _ (* 1 *) -> struct (Op.BNSLR, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// bflr 4*crs = bnllr crs = bgelr crs = bclr 4,4*crs - | 0b00u -> struct (Op.BGELR, OneOperand crs) - /// bflr 4*crs+1 = bnglr crs = blelr crs = bclr 4,4*crs+1 - | 0b01u -> struct (Op.BLELR, OneOperand crs) - /// bflr 4*crs+2 = bnelr crs = bclr 4,4*crs+2 - | 0b10u -> struct (Op.BNELR, OneOperand crs) - /// bflr 4*crs+3 = bnulr crs = bnslr crs = bclr 4,4*crs+3 - | _ (* 1 *) -> struct (Op.BNSLR, OneOperand crs) - /// bdnztlr bi = bclr 8,bi - | 0x8u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZTLR, OneOperand bi) - /// bdztlr bi = bclr 10,bi - | 0xAu -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZTLR, OneOperand bi) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// btlr 0 = bltlr = bclr 12,0 - | 0b00u -> struct (Op.BLTLR, NoOperand) - /// btlr 1 = bgtlr = bclr 12,1 - | 0b01u -> struct (Op.BGTLR, NoOperand) - /// btlr 2 = beqlr = bclr 12,2 - | 0b10u -> struct (Op.BEQLR, NoOperand) - /// btlr 3 = bunlr 0 = bsolr = bclr 12,3 - | _ (* 1 *) -> struct (Op.BSOLR, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// btlr 4*crs = bltlr crs = bclr 12,4*crs - | 0b00u -> struct (Op.BLTLR, OneOperand crs) - /// btlr 4*crs+1,0 = bgtlr crs = bclr 12,4*crs+1 - | 0b01u -> struct (Op.BGTLR, OneOperand crs) - /// btlr 4*crs+2,0 = beqlr crs = bclr 12,4*crs+2 - | 0b10u -> struct (Op.BEQLR, OneOperand crs) - /// btlr 4*crs+3,0 = bunlr crs = bsolr crs = bclr 12,4*crs+3 - | _ (* 1 *) -> struct (Op.BSOLR, OneOperand crs) - | 0x10u -> - match extract bin 20u 16u with - /// bdnzlr = bclr 16,0 - | 0b0u -> struct (Op.BDNZLR, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLR, TwoOperands (bo, bi)) - | 0x12u -> - match extract bin 20u 16u with - /// bdzlr = bclr 18,0 - | 0b0u -> struct (Op.BDZLR, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLR, TwoOperands (bo, bi)) - | 0x14u -> - match extract bin 20u 16u with - /// blr = bclr 20,0 - | 0b0u -> struct (Op.BLR, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLR, TwoOperands (bo, bi)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLR, TwoOperands (bo, bi)) - | 0b1u when extract bin 15u 11u = 0u -> - match extract bin 25u 21u with - /// bdnzflrl bi = bclrl 0,bi - | 0x0u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZFLRL, OneOperand bi) - /// bdzflrl bi = bclrl 2,bi - | 0x2u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZFLRL, OneOperand bi) - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bflrl 0 = bnllrl 0 = bgelrl = bclrl 4,0 - | 0b00u -> struct (Op.BGELRL, NoOperand) - /// bflrl 1 = bnglrl 0 = blelrl = bclrl 4,1 - | 0b01u -> struct (Op.BLELRL, NoOperand) - /// bflrl 2 = bnelrl = bclrl 4,2 - | 0b10u -> struct (Op.BNELRL, NoOperand) - /// bflrl 3 = bnulrl 0 = bnslrl = bclrl 4,3 - | _ (* 1 *) -> struct (Op.BNSLRL, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// bflrl 4*crs = bnllrl crs = bgelrl crs = bclrl 4,4*crs - | 0b00u -> struct (Op.BGELRL, OneOperand crs) - /// bflrl 4*crs+1 = bnglrl crs = blelrl crs = bclrl 4,4*crs+1 - | 0b01u -> struct (Op.BLELRL, OneOperand crs) - /// bflrl 4*crs+2 = bnelrl crs = bclrl 4,4*crs+2 - | 0b10u -> struct (Op.BNELRL, OneOperand crs) - /// bflrl 4*crs+3 = bnulrl crs = bnslrl crs = bclrl 4,4*crs+3 - | _ (* 1 *) -> struct (Op.BNSLRL, OneOperand crs) - /// bdnztlrl bi = bclrl 8,bi - | 0x8u -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDNZTLRL, OneOperand bi) - /// bdztlrl bi = bclr 10,bi - | 0xAu -> - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BDZTLRL, OneOperand bi) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// btlrl 0 = bltlrl = bclrl 12,0 - | 0b00u -> struct (Op.BLTLRL, NoOperand) - /// btlrl 1 = bgtlrl = bclrl 12,1 - | 0b01u -> struct (Op.BGTLRL, NoOperand) - /// btlrl 2 = beqlrl = bclrl 12,2 - | 0b10u -> struct (Op.BEQLRL, NoOperand) - /// btlrl 3 = bunlrl 0 = bsolrl = bclrl 12,3 - | _ (* 1 *) -> struct (Op.BSOLRL, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// btlrl 4*crs = bltlrl crs = bclrl 12,4*crs - | 0b00u -> struct (Op.BLTLRL, OneOperand crs) - /// btlrl 4*crs+1,0 = bgtlrl crs = bclrl 12,4*crs+1 - | 0b01u -> struct (Op.BGTLRL, OneOperand crs) - /// btlrl 4*crs+2,0 = beqlrl crs = bclrl 12,4*crs+2 - | 0b10u -> struct (Op.BEQLRL, OneOperand crs) - /// btlrl 4*crs+3,0 = bunlrl crs = bsolrl crs = bclrl 12,4*crs+3 - | _ (* 1 *) -> struct (Op.BSOLRL, OneOperand crs) - | 0x10u -> - match extract bin 20u 16u with - /// bdnzlrl = bclrl 16,0 - | 0b0u -> struct (Op.BDNZLRL, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLRL, TwoOperands (bo, bi)) - | 0x12u -> - match extract bin 20u 16u with - /// bdzlrl = bclrl 18,0 - | 0b0u -> struct (Op.BDZLRL, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLRL, TwoOperands (bo, bi)) - | 0x14u -> - match extract bin 20u 16u with - /// blrl = bclrl 20,0 - | 0b0u -> struct (Op.BLRL, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLRL, TwoOperands (bo, bi)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCLRL, TwoOperands (bo, bi)) - | _ -> raise ParsingFailureException - -let parseCRNOR bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - let crba = getFPSCRegister (extract bin 20u 16u) - /// crnot crbd,crba = crnor crbd,crba,crba - if extract bin 20u 16u = extract bin 15u 11u then - struct (Op.CRNOT, TwoOperands (crbd, crba)) - else - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRNOR, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseRFI bin = - match pickBit bin 0u with - | 0b0u when extract bin 25u 11u = 0u -> - struct (Op.RFI, NoOperand) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCRANDC bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRANDC, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseISYNC bin = - match pickBit bin 0u with - | 0b0u when extract bin 25u 11u = 0u -> - struct (Op.ISYNC, NoOperand) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCRXOR bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - /// crclr crbd = crxor crbd,crbd,crbd - if extract bin 25u 21u = extract bin 20u 16u then - if extract bin 20u 16u = extract bin 15u 11u then - struct (Op.CRCLR, OneOperand crbd) - else - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRXOR, ThreeOperands (crbd, crba, crbb)) - else - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRXOR, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCRNAND bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRNAND, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCRAND bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRAND, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCREQV bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - /// crset crbd = creqv crbd,crbd,crbd - if extract bin 25u 21u = extract bin 20u 16u then - if extract bin 20u 16u = extract bin 15u 11u then - struct (Op.CRSET, OneOperand crbd) - else - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CREQV, ThreeOperands (crbd, crba, crbb)) - else - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CREQV, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCRORC bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - let crba = getFPSCRegister (extract bin 20u 16u) - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CRORC, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseCROR bin = - match pickBit bin 0u with - | 0b0u -> - let crbd = getFPSCRegister (extract bin 25u 21u) - let crba = getFPSCRegister (extract bin 20u 16u) - /// crmove crbd,crba = cror crbd,crba,crba - if extract bin 20u 16u = extract bin 15u 11u then - struct (Op.CRMOVE, TwoOperands (crbd, crba)) - else - let crbb = getFPSCRegister (extract bin 15u 11u) - struct (Op.CROR, ThreeOperands (crbd, crba, crbb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseBCCTRx bin = - match pickBit bin 0u with - | 0b0u when extract bin 15u 11u = 0u -> - match extract bin 25u 21u with - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bfctr 0 = bnctr 0 = bgectr = bcctr 4,0 - | 0b00u -> struct (Op.BGECTR, NoOperand) - /// bfctr 1 = bngctr 0 = blectr = bcctr 4,1 - | 0b01u -> struct (Op.BLECTR, NoOperand) - /// bfctr 2 = bnectr = bcctr 4,2 - | 0b10u -> struct (Op.BNECTR, NoOperand) - /// bfctr 3 = bnuctr 0 = bnsctr = bcctr 4,3 - | _ (* 1 *) -> struct (Op.BNSCTR, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// bfctr 4*crs = bnlctr crs = bgectr crs = bcctr 4,4*crs - | 0b00u -> struct (Op.BGECTR, OneOperand crs) - /// bfctr 4*crs+1 = bngctr crs = blectr crs = bcctr 4,4*crs+1 - | 0b01u -> struct (Op.BLECTR, OneOperand crs) - /// bfctr 4*crs+2 = bnectr crs = bcctr 4,4*crs+2 - | 0b10u -> struct (Op.BNECTR, OneOperand crs) - /// bfctr 4*crs+3 = bnuctr crs = bnsctr crs = bcctr 4,4*crs+3 - | _ (* 1 *) -> struct (Op.BNSCTR, OneOperand crs) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// btctr 0 = bltctr = bcctr 12,0 - | 0b00u -> struct (Op.BLTCTR, NoOperand) - /// btctr 1 = bgtctr = bcctr 12,1 - | 0b01u -> struct (Op.BGTCTR, NoOperand) - /// btctr 2 = beqctr = bcctr 12,2 - | 0b10u -> struct (Op.BEQCTR, NoOperand) - /// btctr 3 = bunctr 0 = bsoctr = bcctr 12,3 - | _ (* 1 *) -> struct (Op.BSOCTR, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// btctr 4*crs = bltctr crs = bcctr 12,4*crs - | 0b00u -> struct (Op.BLTCTR, OneOperand crs) - /// btctr 4*crs+1,0 = bgtctr crs = bcctr 12,4*crs+1 - | 0b01u -> struct (Op.BGTCTR, OneOperand crs) - /// btctr 4*crs+2,0 = beqctr crs = bcctr 12,4*crs+2 - | 0b10u -> struct (Op.BEQCTR, OneOperand crs) - /// btctr 4*crs+3,0 = bunctr crs = bsoctr crs = bcctr 12,4*crs+3 - | _ (* 1 *) -> struct (Op.BSOCTR, OneOperand crs) - | 0x14u -> - match extract bin 20u 16u with - /// bctr = bcctr 20,0 - | 0b0u -> struct (Op.BCTR, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCCTR, TwoOperands (bo, bi)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCCTR, TwoOperands (bo, bi)) - | 0b1u when extract bin 15u 11u = 0u -> - match extract bin 25u 21u with - | 0x4u -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// bfctrl 0 = bnctrl 0 = bgectrl = bcctrl 4,0 - | 0b00u -> struct (Op.BGECTRL, NoOperand) - /// bfctrl 1 = bngctrl 0 = blectrl = bcctrl 4,1 - | 0b01u -> struct (Op.BLECTRL, NoOperand) - /// bfctrl 2 = bnectrl = bcctrl 4,2 - | 0b10u -> struct (Op.BNECTRL, NoOperand) - /// bfctrl 3 = bnuctrl 0 = bnsctrl = bcctrl 4,3 - | _ (* 1 *) -> struct (Op.BNSCTRL, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// bfctrl 4*crs = bnlctrl crs = bgectrl crs = bcctrl 4,4*crs - | 0b00u -> struct (Op.BGECTRL, OneOperand crs) - /// bfctrl 4*crs+1 = bngctrl crs = blectrl crs = bcctrl 4,4*crs+1 - | 0b01u -> struct (Op.BLECTRL, OneOperand crs) - /// bfctrl 4*crs+2 = bnectrl crs = bcctrl 4,4*crs+2 - | 0b10u -> struct (Op.BNECTRL, OneOperand crs) - /// bfctrl 4*crs+3 = bnuctrl crs = bnsctrl crs = bcctrl 4,4*crs+3 - | _ (* 1 *) -> struct (Op.BNSCTRL, OneOperand crs) - | 0xCu -> - match extract bin 20u 18u with - | 0b0u -> - match extract bin 17u 16u with - /// btctrl 0 = bltctrl = bcctrl 12,0 - | 0b00u -> struct (Op.BLTCTRL, NoOperand) - /// btctrl 1 = bgtctrl = bcctrl 12,1 - | 0b01u -> struct (Op.BGTCTRL, NoOperand) - /// btctrl 2 = beqctrl = bcctrl 12,2 - | 0b10u -> struct (Op.BEQCTRL, NoOperand) - /// btctrl 3 = bunctrl 0 = bsoctrl = bcctrl 12,3 - | _ (* 1 *) -> struct (Op.BSOCTRL, NoOperand) - | _ -> - let crs = getCondRegister (extract bin 20u 18u) |> OpReg - match extract bin 17u 16u with - /// btctrl 4*crs = bltctrl crs = bcctrl 12,4*crs - | 0b00u -> struct (Op.BLTCTRL, OneOperand crs) - /// btctrl 4*crs+1,0 = bgtctrl crs = bcctrl 12,4*crs+1 - | 0b01u -> struct (Op.BGTCTRL, OneOperand crs) - /// btctrl 4*crs+2,0 = beqctrl crs = bcctrl 12,4*crs+2 - | 0b10u -> struct (Op.BEQCTRL, OneOperand crs) - /// btctrl 4*crs+3,0 = bunctrl crs = bsoctrl crs = bcctrl 12,4*crs+3 - | _ (* 1 *) -> struct (Op.BSOCTRL, OneOperand crs) - | 0x14u -> - match extract bin 20u 16u with - /// bctrl = bcctrl 20,0 - | 0b0u -> struct (Op.BCTRL, NoOperand) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCCTRL, TwoOperands (bo, bi)) - | _ -> - let bo = extract bin 25u 21u |> uint64 |> Immediate - let bi = extract bin 20u 16u |> uint64 |> Branch - struct (Op.BCCTRL, TwoOperands (bo, bi)) - | _ -> raise ParsingFailureException - -let parse13 bin = - match extract bin 10u 1u with - | 0x0u -> parseMCRF bin - | 0x10u -> parseBCLRx bin - | 0x21u -> parseCRNOR bin - | 0x32u -> parseRFI bin - | 0x81u -> parseCRANDC bin - | 0x96u -> parseISYNC bin - | 0xC1u -> parseCRXOR bin - | 0xE1u -> parseCRNAND bin - | 0x101u -> parseCRAND bin - | 0x121u -> parseCREQV bin - | 0x1A1u -> parseCRORC bin - | 0x1C1u -> parseCROR bin - | 0x210u -> parseBCCTRx bin - | _ -> raise ParsingFailureException - -let parseRLWIMIx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let sh = extract bin 15u 11u |> uint64 |> Immediate - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - match pickBit bin 0u with - (* inslwi ra,rs,n,b = rlwimi ra,rs,32-b,b,b+n-1 - insrwi ra,rs,n,b (n>0) = rlwimi ra,rs,32-(b+n),b,(b+n)-1 *) - | 0b0u -> struct (Op.RLWIMI, FiveOperands(ra, rs, sh, mb, me)) - | _ (* 1 *) -> struct (Op.RLWIMIdot, FiveOperands(ra, rs, sh, mb, me)) - -let parseRLWINMx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match pickBit bin 0u with - | 0b0u -> - match extract bin 15u 11u with - | 0b0u when extract bin 5u 1u = 0x1Fu -> - let n = extract bin 15u 11u |> uint64 |> Immediate - match extract bin 10u 6u with - /// slwi ra,rs,0 = rlwinm ra,rs,0,0,31 - | 0x0u -> - struct (Op.SLWI, ThreeOperands(ra, rs, n)) - /// clrlwi ra,rs,n = rlwinm ra,rs,0,n,31 - | _ -> - struct (Op.CLRLWI, ThreeOperands(ra, rs, n)) - | _ -> - match extract bin 10u 6u with - | 0x0u -> - let n = extract bin 15u 11u - /// rotlwi ra,rs,n = rotrwi ra,rs,n = rlwinm ra,rs,n,0,31 - if extract bin 5u 1u = 0x1Fu then - let n = extract bin 15u 11u |> uint64 |> Immediate - struct (Op.ROTLWI, ThreeOperands(ra, rs, n)) - /// slwi ra,rs,n = rlwinm ra,rs,n,0,31-n - elif extract bin 5u 1u = 0x1Fu - n then - let n = extract bin 15u 11u |> uint64 |> Immediate - struct (Op.SLWI, ThreeOperands(ra, rs, n)) - else - let sh = extract bin 15u 11u |> uint64 |> Immediate - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - struct (Op.RLWINM, FiveOperands(ra, rs, sh, mb, me)) - | _ -> - let n = extract bin 10u 6u - if extract bin 15u 11u = 0x20u - n then - match extract bin 5u 1u with - /// srwi ra,rs,n = rlwinm ra,rs,32-n,n,31 - | 0x1Fu -> - let n = extract bin 10u 6u |> uint64 |> Immediate - struct (Op.SRWI, ThreeOperands(ra, rs, n)) - | _ -> - let sh = extract bin 15u 11u |> uint64 |> Immediate - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - struct (Op.RLWINM, FiveOperands(ra, rs, sh, mb, me)) - (* extlwi ra,rs,n,b = rlwinm ra,rs,b,0,n-1, - extrwi ra,rs,n,b = rlwinm ra,rs,b+n,32-n,31 - clrrwi ra,rs,n = rlwinm ra,rs,0,0,31-n - clrlslwi ra,rs,b,n = rlwinm ra,rs,n,b-n,31-n *) - else - let sh = extract bin 15u 11u |> uint64 |> Immediate - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - struct (Op.RLWINM, FiveOperands(ra, rs, sh, mb, me)) - | _ (* 1 *) -> - let sh = extract bin 15u 11u |> uint64 |> Immediate - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - struct (Op.RLWINMdot, FiveOperands(ra, rs, sh, mb, me)) - -let parseRLWNMx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> - match extract bin 10u 1u with - /// rotlw ra,rs,rb = rlwnm ra,rs,rb,mb,me - | 0x1Fu -> struct (Op.ROTLW, ThreeOperands(ra, rs, rb)) - | _ -> - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - struct (Op.RLWNM, FiveOperands(ra, rs, rb, mb, me)) - | _ (* 1 *) -> - let mb = extract bin 10u 6u |> uint64 |> Immediate - let me = extract bin 5u 1u |> uint64 |> Immediate - struct (Op.RLWNMdot, FiveOperands(ra, rs, rb, mb, me)) - -let parseORI bin = - match extract bin 25u 0u with - /// nop = ori 0,0,0 - | 0b0u -> struct (Op.NOP, NoOperand) - | _ -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.ORI, ThreeOperands(rs, ra, uimm)) - -let parseORIS bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.ORIS, ThreeOperands(rs, ra, uimm)) - -let parseXORI bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.XORI, ThreeOperands(rs, ra, uimm)) - -let parseXORIS bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.XORIS, ThreeOperands(rs, ra, uimm)) - -let parseANDIdot bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.ANDIdot, ThreeOperands(rs, ra, uimm)) - -let parseANDISdot bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let uimm = extract bin 15u 0u |> uint64 |> Immediate - struct (Op.ANDISdot, ThreeOperands(rs, ra, uimm)) - -let parseCMPandMCRXR bin = - match pickBit bin 10u with - | 0b0u when pickBit bin 22u = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 21u with - /// cmpw crfd,ra,rb = cmp crfd,0,ra,rb - | 0b0u -> struct (Op.CMPW, ThreeOperands (crfd, ra, rb)) - | _ (* 1 *) -> struct (Op.CMP, FourOperands (crfd, Immediate 1UL, ra, rb)) - | 0b1u when extract bin 22u 11u = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - struct (Op.MCRXR, OneOperand (crfd)) - | _ -> raise ParsingFailureException - -let parseTW bin = - match pickBit bin 10u with - | 0b0u -> - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match extract bin 25u 21u with - /// twlgt ra,rb = tw 1,ra,rb - | 0x1u -> struct (Op.TWLGT, TwoOperands (ra, rb)) - /// twllt ra,rb = tw 2,ra,rb - | 0x2u -> struct (Op.TWLLT, TwoOperands (ra, rb)) - /// tweq ra,rb = tw 4,ra,rb - | 0x4u -> struct (Op.TWEQ, TwoOperands (ra, rb)) - /// twlnl ra,rb = tw 5,ra,rb - | 0x5u -> struct (Op.TWLNL, TwoOperands (ra, rb)) - /// twgt ra,rb = tw 8,ra,rb - | 0x8u -> struct (Op.TWGT, TwoOperands (ra, rb)) - /// twlt ra,rb = tw 16,ra,rb - | 0x10u -> struct (Op.TWLT, TwoOperands (ra, rb)) - /// twne ra,rb = tw 24,ra,rb - | 0x18u -> struct (Op.TWNE, TwoOperands (ra, rb)) - | 0x1Fu -> - match extract bin 20u 11u with - | 0x0u -> struct (Op.TRAP, NoOperand) - (* twlle ra,rb = twlng ra, rb = tw 6,ra,rb - twge ra,rb = twlge ra, rb = twnl ra, rb = tw 12,ra,rb - twle ra,rb = twng ra, rb = tw 20,ra,rb *) - | _ -> - let tO = extract bin 25u 21u |> uint64 |> Immediate - struct (Op.TW, ThreeOperands (tO, ra, rb)) - | _ -> - let tO = extract bin 25u 21u |> uint64 |> Immediate - struct (Op.TW, ThreeOperands (tO, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseSUBFCx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - /// subc rd,ra,rb = subfc rd,rb,ra - | 0b00u -> struct (Op.SUBFC, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.SUBFCdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.SUBFCO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.SUBFCOdot, ThreeOperands (rd, ra, rb)) - -let parseADDCx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.ADDC, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.ADDCdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.ADDCO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.ADDCOdot, ThreeOperands (rd, ra, rb)) - -let parseMULHWUx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.MULHWU, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> struct (Op.MULHWUdot, ThreeOperands (rd, ra, rb)) - -let parseMFCR bin = - match pickBit bin 10u with - | 0b0u when extract bin 20u 11u = 0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.MFCR, OneOperand (rd)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseLWARX bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LWARX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseLSWX bin = - match pickBit bin 10u with - | 0b1u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LSWX, ThreeOperands (rd, ra, rb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseLWBRX bin = - match pickBit bin 10u with - | 0b1u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LWBRX, ThreeOperands (rd, ra, rb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseLWZXandLFSX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.LWZX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.LFSX, ThreeOperands (frd, ra, rb)) - -let parseSLWxandSRWx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u -> struct (Op.SLW, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.SLWdot, ThreeOperands (ra, rs, rb)) - | 0b10u -> struct (Op.SRW, ThreeOperands (ra, rs, rb)) - | _ (* 11 *) -> struct (Op.SRWdot, ThreeOperands (ra, rs, rb)) - -let parseCNTLZWx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u when extract bin 15u 11u = 0u -> - struct (Op.CNTLZW, TwoOperands (ra, rs)) - | 0b01u when extract bin 15u 11u = 0u -> - struct (Op.CNTLZWdot, TwoOperands (ra, rs)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseANDx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u -> struct (Op.AND, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.ANDdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseCMPL bin = - match pickBit bin 10u with - | 0b0u when pickBit bin 22u = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 21u with - /// cmplw crfd,ra,rb = cmpl crfd,0,ra,rb - | 0b0u -> struct (Op.CMPLW, ThreeOperands (crfd, ra, rb)) - | _ (* 1 *)-> struct (Op.CMPL, FourOperands (crfd, Immediate 1UL, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseSUBFx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - /// sub rd,rb,ra = subf rd,ra,rb - | 0b00u -> struct (Op.SUBF, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.SUBFdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.SUBFO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.SUBFOdot, ThreeOperands (rd, ra, rb)) - -let parseDCBSTandTLBSYNC bin = - match pickBit bin 10u with - | 0b0u when extract bin 25u 21u = 0u -> - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.DCBST, TwoOperands (ra, rb)) - | 0b1u when extract bin 25u 11u = 0u -> - struct (Op.TLBSYNC, NoOperand) - | _ -> raise ParsingFailureException - -let parseLWZUXandLFSUX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.LWZUX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.LFSUX, ThreeOperands (frd, ra, rb)) - -let parseANDCx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u -> struct (Op.ANDC, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.ANDCdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseMULHWx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.MULHW, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> struct (Op.MULHWdot, ThreeOperands (rd, ra, rb)) - -let parseMFMSRandMFSR bin = - match pickBit bin 10u with - | 0b0u when extract bin 20u 11u = 0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.MFMSR, OneOperand (rd)) - | 0b1u when (concat (pickBit bin 20u) (extract bin 15u 11u) 1) = 0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - (* FIXME : SegRegister *) - let sr = getSegRegister (extract bin 19u 16u) - struct (Op.MFSR, TwoOperands (sr, rd)) - | _ -> raise ParsingFailureException - -let parseLSWI bin = - match pickBit bin 10u with - | 0b1u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let nb = extract bin 15u 11u |> uint64 |> Immediate - struct (Op.LSWI, ThreeOperands(rd, ra, nb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseDCBFandSYNC bin = - match pickBit bin 10u with - | 0b0u when extract bin 25u 21u = 0u -> - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.DCBF, TwoOperands (ra, rb)) - | 0b1u when extract bin 25u 11u = 0u -> - struct (Op.SYNC, NoOperand) - | _ -> raise ParsingFailureException - -let parseLBZXandLFDX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.LBZX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LFDX, ThreeOperands (frd, ra, rb)) - -let parseNEGx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u when extract bin 15u 11u = 0u -> - struct (Op.NEG, TwoOperands (rd, ra)) - | 0b01u when extract bin 15u 11u = 0u -> - struct (Op.NEGdot, TwoOperands (rd, ra)) - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.NEGO, TwoOperands (rd, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.NEGOdot, TwoOperands (rd, ra)) - | _ -> raise ParsingFailureException - -let parseLBZUXandLFDUX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.LBZUX, ThreeOperands (rd, ra, rb)) - | 0b1u -> - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.LFDUX, ThreeOperands (frd, ra, rb)) - | _ -> raise ParsingFailureException - -let parseNORx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - /// not rd,rs = nor ra,rs,rs - | 0b00u -> struct (Op.NOR, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.NORdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseSUBFEx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.SUBFE, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.SUBFEdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.SUBFEO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.SUBFEOdot, ThreeOperands (rd, ra, rb)) - -let parseADDEx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.ADDE, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.ADDEdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.ADDEO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.ADDEOdot, ThreeOperands (rd, ra, rb)) - -let parseMTCRF bin = - match pickBit bin 10u with - /// mtcr rs = mtcrf 0xff,rs - | 0b0u when concat (pickBit bin 20u) (pickBit bin 11u) 1 = 00u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - (* FIXME : CRM *) - let crm = getCRM (extract bin 19u 12u) - struct (Op.MTCRF, TwoOperands (crm, rs)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseMTMSR bin = - match pickBit bin 10u with - | 0b0u when extract bin 20u 11u = 0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.MFMSR, OneOperand (rs)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseMFSRIN bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b10u when extract bin 20u 16u = 0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.MFSRIN, TwoOperands (rd, rb)) - | _ (* 11, 0x *) -> raise ParsingFailureException - -let parseSTSWX bin = - match pickBit bin 10u with - | 0b1u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.STSWX, ThreeOperands (rs, ra, rb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseSTWCXdotandSTWBRX bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b01u -> struct (Op.STWCXdot, ThreeOperands (rs, ra, rb)) - | 0b10u -> struct (Op.STWBRX, ThreeOperands (rs, ra, rb)) - | _ (* 00, 11 *) -> raise ParsingFailureException - -let parseSTWXandSTFSX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.STWX, ThreeOperands (rs, ra, rb)) - | _ (* 1 *) -> - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.STFSX, ThreeOperands (frs, ra, rb)) - -let parseSTWUXandSTFSUX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.STWUX, ThreeOperands (rs, ra, rb)) - | _ (* 1 *) -> - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.STFSUX, ThreeOperands (frs, ra, rb)) - -let parseSUBFZEx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u when extract bin 15u 11u = 0u -> - struct (Op.SUBFZE, TwoOperands (rd, ra)) - | 0b01u when extract bin 15u 11u = 0u -> - struct (Op.SUBFZEdot, TwoOperands (rd, ra)) - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.SUBFZEO, TwoOperands (rd, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.SUBFZEOdot, TwoOperands (rd, ra)) - | _ -> raise ParsingFailureException - -let parseADDZEx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u when extract bin 15u 11u = 0u -> - struct (Op.ADDZE, TwoOperands (rd, ra)) - | 0b01u when extract bin 15u 11u = 0u -> - struct (Op.ADDZEdot, TwoOperands (rd, ra)) - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.ADDZEO, TwoOperands (rd, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.ADDZEOdot, TwoOperands (rd, ra)) - | _ -> raise ParsingFailureException - -let parseMTSR bin = - match pickBit bin 10u with - | 0b0u when (concat (pickBit bin 20u) (extract bin 15u 11u) 1) = 0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - /// (* FIXME : SegRegister *) - let sr = getSegRegister (extract bin 19u 16u) - struct (Op.MTSR, TwoOperands (sr, rs)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseSTSWI bin = - match pickBit bin 10u with - | 0b1u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let nb = extract bin 15u 11u |> uint64 |> Immediate - struct (Op.STSWI, ThreeOperands (rs, ra, nb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseSTBXandSTFDX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b00u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.STBX, ThreeOperands (rs, ra, rb)) - | 0b10u -> - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.STFDX, ThreeOperands (frs, ra, rb)) - | _ (* 01, 11 *) -> raise ParsingFailureException - -let parseSUBFMEx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u when extract bin 15u 11u = 0u -> - struct (Op.SUBFME, TwoOperands (rd, ra)) - | 0b01u when extract bin 15u 11u = 0u -> - struct (Op.SUBFMEdot, TwoOperands (rd, ra)) - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.SUBFMEO, TwoOperands (rd, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.SUBFMEOdot, TwoOperands (rd, ra)) - | _ -> raise ParsingFailureException - -let parseADDMEx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u when extract bin 15u 11u = 0u -> - struct (Op.ADDME, TwoOperands (rd, ra)) - | 0b01u when extract bin 15u 11u = 0u -> - struct (Op.ADDMEdot, TwoOperands (rd, ra)) - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.ADDMEO, TwoOperands (rd, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.ADDMEOdot, TwoOperands (rd, ra)) - | _ -> raise ParsingFailureException - -let parseMULLWx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.MULLW, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.MULLWdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.MULLWO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.MULLWOdot, ThreeOperands (rd, ra, rb)) - -let parseMTSRIN bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b10u when extract bin 20u 16u = 0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.MTSRIN, TwoOperands (rd, rb)) - | _ (* 11, 0x *) -> raise ParsingFailureException - -let parseDCBTSTandDCBA bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u when extract bin 25u 21u = 0u -> - (* CT = 0u *) - struct (Op.DCBTST, TwoOperands (ra, rb)) - | 0b1u when extract bin 25u 21u = 0u -> - struct (Op.DCBA, TwoOperands (ra, rb)) - | _ -> raise ParsingFailureException - -let parseSTBUXandSTFDUX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b00u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.STBUX, ThreeOperands (rs, ra, rb)) - | 0b10u -> - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - struct (Op.STFDUX, ThreeOperands (frs, ra, rb)) - | _ (* 01, 11 *) -> raise ParsingFailureException - -let parseADDx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.ADD, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.ADDdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.ADDO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.ADDOdot, ThreeOperands (rd, ra, rb)) - -let parseDCBTandLHBRX bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u when extract bin 25u 21u = 0u -> - (* CT = 0u *) - struct (Op.DCBT, TwoOperands (ra, rb)) - | 0b1u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - struct (Op.LHBRX, ThreeOperands (rd, ra, rb)) - | _ -> raise ParsingFailureException - -let parseLHZX bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LHZX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseSRAWx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 1:RC *) with - | 0b10u -> struct (Op.SRAW, ThreeOperands (ra, rs, rb)) - | 0b11u -> struct (Op.SRAWdot, ThreeOperands (ra, rs, rb)) - | _ (* 0x *) -> raise ParsingFailureException - -let parseEQVx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:Rc *) with - | 0b00u -> struct (Op.EQV, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.EQVdot, ThreeOperands (rd, ra, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseTLBIE bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b00u -> - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.TLBIE, OneOperand(rb)) - | _ (* 01, 1x *) -> raise ParsingFailureException - -let parseECIWX bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b00u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.ECIWX, ThreeOperands (rd, ra, rb)) - | _ (* 01, 1x *) -> raise ParsingFailureException - -let parseLHZUX bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LHZUX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseSRAWIx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let sh = extract bin 15u 11u |> uint64 |> Immediate - match pickBit bin 0u with - | 0b0u -> struct (Op.SRAWI, ThreeOperands (rs, ra, sh)) - | _ (* 1 *) -> struct (Op.SRAWIdot, ThreeOperands (rs, ra, sh)) - -let parseXORx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u -> struct (Op.XOR, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.XORdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseMFSPR bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - match concat (extract bin 15u 11u) (extract bin 20u 16u) 5 with - /// mfxer rd = mfspr rd,1 - | 0x1u -> struct (Op.MFXER, OneOperand rd) - /// mflr rd = mfspr rd,8 - | 0x8u -> struct (Op.MFLR, OneOperand rd) - /// mfctr rd = mfspr rd,9 - | 0x9u -> struct (Op.MFCTR, OneOperand rd) - | _ -> - (* FIXME : SPRegister *) - let spr = - getSPRegister (concat (extract bin 15u 11u) (extract bin 20u 16u) 5) - struct (Op.MFSPR, TwoOperands (rd, spr)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseEIEIO bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b10u when extract bin 25u 11u = 0u -> - struct (Op.EIEIO, NoOperand) - | _ (* 11, 0x *) -> raise ParsingFailureException - -let parseLHAX bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LHAX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseTLBIA bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b00u -> - struct (Op.TLBIA, NoOperand) - | _ (* 01, 1x *) -> raise ParsingFailureException - -let parseMFTB bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - (* FIXME : TBRRegister *) - let tbr = - getTBRRegister (concat (extract bin 15u 11u) (extract bin 20u 16u) 5) - match concat (extract bin 15u 11u) (extract bin 20u 16u) 5 with - /// mftbu rd = mftb rd,269 - | 0x10du -> struct (Op.MFTBU, OneOperand rd) - /// mftb rd = mftb rd,268 - | _ -> struct (Op.MFTB, TwoOperands (rd, tbr)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseLHAUX bin = - match pickBit bin 10u with - | 0b0u -> - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.LHAUX, ThreeOperands (rd, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseSTHBRX bin = - match pickBit bin 10u with - | 0b1u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.STHBRX, ThreeOperands (rs, ra, rb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseSTHX bin = - match pickBit bin 10u with - | 0b0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.STHX, ThreeOperands (rs, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseEXTSHx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 1:Rc *) with - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.EXTSH, TwoOperands (rs, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.EXTSHdot, TwoOperands (rs, ra)) - | _ (* 0x *) -> raise ParsingFailureException - -let parseORCx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u -> struct (Op.ORC, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.ORCdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseECOWX bin = - match concat (pickBit bin 10u) (pickBit bin 0u) 1 with - | 0b00u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.ECOWX, ThreeOperands (rs, ra, rb)) - | _ (* 01, 1x *) -> raise ParsingFailureException - -let parseSTHUX bin = - match pickBit bin 10u with - | 0b0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.STHUX, ThreeOperands (rs, ra, rb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseEXTSBx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 1:Rc *) with - | 0b10u when extract bin 15u 11u = 0u -> - struct (Op.EXTSB, TwoOperands (rs, ra)) - | 0b11u when extract bin 15u 11u = 0u -> - struct (Op.EXTSBdot, TwoOperands (rs, ra)) - | _ (* 0x *) -> raise ParsingFailureException - -let parseORx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - /// mr ra,rs = or ra,rs,rs - | 0b00u -> - if extract bin 25u 21u = extract bin 15u 11u then - struct (Op.MR, TwoOperands (ra, rs)) - else - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.OR, ThreeOperands (ra, rs, rb)) - | 0b01u -> - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.ORdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseDIVWUx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.DIVWU, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.DIVWUdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.DIVWUO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.DIVWUOdot, ThreeOperands (rd, ra, rb)) - -let parseMTSPR bin = - match pickBit bin 10u with - | 0b0u -> - let rs = getRegister (extract bin 25u 21u) |> OpReg - match concat (extract bin 15u 11u) (extract bin 20u 16u) 5 with - /// mtxer rd = mtspr rd,1 - | 0x1u -> struct (Op.MTXER, OneOperand rs) - /// mtlr rd = mtspr rd,8 - | 0x8u -> struct (Op.MTLR, OneOperand rs) - /// mtctr rd = mtspr rd,9 - | 0x9u -> struct (Op.MTCTR, OneOperand rs) - | _ -> - (* FIXME : SPRegister *) - let spr = - getSPRegister (concat (extract bin 15u 11u) (extract bin 20u 16u) 5) - struct (Op.MTSPR, TwoOperands (rs, spr)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseDCBIandICBI bin = - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 10u with - | 0b0u when extract bin 25u 21u = 0u -> - struct (Op.DCBI, TwoOperands (ra, rb)) - | 0b1u when extract bin 25u 21u = 0u -> - struct (Op.ICBI, TwoOperands (ra, rb)) - | _ -> raise ParsingFailureException - -let parseSTFIWX bin = - match pickBit bin 10u with - | 0b1u -> - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.STFIWX, ThreeOperands (frs, ra, rb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parseNANDx bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with - | 0b00u -> struct (Op.NAND, ThreeOperands (ra, rs, rb)) - | 0b01u -> struct (Op.NANDdot, ThreeOperands (ra, rs, rb)) - | _ (* 1x *) -> raise ParsingFailureException - -let parseDIVWx bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with - | 0b00u -> struct (Op.DIVW, ThreeOperands (rd, ra, rb)) - | 0b01u -> struct (Op.DIVWdot, ThreeOperands (rd, ra, rb)) - | 0b10u -> struct (Op.DIVWO, ThreeOperands (rd, ra, rb)) - | _ (* 11 *) -> struct (Op.DIVWOdot, ThreeOperands (rd, ra, rb)) - -let parseDCBZ bin = - match pickBit bin 10u with - | 0b1u when extract bin 25u 21u = 0u -> - let ra = getRegister (extract bin 20u 16u) |> OpReg - let rb = getRegister (extract bin 15u 11u) |> OpReg - struct (Op.DCBZ, TwoOperands (ra, rb)) - | _ (* 0 *) -> raise ParsingFailureException - -let parse1F bin = - match extract bin 9u 1u with - | 0x0u when pickBit bin 0u = 0u -> parseCMPandMCRXR bin - | 0x4u when pickBit bin 0u = 0u -> parseTW bin - | 0x8u -> parseSUBFCx bin - | 0xAu -> parseADDCx bin - | 0xBu when pickBit bin 10u = 0u -> parseMULHWUx bin - | 0x13u when pickBit bin 0u = 0u -> parseMFCR bin - (* FIXME : LWARX RegA = 0 *) - | 0x14u when pickBit bin 0u = 0u -> parseLWARX bin - | 0x15u when pickBit bin 0u = 0u -> parseLSWX bin - (* FIXME : LWBRX RegA = 0 *) - | 0x16u when pickBit bin 0u = 0u -> parseLWBRX bin - (* FIXME : LWZX / LFSX RegA = 0 *) - | 0x17u when pickBit bin 0u = 0u -> parseLWZXandLFSX bin - | 0x18u -> parseSLWxandSRWx bin - | 0x1Au -> parseCNTLZWx bin - | 0x1Cu -> parseANDx bin - | 0x20u when pickBit bin 0u = 0u -> parseCMPL bin - | 0x28u -> parseSUBFx bin - (* FIXME : DCBST RegA = 0 *) - | 0x36u when pickBit bin 0u = 0u -> parseDCBSTandTLBSYNC bin - (* FIXME : LWZUX / LFSUX RegA = 0 *) - | 0x37u when pickBit bin 0u = 0u -> parseLWZUXandLFSUX bin - | 0x3Cu -> parseANDCx bin - | 0x4Bu when pickBit bin 10u = 0u -> parseMULHWx bin - (* FIXME : SegRegister *) - | 0x53u when pickBit bin 0u = 0u -> parseMFMSRandMFSR bin - | 0x55u when pickBit bin 0u = 0u -> parseLSWI bin - (* FIXME : DCBF RegA = 0 / SYNC 0 *) - | 0x56u when pickBit bin 0u = 0u -> parseDCBFandSYNC bin - (* FIXME : LBZX / LFDX RegA = 0 *) - | 0x57u when pickBit bin 0u = 0u -> parseLBZXandLFDX bin - | 0x68u -> parseNEGx bin - (* FIXME : LBZUX / LFDUX RegA = 0 *) - | 0x77u when pickBit bin 0u = 0u -> parseLBZUXandLFDUX bin - | 0x7Cu -> parseNORx bin - | 0x88u -> parseSUBFEx bin - | 0x8Au -> parseADDEx bin - (* FIXME : CRM *) - | 0x90u when pickBit bin 0u = 0u -> parseMTCRF bin - | 0x92u when pickBit bin 0u = 0u -> parseMTMSR bin - | 0x93u -> parseMFSRIN bin - | 0x95u when pickBit bin 0u = 0u -> parseSTSWX bin - (* FIXME : STWCXdot / STWBRX RegA = 0 *) - | 0x96u -> parseSTWCXdotandSTWBRX bin - (* FIXME : STWX / STFSX RegA = 0 *) - | 0x97u when pickBit bin 0u = 0u -> parseSTWXandSTFSX bin - (* FIXME : STWUX / STFSUX RegA = 0 *) - | 0xB7u when pickBit bin 0u = 0u -> parseSTWUXandSTFSUX bin - | 0xC8u -> parseSUBFZEx bin - | 0xCAu -> parseADDZEx bin - (* FIXME : SegRegister *) - | 0xD2u when pickBit bin 0u = 0u -> parseMTSR bin - (* FIXME : SpecialRegister *) - | 0xD5u when pickBit bin 0u = 0u -> parseSTSWI bin - (* FIXME : STBX / STFDX RegA = 0 *) - | 0xD7u -> parseSTBXandSTFDX bin - | 0xE8u -> parseSUBFMEx bin - | 0xEAu -> parseADDMEx bin - | 0xEBu -> parseMULLWx bin - | 0xF2u -> parseMTSRIN bin - (* FIXME : DCBTST / DCBA RegA = 0 *) - | 0xF6u when pickBit bin 0u = 0u -> parseDCBTSTandDCBA bin - (* FIXME : STBUX / STFDUX RegA = 0 *) - | 0xF7u -> parseSTBUXandSTFDUX bin - | 0x10Au -> parseADDx bin - (* FIXME : DCBT / LHBRX RegA = 0 *) - | 0x116u when pickBit bin 0u = 0u -> parseDCBTandLHBRX bin - (* FIXME : LHZX RegA = 0 *) - | 0x117u when pickBit bin 0u = 0u -> parseLHZX bin - | 0x118u -> parseSRAWx bin - | 0x11Cu -> parseEQVx bin - | 0x132u -> parseTLBIE bin - | 0x136u when pickBit bin 0u = 0u -> parseECIWX bin - (* FIXME : LHZUX RegA = 0 *) - | 0x137u when pickBit bin 0u = 0u -> parseLHZUX bin - | 0x138u when pickBit bin 10u = 1u -> parseSRAWIx bin - | 0x13Cu -> parseXORx bin - (* FIXME : SpecialRegister *) - | 0x153u when pickBit bin 0u = 0u -> parseMFSPR bin - | 0x156u when pickBit bin 0u = 0u -> parseEIEIO bin - (* FIXME : LHAX RegA = 0 *) - | 0x157u when pickBit bin 0u = 0u -> parseLHAX bin - | 0x172u -> parseTLBIA bin - (* FIXME : TBRRegister *) - | 0x173u when pickBit bin 0u = 0u -> parseMFTB bin - (* FIXME : LHAUX RegA = 0 *) - | 0x177u when pickBit bin 0u = 0u -> parseLHAUX bin - (* FIXME : STHBRX RegA = 0 *) - | 0x196u when pickBit bin 0u = 0u -> parseSTHBRX bin - (* FIXME : STHX RegA = 0 *) - | 0x197u when pickBit bin 0u = 0u -> parseSTHX bin - | 0x19Au -> parseEXTSHx bin - | 0x19Cu -> parseORCx bin - | 0x1B6u when pickBit bin 0u = 0u -> parseECOWX bin - (* FIXME : STHUX RegA = 0 *) - | 0x1B7u when pickBit bin 0u = 0u -> parseSTHUX bin - | 0x1BAu -> parseEXTSBx bin - | 0x1BCu -> parseORx bin - | 0x1CBu -> parseDIVWUx bin - | 0x1D3u when pickBit bin 0u = 0u -> parseMTSPR bin - (* FIXME : DCBI / ICBI RegA = 0 *) - | 0x1D6u when pickBit bin 0u = 0u -> parseDCBIandICBI bin - (* FIXME : STFIWX RegA = 0 *) - | 0x1D7u when pickBit bin 0u = 0u -> parseSTFIWX bin - | 0x1DCu -> parseNANDx bin - | 0x1EBu -> parseDIVWx bin - (* FIXME : DCBZ RegA = 0 *) - | 0x1F6u when pickBit bin 0u = 0u -> parseDCBZ bin - | _ -> raise ParsingFailureException - -let parseLWZ bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LWZ, TwoOperands(rd, d(ra))) - -let parseLWZU bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LWZU, TwoOperands(rd, d(ra))) - -let parseLBZ bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LBZ, TwoOperands(rd, d(ra))) - -let parseLBZU bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LBZU, TwoOperands(rd, d(ra))) - -let parseSTW bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STW, TwoOperands(rs, d(ra))) - -let parseSTWU bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STWU, TwoOperands(rs, d(ra))) - -let parseSTB bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STB, TwoOperands(rs, d(ra))) - -let parseSTBU bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STBU, TwoOperands(rs, d(ra))) - -let parseLHZ bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LHZ, TwoOperands(rd, d(ra))) - -let parseLHZU bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LHZU, TwoOperands(rd, d(ra))) - -let parseLHA bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LHA, TwoOperands(rd, d(ra))) - -let parseLHAU bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LHAU, TwoOperands(rd, d(ra))) - -let parseSTH bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STH, TwoOperands(rs, d(ra))) - -let parseSTHU bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STHU, TwoOperands(rs, d(ra))) - -let parseLMW bin = - let rd = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LMW, TwoOperands(rd, d(ra))) - -let parseSTMW bin = - let rs = getRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.STMW, TwoOperands(rs, d(ra))) - -let parseLFS bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LFS, TwoOperands(frd, d(ra))) - -let parseLFSU bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LFSU, TwoOperands(frd, d(ra))) - -let parseLFD bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LFD, TwoOperands(frd, d(ra))) - -let parseLFDU bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d, ra) |> ImmOp - struct (Op.LFDU, TwoOperands(frd, d(ra))) - -let parseSTFS bin = - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d,ra) |> ImmOp - struct (Op.STFS, TwoOperands(frs, d(ra))) - -let parseSTFSU bin = - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d,ra) |> ImmOp - struct (Op.STFSU, TwoOperands(frs, d(ra))) - -let parseSTFD bin = - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d,ra) |> ImmOp - struct (Op.STFD, TwoOperands(frs, d(ra))) - -let parseSTFDU bin = - let frs = getFPRegister (extract bin 25u 21u) |> OpReg - let ra = getRegister (extract bin 20u 16u) - let d = extract bin 15u 0u |> uint64 - let d(ra) = (d,ra) |> ImmOp - struct (Op.STFDU, TwoOperands(frs, d(ra))) - -let parseFDIVSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FDIVS, ThreeOperands (frd, fra, frb)) - | _ (* 1 *) -> struct (Op.FDIVSdot, ThreeOperands (frd, fra, frb)) - -let parseFSUBSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FSUBS, ThreeOperands (frd, fra, frb)) - | _ (* 1 *) -> struct (Op.FSUBSdot, ThreeOperands (frd, fra, frb)) - -let parseFADDSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FADDS, ThreeOperands (frd, fra, frb)) - | _ (* 1 *) -> struct (Op.FADDSdot, ThreeOperands (frd, fra, frb)) - -let parseFSQRTSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FSQRTS, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FSQRTSdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFRESx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FRES, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FRESdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFMULSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 15u 11u = 0u -> - struct (Op.FMULS, ThreeOperands (frd, fra, frc)) - | 0b1u when extract bin 15u 11u = 0u -> - struct (Op.FMULSdot, ThreeOperands (frd, fra, frc)) - | _ -> raise ParsingFailureException - -let parseFMSUBSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FMSUBS, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FMSUBSdot, FourOperands (frd, fra, frc, frb)) - -let parseFMADDSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FMADDS, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FMADDSdot, FourOperands (frd, fra, frc, frb)) - -let parseFNMSUBSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FNMSUBS, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FNMSUBSdot, FourOperands (frd, fra, frc, frb)) - -let parseFNMADDSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FNMADDS, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FNMADDSdot, FourOperands (frd, fra, frc, frb)) - -let parse3B bin = - match extract bin 5u 1u with - | 0x12u when extract bin 10u 6u = 0u -> parseFDIVSx bin - | 0x14u when extract bin 10u 6u = 0u -> parseFSUBSx bin - | 0x15u when extract bin 10u 6u = 0u -> parseFADDSx bin - | 0x16u when extract bin 10u 6u = 0u -> parseFSQRTSx bin - | 0x18u when extract bin 10u 6u = 0u -> parseFRESx bin - | 0x19u -> parseFMULSx bin - | 0x1Cu -> parseFMSUBSx bin - | 0x1Du -> parseFMADDSx bin - | 0x1Eu -> parseFNMSUBSx bin - | 0x1Fu -> parseFNMADDSx bin - | _ -> raise ParsingFailureException - -let parseFCMPU bin = - match pickBit bin 0u with - | 0b0u when extract bin 22u 21u = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - struct (Op.FCMPU, ThreeOperands (crfd, fra, frb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseFRSPx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FRSP, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FRSPdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFCTIWx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FCTIW, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FCTIWdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFCTIWZx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FCTIWZ, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FCTIWZdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFDIVx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FDIV, ThreeOperands (frd, fra, frb)) - | _ (* 1 *) -> struct (Op.FDIVdot, ThreeOperands (frd, fra, frb)) - -let parseFSUBx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FSUB, ThreeOperands (frd, fra, frb)) - | _ (* 1 *) -> struct (Op.FSUBdot, ThreeOperands (frd, fra, frb)) - -let parseFADDx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FADD, ThreeOperands (frd, fra, frb)) - | _ (* 1 *) -> struct (Op.FADDdot, ThreeOperands (frd, fra, frb)) - -let parseFSQRTx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FSQRT, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FSQRTdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFSELx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FSEL, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FSELdot, FourOperands (frd, fra, frc, frb)) - -let parseFMULx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 15u 11u = 0u -> - struct (Op.FMUL, ThreeOperands (frd, fra, frc)) - | 0b1u when extract bin 15u 11u = 0u -> - struct (Op.FMULdot, ThreeOperands (frd, fra, frc)) - | _ -> raise ParsingFailureException - -let parseFRSQRTEx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when concat (extract bin 20u 16u) (extract bin 10u 6u) 5 = 0u -> - struct (Op.FRSQRTE, TwoOperands (frd, frb)) - | 0b1u when extract bin 15u 11u = 0u -> - struct (Op.FRSQRTEdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFMSUBx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FMSUB, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FMSUBdot, FourOperands (frd, fra, frc, frb)) - -let parseFMADDx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FMADD, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FMADDdot, FourOperands (frd, fra, frc, frb)) - -let parseFNMSUBx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FNMSUB, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FNMSUBdot, FourOperands (frd, fra, frc, frb)) - -let parseFNMADDx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - let frc = getFPRegister (extract bin 10u 6u) |> OpReg - match pickBit bin 0u with - | 0b0u -> struct (Op.FNMADD, FourOperands (frd, fra, frc, frb)) - | _ (* 1 *) -> struct (Op.FNMADDdot, FourOperands (frd, fra, frc, frb)) - -let parseFCMPO bin = - match pickBit bin 0u with - | 0b0u when extract bin 22u 21u = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let fra = getFPRegister (extract bin 20u 16u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - struct (Op.FCMPO, ThreeOperands (crfd, fra, frb)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseMTFSB1x bin = - let crbd = getFPSCRegister (extract bin 25u 21u) - match pickBit bin 0u with - | 0b0u when extract bin 20u 11u = 0u -> - (* FIXME : FPSCRegister *) - struct (Op.MTFSB1, OneOperand crbd) - | 0b1u when extract bin 20u 11u = 0u -> - (* FIXME : FPSCRegister *) - struct (Op.MTFSB1dot, OneOperand crbd) - | _ -> raise ParsingFailureException - -let parseFNEGx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 11u = 0u -> - struct (Op.FNEG, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 11u = 0u -> - struct (Op.FNEGdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseMCRFS bin = - match pickBit bin 0u with - | 0b0u when concat (extract bin 22u 21u) (extract bin 17u 11u) 2 = 0u -> - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let crfs = getCondRegister (extract bin 20u 18u) |> OpReg - struct (Op.MCRFS, TwoOperands (crfd, crfs)) - | _ (* 1 *) -> raise ParsingFailureException - -let parseMTFSB0x bin = - let crbd = getFPSCRegister (extract bin 25u 21u) - match pickBit bin 0u with - | 0b0u when extract bin 20u 11u = 0u -> - (* FIXME : FPSCRegister *) - struct (Op.MTFSB0, OneOperand crbd) - | 0b1u when extract bin 20u 11u = 0u -> - (* FIXME : FPSCRegister *) - struct (Op.MTFSB0dot, OneOperand crbd) - | _ -> raise ParsingFailureException - -let parseFMRx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FMR, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FMRdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseMTFSFIx bin = - let crfd = getCondRegister (extract bin 25u 23u) |> OpReg - let IMM = extract bin 15u 12u |> uint64 |> Immediate - match pickBit bin 0u with - | 0b0u when concat (extract bin 22u 16u) (pickBit bin 11u) 7 = 0u -> - struct (Op.MTFSFI, TwoOperands (crfd, IMM)) - | 0b1u when concat (extract bin 22u 16u) (pickBit bin 11u) 7 = 0u -> - struct (Op.MTFSFIdot, TwoOperands (crfd, IMM)) - | _ -> raise ParsingFailureException - -let parseFNABSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FNABS, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FNABSdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseFABSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 16u = 0u -> - struct (Op.FABS, TwoOperands (frd, frb)) - | 0b1u when extract bin 20u 16u = 0u -> - struct (Op.FABSdot, TwoOperands (frd, frb)) - | _ -> raise ParsingFailureException - -let parseMFFSx bin = - let frd = getFPRegister (extract bin 25u 21u) |> OpReg - match pickBit bin 0u with - | 0b0u when extract bin 20u 11u = 0u -> - struct (Op.MFFS, OneOperand frd) - | 0b1u when extract bin 20u 11u = 0u -> - struct (Op.MFFSdot, OneOperand frd) - | _ -> raise ParsingFailureException - -let parseMTFSFx bin = - let fm = getFM (extract bin 24u 17u) - let frb = getFPRegister (extract bin 15u 11u) |> OpReg - match pickBit bin 0u with - | 0b0u when concat (pickBit bin 25u) (pickBit bin 16u) 1 = 0u -> - struct (Op.MTFSF, TwoOperands (fm, frb)) - | 0b1u when concat (pickBit bin 25u) (pickBit bin 16u) 1 = 0u -> - struct (Op.MTFSFdot, TwoOperands (fm, frb)) - | _ -> raise ParsingFailureException - -let parse3F bin = - match extract bin 5u 1u with - | 0x0u -> - match extract bin 10u 6u with - | 0x0u -> parseFCMPU bin - | 0x1u -> parseFCMPO bin - | 0x2u -> parseMCRFS bin - | _ -> raise ParsingFailureException - | 0x6u -> - (* FIXME : FPSCRegister *) - match extract bin 10u 6u with - | 0x1u -> parseMTFSB1x bin - (* FIXME : FPSCRegister *) - | 0x2u -> parseMTFSB0x bin - | 0x4u -> parseMTFSFIx bin - | _ -> raise ParsingFailureException - | 0x7u -> - match extract bin 10u 6u with - | 0x12u -> parseMFFSx bin - | 0x16u -> parseMTFSFx bin - | _ -> raise ParsingFailureException - | 0x8u -> - match extract bin 10u 6u with - | 0x1u -> parseFNEGx bin - | 0x2u -> parseFMRx bin - | 0x4u -> parseFNABSx bin - | 0x8u -> parseFABSx bin - | _ -> raise ParsingFailureException - | 0xCu when extract bin 10u 6u = 0u -> parseFRSPx bin - | 0xEu when extract bin 10u 6u = 0u -> parseFCTIWx bin - | 0xFu when extract bin 10u 6u = 0u -> parseFCTIWZx bin - | 0x12u when extract bin 10u 6u = 0u -> parseFDIVx bin - | 0x14u when extract bin 10u 6u = 0u -> parseFSUBx bin - | 0x15u when extract bin 10u 6u = 0u -> parseFADDx bin - | 0x16u when extract bin 10u 6u = 0u -> parseFSQRTx bin - | 0x17u -> parseFSELx bin - | 0x19u -> parseFMULx bin - | 0x1Au -> parseFRSQRTEx bin - | 0x1Cu -> parseFMSUBx bin - | 0x1Du -> parseFMADDx bin - | 0x1Eu -> parseFNMSUBx bin - | 0x1Fu -> parseFNMADDx bin - | _ -> raise ParsingFailureException - -let private parseInstruction bin = - match extract bin 31u 26u with - | 0x3u -> parseTWI bin - | 0x7u -> parseMULLI bin - | 0x8u -> parseSUBFIC bin - | 0xAu -> parseCMPLI bin - | 0xBu -> parseCMPI bin - | 0xCu -> parseADDIC bin - | 0xDu -> parseADDICdot bin - | 0xEu -> parseADDI bin - | 0xFu -> parseADDIS bin - | 0x10u -> parseBCx bin - | 0x11u when pickBit bin 0u = 0u -> parseSC bin - | 0x12u -> parseBx bin - | 0x13u -> parse13 bin - | 0x14u -> parseRLWIMIx bin - | 0x15u -> parseRLWINMx bin - | 0x17u -> parseRLWNMx bin - | 0x18u -> parseORI bin - | 0x19u -> parseORIS bin - | 0x1Au -> parseXORI bin - | 0x1Bu -> parseXORIS bin - | 0x1Cu -> parseANDIdot bin - | 0x1Du -> parseANDISdot bin - | 0x1Fu -> parse1F bin - | 0x20u -> parseLWZ bin - | 0x21u -> parseLWZU bin - | 0x22u -> parseLBZ bin - | 0x23u -> parseLBZU bin - | 0x24u -> parseSTW bin - | 0x25u -> parseSTWU bin - | 0x26u -> parseSTB bin - | 0x27u -> parseSTBU bin - | 0x28u -> parseLHZ bin - | 0x29u -> parseLHZU bin - | 0x2Au -> parseLHA bin - | 0x2Bu -> parseLHAU bin - | 0x2Cu -> parseSTH bin - | 0x2Du -> parseSTHU bin - | 0x2Eu -> parseLMW bin - | 0x2Fu -> parseSTMW bin - | 0x30u -> parseLFS bin - | 0x31u -> parseLFSU bin - | 0x32u -> parseLFD bin - | 0x33u -> parseLFDU bin - | 0x34u -> parseSTFS bin - | 0x35u -> parseSTFSU bin - | 0x36u -> parseSTFD bin - | 0x37u -> parseSTFDU bin - | 0x3Bu -> parse3B bin - | 0x3Fu -> parse3F bin - | _ -> raise ParsingFailureException - -let parse (span: ByteSpan) (reader: IBinReader) addr = - let bin = reader.ReadUInt32 (span, 0) - let struct (opcode, operands) = parseInstruction bin - let insInfo = - { Address = addr - NumBytes = 4u - Opcode = opcode - Operands = operands - OperationSize = 32 - EffectiveAddress = 0UL } - PPC32Instruction (addr, 4u, insInfo) - -// vim: set tw=80 sts=2 sw=2: + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32ParsingMain.fs b/src/FrontEnd/BinLifter/PPC32/PPC32ParsingMain.fs new file mode 100644 index 00000000..1e709f77 --- /dev/null +++ b/src/FrontEnd/BinLifter/PPC32/PPC32ParsingMain.fs @@ -0,0 +1,1981 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.PPC32.ParsingMain + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData +open B2R2.FrontEnd.BinLifter.PPC32.OperandHelper + +let parseTWI bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + match extract bin 25u 21u with + (* twlgti ra,value = twi 1,ra,value *) + | 1u -> struct (Op.TWLGTI, TwoOperands (ra, value)) + (* twllti ra,value = twi 2,ra,value *) + | 2u -> struct (Op.TWLLTI, TwoOperands (ra, value)) + (* tweqi ra,value = twi 4,ra,value *) + | 4u -> struct (Op.TWEQI, TwoOperands (ra, value)) + (* twlnli ra,value = twi 5,ra,value *) + | 5u -> struct (Op.TWLNLI, TwoOperands (ra, value)) + (* twllei ra,value = twi 6,ra,value *) + | 6u -> struct (Op.TWLLEI, TwoOperands (ra, value)) + (* twgti ra,value = twi 8,ra,value *) + | 8u -> struct (Op.TWGTI, TwoOperands (ra, value)) + (* twgei ra,value = twi 12,ra,value *) + | 12u -> struct (Op.TWGEI, TwoOperands (ra, value)) + (* twlti ra,value = twi 16,ra,value *) + | 16u -> struct (Op.TWLTI, TwoOperands (ra, value)) + (* twlei ra,value = twi 20,ra,value *) + | 20u -> struct (Op.TWLEI, TwoOperands (ra, value)) + (* twnei ra,value = twi 24,ra,value *) + | 24u -> struct (Op.TWNEI, TwoOperands (ra, value)) + (* twllei ra,value = twlngi ra, value = twi 6,ra,value + twgei ra,value = twlgei ra, value = twnli ra, value = twi 12,ra,value + twlei ra,value = twngi ra, value = twi 20,ra,value *) + | _ -> + let tO = extract bin 25u 21u |> uint64 |> OprImm + struct (Op.TWI, ThreeOperands (tO, ra, value)) + +let parseMULLI bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + struct (Op.MULLI, ThreeOperands (rd, ra, value)) + +let parseSUBFIC bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + struct (Op.SUBFIC, ThreeOperands (rd, ra, value)) + +let parseCMPLI bin = + match pickBit bin 22u with + | 0b0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + match pickBit bin 21u with + (* cmplwi crfd,ra,uimm = cmpli crfd,0,ra,uimm *) + | 0b0u -> struct (Op.CMPLWI, ThreeOperands (crfd, ra, uimm)) + | _ -> struct (Op.CMPLI, FourOperands (crfd, OprImm 1UL, ra, uimm)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCMPI bin = + match pickBit bin 22u with + | 0b0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + match pickBit bin 21u with + (* cmpwl crfd,ra,uimm = cmpl crfd,0,ra,uimm *) + | 0b0u -> struct (Op.CMPWI, ThreeOperands (crfd, ra, value)) + | _ -> struct (Op.CMPI, FourOperands (crfd, OprImm 1UL, ra, value)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseADDIC bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + (* subic rd,ra,value = addic rd,ra,-value *) + struct (Op.ADDIC, ThreeOperands (rd, ra, value)) + +let parseADDICdot bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + (* subic. rd,ra,value = addic. rd,ra,-value *) + struct (Op.ADDICdot, ThreeOperands (rd, ra, value)) + +let parseADDI bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + match extract bin 20u 16u with + | 0b0u -> struct (Op.LI, TwoOperands (rd, value)) + (* subi rd,ra,value = addi rd,ra,-value *) + | _ -> + let ra = getRegister (extract bin 20u 16u) |> OprReg + struct (Op.ADDI, ThreeOperands (rd, ra, value)) + +let parseADDIS bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let simm = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 simm |> uint64 |> OprImm + match extract bin 20u 16u with + | 0b0u -> struct (Op.LIS, TwoOperands (rd, value)) + (* subis rd,ra,value = addis rd,ra,-value *) + | _ -> + let ra = getRegister (extract bin 20u 16u) |> OprReg + struct (Op.ADDIS, ThreeOperands (rd, ra, value)) + +let parseBCx bin = + let idx = (extract bin 1u 0u |> int) (* opcode *) + let bd = extract bin 15u 2u <<< 2 |> uint64 + let value = signExtend 16 32 bd |> uint64 |> OprAddr (* TargetAddress *) + let op = [| Op.BC; Op.BCL; Op.BCA; Op.BCLA |].[idx] + let bo = extract bin 25u 21u |> uint64 |> OprImm + struct (op, ThreeOperands (bo, OprBI (extract bin 20u 16u), value)) + +let parseSC bin = + match pickBit bin 1u with + | 0b1u -> struct (Op.SC, NoOperand) + | _ -> raise ParsingFailureException + +let parseBx bin addr = + let li = extract bin 25u 2u |> uint64 + let signExtended = signExtend 25 32 (li <<< 2) + match extract bin 1u 0u (* AA:LK *) with + | 0b00u -> + let value = uint32 addr + uint32 signExtended |> uint64 |> OprImm + struct (Op.B, OneOperand value) + | 0b01u -> + let value = uint32 addr + uint32 signExtended |> uint64 |> OprImm + struct (Op.BL, OneOperand value) + | 0b10u -> + let value = signExtended |> OprImm + struct (Op.BA, OneOperand value) + | _ (* 11 *) -> + let value = signExtended |> OprImm + struct (Op.BLA, OneOperand value) + +let parseMCRF bin = + match pickBit bin 0u with + | 0b0u when concat (extract bin 22u 21u) (extract bin 17u 11u) 2 = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let crfs = getCondRegister (extract bin 20u 18u) |> OprReg + struct (Op.MCRF, TwoOperands (crfd, crfs)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseBCLRx bin = + if extract bin 15u 11u <> 0u then raise ParsingFailureException + else + let idx = pickBit bin 0u |> int (* opcode *) + let op = [| Op.BCLR; Op.BCLRL |].[idx] + let bo = extract bin 25u 21u |> uint64 |> OprImm + struct (op, TwoOperands (bo, OprBI (extract bin 20u 16u))) + +let parseCRNOR bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + (* crnot crbd,crba = crnor crbd,crba,crba *) + if extract bin 20u 16u = extract bin 15u 11u then + struct (Op.CRNOT, TwoOperands (crbd, crba)) + else + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CRNOR, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseRFI bin = + match pickBit bin 0u with + | 0b0u when extract bin 25u 11u = 0u -> + struct (Op.RFI, NoOperand) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCRANDC bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CRANDC, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseISYNC bin = + match pickBit bin 0u with + | 0b0u when extract bin 25u 11u = 0u -> + struct (Op.ISYNC, NoOperand) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCRXOR bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + if (crbd = crba) && (crbd = crbb) then + struct (Op.CRCLR, OneOperand crbd) + else + struct (Op.CRXOR, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCRNAND bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CRNAND, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCRAND bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CRAND, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCREQV bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + (* crset crbd = creqv crbd,crbd,crbd *) + if extract bin 25u 21u = extract bin 20u 16u then + if extract bin 20u 16u = extract bin 15u 11u then + struct (Op.CRSET, OneOperand crbd) + else + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CREQV, ThreeOperands (crbd, crba, crbb)) + else + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CREQV, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCRORC bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CRORC, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseCROR bin = + match pickBit bin 0u with + | 0b0u -> + let crbd = extract bin 25u 21u |> OprBI + let crba = extract bin 20u 16u |> OprBI + (* crmove crbd,crba = cror crbd,crba,crba *) + if extract bin 20u 16u = extract bin 15u 11u then + struct (Op.CRMOVE, TwoOperands (crbd, crba)) + else + let crbb = extract bin 15u 11u |> OprBI + struct (Op.CROR, ThreeOperands (crbd, crba, crbb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseBCCTRx bin = + match pickBit bin 0u with + | 0b0u when extract bin 15u 11u = 0u -> + let bo = extract bin 25u 21u |> uint64 |> OprImm + struct (Op.BCCTR, TwoOperands (bo, OprBI (extract bin 20u 16u))) + | 0b1u when extract bin 15u 11u = 0u -> + let bo = extract bin 25u 21u |> uint64 |> OprImm + struct (Op.BCCTRL, TwoOperands (bo, OprBI (extract bin 20u 16u))) + | _ -> raise ParsingFailureException + +let parse13 bin = + match extract bin 10u 1u with + | 0x0u -> parseMCRF bin + | 0x10u -> parseBCLRx bin + | 0x21u -> parseCRNOR bin + | 0x32u -> parseRFI bin + | 0x81u -> parseCRANDC bin + | 0x96u -> parseISYNC bin + | 0xC1u -> parseCRXOR bin + | 0xE1u -> parseCRNAND bin + | 0x101u -> parseCRAND bin + | 0x121u -> parseCREQV bin + | 0x1A1u -> parseCRORC bin + | 0x1C1u -> parseCROR bin + | 0x210u -> parseBCCTRx bin + | _ -> raise ParsingFailureException + +let parseRLWIMIx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let sh = extract bin 15u 11u |> uint64 |> OprImm + let mb = extract bin 10u 6u |> uint64 |> OprImm + let me = extract bin 5u 1u |> uint64 |> OprImm + match pickBit bin 0u with + (* inslwi ra,rs,n,b = rlwimi ra,rs,32-b,b,b+n-1 + insrwi ra,rs,n,b (n>0) = rlwimi ra,rs,32-(b+n),b,(b+n)-1 *) + | 0b0u -> struct (Op.RLWIMI, FiveOperands(ra, rs, sh, mb, me)) + | _ (* 1 *) -> struct (Op.RLWIMIdot, FiveOperands(ra, rs, sh, mb, me)) + +let parseRLWINMx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match pickBit bin 0u with + | 0b0u -> + let sh = extract bin 15u 11u |> uint64 |> OprImm + let mb = extract bin 10u 6u |> uint64 |> OprImm + let me = extract bin 5u 1u |> uint64 |> OprImm + struct (Op.RLWINM, FiveOperands(ra, rs, sh, mb, me)) + | _ (* 1 *) -> + let sh = extract bin 15u 11u |> uint64 |> OprImm + let mb = extract bin 10u 6u |> uint64 |> OprImm + let me = extract bin 5u 1u |> uint64 |> OprImm + struct (Op.RLWINMdot, FiveOperands(ra, rs, sh, mb, me)) + +let parseRLWNMx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> + match extract bin 10u 1u with + (* rotlw ra,rs,rb = rlwnm ra,rs,rb,mb,me *) + | 0x1Fu -> struct (Op.ROTLW, ThreeOperands(ra, rs, rb)) + | _ -> + let mb = extract bin 10u 6u |> uint64 |> OprImm + let me = extract bin 5u 1u |> uint64 |> OprImm + struct (Op.RLWNM, FiveOperands(ra, rs, rb, mb, me)) + | _ (* 1 *) -> + let mb = extract bin 10u 6u |> uint64 |> OprImm + let me = extract bin 5u 1u |> uint64 |> OprImm + struct (Op.RLWNMdot, FiveOperands(ra, rs, rb, mb, me)) + +let parseORI bin = + match extract bin 25u 0u with + (* nop = ori 0,0,0 *) + | 0b0u -> struct (Op.NOP, NoOperand) + | _ -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + struct (Op.ORI, ThreeOperands(ra, rs, uimm)) + +let parseORIS bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + struct (Op.ORIS, ThreeOperands(ra, rs, uimm)) + +let parseXORI bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + struct (Op.XORI, ThreeOperands(ra, rs, uimm)) + +let parseXORIS bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + struct (Op.XORIS, ThreeOperands(ra, rs, uimm)) + +let parseANDIdot bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + struct (Op.ANDIdot, ThreeOperands(ra, rs, uimm)) + +let parseANDISdot bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let uimm = extract bin 15u 0u |> uint64 |> OprImm + struct (Op.ANDISdot, ThreeOperands(ra, rs, uimm)) + +let parseCMPandMCRXR bin = + match pickBit bin 10u with + | 0b0u when pickBit bin 22u = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 21u with + (* cmpw crfd,ra,rb = cmp crfd,0,ra,rb *) + | 0b0u -> struct (Op.CMPW, ThreeOperands (crfd, ra, rb)) + | _ (* 1 *) -> struct (Op.CMP, FourOperands (crfd, OprImm 1UL, ra, rb)) + | 0b1u when extract bin 22u 11u = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + struct (Op.MCRXR, OneOperand (crfd)) + | _ -> raise ParsingFailureException + +let parseTW bin = + match pickBit bin 10u with + | 0b0u -> + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match extract bin 25u 21u with + (* twlgt ra,rb = tw 1,ra,rb *) + | 1u -> struct (Op.TWLGT, TwoOperands (ra, rb)) + (* twllt ra,rb = tw 2,ra,rb *) + | 2u -> struct (Op.TWLLT, TwoOperands (ra, rb)) + (* tweq ra,rb = tw 4,ra,rb *) + | 4u -> struct (Op.TWEQ, TwoOperands (ra, rb)) + (* twlnl ra,rb = tw 5,ra,rb *) + | 5u -> struct (Op.TWLNL, TwoOperands (ra, rb)) + (* twllel ra,rb = tw 6,ra,rb *) + | 6u -> struct (Op.TWLLE, TwoOperands (ra, rb)) + (* twgt ra,rb = tw 8,ra,rb *) + | 8u -> struct (Op.TWGT, TwoOperands (ra, rb)) + (* twge ra,rb = tw 12,ra,rb *) + | 12u -> struct (Op.TWGE, TwoOperands (ra, rb)) + (* twlt ra,rb = tw 16,ra,rb *) + | 16u -> struct (Op.TWLT, TwoOperands (ra, rb)) + (* twle ra,rb = tw 20,ra,rb *) + | 20u -> struct (Op.TWLE, TwoOperands (ra, rb)) + (* twne ra,rb = tw 24,ra,rb *) + | 24u -> struct (Op.TWNE, TwoOperands (ra, rb)) + | 31u when extract bin 20u 11u = 0u -> struct (Op.TRAP, NoOperand) + | _ -> + let tO = extract bin 25u 21u |> uint64 |> OprImm + struct (Op.TW, ThreeOperands (tO, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseSUBFCx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + (* subc rd,ra,rb = subfc rd,rb,ra *) + | 0b00u -> struct (Op.SUBFC, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.SUBFCdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.SUBFCO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.SUBFCOdot, ThreeOperands (rd, ra, rb)) + +let parseADDCx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.ADDC, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.ADDCdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.ADDCO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.ADDCOdot, ThreeOperands (rd, ra, rb)) + +let parseMULHWUx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.MULHWU, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> struct (Op.MULHWUdot, ThreeOperands (rd, ra, rb)) + +let parseMFCR bin = + match pickBit bin 10u with + | 0b0u when extract bin 20u 11u = 0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.MFCR, OneOperand (rd)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseLWARX bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LWARX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseLSWX bin = + match pickBit bin 10u with + | 0b1u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LSWX, ThreeOperands (rd, ra, rb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseLWBRX bin = + match pickBit bin 10u with + | 0b1u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LWBRX, ThreeOperands (rd, ra, rb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseLWZXandLFSX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.LWZX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.LFSX, ThreeOperands (frd, ra, rb)) + +let parseSLWxandSRWx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u -> struct (Op.SLW, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.SLWdot, ThreeOperands (ra, rs, rb)) + | 0b10u -> struct (Op.SRW, ThreeOperands (ra, rs, rb)) + | _ (* 11 *) -> struct (Op.SRWdot, ThreeOperands (ra, rs, rb)) + +let parseCNTLZWx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u when extract bin 15u 11u = 0u -> + struct (Op.CNTLZW, TwoOperands (ra, rs)) + | 0b01u when extract bin 15u 11u = 0u -> + struct (Op.CNTLZWdot, TwoOperands (ra, rs)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseANDx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u -> struct (Op.AND, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.ANDdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseCMPL bin = + match pickBit bin 10u with + | 0b0u when pickBit bin 22u = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 21u with + (* cmplw crfd,ra,rb = cmpl crfd,0,ra,rb *) + | 0b0u -> struct (Op.CMPLW, ThreeOperands (crfd, ra, rb)) + | _ (* 1 *)-> struct (Op.CMPL, FourOperands (crfd, OprImm 1UL, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseSUBFx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + (* sub rd,rb,ra = subf rd,ra,rb *) + | 0b00u -> struct (Op.SUBF, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.SUBFdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.SUBFO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.SUBFOdot, ThreeOperands (rd, ra, rb)) + +let parseDCBSTandTLBSYNC bin = + match pickBit bin 10u with + | 0b0u when extract bin 25u 21u = 0u -> + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.DCBST, TwoOperands (ra, rb)) + | 0b1u when extract bin 25u 11u = 0u -> + struct (Op.TLBSYNC, NoOperand) + | _ -> raise ParsingFailureException + +let parseLWZUXandLFSUX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.LWZUX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.LFSUX, ThreeOperands (frd, ra, rb)) + +let parseANDCx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u -> struct (Op.ANDC, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.ANDCdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseMULHWx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.MULHW, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> struct (Op.MULHWdot, ThreeOperands (rd, ra, rb)) + +let parseMFMSRandMFSR bin = + match pickBit bin 10u with + | 0b0u when extract bin 20u 11u = 0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.MFMSR, OneOperand (rd)) + | 0b1u when (concat (pickBit bin 20u) (extract bin 15u 11u) 1) = 0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + (* FIXME: SegRegister *) + let sr = getSegRegister (extract bin 19u 16u) + struct (Op.MFSR, TwoOperands (rd, sr)) + | _ -> raise ParsingFailureException + +let parseLSWI bin = + match pickBit bin 10u with + | 0b1u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let nb = extract bin 15u 11u |> uint64 |> OprImm + struct (Op.LSWI, ThreeOperands(rd, ra, nb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseDCBFandSYNC bin = + match pickBit bin 10u with + | 0b0u when extract bin 25u 21u = 0u -> + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.DCBF, TwoOperands (ra, rb)) + | 0b1u when extract bin 25u 11u = 0u -> + struct (Op.SYNC, NoOperand) + | 0b1u when extract bin 25u 21u = 1u -> + struct (Op.LWSYNC, NoOperand) + | _ -> raise ParsingFailureException + +let parseLBZXandLFDX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.LBZX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LFDX, ThreeOperands (frd, ra, rb)) + +let parseNEGx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u when extract bin 15u 11u = 0u -> + struct (Op.NEG, TwoOperands (rd, ra)) + | 0b01u when extract bin 15u 11u = 0u -> + struct (Op.NEGdot, TwoOperands (rd, ra)) + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.NEGO, TwoOperands (rd, ra)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.NEGOdot, TwoOperands (rd, ra)) + | _ -> raise ParsingFailureException + +let parseLBZUXandLFDUX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.LBZUX, ThreeOperands (rd, ra, rb)) + | 0b1u -> + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.LFDUX, ThreeOperands (frd, ra, rb)) + | _ -> raise ParsingFailureException + +let parseNORx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + (* not rd,rs = nor ra,rs,rs *) + | 0b00u -> struct (Op.NOR, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.NORdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseSUBFEx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.SUBFE, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.SUBFEdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.SUBFEO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.SUBFEOdot, ThreeOperands (rd, ra, rb)) + +let parseADDEx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.ADDE, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.ADDEdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.ADDEO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.ADDEOdot, ThreeOperands (rd, ra, rb)) + +let parseMTCRF bin = + match pickBit bin 10u with + (* mtcr rs = mtcrf 0xff,rs *) + | 0b0u when concat (pickBit bin 20u) (pickBit bin 11u) 1 = 00u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let crm = extract bin 19u 12u |> uint64 |> OprImm + struct (Op.MTCRF, TwoOperands (crm, rs)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseMTMSR bin = + match pickBit bin 10u with + | 0b0u when extract bin 20u 11u = 0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.MFMSR, OneOperand rs) + | _ (* 1 *) -> raise ParsingFailureException + +let parseMFSRIN bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b10u when extract bin 20u 16u = 0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.MFSRIN, TwoOperands (rd, rb)) + | _ (* 11, 0x *) -> raise ParsingFailureException + +let parseSTSWX bin = + match pickBit bin 10u with + | 0b1u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.STSWX, ThreeOperands (rs, ra, rb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseSTWCXdotandSTWBRX bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b01u -> struct (Op.STWCXdot, ThreeOperands (rs, ra, rb)) + | 0b10u -> struct (Op.STWBRX, ThreeOperands (rs, ra, rb)) + | _ (* 00, 11 *) -> raise ParsingFailureException + +let parseSTWXandSTFSX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.STWX, ThreeOperands (rs, ra, rb)) + | _ (* 1 *) -> + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.STFSX, ThreeOperands (frs, ra, rb)) + +let parseSTWUXandSTFSUX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.STWUX, ThreeOperands (rs, ra, rb)) + | _ (* 1 *) -> + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.STFSUX, ThreeOperands (frs, ra, rb)) + +let parseSUBFZEx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u when extract bin 15u 11u = 0u -> + struct (Op.SUBFZE, TwoOperands (rd, ra)) + | 0b01u when extract bin 15u 11u = 0u -> + struct (Op.SUBFZEdot, TwoOperands (rd, ra)) + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.SUBFZEO, TwoOperands (rd, ra)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.SUBFZEOdot, TwoOperands (rd, ra)) + | _ -> raise ParsingFailureException + +let parseADDZEx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u when extract bin 15u 11u = 0u -> + struct (Op.ADDZE, TwoOperands (rd, ra)) + | 0b01u when extract bin 15u 11u = 0u -> + struct (Op.ADDZEdot, TwoOperands (rd, ra)) + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.ADDZEO, TwoOperands (rd, ra)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.ADDZEOdot, TwoOperands (rd, ra)) + | _ -> raise ParsingFailureException + +let parseMTSR bin = + match pickBit bin 10u with + | 0b0u when (concat (pickBit bin 20u) (extract bin 15u 11u) 1) = 0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + (* FIXME: SegRegister *) + let sr = getSegRegister (extract bin 19u 16u) + struct (Op.MTSR, TwoOperands (sr, rs)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseSTSWI bin = + match pickBit bin 10u with + | 0b1u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let nb = extract bin 15u 11u |> uint64 |> OprImm + struct (Op.STSWI, ThreeOperands (rs, ra, nb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseSTBXandSTFDX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b00u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.STBX, ThreeOperands (rs, ra, rb)) + | 0b10u -> + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.STFDX, ThreeOperands (frs, ra, rb)) + | _ (* 01, 11 *) -> raise ParsingFailureException + +let parseSUBFMEx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u when extract bin 15u 11u = 0u -> + struct (Op.SUBFME, TwoOperands (rd, ra)) + | 0b01u when extract bin 15u 11u = 0u -> + struct (Op.SUBFMEdot, TwoOperands (rd, ra)) + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.SUBFMEO, TwoOperands (rd, ra)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.SUBFMEOdot, TwoOperands (rd, ra)) + | _ -> raise ParsingFailureException + +let parseADDMEx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u when extract bin 15u 11u = 0u -> + struct (Op.ADDME, TwoOperands (rd, ra)) + | 0b01u when extract bin 15u 11u = 0u -> + struct (Op.ADDMEdot, TwoOperands (rd, ra)) + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.ADDMEO, TwoOperands (rd, ra)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.ADDMEOdot, TwoOperands (rd, ra)) + | _ -> raise ParsingFailureException + +let parseMULLWx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.MULLW, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.MULLWdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.MULLWO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.MULLWOdot, ThreeOperands (rd, ra, rb)) + +let parseMTSRIN bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b10u when extract bin 20u 16u = 0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.MTSRIN, TwoOperands (rs, rb)) + | _ (* 11, 0x *) -> raise ParsingFailureException + +let parseDCBTSTandDCBA bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u when extract bin 25u 21u = 0u -> + (* CT = 0u *) + struct (Op.DCBTST, TwoOperands (ra, rb)) + | 0b1u when extract bin 25u 21u = 0u -> + struct (Op.DCBA, TwoOperands (ra, rb)) + | _ -> raise ParsingFailureException + +let parseSTBUXandSTFDUX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b00u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.STBUX, ThreeOperands (rs, ra, rb)) + | 0b10u -> + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + struct (Op.STFDUX, ThreeOperands (frs, ra, rb)) + | _ (* 01, 11 *) -> raise ParsingFailureException + +let parseADDx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.ADD, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.ADDdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.ADDO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.ADDOdot, ThreeOperands (rd, ra, rb)) + +let parseDCBTandLHBRX bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u when extract bin 25u 21u = 0u -> + (* CT = 0u *) + struct (Op.DCBT, TwoOperands (ra, rb)) + | 0b1u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + struct (Op.LHBRX, ThreeOperands (rd, ra, rb)) + | _ -> raise ParsingFailureException + +let parseLHZX bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LHZX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseSRAWx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 1:RC *) with + | 0b10u -> struct (Op.SRAW, ThreeOperands (ra, rs, rb)) + | 0b11u -> struct (Op.SRAWdot, ThreeOperands (ra, rs, rb)) + | _ (* 0x *) -> raise ParsingFailureException + +let parseEQVx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:Rc *) with + | 0b00u -> struct (Op.EQV, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.EQVdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseTLBIE bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b00u -> + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.TLBIE, OneOperand rb) + | _ (* 01, 1x *) -> raise ParsingFailureException + +let parseECIWX bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b00u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.ECIWX, ThreeOperands (rd, ra, rb)) + | _ (* 01, 1x *) -> raise ParsingFailureException + +let parseLHZUX bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LHZUX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseSRAWIx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let sh = extract bin 15u 11u |> uint64 |> OprImm + match pickBit bin 0u with + | 0b0u -> struct (Op.SRAWI, ThreeOperands (ra, rs, sh)) + | _ (* 1 *) -> struct (Op.SRAWIdot, ThreeOperands (ra, rs, sh)) + +let parseXORx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u -> struct (Op.XOR, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.XORdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseMFSPR bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + match concat (extract bin 15u 11u) (extract bin 20u 16u) 5 with + (* mfxer rd = mfspr rd,1 *) + | 1u -> struct (Op.MFXER, OneOperand rd) + (* mflr rd = mfspr rd,8 *) + | 8u -> struct (Op.MFLR, OneOperand rd) + (* mfctr rd = mfspr rd,9 *) + | 9u -> struct (Op.MFCTR, OneOperand rd) + | 18u | 19u | 22u | 25u | 26u | 27u | 272u | 273u | 274u | 275u | 282u + | 287u | 528u | 529u | 530u | 531u | 532u | 533u | 534u | 535u | 536u + | 537u | 538u | 539u | 540u | 541u | 542u | 543u | 1013u -> + let spr = + getSPRegister (concat (extract bin 15u 11u) (extract bin 20u 16u) 5) + struct (Op.MFSPR, TwoOperands (rd, spr)) + | _ -> raise ParsingFailureException + | _ (* 1 *) -> raise ParsingFailureException + +let parseEIEIO bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b10u when extract bin 25u 11u = 0u -> + struct (Op.EIEIO, NoOperand) + | _ (* 11, 0x *) -> raise ParsingFailureException + +let parseLHAX bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LHAX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseTLBIA bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b00u -> + struct (Op.TLBIA, NoOperand) + | _ (* 01, 1x *) -> raise ParsingFailureException + +let parseMFTB bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + (* FIXME: TBRRegister *) + let tbr = + getTBRRegister (concat (extract bin 15u 11u) (extract bin 20u 16u) 5) + match concat (extract bin 15u 11u) (extract bin 20u 16u) 5 with + (* mftbu rd = mftb rd,269 *) + | 0x10du -> struct (Op.MFTBU, OneOperand rd) + (* mftb rd = mftb rd,268 *) + | _ -> struct (Op.MFTB, TwoOperands (rd, tbr)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseLHAUX bin = + match pickBit bin 10u with + | 0b0u -> + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.LHAUX, ThreeOperands (rd, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseSTHBRX bin = + match pickBit bin 10u with + | 0b1u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.STHBRX, ThreeOperands (rs, ra, rb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseSTHX bin = + match pickBit bin 10u with + | 0b0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.STHX, ThreeOperands (rs, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseEXTSHx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 1:Rc *) with + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.EXTSH, TwoOperands (ra, rs)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.EXTSHdot, TwoOperands (ra, rs)) + | _ (* 0x *) -> raise ParsingFailureException + +let parseORCx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u -> struct (Op.ORC, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.ORCdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseECOWX bin = + match concat (pickBit bin 10u) (pickBit bin 0u) 1 with + | 0b00u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.ECOWX, ThreeOperands (rs, ra, rb)) + | _ (* 01, 1x *) -> raise ParsingFailureException + +let parseSTHUX bin = + match pickBit bin 10u with + | 0b0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.STHUX, ThreeOperands (rs, ra, rb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseEXTSBx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 1:Rc *) with + | 0b10u when extract bin 15u 11u = 0u -> + struct (Op.EXTSB, TwoOperands (ra, rs)) + | 0b11u when extract bin 15u 11u = 0u -> + struct (Op.EXTSBdot, TwoOperands (ra, rs)) + | _ (* 0x *) -> raise ParsingFailureException + +let parseORx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + (* mr ra,rs = or ra,rs,rs *) + | 0b00u -> + if extract bin 25u 21u = extract bin 15u 11u then + struct (Op.MR, TwoOperands (ra, rs)) + else + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.OR, ThreeOperands (ra, rs, rb)) + | 0b01u -> + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.ORdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseDIVWUx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.DIVWU, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.DIVWUdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.DIVWUO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.DIVWUOdot, ThreeOperands (rd, ra, rb)) + +let parseMTSPR bin = + match pickBit bin 10u with + | 0b0u -> + let rs = getRegister (extract bin 25u 21u) |> OprReg + match concat (extract bin 15u 11u) (extract bin 20u 16u) 5 with + (* mtxer rd = mtspr rd,1 *) + | 0x1u -> struct (Op.MTXER, OneOperand rs) + (* mtlr rd = mtspr rd,8 *) + | 0x8u -> struct (Op.MTLR, OneOperand rs) + (* mtctr rd = mtspr rd,9 *) + | 0x9u -> struct (Op.MTCTR, OneOperand rs) + | _ -> + (* FIXME: SPRegister *) + let spr = + getSPRegister (concat (extract bin 15u 11u) (extract bin 20u 16u) 5) + struct (Op.MTSPR, TwoOperands (spr, rs)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseDCBIandICBI bin = + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 10u with + | 0b0u when extract bin 25u 21u = 0u -> + struct (Op.DCBI, TwoOperands (ra, rb)) + | 0b1u when extract bin 25u 21u = 0u -> + struct (Op.ICBI, TwoOperands (ra, rb)) + | _ -> raise ParsingFailureException + +let parseSTFIWX bin = + match pickBit bin 10u with + | 0b1u -> + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.STFIWX, ThreeOperands (frs, ra, rb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parseNANDx bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* 0:RC *) with + | 0b00u -> struct (Op.NAND, ThreeOperands (ra, rs, rb)) + | 0b01u -> struct (Op.NANDdot, ThreeOperands (ra, rs, rb)) + | _ (* 1x *) -> raise ParsingFailureException + +let parseDIVWx bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + match concat (pickBit bin 10u) (pickBit bin 0u) 1 (* OE:RC *) with + | 0b00u -> struct (Op.DIVW, ThreeOperands (rd, ra, rb)) + | 0b01u -> struct (Op.DIVWdot, ThreeOperands (rd, ra, rb)) + | 0b10u -> struct (Op.DIVWO, ThreeOperands (rd, ra, rb)) + | _ (* 11 *) -> struct (Op.DIVWOdot, ThreeOperands (rd, ra, rb)) + +let parseDCBZ bin = + match pickBit bin 10u with + | 0b1u when extract bin 25u 21u = 0u -> + let ra = getRegister (extract bin 20u 16u) |> OprReg + let rb = getRegister (extract bin 15u 11u) |> OprReg + struct (Op.DCBZ, TwoOperands (ra, rb)) + | _ (* 0 *) -> raise ParsingFailureException + +let parse1F bin = + match extract bin 9u 1u with + | 0x0u when pickBit bin 0u = 0u -> parseCMPandMCRXR bin + | 0x4u when pickBit bin 0u = 0u -> parseTW bin + | 0x8u -> parseSUBFCx bin + | 0xAu -> parseADDCx bin + | 0xBu when pickBit bin 10u = 0u -> parseMULHWUx bin + | 0x13u when pickBit bin 0u = 0u -> parseMFCR bin + (* FIXME: LWARX RegA = 0 *) + | 0x14u when pickBit bin 0u = 0u -> parseLWARX bin + | 0x15u when pickBit bin 0u = 0u -> parseLSWX bin + (* FIXME: LWBRX RegA = 0 *) + | 0x16u when pickBit bin 0u = 0u -> parseLWBRX bin + (* FIXME: LWZX / LFSX RegA = 0 *) + | 0x17u when pickBit bin 0u = 0u -> parseLWZXandLFSX bin + | 0x18u -> parseSLWxandSRWx bin + | 0x1Au -> parseCNTLZWx bin + | 0x1Cu -> parseANDx bin + | 0x20u when pickBit bin 0u = 0u -> parseCMPL bin + | 0x28u -> parseSUBFx bin + (* FIXME: DCBST RegA = 0 *) + | 0x36u when pickBit bin 0u = 0u -> parseDCBSTandTLBSYNC bin + (* FIXME: LWZUX / LFSUX RegA = 0 *) + | 0x37u when pickBit bin 0u = 0u -> parseLWZUXandLFSUX bin + | 0x3Cu -> parseANDCx bin + | 0x4Bu when pickBit bin 10u = 0u -> parseMULHWx bin + (* FIXME: SegRegister *) + | 0x53u when pickBit bin 0u = 0u -> parseMFMSRandMFSR bin + | 0x55u when pickBit bin 0u = 0u -> parseLSWI bin + (* FIXME: DCBF RegA = 0 / SYNC 0 *) + | 0x56u when pickBit bin 0u = 0u -> parseDCBFandSYNC bin + (* FIXME: LBZX / LFDX RegA = 0 *) + | 0x57u when pickBit bin 0u = 0u -> parseLBZXandLFDX bin + | 0x68u -> parseNEGx bin + (* FIXME: LBZUX / LFDUX RegA = 0 *) + | 0x77u when pickBit bin 0u = 0u -> parseLBZUXandLFDUX bin + | 0x7Cu -> parseNORx bin + | 0x88u -> parseSUBFEx bin + | 0x8Au -> parseADDEx bin + (* FIXME: CRM *) + | 0x90u when pickBit bin 0u = 0u -> parseMTCRF bin + | 0x92u when pickBit bin 0u = 0u -> parseMTMSR bin + | 0x93u -> parseMFSRIN bin + | 0x95u when pickBit bin 0u = 0u -> parseSTSWX bin + (* FIXME: STWCXdot / STWBRX RegA = 0 *) + | 0x96u -> parseSTWCXdotandSTWBRX bin + (* FIXME: STWX / STFSX RegA = 0 *) + | 0x97u when pickBit bin 0u = 0u -> parseSTWXandSTFSX bin + (* FIXME: STWUX / STFSUX RegA = 0 *) + | 0xB7u when pickBit bin 0u = 0u -> parseSTWUXandSTFSUX bin + | 0xC8u -> parseSUBFZEx bin + | 0xCAu -> parseADDZEx bin + (* FIXME: SegRegister *) + | 0xD2u when pickBit bin 0u = 0u -> parseMTSR bin + (* FIXME: SpecialRegister *) + | 0xD5u when pickBit bin 0u = 0u -> parseSTSWI bin + (* FIXME: STBX / STFDX RegA = 0 *) + | 0xD7u -> parseSTBXandSTFDX bin + | 0xE8u -> parseSUBFMEx bin + | 0xEAu -> parseADDMEx bin + | 0xEBu -> parseMULLWx bin + | 0xF2u -> parseMTSRIN bin + (* FIXME: DCBTST / DCBA RegA = 0 *) + | 0xF6u when pickBit bin 0u = 0u -> parseDCBTSTandDCBA bin + (* FIXME: STBUX / STFDUX RegA = 0 *) + | 0xF7u -> parseSTBUXandSTFDUX bin + | 0x10Au -> parseADDx bin + (* FIXME: DCBT / LHBRX RegA = 0 *) + | 0x116u when pickBit bin 0u = 0u -> parseDCBTandLHBRX bin + (* FIXME: LHZX RegA = 0 *) + | 0x117u when pickBit bin 0u = 0u -> parseLHZX bin + | 0x118u -> parseSRAWx bin + | 0x11Cu -> parseEQVx bin + | 0x132u -> parseTLBIE bin + | 0x136u when pickBit bin 0u = 0u -> parseECIWX bin + (* FIXME: LHZUX RegA = 0 *) + | 0x137u when pickBit bin 0u = 0u -> parseLHZUX bin + | 0x138u when pickBit bin 10u = 1u -> parseSRAWIx bin + | 0x13Cu -> parseXORx bin + (* FIXME: SpecialRegister *) + | 0x153u when pickBit bin 0u = 0u -> parseMFSPR bin + | 0x156u when pickBit bin 0u = 0u -> parseEIEIO bin + (* FIXME: LHAX RegA = 0 *) + | 0x157u when pickBit bin 0u = 0u -> parseLHAX bin + | 0x172u -> parseTLBIA bin + (* FIXME: TBRRegister *) + | 0x173u when pickBit bin 0u = 0u -> parseMFTB bin + (* FIXME: LHAUX RegA = 0 *) + | 0x177u when pickBit bin 0u = 0u -> parseLHAUX bin + (* FIXME: STHBRX RegA = 0 *) + | 0x196u when pickBit bin 0u = 0u -> parseSTHBRX bin + (* FIXME: STHX RegA = 0 *) + | 0x197u when pickBit bin 0u = 0u -> parseSTHX bin + | 0x19Au -> parseEXTSHx bin + | 0x19Cu -> parseORCx bin + | 0x1B6u when pickBit bin 0u = 0u -> parseECOWX bin + (* FIXME: STHUX RegA = 0 *) + | 0x1B7u when pickBit bin 0u = 0u -> parseSTHUX bin + | 0x1BAu -> parseEXTSBx bin + | 0x1BCu -> parseORx bin + | 0x1CBu -> parseDIVWUx bin + | 0x1D3u when pickBit bin 0u = 0u -> parseMTSPR bin + (* FIXME: DCBI / ICBI RegA = 0 *) + | 0x1D6u when pickBit bin 0u = 0u -> parseDCBIandICBI bin + (* FIXME: STFIWX RegA = 0 *) + | 0x1D7u when pickBit bin 0u = 0u -> parseSTFIWX bin + | 0x1DCu -> parseNANDx bin + | 0x1EBu -> parseDIVWx bin + (* FIXME: DCBZ RegA = 0 *) + | 0x1F6u when pickBit bin 0u = 0u -> parseDCBZ bin + | _ -> raise ParsingFailureException + +let parseLWZ bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LWZ, TwoOperands(rd, mem)) + +let parseLWZU bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LWZU, TwoOperands(rd, mem)) + +let parseLBZ bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LBZ, TwoOperands(rd, mem)) + +let parseLBZU bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LBZU, TwoOperands(rd, mem)) + +let parseSTW bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STW, TwoOperands(rs, mem)) + +let parseSTWU bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STWU, TwoOperands(rs, mem)) + +let parseSTB bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STB, TwoOperands(rs, mem)) + +let parseSTBU bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STBU, TwoOperands(rs, mem)) + +let parseLHZ bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LHZ, TwoOperands(rd, mem)) + +let parseLHZU bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LHZU, TwoOperands(rd, mem)) + +let parseLHA bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LHA, TwoOperands(rd, mem)) + +let parseLHAU bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LHAU, TwoOperands(rd, mem)) + +let parseSTH bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STH, TwoOperands(rs, mem)) + +let parseSTHU bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STHU, TwoOperands(rs, mem)) + +let parseLMW bin = + let rd = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LMW, TwoOperands(rd, mem)) + +let parseSTMW bin = + let rs = getRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STMW, TwoOperands(rs, mem)) + +let parseLFS bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LFS, TwoOperands(frd, mem)) + +let parseLFSU bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LFSU, TwoOperands(frd, mem)) + +let parseLFD bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LFD, TwoOperands(frd, mem)) + +let parseLFDU bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.LFDU, TwoOperands(frd, mem)) + +let parseSTFS bin = + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STFS, TwoOperands(frs, mem)) + +let parseSTFSU bin = + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STFSU, TwoOperands(frs, mem)) + +let parseSTFD bin = + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STFD, TwoOperands(frs, mem)) + +let parseSTFDU bin = + let frs = getFPRegister (extract bin 25u 21u) |> OprReg + let ra = getRegister (extract bin 20u 16u) + let d = extract bin 15u 0u |> uint64 + let value = signExtend 16 32 d |> int32 + let mem = (value, ra) |> OprMem (* d (rA) *) + struct (Op.STFDU, TwoOperands(frs, mem)) + +let parseFDIVSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FDIVS, ThreeOperands (frd, fra, frb)) + | _ (* 1 *) -> struct (Op.FDIVSdot, ThreeOperands (frd, fra, frb)) + +let parseFSUBSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FSUBS, ThreeOperands (frd, fra, frb)) + | _ (* 1 *) -> struct (Op.FSUBSdot, ThreeOperands (frd, fra, frb)) + +let parseFADDSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FADDS, ThreeOperands (frd, fra, frb)) + | _ (* 1 *) -> struct (Op.FADDSdot, ThreeOperands (frd, fra, frb)) + +let parseFSQRTSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FSQRTS, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FSQRTSdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFRESx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FRES, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FRESdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFMULSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 15u 11u = 0u -> + struct (Op.FMULS, ThreeOperands (frd, fra, frc)) + | 0b1u when extract bin 15u 11u = 0u -> + struct (Op.FMULSdot, ThreeOperands (frd, fra, frc)) + | _ -> raise ParsingFailureException + +let parseFMSUBSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FMSUBS, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FMSUBSdot, FourOperands (frd, fra, frc, frb)) + +let parseFMADDSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FMADDS, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FMADDSdot, FourOperands (frd, fra, frc, frb)) + +let parseFNMSUBSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FNMSUBS, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FNMSUBSdot, FourOperands (frd, fra, frc, frb)) + +let parseFNMADDSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FNMADDS, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FNMADDSdot, FourOperands (frd, fra, frc, frb)) + +let parse3B bin = + match extract bin 5u 1u with + | 0x12u when extract bin 10u 6u = 0u -> parseFDIVSx bin + | 0x14u when extract bin 10u 6u = 0u -> parseFSUBSx bin + | 0x15u when extract bin 10u 6u = 0u -> parseFADDSx bin + | 0x16u when extract bin 10u 6u = 0u -> parseFSQRTSx bin + | 0x18u when extract bin 10u 6u = 0u -> parseFRESx bin + | 0x19u -> parseFMULSx bin + | 0x1Cu -> parseFMSUBSx bin + | 0x1Du -> parseFMADDSx bin + | 0x1Eu -> parseFNMSUBSx bin + | 0x1Fu -> parseFNMADDSx bin + | _ -> raise ParsingFailureException + +let parseFCMPU bin = + match pickBit bin 0u with + | 0b0u when extract bin 22u 21u = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + struct (Op.FCMPU, ThreeOperands (crfd, fra, frb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseFRSPx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FRSP, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FRSPdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFCTIWx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FCTIW, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FCTIWdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFCTIWZx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FCTIWZ, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FCTIWZdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFDIVx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FDIV, ThreeOperands (frd, fra, frb)) + | _ (* 1 *) -> struct (Op.FDIVdot, ThreeOperands (frd, fra, frb)) + +let parseFSUBx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FSUB, ThreeOperands (frd, fra, frb)) + | _ (* 1 *) -> struct (Op.FSUBdot, ThreeOperands (frd, fra, frb)) + +let parseFADDx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FADD, ThreeOperands (frd, fra, frb)) + | _ (* 1 *) -> struct (Op.FADDdot, ThreeOperands (frd, fra, frb)) + +let parseFSQRTx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FSQRT, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FSQRTdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFSELx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FSEL, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FSELdot, FourOperands (frd, fra, frc, frb)) + +let parseFMULx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 15u 11u = 0u -> + struct (Op.FMUL, ThreeOperands (frd, fra, frc)) + | 0b1u when extract bin 15u 11u = 0u -> + struct (Op.FMULdot, ThreeOperands (frd, fra, frc)) + | _ -> raise ParsingFailureException + +let parseFRSQRTEx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when concat (extract bin 20u 16u) (extract bin 10u 6u) 5 = 0u -> + struct (Op.FRSQRTE, TwoOperands (frd, frb)) + | 0b1u when extract bin 15u 11u = 0u -> + struct (Op.FRSQRTEdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFMSUBx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FMSUB, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FMSUBdot, FourOperands (frd, fra, frc, frb)) + +let parseFMADDx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FMADD, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FMADDdot, FourOperands (frd, fra, frc, frb)) + +let parseFNMSUBx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FNMSUB, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FNMSUBdot, FourOperands (frd, fra, frc, frb)) + +let parseFNMADDx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + let frc = getFPRegister (extract bin 10u 6u) |> OprReg + match pickBit bin 0u with + | 0b0u -> struct (Op.FNMADD, FourOperands (frd, fra, frc, frb)) + | _ (* 1 *) -> struct (Op.FNMADDdot, FourOperands (frd, fra, frc, frb)) + +let parseFCMPO bin = + match pickBit bin 0u with + | 0b0u when extract bin 22u 21u = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let fra = getFPRegister (extract bin 20u 16u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + struct (Op.FCMPO, ThreeOperands (crfd, fra, frb)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseMTFSB1x bin = + let crbd = getFPSCRBit (extract bin 25u 21u) + match pickBit bin 0u with + | 0b0u when extract bin 20u 11u = 0u -> + (* FIXME: FPSCRegister *) + struct (Op.MTFSB1, OneOperand crbd) + | 0b1u when extract bin 20u 11u = 0u -> + (* FIXME: FPSCRegister *) + struct (Op.MTFSB1dot, OneOperand crbd) + | _ -> raise ParsingFailureException + +let parseFNEGx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FNEG, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FNEGdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseMCRFS bin = + match pickBit bin 0u with + | 0b0u when concat (extract bin 22u 21u) (extract bin 17u 11u) 2 = 0u -> + let crfd = getCondRegister (extract bin 25u 23u) |> OprReg + let crfs = getCondRegister (extract bin 20u 18u) |> OprReg + struct (Op.MCRFS, TwoOperands (crfd, crfs)) + | _ (* 1 *) -> raise ParsingFailureException + +let parseMTFSB0x bin = + let crbd = getFPSCRBit (extract bin 25u 21u) + match pickBit bin 0u with + | 0b0u when extract bin 20u 11u = 0u -> + (* FIXME: FPSCRegister *) + struct (Op.MTFSB0, OneOperand crbd) + | 0b1u when extract bin 20u 11u = 0u -> + (* FIXME: FPSCRegister *) + struct (Op.MTFSB0dot, OneOperand crbd) + | _ -> raise ParsingFailureException + +let parseFMRx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FMR, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FMRdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseMTFSFIx bin = + let crfd = extract bin 25u 23u |> uint64 |> OprImm + let imm = extract bin 15u 12u |> uint64 |> OprImm + match pickBit bin 0u with + | 0b0u when concat (extract bin 22u 16u) (pickBit bin 11u) 7 = 0u -> + struct (Op.MTFSFI, TwoOperands (crfd, imm)) + | 0b1u when concat (extract bin 22u 16u) (pickBit bin 11u) 7 = 0u -> + struct (Op.MTFSFIdot, TwoOperands (crfd, imm)) + | _ -> raise ParsingFailureException + +let parseFNABSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FNABS, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FNABSdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseFABSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 16u = 0u -> + struct (Op.FABS, TwoOperands (frd, frb)) + | 0b1u when extract bin 20u 16u = 0u -> + struct (Op.FABSdot, TwoOperands (frd, frb)) + | _ -> raise ParsingFailureException + +let parseMFFSx bin = + let frd = getFPRegister (extract bin 25u 21u) |> OprReg + match pickBit bin 0u with + | 0b0u when extract bin 20u 11u = 0u -> + struct (Op.MFFS, OneOperand frd) + | 0b1u when extract bin 20u 11u = 0u -> + struct (Op.MFFSdot, OneOperand frd) + | _ -> raise ParsingFailureException + +let parseMTFSFx bin = + let fm = extract bin 24u 17u |> uint64 |> OprImm + let frb = getFPRegister (extract bin 15u 11u) |> OprReg + (* FIXME: PowerISA v3.1 *) + match pickBit bin 0u with + | 0b0u -> struct (Op.MTFSF, TwoOperands (fm, frb)) + | 0b1u -> struct (Op.MTFSFdot, TwoOperands (fm, frb)) + | _ -> raise ParsingFailureException + +let parse3F bin = + match extract bin 5u 1u with + | 0x0u -> + match extract bin 10u 6u with + | 0x0u -> parseFCMPU bin + | 0x1u -> parseFCMPO bin + | 0x2u -> parseMCRFS bin + | _ -> raise ParsingFailureException + | 0x6u -> + (* FIXME: FPSCRegister *) + match extract bin 10u 6u with + | 0x1u -> parseMTFSB1x bin + (* FIXME: FPSCRegister *) + | 0x2u -> parseMTFSB0x bin + | 0x4u -> parseMTFSFIx bin + | _ -> raise ParsingFailureException + | 0x7u -> + match extract bin 10u 6u with + | 0x12u -> parseMFFSx bin + | 0x16u -> parseMTFSFx bin + | _ -> raise ParsingFailureException + | 0x8u -> + match extract bin 10u 6u with + | 0x1u -> parseFNEGx bin + | 0x2u -> parseFMRx bin + | 0x4u -> parseFNABSx bin + | 0x8u -> parseFABSx bin + | _ -> raise ParsingFailureException + | 0xCu when extract bin 10u 6u = 0u -> parseFRSPx bin + | 0xEu when extract bin 10u 6u = 0u -> parseFCTIWx bin + | 0xFu when extract bin 10u 6u = 0u -> parseFCTIWZx bin + | 0x12u when extract bin 10u 6u = 0u -> parseFDIVx bin + | 0x14u when extract bin 10u 6u = 0u -> parseFSUBx bin + | 0x15u when extract bin 10u 6u = 0u -> parseFADDx bin + | 0x16u when extract bin 10u 6u = 0u -> parseFSQRTx bin + | 0x17u -> parseFSELx bin + | 0x19u -> parseFMULx bin + | 0x1Au -> parseFRSQRTEx bin + | 0x1Cu -> parseFMSUBx bin + | 0x1Du -> parseFMADDx bin + | 0x1Eu -> parseFNMSUBx bin + | 0x1Fu -> parseFNMADDx bin + | _ -> raise ParsingFailureException + +let private parseInstruction bin addr = + match extract bin 31u 26u with + | 0x3u -> parseTWI bin + | 0x7u -> parseMULLI bin + | 0x8u -> parseSUBFIC bin + | 0xAu -> parseCMPLI bin + | 0xBu -> parseCMPI bin + | 0xCu -> parseADDIC bin + | 0xDu -> parseADDICdot bin + | 0xEu -> parseADDI bin + | 0xFu -> parseADDIS bin + | 0x10u -> parseBCx bin + | 0x11u when pickBit bin 0u = 0u -> parseSC bin + | 0x12u -> parseBx bin addr + | 0x13u -> parse13 bin + | 0x14u -> parseRLWIMIx bin + | 0x15u -> parseRLWINMx bin + | 0x17u -> parseRLWNMx bin + | 0x18u -> parseORI bin + | 0x19u -> parseORIS bin + | 0x1Au -> parseXORI bin + | 0x1Bu -> parseXORIS bin + | 0x1Cu -> parseANDIdot bin + | 0x1Du -> parseANDISdot bin + | 0x1Fu -> parse1F bin + | 0x20u -> parseLWZ bin + | 0x21u -> parseLWZU bin + | 0x22u -> parseLBZ bin + | 0x23u -> parseLBZU bin + | 0x24u -> parseSTW bin + | 0x25u -> parseSTWU bin + | 0x26u -> parseSTB bin + | 0x27u -> parseSTBU bin + | 0x28u -> parseLHZ bin + | 0x29u -> parseLHZU bin + | 0x2Au -> parseLHA bin + | 0x2Bu -> parseLHAU bin + | 0x2Cu -> parseSTH bin + | 0x2Du -> parseSTHU bin + | 0x2Eu -> parseLMW bin + | 0x2Fu -> parseSTMW bin + | 0x30u -> parseLFS bin + | 0x31u -> parseLFSU bin + | 0x32u -> parseLFD bin + | 0x33u -> parseLFDU bin + | 0x34u -> parseSTFS bin + | 0x35u -> parseSTFSU bin + | 0x36u -> parseSTFD bin + | 0x37u -> parseSTFDU bin + | 0x3Bu -> parse3B bin + | 0x3Fu -> parse3F bin + | _ -> raise ParsingFailureException + +let parse (span: ByteSpan) (reader: IBinReader) addr = + let bin = reader.ReadUInt32 (span, 0) + let struct (opcode, operands) = parseInstruction bin addr + let insInfo = + { Address = addr + NumBytes = 4u + Opcode = opcode + Operands = operands + OperationSize = 32 + EffectiveAddress = 0UL } + PPC32Instruction (addr, 4u, insInfo) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32RegExprs.fs b/src/FrontEnd/BinLifter/PPC32/PPC32RegExprs.fs index 2c1ebc1f..f14ac9a5 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32RegExprs.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32RegExprs.fs @@ -25,16 +25,255 @@ namespace B2R2.FrontEnd.BinLifter.PPC32 open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (PPC32RegisterSet.singleton t) +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name (* Registers *) let regType = WordSize.toRegType wordSize + member val R0 = var regType (Register.toRegID Register.R0) "R0" with get + member val R1 = var regType (Register.toRegID Register.R1) "R1" with get + member val R2 = var regType (Register.toRegID Register.R2) "R2" with get + member val R3 = var regType (Register.toRegID Register.R3) "R3" with get + member val R4 = var regType (Register.toRegID Register.R4) "R4" with get + member val R5 = var regType (Register.toRegID Register.R5) "R5" with get + member val R6 = var regType (Register.toRegID Register.R6) "R6" with get + member val R7 = var regType (Register.toRegID Register.R7) "R7" with get + member val R8 = var regType (Register.toRegID Register.R8) "R8" with get + member val R9 = var regType (Register.toRegID Register.R9) "R9" with get + member val R10 = var regType (Register.toRegID Register.R10) "R10" with get + member val R11 = var regType (Register.toRegID Register.R11) "R11" with get + member val R12 = var regType (Register.toRegID Register.R12) "R12" with get + member val R13 = var regType (Register.toRegID Register.R13) "R13" with get + member val R14 = var regType (Register.toRegID Register.R14) "R14" with get + member val R15 = var regType (Register.toRegID Register.R15) "R15" with get + member val R16 = var regType (Register.toRegID Register.R16) "R16" with get + member val R17 = var regType (Register.toRegID Register.R17) "R17" with get + member val R18 = var regType (Register.toRegID Register.R18) "R18" with get + member val R19 = var regType (Register.toRegID Register.R19) "R19" with get + member val R20 = var regType (Register.toRegID Register.R20) "R20" with get + member val R21 = var regType (Register.toRegID Register.R21) "R21" with get + member val R22 = var regType (Register.toRegID Register.R22) "R22" with get + member val R23 = var regType (Register.toRegID Register.R23) "R23" with get + member val R24 = var regType (Register.toRegID Register.R24) "R24" with get + member val R25 = var regType (Register.toRegID Register.R25) "R25" with get + member val R26 = var regType (Register.toRegID Register.R26) "R26" with get + member val R27 = var regType (Register.toRegID Register.R27) "R27" with get + member val R28 = var regType (Register.toRegID Register.R28) "R28" with get + member val R29 = var regType (Register.toRegID Register.R29) "R29" with get + member val R30 = var regType (Register.toRegID Register.R30) "R30" with get + member val R31 = var regType (Register.toRegID Register.R31) "R31" with get + member val F0 = var 64 (Register.toRegID Register.F0) "F0" with get + member val F1 = var 64 (Register.toRegID Register.F1) "F1" with get + member val F2 = var 64 (Register.toRegID Register.F2) "F2" with get + member val F3 = var 64 (Register.toRegID Register.F3) "F3" with get + member val F4 = var 64 (Register.toRegID Register.F4) "F4" with get + member val F5 = var 64 (Register.toRegID Register.F5) "F5" with get + member val F6 = var 64 (Register.toRegID Register.F6) "F6" with get + member val F7 = var 64 (Register.toRegID Register.F7) "F7" with get + member val F8 = var 64 (Register.toRegID Register.F8) "F8" with get + member val F9 = var 64 (Register.toRegID Register.F9) "F9" with get + member val F10 = var 64 (Register.toRegID Register.F10) "F10" with get + member val F11 = var 64 (Register.toRegID Register.F11) "F11" with get + member val F12 = var 64 (Register.toRegID Register.F12) "F12" with get + member val F13 = var 64 (Register.toRegID Register.F13) "F13" with get + member val F14 = var 64 (Register.toRegID Register.F14) "F14" with get + member val F15 = var 64 (Register.toRegID Register.F15) "F15" with get + member val F16 = var 64 (Register.toRegID Register.F16) "F16" with get + member val F17 = var 64 (Register.toRegID Register.F17) "F17" with get + member val F18 = var 64 (Register.toRegID Register.F18) "F18" with get + member val F19 = var 64 (Register.toRegID Register.F19) "F19" with get + member val F20 = var 64 (Register.toRegID Register.F20) "F20" with get + member val F21 = var 64 (Register.toRegID Register.F21) "F21" with get + member val F22 = var 64 (Register.toRegID Register.F22) "F22" with get + member val F23 = var 64 (Register.toRegID Register.F23) "F23" with get + member val F24 = var 64 (Register.toRegID Register.F24) "F24" with get + member val F25 = var 64 (Register.toRegID Register.F25) "F25" with get + member val F26 = var 64 (Register.toRegID Register.F26) "F26" with get + member val F27 = var 64 (Register.toRegID Register.F27) "F27" with get + member val F28 = var 64 (Register.toRegID Register.F28) "F28" with get + member val F29 = var 64 (Register.toRegID Register.F29) "F29" with get + member val F30 = var 64 (Register.toRegID Register.F30) "F30" with get + member val F31 = var 64 (Register.toRegID Register.F31) "F31" with get + member val CR0_0 = + var 1 (Register.toRegID Register.CR0_0) "CR0_0" with get + member val CR0_1 = + var 1 (Register.toRegID Register.CR0_1) "CR0_1" with get + member val CR0_2 = + var 1 (Register.toRegID Register.CR0_2) "CR0_2" with get + member val CR0_3 = + var 1 (Register.toRegID Register.CR0_3) "CR0_3" with get + member val CR1_0 = + var 1 (Register.toRegID Register.CR1_0) "CR1_0" with get + member val CR1_1 = + var 1 (Register.toRegID Register.CR1_1) "CR1_1" with get + member val CR1_2 = + var 1 (Register.toRegID Register.CR1_2) "CR1_2" with get + member val CR1_3 = + var 1 (Register.toRegID Register.CR1_3) "CR1_3" with get + member val CR2_0 = + var 1 (Register.toRegID Register.CR2_0) "CR2_0" with get + member val CR2_1 = + var 1 (Register.toRegID Register.CR2_1) "CR2_1" with get + member val CR2_2 = + var 1 (Register.toRegID Register.CR2_2) "CR2_2" with get + member val CR2_3 = + var 1 (Register.toRegID Register.CR2_3) "CR2_3" with get + member val CR3_0 = + var 1 (Register.toRegID Register.CR3_0) "CR3_0" with get + member val CR3_1 = + var 1 (Register.toRegID Register.CR3_1) "CR3_1" with get + member val CR3_2 = + var 1 (Register.toRegID Register.CR3_2) "CR3_2" with get + member val CR3_3 = + var 1 (Register.toRegID Register.CR3_3) "CR3_3" with get + member val CR4_0 = + var 1 (Register.toRegID Register.CR4_0) "CR4_0" with get + member val CR4_1 = + var 1 (Register.toRegID Register.CR4_1) "CR4_1" with get + member val CR4_2 = + var 1 (Register.toRegID Register.CR4_2) "CR4_2" with get + member val CR4_3 = + var 1 (Register.toRegID Register.CR4_3) "CR4_3" with get + member val CR5_0 = + var 1 (Register.toRegID Register.CR5_0) "CR5_0" with get + member val CR5_1 = + var 1 (Register.toRegID Register.CR5_1) "CR5_1" with get + member val CR5_2 = + var 1 (Register.toRegID Register.CR5_2) "CR5_2" with get + member val CR5_3 = + var 1 (Register.toRegID Register.CR5_3) "CR5_3" with get + member val CR6_0 = + var 1 (Register.toRegID Register.CR6_0) "CR6_0" with get + member val CR6_1 = + var 1 (Register.toRegID Register.CR6_1) "CR6_1" with get + member val CR6_2 = + var 1 (Register.toRegID Register.CR6_2) "CR6_2" with get + member val CR6_3 = + var 1 (Register.toRegID Register.CR6_3) "CR6_3" with get + member val CR7_0 = + var 1 (Register.toRegID Register.CR7_0) "CR7_0" with get + member val CR7_1 = + var 1 (Register.toRegID Register.CR7_1) "CR7_1" with get + member val CR7_2 = + var 1 (Register.toRegID Register.CR7_2) "CR7_2" with get + member val CR7_3 = + var 1 (Register.toRegID Register.CR7_3) "CR7_3" with get + member val FPSCR = + var 32 (Register.toRegID Register.FPSCR) "FPSCR" with get + member val XER = var 32 (Register.toRegID Register.XER) "XER" with get + member val LR = var regType (Register.toRegID Register.LR) "LR" with get + member val CTR = var regType (Register.toRegID Register.CTR) "CTR" with get + member val PVR = var 32 (Register.toRegID Register.PVR) "PVR" with get + member val RES = var 1 (Register.toRegID Register.RES) "RES" with get + member __.GetRegVar (name) = match name with - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | R.R0 -> __.R0 + | R.R1 -> __.R1 + | R.R2 -> __.R2 + | R.R3 -> __.R3 + | R.R4 -> __.R4 + | R.R5 -> __.R5 + | R.R6 -> __.R6 + | R.R7 -> __.R7 + | R.R8 -> __.R8 + | R.R9 -> __.R9 + | R.R10 -> __.R10 + | R.R11 -> __.R11 + | R.R12 -> __.R12 + | R.R13 -> __.R13 + | R.R14 -> __.R14 + | R.R15 -> __.R15 + | R.R16 -> __.R16 + | R.R17 -> __.R17 + | R.R18 -> __.R18 + | R.R19 -> __.R19 + | R.R20 -> __.R20 + | R.R21 -> __.R21 + | R.R22 -> __.R22 + | R.R23 -> __.R23 + | R.R24 -> __.R24 + | R.R25 -> __.R25 + | R.R26 -> __.R26 + | R.R27 -> __.R27 + | R.R28 -> __.R28 + | R.R29 -> __.R29 + | R.R30 -> __.R30 + | R.R31 -> __.R31 + | R.F0 -> __.F0 + | R.F1 -> __.F1 + | R.F2 -> __.F2 + | R.F3 -> __.F3 + | R.F4 -> __.F4 + | R.F5 -> __.F5 + | R.F6 -> __.F6 + | R.F7 -> __.F7 + | R.F8 -> __.F8 + | R.F9 -> __.F9 + | R.F10 -> __.F10 + | R.F11 -> __.F11 + | R.F12 -> __.F12 + | R.F13 -> __.F13 + | R.F14 -> __.F14 + | R.F15 -> __.F15 + | R.F16 -> __.F16 + | R.F17 -> __.F17 + | R.F18 -> __.F18 + | R.F19 -> __.F19 + | R.F20 -> __.F20 + | R.F21 -> __.F21 + | R.F22 -> __.F22 + | R.F23 -> __.F23 + | R.F24 -> __.F24 + | R.F25 -> __.F25 + | R.F26 -> __.F26 + | R.F27 -> __.F27 + | R.F28 -> __.F28 + | R.F29 -> __.F29 + | R.F30 -> __.F30 + | R.F31 -> __.F31 + | R.CR0_0 -> __.CR0_0 + | R.CR0_1 -> __.CR0_1 + | R.CR0_2 -> __.CR0_2 + | R.CR0_3 -> __.CR0_3 + | R.CR1_0 -> __.CR1_0 + | R.CR1_1 -> __.CR1_1 + | R.CR1_2 -> __.CR1_2 + | R.CR1_3 -> __.CR1_3 + | R.CR2_0 -> __.CR2_0 + | R.CR2_1 -> __.CR2_1 + | R.CR2_2 -> __.CR2_2 + | R.CR2_3 -> __.CR2_3 + | R.CR3_0 -> __.CR3_0 + | R.CR3_1 -> __.CR3_1 + | R.CR3_2 -> __.CR3_2 + | R.CR3_3 -> __.CR3_3 + | R.CR4_0 -> __.CR4_0 + | R.CR4_1 -> __.CR4_1 + | R.CR4_2 -> __.CR4_2 + | R.CR4_3 -> __.CR4_3 + | R.CR5_0 -> __.CR5_0 + | R.CR5_1 -> __.CR5_1 + | R.CR5_2 -> __.CR5_2 + | R.CR5_3 -> __.CR5_3 + | R.CR6_0 -> __.CR6_0 + | R.CR6_1 -> __.CR6_1 + | R.CR6_2 -> __.CR6_2 + | R.CR6_3 -> __.CR6_3 + | R.CR7_0 -> __.CR7_0 + | R.CR7_1 -> __.CR7_1 + | R.CR7_2 -> __.CR7_2 + | R.CR7_3 -> __.CR7_3 + | R.FPSCR -> __.FPSCR + | R.XER -> __.XER + | R.LR -> __.LR + | R.CTR -> __.CTR + | R.PVR -> __.PVR + | R.RES -> __.RES + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32Register.fs b/src/FrontEnd/BinLifter/PPC32/PPC32Register.fs index 88b7eb4d..c62f3eee 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32Register.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32Register.fs @@ -91,6 +91,7 @@ type Register = | F29 = 0x3D | F30 = 0x3E | F31 = 0x3F + /// CR0 - CR7 is 4bit chunk of CR. | CR0 = 0x40 | CR1 = 0x41 | CR2 = 0x42 @@ -99,14 +100,87 @@ type Register = | CR5 = 0x45 | CR6 = 0x46 | CR7 = 0x47 + /// CR0_0 is the 1st 1-bit chunk of CR0. + | CR0_0 = 0x48 + /// CR0_1 is the 2nd 1-bit chunk of CR0. + | CR0_1 = 0x49 + /// CR0_2 is the 3rd 1-bit chunk of CR0. + | CR0_2 = 0x4A + /// CR0_3 is the 4th 1-bit chunk of CR0. + | CR0_3 = 0x4B + /// CR1_0 is the 1st 1-bit chunk of CR1. + | CR1_0 = 0x4C + /// CR1_1 is the 2nd 1-bit chunk of CR1. + | CR1_1 = 0x4D + /// CR1_2 is the 3rd 1-bit chunk of CR1. + | CR1_2 = 0x4E + /// CR1_3 is the 4th 1-bit chunk of CR1. + | CR1_3 = 0x4F + /// CR2_0 is the 1st 1-bit chunk of CR2. + | CR2_0 = 0x50 + /// CR2_1 is the 2nd 1-bit chunk of CR2. + | CR2_1 = 0x51 + /// CR2_2 is the 3rd 1-bit chunk of CR2. + | CR2_2 = 0x52 + /// CR2_3 is the 4th 1-bit chunk of CR2. + | CR2_3 = 0x53 + /// CR3_0 is the 1st 1-bit chunk of CR3. + | CR3_0 = 0x54 + /// CR3_1 is the 2nd 1-bit chunk of CR3. + | CR3_1 = 0x55 + /// CR3_2 is the 3rd 1-bit chunk of CR3. + | CR3_2 = 0x56 + /// CR3_3 is the 4th 1-bit chunk of CR3. + | CR3_3 = 0x57 + /// CR4_0 is the 1st 1-bit chunk of CR4. + | CR4_0 = 0x58 + /// CR4_1 is the 2nd 1-bit chunk of CR4. + | CR4_1 = 0x59 + /// CR4_2 is the 3rd 1-bit chunk of CR4. + | CR4_2 = 0x5A + /// CR4_3 is the 4th 1-bit chunk of CR4. + | CR4_3 = 0x5B + /// CR5_0 is the 1st 1-bit chunk of CR5. + | CR5_0 = 0x5C + /// CR5_1 is the 2nd 1-bit chunk of CR5. + | CR5_1 = 0x5D + /// CR5_2 is the 3rd 1-bit chunk of CR5. + | CR5_2 = 0x5E + /// CR5_3 is the 4th 1-bit chunk of CR5. + | CR5_3 = 0x5F + /// CR6_0 is the 1st 1-bit chunk of CR6. + | CR6_0 = 0x60 + /// CR6_1 is the 2nd 1-bit chunk of CR6. + | CR6_1 = 0x61 + /// CR6_2 is the 3rd 1-bit chunk of CR6. + | CR6_2 = 0x62 + /// CR6_3 is the 4th 1-bit chunk of CR6. + | CR6_3 = 0x63 + /// CR7_0 is the 1st 1-bit chunk of CR7. + | CR7_0 = 0x64 + /// CR7_1 is the 2nd 1-bit chunk of CR7. + | CR7_1 = 0x65 + /// CR7_2 is the 3rd 1-bit chunk of CR7. + | CR7_2 = 0x66 + /// CR7_3 is the 4th 1-bit chunk of CR7. + | CR7_3 = 0x67 + /// XER Register. + | XER = 0x70 + /// LR Register. + | LR = 0x71 + /// Count Register. + | CTR = 0x72 + /// FPSCR Register + | FPSCR = 0x73 + /// Processor Version Register. + | PVR = 0x74 + /// Pseudo register for Reserve. + | RES = 0x75 /// Shortcut for Register type. type internal R = Register -type internal F = Register -type internal CR = Register -/// This module exposes several useful functions to handle PPC32 -/// registers. +/// This module exposes several useful functions to handle PPC32 registers. [] module Register = let inline ofRegID (n: RegisterID): Register = @@ -117,7 +191,7 @@ module Register = let ofString (str: string) = match str.ToLower () with - | "r0" -> R.R0 (* FIXME: Add Registers *) + | "r0" -> R.R0 | "r1" -> R.R1 | "r2" -> R.R2 | "r3" -> R.R3 @@ -149,50 +223,83 @@ module Register = | "r29" -> R.R29 | "r30" -> R.R30 | "r31" -> R.R31 - | "f0" -> F.F0 - | "f1" -> F.F1 - | "f2" -> F.F2 - | "f3" -> F.F3 - | "f4" -> F.F4 - | "f5" -> F.F5 - | "f6" -> F.F6 - | "f7" -> F.F7 - | "f8" -> F.F8 - | "f9" -> F.F9 - | "f10" -> F.F10 - | "f11" -> F.F11 - | "f12" -> F.F12 - | "f13" -> F.F13 - | "f14" -> F.F14 - | "f15" -> F.F15 - | "f16" -> F.F16 - | "f17" -> F.F17 - | "f18" -> F.F18 - | "f19" -> F.F19 - | "f20" -> F.F20 - | "f21" -> F.F21 - | "f22" -> F.F22 - | "f23" -> F.F23 - | "f24" -> F.F24 - | "f25" -> F.F25 - | "f26" -> F.F26 - | "f27" -> F.F27 - | "f28" -> F.F28 - | "f29" -> F.F29 - | "f30" -> F.F30 - | "f31" -> F.F31 - | "cr0" -> CR.CR0 - | "cr1" -> CR.CR1 - | "cr2" -> CR.CR2 - | "cr3" -> CR.CR3 - | "cr4" -> CR.CR4 - | "cr5" -> CR.CR5 - | "cr6" -> CR.CR6 - | "cr7" -> CR.CR7 + | "f0" -> R.F0 + | "f1" -> R.F1 + | "f2" -> R.F2 + | "f3" -> R.F3 + | "f4" -> R.F4 + | "f5" -> R.F5 + | "f6" -> R.F6 + | "f7" -> R.F7 + | "f8" -> R.F8 + | "f9" -> R.F9 + | "f10" -> R.F10 + | "f11" -> R.F11 + | "f12" -> R.F12 + | "f13" -> R.F13 + | "f14" -> R.F14 + | "f15" -> R.F15 + | "f16" -> R.F16 + | "f17" -> R.F17 + | "f18" -> R.F18 + | "f19" -> R.F19 + | "f20" -> R.F20 + | "f21" -> R.F21 + | "f22" -> R.F22 + | "f23" -> R.F23 + | "f24" -> R.F24 + | "f25" -> R.F25 + | "f26" -> R.F26 + | "f27" -> R.F27 + | "f28" -> R.F28 + | "f29" -> R.F29 + | "f30" -> R.F30 + | "f31" -> R.F31 + | "cr0" -> R.CR0 + | "cr1" -> R.CR1 + | "cr2" -> R.CR2 + | "cr3" -> R.CR3 + | "cr4" -> R.CR4 + | "cr5" -> R.CR5 + | "cr6" -> R.CR6 + | "cr7" -> R.CR7 + | "cr0_0" -> R.CR0_0 + | "cr0_1" -> R.CR0_1 + | "cr0_2" -> R.CR0_2 + | "cr0_3" -> R.CR0_3 + | "cr1_0" -> R.CR1_0 + | "cr1_1" -> R.CR1_1 + | "cr1_2" -> R.CR1_2 + | "cr1_3" -> R.CR1_3 + | "cr2_0" -> R.CR2_0 + | "cr2_1" -> R.CR2_1 + | "cr2_2" -> R.CR2_2 + | "cr2_3" -> R.CR2_3 + | "cr3_0" -> R.CR3_0 + | "cr3_1" -> R.CR3_1 + | "cr3_2" -> R.CR3_2 + | "cr3_3" -> R.CR3_3 + | "cr4_0" -> R.CR4_0 + | "cr4_1" -> R.CR4_1 + | "cr4_2" -> R.CR4_2 + | "cr4_3" -> R.CR4_3 + | "cr5_0" -> R.CR5_0 + | "cr5_1" -> R.CR5_1 + | "cr5_2" -> R.CR5_2 + | "cr5_3" -> R.CR5_3 + | "cr6_0" -> R.CR6_0 + | "cr6_1" -> R.CR6_1 + | "cr6_2" -> R.CR6_2 + | "cr6_3" -> R.CR6_3 + | "cr7_0" -> R.CR7_0 + | "cr7_1" -> R.CR7_1 + | "cr7_2" -> R.CR7_2 + | "cr7_3" -> R.CR7_3 + | "res" -> R.RES | _ -> Utils.impossible () let toString = function - | R.R0 -> "r0" (* FIXME: Add Registers *) + | R.R0 -> "r0" | R.R1 -> "r1" | R.R2 -> "r2" | R.R3 -> "r3" @@ -224,44 +331,77 @@ module Register = | R.R29 -> "r29" | R.R30 -> "r30" | R.R31 -> "r31" - | F.F0 -> "f0" - | F.F1 -> "f1" - | F.F2 -> "f2" - | F.F3 -> "f3" - | F.F4 -> "f4" - | F.F5 -> "f5" - | F.F6 -> "f6" - | F.F7 -> "f7" - | F.F8 -> "f8" - | F.F9 -> "f9" - | F.F10 -> "f10" - | F.F11 -> "f11" - | F.F12 -> "f12" - | F.F13 -> "f13" - | F.F14 -> "f14" - | F.F15 -> "f15" - | F.F16 -> "f16" - | F.F17 -> "f17" - | F.F18 -> "f18" - | F.F19 -> "f19" - | F.F20 -> "f20" - | F.F21 -> "f21" - | F.F22 -> "f22" - | F.F23 -> "f23" - | F.F24 -> "f24" - | F.F25 -> "f25" - | F.F26 -> "f26" - | F.F27 -> "f27" - | F.F28 -> "f28" - | F.F29 -> "f29" - | F.F30 -> "f30" - | F.F31 -> "f31" - | CR.CR0 -> "cr0" - | CR.CR1 -> "cr1" - | CR.CR2 -> "cr2" - | CR.CR3 -> "cr3" - | CR.CR4 -> "cr4" - | CR.CR5 -> "cr5" - | CR.CR6 -> "cr6" - | CR.CR7 -> "cr7" + | R.F0 -> "f0" + | R.F1 -> "f1" + | R.F2 -> "f2" + | R.F3 -> "f3" + | R.F4 -> "f4" + | R.F5 -> "f5" + | R.F6 -> "f6" + | R.F7 -> "f7" + | R.F8 -> "f8" + | R.F9 -> "f9" + | R.F10 -> "f10" + | R.F11 -> "f11" + | R.F12 -> "f12" + | R.F13 -> "f13" + | R.F14 -> "f14" + | R.F15 -> "f15" + | R.F16 -> "f16" + | R.F17 -> "f17" + | R.F18 -> "f18" + | R.F19 -> "f19" + | R.F20 -> "f20" + | R.F21 -> "f21" + | R.F22 -> "f22" + | R.F23 -> "f23" + | R.F24 -> "f24" + | R.F25 -> "f25" + | R.F26 -> "f26" + | R.F27 -> "f27" + | R.F28 -> "f28" + | R.F29 -> "f29" + | R.F30 -> "f30" + | R.F31 -> "f31" + | R.CR0 -> "cr0" + | R.CR1 -> "cr1" + | R.CR2 -> "cr2" + | R.CR3 -> "cr3" + | R.CR4 -> "cr4" + | R.CR5 -> "cr5" + | R.CR6 -> "cr6" + | R.CR7 -> "cr7" + | R.CR0_0 -> "cr0_0" + | R.CR0_1 -> "cr0_1" + | R.CR0_2 -> "cr0_2" + | R.CR0_3 -> "cr0_3" + | R.CR1_0 -> "cr1_0" + | R.CR1_1 -> "cr1_1" + | R.CR1_2 -> "cr1_2" + | R.CR1_3 -> "cr1_3" + | R.CR2_0 -> "cr2_0" + | R.CR2_1 -> "cr2_1" + | R.CR2_2 -> "cr2_2" + | R.CR2_3 -> "cr2_3" + | R.CR3_0 -> "cr3_0" + | R.CR3_1 -> "cr3_1" + | R.CR3_2 -> "cr3_2" + | R.CR3_3 -> "cr3_3" + | R.CR4_0 -> "cr4_0" + | R.CR4_1 -> "cr4_1" + | R.CR4_2 -> "cr4_2" + | R.CR4_3 -> "cr4_3" + | R.CR5_0 -> "cr5_0" + | R.CR5_1 -> "cr5_1" + | R.CR5_2 -> "cr5_2" + | R.CR5_3 -> "cr5_3" + | R.CR6_0 -> "cr6_0" + | R.CR6_1 -> "cr6_1" + | R.CR6_2 -> "cr6_2" + | R.CR6_3 -> "cr6_3" + | R.CR7_0 -> "cr7_0" + | R.CR7_1 -> "cr7_1" + | R.CR7_2 -> "cr7_2" + | R.CR7_3 -> "cr7_3" + | R.RES -> "res" | _ -> Utils.impossible () \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32RegisterBay.fs b/src/FrontEnd/BinLifter/PPC32/PPC32RegisterBay.fs deleted file mode 100644 index eb333870..00000000 --- a/src/FrontEnd/BinLifter/PPC32/PPC32RegisterBay.fs +++ /dev/null @@ -1,58 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.PPC32 - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR.LowUIR - -type PPC32RegisterBay () = - - inherit RegisterBay () - - override __.GetAllRegExprs () = Utils.futureFeature () - - override __.GetAllRegNames () = Utils.futureFeature () - - override __.GetGeneralRegExprs () = Utils.futureFeature () - - override __.RegIDFromRegExpr (e) = - match e.E with - | Var (_, id, _ ,_) -> id - | PCVar (_, _) -> Register.toRegID Register.R0 - | _ -> failwith "not a register expression" - - override __.RegIDToRegExpr (id) = Utils.futureFeature () - override __.StrToRegExpr _s = Utils.futureFeature () - override __.RegIDFromString _s = Utils.futureFeature () - override __.RegIDToString _ = Utils.futureFeature () - override __.RegIDToRegType _ = Utils.futureFeature () - override __.GetRegisterAliases _ = Utils.futureFeature () - override __.ProgramCounter = Utils.futureFeature () - override __.StackPointer = Utils.futureFeature () - override __.FramePointer = Utils.futureFeature () - override __.IsProgramCounter _ = Utils.futureFeature () - override __.IsStackPointer _ = Utils.futureFeature () - override __.IsFramePointer _ = Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32RegisterFactory.fs b/src/FrontEnd/BinLifter/PPC32/PPC32RegisterFactory.fs new file mode 100644 index 00000000..e805043c --- /dev/null +++ b/src/FrontEnd/BinLifter/PPC32/PPC32RegisterFactory.fs @@ -0,0 +1,188 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PPC32 + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type PPC32RegisterFactory (wordSize, r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + [ r.R0; r.R1; r.R2; r.R3; r.R4; r.R5; r.R6; r.R7; r.R8; r.R9; r.R10; r.R11 + r.R12; r.R13; r.R14; r.R15; r.R16; r.R17; r.R18; r.R19; r.R20; r.R21 + r.R22; r.R23; r.R24; r.R25; r.R26; r.R27; r.R28; r.R29; r.R30; r.R31 + r.F0; r.F1; r.F2; r.F3; r.F4; r.F5; r.F6; r.F7; r.F8; r.F9; r.F10; r.F11 + r.F12; r.F13; r.F14; r.F15; r.F16; r.F17; r.F18; r.F19; r.F20; r.F21 + r.F22; r.F23; r.F24; r.F25; r.F26; r.F27; r.F28; r.F29; r.F30; r.F31 + r.CR0_0; r.CR0_1; r.CR0_2; r.CR0_3; r.CR1_0; r.CR1_1; r.CR1_2; r.CR1_3; + r.CR2_0; r.CR2_1; r.CR2_2; r.CR2_3; r.CR3_0; r.CR3_2; r.CR3_2; r.CR3_3; + r.CR4_0; r.CR4_1; r.CR4_2; r.CR4_3; r.CR5_0; r.CR5_1; r.CR5_2; r.CR5_3; + r.CR6_0; r.CR6_1; r.CR6_2; r.CR6_3; r.CR7_0; r.CR7_1; r.CR7_2; r.CR7_3; ] + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + [ r.R0; r.R1; r.R2; r.R3; r.R4; r.R5; r.R6; r.R7; r.R8; r.R9; r.R10; r.R11 + r.R12; r.R13; r.R14; r.R15; r.R16; r.R17; r.R18; r.R19; r.R20; r.R21 + r.R22; r.R23; r.R24; r.R25; r.R26; r.R27; r.R28; r.R29; r.R30; r.R31 ] + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_, id, _) -> id + | _ -> raise InvalidRegisterException + + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> r.GetRegVar + + override __.StrToRegExpr s = + match s.ToLowerInvariant () with + | "r0" -> r.R0 + | "r1" -> r.R1 + | "r2" -> r.R2 + | "r3" -> r.R3 + | "r4" -> r.R4 + | "r5" -> r.R5 + | "r6" -> r.R6 + | "r7" -> r.R7 + | "r8" -> r.R8 + | "r9" -> r.R9 + | "r10" -> r.R10 + | "r11" -> r.R11 + | "r12" -> r.R12 + | "r13" -> r.R13 + | "r14" -> r.R14 + | "r15" -> r.R15 + | "r16" -> r.R16 + | "r17" -> r.R17 + | "r18" -> r.R18 + | "r19" -> r.R19 + | "r20" -> r.R20 + | "r21" -> r.R21 + | "r22" -> r.R22 + | "r23" -> r.R23 + | "r24" -> r.R24 + | "r25" -> r.R25 + | "r26" -> r.R26 + | "r27" -> r.R27 + | "r28" -> r.R28 + | "r29" -> r.R29 + | "r30" -> r.R30 + | "r31" -> r.R31 + | "f0" -> r.F0 + | "f1" -> r.F1 + | "f2" -> r.F2 + | "f3" -> r.F3 + | "f4" -> r.F4 + | "f5" -> r.F5 + | "f6" -> r.F6 + | "f7" -> r.F7 + | "f8" -> r.F8 + | "f9" -> r.F9 + | "f10" -> r.F10 + | "f11" -> r.F11 + | "f12" -> r.F12 + | "f13" -> r.F13 + | "f14" -> r.F14 + | "f15" -> r.F15 + | "f16" -> r.F16 + | "f17" -> r.F17 + | "f18" -> r.F18 + | "f19" -> r.F19 + | "f20" -> r.F20 + | "f21" -> r.F21 + | "f22" -> r.F22 + | "f23" -> r.F23 + | "f24" -> r.F24 + | "f25" -> r.F25 + | "f26" -> r.F26 + | "f27" -> r.F27 + | "f28" -> r.F28 + | "f29" -> r.F29 + | "f30" -> r.F30 + | "f31" -> r.F31 + | "cr0_0" -> r.CR0_0 + | "cr0_1" -> r.CR0_1 + | "cr0_2" -> r.CR0_2 + | "cr0_3" -> r.CR0_3 + | "cr1_0" -> r.CR1_0 + | "cr1_1" -> r.CR1_1 + | "cr1_2" -> r.CR1_2 + | "cr1_3" -> r.CR1_3 + | "cr2_0" -> r.CR2_0 + | "cr2_1" -> r.CR2_1 + | "cr2_2" -> r.CR2_2 + | "cr2_3" -> r.CR2_3 + | "cr3_0" -> r.CR3_0 + | "cr3_1" -> r.CR3_1 + | "cr3_2" -> r.CR3_2 + | "cr3_3" -> r.CR3_3 + | "cr4_0" -> r.CR4_0 + | "cr4_1" -> r.CR4_1 + | "cr4_2" -> r.CR4_2 + | "cr4_3" -> r.CR4_3 + | "cr5_0" -> r.CR5_0 + | "cr5_1" -> r.CR5_1 + | "cr5_2" -> r.CR5_2 + | "cr5_3" -> r.CR5_3 + | "cr6_0" -> r.CR6_0 + | "cr6_1" -> r.CR6_1 + | "cr6_2" -> r.CR6_2 + | "cr6_3" -> r.CR6_3 + | "cr7_0" -> r.CR7_0 + | "cr7_1" -> r.CR7_1 + | "cr7_2" -> r.CR7_2 + | "cr7_3" -> r.CR7_3 + | _ -> raise UnhandledRegExprException + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + if rid < 0x40 then WordSize.toRegType wordSize + else 4 + + override __.GetRegisterAliases rid = + [| rid |] + + override __.ProgramCounter = Utils.futureFeature () + + override __.StackPointer = + Register.R1 |> Register.toRegID |> Some + + override __.FramePointer = None + + override __.IsProgramCounter _ = false + + override __.IsStackPointer rid = + (__.StackPointer |> Option.get) = rid + + override __.IsFramePointer _ = false diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32TranslationContext.fs b/src/FrontEnd/BinLifter/PPC32/PPC32TranslationContext.fs new file mode 100644 index 00000000..c27a63c8 --- /dev/null +++ b/src/FrontEnd/BinLifter/PPC32/PPC32TranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.PPC32 + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for PPC32 instructions. +type PPC32TranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/PPC32/PPC32Types.fs b/src/FrontEnd/BinLifter/PPC32/PPC32Types.fs index 1b530501..c87abb2b 100644 --- a/src/FrontEnd/BinLifter/PPC32/PPC32Types.fs +++ b/src/FrontEnd/BinLifter/PPC32/PPC32Types.fs @@ -1,4 +1,4 @@ -(* +(* B2R2 - the Next-Generation Reversing Platform Copyright (c) SoftSec Lab. @ KAIST, since 2016 @@ -36,451 +36,494 @@ do () /// file. /// type Opcode = - | ADD = 0 (* FIXME: Add Opcodes *) - | ADDdot = 1 - | ADDO = 2 - | ADDOdot = 3 - | ADDC = 4 - | ADDCdot = 5 - | ADDCO = 6 - | ADDCOdot = 7 - | ADDE = 8 - | ADDEdot = 9 - | ADDEO = 10 - | ADDEOdot = 11 - | ADDME = 12 - | ADDMEdot = 13 - | ADDMEO = 14 - | ADDMEOdot = 15 - | ADDZE = 16 - | ADDZEdot = 17 - | ADDZEO = 18 - | ADDZEOdot = 19 - | DIVW = 20 - | DIVWdot = 21 - | DIVWO = 22 - | DIVWOdot = 23 - | DIVWU = 24 - | DIVWUdot = 25 - | DIVWUO = 26 - | DIVWUOdot = 27 - | MULLW = 28 - | MULLWdot = 29 - | MULLWO = 30 - | MULLWOdot = 31 - | NEG = 32 - | NEGdot = 33 - | NEGO = 34 - | NEGOdot = 35 - | SUBF = 36 - | SUBFdot = 37 - | SUBFO = 38 - | SUBFOdot = 39 - | SUBFC = 40 - | SUBFCdot = 41 - | SUBFCO = 42 - | SUBFCOdot = 43 - | SUBFE = 44 - | SUBFEdot = 45 - | SUBFEO = 46 - | SUBFEOdot = 47 - | SUBFME = 48 - | SUBFMEdot = 49 - | SUBFMEO = 50 - | SUBFMEOdot = 51 - | SUBFZE = 52 - | SUBFZEdot = 53 - | SUBFZEO = 54 - | SUBFZEOdot = 55 - | MULHW = 56 - | MULHWdot = 57 - | MULHWU = 58 - | MULHWUdot = 59 - | AND = 60 - | ANDdot = 61 - | ANDC = 62 - | ANDCdot = 63 - | CNTLZW = 64 - | CNTLZWdot = 65 - | DCBTST = 66 - | DCBA = 67 - | DCBF = 68 - | DCBI = 69 - | ICBI = 70 - | DCBST = 71 - | DCBT = 72 - | DCBZ = 73 - | ECIWX = 74 - | ECOWX = 75 - | EIEIO = 76 - | EQV = 77 - | EQVdot = 78 - | EXTSB = 79 - | EXTSBdot = 80 - | EXTSH = 81 - | EXTSHdot = 82 - | LBZUX = 83 - | LBZX = 84 - | LFDUX = 85 - | LFDX = 86 - | LFSUX = 87 - | LFSX = 88 - | LHAUX = 89 - | LHAX = 90 - | LHBRX = 91 - | LHZUX = 92 - | LHZX = 93 - | LSWI = 94 - | LSWX = 95 - | LWARX = 96 - | LWBRX = 97 - | LWZUX = 98 - | LWZX = 99 - | CMP = 100 - | CMPL = 101 - | MCRXR = 102 - | MFCR = 103 - | MFMSR = 104 - | MFSRIN = 105 - | MTMSR = 106 - | MTSRIN = 107 - | NAND = 108 - | NANDdot = 109 - | NOR = 110 - | NORdot = 111 - | OR = 112 - | ORdot = 113 - | ORC = 114 - | ORCdot = 115 - | SLW = 116 - | SLWdot = 117 - | SRAW = 118 - | SRAWdot = 119 - | SRW = 120 - | SRWdot = 121 - | STBUX = 122 - | STBX = 123 - | STFDUX = 124 - | STFDX = 125 - | STFIWX = 126 - | STWUX = 127 - | STFSUX = 128 - | STWX = 129 - | STFSX = 130 - | STHBRX = 131 - | STHUX = 132 - | STHX = 133 - | STWBRX = 134 - | STWCXdot = 135 - | SYNC = 136 - | TLBIA = 137 - | TLBIE = 138 - | TLBSYNC = 139 - | XOR = 140 - | XORdot = 141 - | STSWX = 142 - | CMPW = 143 - | CMPLW = 144 - | TW = 145 - | TWEQ = 146 - | TRAP = 147 - | MTCRF = 148 - | MTSR = 149 - | MFSPR = 150 - | MFXER = 151 - | MFLR = 152 - | MFCTR = 153 - | MFTB = 154 - | MFTBU = 155 - | MTSPR = 156 - | MTXER = 157 - | MTLR = 158 - | MTCTR = 159 - | MFSR = 160 - | STSWI = 161 - | SRAWI = 162 - | SRAWIdot = 163 - | FCMPU = 164 - | FRSP = 165 - | FRSPdot = 166 - | FCTIW = 167 - | FCTIWdot = 168 - | FCTIWZ = 169 - | FCTIWZdot = 170 - | FDIV = 171 - | FDIVdot = 172 - | FSUB = 173 - | FSUBdot = 174 - | FADD = 175 - | FADDdot = 176 - | FSQRT = 177 - | FSQRTdot = 178 - | FSEL = 179 - | FSELdot = 180 - | FMUL =181 - | FMULdot = 182 - | FRSQRTE = 183 - | FRSQRTEdot = 184 - | FMSUB = 185 - | FMSUBdot = 186 - | FMADD = 187 - | FMADDdot = 188 - | FNMSUB = 189 - | FNMSUBdot = 190 - | FNMADD = 191 - | FNMADDdot = 192 - | FCMPO = 193 - | MTFSB1 = 194 - | MTFSB1dot = 195 - | FNEG = 196 - | FNEGdot = 197 - | MCRFS = 198 - | MTFSB0 = 199 - | MTFSB0dot = 200 - | FMR = 201 - | FMRdot = 202 - | MTFSFI = 203 - | MTFSFIdot = 204 - | FNABS = 205 - | FNABSdot = 206 - | FABS = 207 - | FABSdot = 208 - | MFFS = 209 - | MFFSdot = 210 - | MTFSF = 211 - | MTFSFdot = 212 - | FDIVS = 213 - | FDIVSdot = 214 - | FSUBS = 215 - | FSUBSdot = 216 - | FADDS = 217 - | FADDSdot = 218 - | FSQRTS = 219 - | FSQRTSdot = 220 - | FRES = 221 - | FRESdot = 222 - | FMULS = 223 - | FMULSdot = 224 - | FMSUBS = 225 - | FMSUBSdot = 226 - | FMADDS = 227 - | FMADDSdot = 228 - | FNMSUBS = 229 - | FNMSUBSdot = 230 - | FNMADDS = 231 - | FNMADDSdot = 232 - | TWLGT = 233 - | TWLLT = 234 - | TWLNL = 235 - | TWGT = 236 - | TWLT = 237 - | TWNE = 238 - | TWI = 239 - | TWLGTI = 240 - | TWLLTI = 241 - | TWEQI = 242 - | TWLNLI = 243 - | TWGTI = 244 - | TWLTI = 245 - | TWNEI = 246 - | MULLI = 247 - | SUBFIC = 248 - | CMPLI = 249 - | CMPLWI = 250 - | CMPI = 251 - | CMPWI = 252 - | ADDIC = 253 - | ADDICdot = 254 - | LI = 255 - | ADDI = 256 - | ADDIS = 257 - | LIS = 258 - | SC = 259 - | B = 260 - | BL = 261 - | BA = 262 - | BLA = 263 - | LWZ = 264 - | LWZU = 265 - | LBZ = 266 - | LBZU = 267 - | STW = 268 - | STWU = 269 - | STB = 270 - | STBU = 271 - | LHZ = 272 - | LHZU = 273 - | LHA = 274 - | LHAU = 275 - | STH = 276 - | STHU = 277 - | LMW = 278 - | STMW = 279 - | LFS = 280 - | LFSU = 281 - | LFD = 282 - | LFDU = 283 - | STFS = 284 - | STFSU = 285 - | STFD = 286 - | STFDU = 287 - | ORI = 288 - | NOP = 289 - | ORIS = 290 - | XORI = 291 - | XORIS = 292 - | ANDIdot = 293 - | ANDISdot = 294 - | RLWNM = 295 - | ROTLW = 296 - | RLWNMdot = 297 - | RLWIMI = 298 - | RLWIMIdot = 299 - | RLWINM = 300 - | RLWINMdot = 301 - | CLRLWI = 302 - | SLWI = 303 - | ROTLWI = 304 - | SRWI = 305 - | MCRF = 306 - | CRNOR = 307 - | CRNOT = 308 - | RFI = 309 - | CRANDC = 310 - | ISYNC = 311 - | CRXOR = 312 - | CRCLR = 313 - | CRAND = 314 - | CRNAND = 315 - | CREQV = 316 - | CRSET = 317 - | CRORC = 318 - | CROR = 319 - | CRMOVE = 320 - | BC = 321 - | BCA = 322 - | BCL = 323 - | BCLA = 324 - | BCLR = 325 - | BCLRL = 326 - | BCCTR = 327 - | BCCTRL = 328 - | BDNZF = 329 - | BDNZFA = 330 - | BDNZFL = 331 - | BDNZFLA = 332 - | BDZF = 333 - | BDZFA = 334 - | BDZFL = 335 - | BDZFLA = 336 - | BGE = 337 - | BLE = 338 - | BNE = 339 - | BNS = 340 - | BGEL = 341 - | BLEL = 342 - | BNEL = 343 - | BNSL = 344 - | BGEA = 345 - | BLEA = 346 - | BNEA = 347 - | BNSA = 348 - | BGELA = 349 - | BLELA = 350 - | BNELA = 351 - | BNSLA = 352 - | BDNZT = 353 - | BDNZTA = 354 - | BDNZTL = 355 - | BDNZTLA = 356 - | BDZT = 357 - | BDZTL = 358 - | BDZTA = 359 - | BDZTLA = 360 - | BLT = 361 - | BGT = 362 - | BEQ = 363 - | BSO = 364 - | BLTL = 365 - | BGTL = 366 - | BEQL = 367 - | BSOL = 368 - | BLTA = 369 - | BGTA = 370 - | BEQA = 371 - | BSOA = 372 - | BLTLA = 373 - | BGTLA = 374 - | BEQLA = 375 - | BSOLA = 376 - | BDNZ = 377 - | BDNZL = 378 - | BDNZA = 379 - | BDNZLA = 380 - | BDZ = 381 - | BDZL = 382 - | BDZA = 383 - | BDZLA = 384 - | BDNZFLR = 385 - | BDNZFLRL = 386 - | BDZFLR = 387 - | BDZFLRL = 388 - | BGELR = 389 - | BLELR = 390 - | BNELR = 391 - | BNSLR = 392 - | BGELRL = 393 - | BLELRL = 394 - | BNELRL = 395 - | BNSLRL = 396 - | BDNZTLR = 397 - | BDNZTLRL = 398 - | BDZTLR = 399 - | BDZTLRL = 400 - | BLTLR = 401 - | BGTLR = 402 - | BEQLR = 403 - | BSOLR = 404 - | BLTLRL = 405 - | BGTLRL = 406 - | BEQLRL = 407 - | BSOLRL = 408 - | BDNZLR = 409 - | BDNZLRL = 410 - | BDZLR = 411 - | BDZLRL = 412 - | BLR = 413 - | BLRL = 414 - | BGECTR = 415 - | BLECTR = 416 - | BNECTR = 417 - | BNSCTR = 418 - | BGECTRL = 419 - | BLECTRL = 420 - | BNECTRL = 421 - | BNSCTRL = 422 - | BLTCTR = 423 - | BGTCTR = 424 - | BEQCTR = 425 - | BSOCTR = 426 - | BLTCTRL = 427 - | BGTCTRL = 428 - | BEQCTRL = 429 - | BSOCTRL = 430 - | BCTR = 431 - | BCTRL = 432 - | MR = 433 - | InvalOP = 434 + | ADD = 0 + | ADDC = 1 + | ADDCdot = 2 + | ADDCO = 3 + | ADDCOdot = 4 + | ADDdot = 5 + | ADDE = 6 + | ADDEdot = 7 + | ADDEO = 8 + | ADDEOdot = 9 + | ADDI = 10 + | ADDIC = 11 + | ADDICdot = 12 + | ADDIS = 13 + | ADDME = 14 + | ADDMEdot = 15 + | ADDMEO = 16 + | ADDMEOdot = 17 + | ADDO = 18 + | ADDOdot = 19 + | ADDZE = 20 + | ADDZEdot = 21 + | ADDZEO = 22 + | ADDZEOdot = 23 + | AND = 24 + | ANDC = 25 + | ANDCdot = 26 + | ANDdot = 27 + | ANDIdot = 28 + | ANDISdot = 29 + | B = 30 + | BA = 31 + | BC = 32 + | BCA = 33 + | BCCTR = 34 + | BCCTRL = 35 + | BCL = 36 + | BCLA = 37 + | BCLR = 38 + | BCLRL = 39 + | BCTR = 40 + | BCTRL = 41 + | BDNZ = 42 + | BDNZA = 43 + | BDNZF = 44 + | BDNZFA = 45 + | BDNZFL = 46 + | BDNZFLA = 47 + | BDNZFLR = 48 + | BDNZFLRL = 49 + | BDNZL = 50 + | BDNZLA = 51 + | BDNZLR = 52 + | BDNZLRL = 53 + | BDNZT = 54 + | BDNZTA = 55 + | BDNZTL = 56 + | BDNZTLA = 57 + | BDNZTLR = 58 + | BDNZTLRL = 59 + | BDZ = 60 + | BDZA = 61 + | BDZF = 62 + | BDZFA = 63 + | BDZFL = 64 + | BDZFLA = 65 + | BDZFLR = 66 + | BDZFLRL = 67 + | BDZL = 68 + | BDZLA = 69 + | BDZLR = 70 + | BDZLRL = 71 + | BDZT = 72 + | BDZTA = 73 + | BDZTL = 74 + | BDZTLA = 75 + | BDZTLR = 76 + | BDZTLRL = 77 + | BEQ = 78 + | BEQA = 79 + | BEQCTR = 80 + | BEQCTRL = 81 + | BEQL = 82 + | BEQLA = 83 + | BEQLR = 84 + | BEQLRL = 85 + | BFLRL = 86 + | BGE = 87 + | BGEA = 88 + | BGECTR = 89 + | BGECTRL = 90 + | BGEL = 91 + | BGELA = 92 + | BGELR = 93 + | BGELRL = 94 + | BGT = 95 + | BGTA = 96 + | BGTCTR = 97 + | BGTCTRL = 98 + | BGTL = 99 + | BGTLA = 100 + | BGTLR = 101 + | BGTLRL = 102 + | BL = 103 + | BLA = 104 + | BLE = 105 + | BLEA = 106 + | BLECTR = 107 + | BLECTRL = 108 + | BLEL = 109 + | BLELA = 110 + | BLELR = 111 + | BLELRL = 112 + | BLR = 113 + | BLRL = 114 + | BLT = 115 + | BLTA = 116 + | BLTCTR = 117 + | BLTCTRL = 118 + | BLTL = 119 + | BLTLA = 120 + | BLTLR = 121 + | BLTLRL = 122 + | BNE = 123 + | BNEA = 124 + | BNECTR = 125 + | BNECTRL = 126 + | BNEL = 127 + | BNELA = 128 + | BNELR = 129 + | BNELRL = 130 + | BNS = 131 + | BNSA = 132 + | BNSCTR = 133 + | BNSCTRL = 134 + | BNSL = 135 + | BNSLA = 136 + | BNSLR = 137 + | BNSLRL = 138 + | BSO = 139 + | BSOA = 140 + | BSOCTR = 141 + | BSOCTRL = 142 + | BSOL = 143 + | BSOLA = 144 + | BSOLR = 145 + | BSOLRL = 146 + | BTCTRL = 147 + | BTLRL = 148 + | CLRLWI = 149 + | CLRRWI = 150 + | CMP = 151 + | CMPI = 152 + | CMPL = 153 + | CMPLI = 154 + | CMPLW = 155 + | CMPLWI = 156 + | CMPW = 157 + | CMPWI = 158 + | CNTLZW = 159 + | CNTLZWdot = 160 + | CRAND = 161 + | CRANDC = 162 + | CRCLR = 163 + | CREQV = 164 + | CRMOVE = 165 + | CRNAND = 166 + | CRNOR = 167 + | CRNOT = 168 + | CROR = 169 + | CRORC = 170 + | CRSET = 171 + | CRXOR = 172 + | DCBA = 173 + | DCBF = 174 + | DCBI = 175 + | DCBST = 176 + | DCBT = 177 + | DCBTST = 178 + | DCBZ = 179 + | DIVW = 180 + | DIVWdot = 181 + | DIVWO = 182 + | DIVWOdot = 183 + | DIVWU = 184 + | DIVWUdot = 185 + | DIVWUO = 186 + | DIVWUOdot = 187 + | ECIWX = 188 + | ECOWX = 189 + | EIEIO = 190 + | EQV = 191 + | EQVdot = 192 + | EXTSB = 193 + | EXTSBdot = 194 + | EXTSH = 195 + | EXTSHdot = 196 + | FABS = 197 + | FABSdot = 198 + | FADD = 199 + | FADDdot = 200 + | FADDS = 201 + | FADDSdot = 202 + | FCMPO = 203 + | FCMPU = 204 + | FCTIW = 205 + | FCTIWdot = 206 + | FCTIWZ = 207 + | FCTIWZdot = 208 + | FDIV = 209 + | FDIVdot = 210 + | FDIVS = 211 + | FDIVSdot = 212 + | FMADD = 213 + | FMADDdot = 214 + | FMADDS = 215 + | FMADDSdot = 216 + | FMR = 217 + | FMRdot = 218 + | FMSUB = 219 + | FMSUBdot = 220 + | FMSUBS = 221 + | FMSUBSdot = 222 + | FMUL = 223 + | FMULdot = 224 + | FMULS = 225 + | FMULSdot = 226 + | FNABS = 227 + | FNABSdot = 228 + | FNEG = 229 + | FNEGdot = 230 + | FNMADD = 231 + | FNMADDdot = 232 + | FNMADDS = 233 + | FNMADDSdot = 234 + | FNMSUB = 235 + | FNMSUBdot = 236 + | FNMSUBS = 237 + | FNMSUBSdot = 238 + | FRES = 239 + | FRESdot = 240 + | FRSP = 241 + | FRSPdot = 242 + | FRSQRTE = 243 + | FRSQRTEdot = 244 + | FSEL = 245 + | FSELdot = 246 + | FSQRT = 247 + | FSQRTdot = 248 + | FSQRTS = 249 + | FSQRTSdot = 250 + | FSUB = 251 + | FSUBdot = 252 + | FSUBS = 253 + | FSUBSdot = 254 + | ICBI = 255 + | InvalOP = 256 + | ISYNC = 257 + | LBZ = 258 + | LBZU = 259 + | LBZUX = 260 + | LBZX = 261 + | LFD = 262 + | LFDU = 263 + | LFDUX = 264 + | LFDX = 265 + | LFS = 266 + | LFSU = 267 + | LFSUX = 268 + | LFSX = 269 + | LHA = 270 + | LHAU = 271 + | LHAUX = 272 + | LHAX = 273 + | LHBRX = 274 + | LHZ = 275 + | LHZU = 276 + | LHZUX = 277 + | LHZX = 278 + | LI = 279 + | LIS = 280 + | LMW = 281 + | LSWI = 282 + | LSWX = 283 + | LWARX = 284 + | LWBRX = 285 + | LWSYNC = 286 + | LWZ = 287 + | LWZU = 288 + | LWZUX = 289 + | LWZX = 290 + | MCRF = 291 + | MCRFS = 292 + | MCRXR = 293 + | MFCR = 294 + | MFCTR = 295 + | MFFS = 296 + | MFFSdot = 297 + | MFLR = 298 + | MFMSR = 299 + | MFSPR = 300 + | MFSR = 301 + | MFSRIN = 302 + | MFTB = 303 + | MFTBU = 304 + | MFXER = 305 + | MR = 306 + | MTCRF = 307 + | MTCTR = 308 + | MTFSB0 = 309 + | MTFSB0dot = 310 + | MTFSB1 = 311 + | MTFSB1dot = 312 + | MTFSF = 313 + | MTFSFdot = 314 + | MTFSFI = 315 + | MTFSFIdot = 316 + | MTLR = 317 + | MTMSR = 318 + | MTSPR = 319 + | MTSR = 320 + | MTSRIN = 321 + | MTXER = 322 + | MULHW = 323 + | MULHWdot = 324 + | MULHWU = 325 + | MULHWUdot = 326 + | MULLI = 327 + | MULLW = 328 + | MULLWdot = 329 + | MULLWO = 330 + | MULLWOdot = 331 + | NAND = 332 + | NANDdot = 333 + | NEG = 334 + | NEGdot = 335 + | NEGO = 336 + | NEGOdot = 337 + | NOP = 338 + | NOR = 339 + | NORdot = 340 + | OR = 341 + | ORC = 342 + | ORCdot = 343 + | ORdot = 344 + | ORI = 345 + | ORIS = 346 + | RFI = 347 + | RLWIMI = 348 + | RLWIMIdot = 349 + | RLWINM = 350 + | RLWINMdot = 351 + | RLWNM = 352 + | RLWNMdot = 353 + | ROTLW = 354 + | ROTLWI = 355 + | SC = 356 + | SLW = 357 + | SLWdot = 358 + | SLWI = 359 + | SRAW = 360 + | SRAWdot = 361 + | SRAWI = 362 + | SRAWIdot = 363 + | SRW = 364 + | SRWdot = 365 + | SRWI = 366 + | STB = 367 + | STBU = 368 + | STBUX = 369 + | STBX = 370 + | STFD = 371 + | STFDU = 372 + | STFDUX = 373 + | STFDX = 374 + | STFIWX = 375 + | STFS = 376 + | STFSU = 377 + | STFSUX = 378 + | STFSX = 379 + | STH = 380 + | STHBRX = 381 + | STHU = 382 + | STHUX = 383 + | STHX = 384 + | STMW = 385 + | STSWI = 386 + | STSWX = 387 + | STW = 388 + | STWBRX = 389 + | STWCXdot = 390 + | STWU = 391 + | STWUX = 392 + | STWX = 393 + | SUBF = 394 + | SUBFC = 395 + | SUBFCdot = 396 + | SUBFCO = 397 + | SUBFCOdot = 398 + | SUBFdot = 399 + | SUBFE = 400 + | SUBFEdot = 401 + | SUBFEO = 402 + | SUBFEOdot = 403 + | SUBFIC = 404 + | SUBFME = 405 + | SUBFMEdot = 406 + | SUBFMEO = 407 + | SUBFMEOdot = 408 + | SUBFO = 409 + | SUBFOdot = 410 + | SUBFZE = 411 + | SUBFZEdot = 412 + | SUBFZEO = 413 + | SUBFZEOdot = 414 + | SYNC = 415 + | TLBIA = 416 + | TLBIE = 417 + | TLBSYNC = 418 + | TRAP = 419 + | TW = 420 + | TWEQ = 421 + | TWEQI = 422 + | TWGE = 423 + | TWGEI = 424 + | TWGT = 425 + | TWGTI = 426 + | TWI = 427 + | TWLE = 428 + | TWLEI = 429 + | TWLGT = 430 + | TWLGTI = 431 + | TWLLE = 432 + | TWLLEI = 433 + | TWLLT = 434 + | TWLLTI = 435 + | TWLNL = 436 + | TWLNLI = 437 + | TWLT = 438 + | TWLTI = 439 + | TWNE = 440 + | TWNEI = 441 + | XOR = 442 + | XORdot = 443 + | XORI = 444 + | XORIS = 445 type internal Op = Opcode +type Condition = + /// Less than [LT]. + | LT = 0x0 + /// Less than or equal (equivalent to ng) [GT]. + | LE = 0x1 + /// Equal [EQ]. + | EQ = 0x2 + /// Greater than or equal (equivalent to nl) [LT]. + | GE = 0x3 + /// Greater than [GT]. + | GT = 0x4 + /// Not less than (equivalent to ge) [LT]. + | NL = 0x5 + /// Not equal [EQ]. + | NE = 0x6 + /// Not greater than (equivalent to le) [GT]. + | NG = 0x7 + /// Summary overflow [SO]. + | SO = 0x8 + /// Not summary overflow [SO]. + | NS = 0x9 + /// Unordered (after floating-point comparison) [SO]. + | UN = 0xA + /// Not unordered (after floating-point comparison) [SO]. + | NU = 0xB + type Operand = - | OpReg of Register - | ImmOp of Imm * Register - | Immediate of Imm - | Branch of bi + | OprReg of Register + | OprMem of D * Register + | OprImm of Imm + | OprAddr of TargetAddr + | OprBI of uint32 +/// Immediate field specifying a 16-bit signed two's complement integer that is +/// sign-extended to 32 bits. +and D = int32 and Imm = uint64 -and bi = uint64 +/// Used to specify a CR bit to be used as the condition of a branch conditional +/// instruction. +and TargetAddr = uint64 type Operands = | NoOperand diff --git a/src/FrontEnd/BinLifter/Sparc64/B2R2.FrontEnd.BinLifter.Sparc64.fsproj b/src/FrontEnd/BinLifter/Python/B2R2.FrontEnd.BinLifter.Python.fsproj similarity index 60% rename from src/FrontEnd/BinLifter/Sparc64/B2R2.FrontEnd.BinLifter.Sparc64.fsproj rename to src/FrontEnd/BinLifter/Python/B2R2.FrontEnd.BinLifter.Python.fsproj index 8f65bfeb..2969d501 100644 --- a/src/FrontEnd/BinLifter/Sparc64/B2R2.FrontEnd.BinLifter.Sparc64.fsproj +++ b/src/FrontEnd/BinLifter/Python/B2R2.FrontEnd.BinLifter.Python.fsproj @@ -1,30 +1,25 @@ - - + LICENSE.md b2r2-240x240.png README.md - B2R2 PPC32 frontend. + B2R2 Python frontend. - - - - - - - - - + + + + + + + - - diff --git a/src/FrontEnd/BinLifter/Python/PythonDisasm.fs b/src/FrontEnd/BinLifter/Python/PythonDisasm.fs new file mode 100644 index 00000000..fc8e37e8 --- /dev/null +++ b/src/FrontEnd/BinLifter/Python/PythonDisasm.fs @@ -0,0 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.Python.Disasm + +// TODO Implement disasm logic diff --git a/src/FrontEnd/BinLifter/Python/PythonInstruction.fs b/src/FrontEnd/BinLifter/Python/PythonInstruction.fs new file mode 100644 index 00000000..591c8958 --- /dev/null +++ b/src/FrontEnd/BinLifter/Python/PythonInstruction.fs @@ -0,0 +1,101 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Python + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// The internal representation for a Python instruction used by our +/// disassembler and lifter. +type PythonInstruction (addr, numBytes, insInfo) = + inherit Instruction (addr, numBytes, WordSize.Bit32) + + /// Basic instruction information. + member val Info: InsInfo = insInfo + + override __.IsBranch () = + match __.Info.Opcode with + | _ -> false + + override __.IsModeChanging () = false + + member __.HasConcJmpTarget () = Utils.futureFeature () + + override __.IsDirectBranch () = + __.IsBranch () && __.HasConcJmpTarget () + + override __.IsIndirectBranch () = + __.IsBranch () && (not <| __.HasConcJmpTarget ()) + + override __.IsCondBranch () = Utils.futureFeature () + + override __.IsCJmpOnTrue () = Utils.futureFeature () + + override __.IsCall () = Utils.futureFeature () + + override __.IsRET () = Utils.futureFeature () + + override __.IsInterrupt () = Utils.futureFeature () + + override __.IsExit () = Utils.futureFeature () + + override __.IsBBLEnd () = + __.IsDirectBranch () || + __.IsIndirectBranch () + + override __.DirectBranchTarget (_addr: byref) = Utils.futureFeature () + + override __.IndirectTrampolineAddr (_addr: byref) = + Utils.futureFeature () + + override __.Immediate (_v: byref) = Utils.futureFeature () + + override __.GetNextInstrAddrs () = Utils.futureFeature () + + override __.InterruptNum (_num: byref) = Utils.futureFeature () + + override __.IsNop () = Utils.futureFeature () + + override __.Translate ctxt = + Utils.futureFeature () + + override __.TranslateToList ctxt = + Utils.futureFeature () + + override __.Disasm (showAddr, _) = + Utils.futureFeature () + + override __.Disasm () = + Utils.futureFeature () + + override __.Decompose (showAddr) = + Utils.futureFeature () + + override __.IsInlinedAssembly () = false + + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Python/PythonLifter.fs b/src/FrontEnd/BinLifter/Python/PythonLifter.fs new file mode 100644 index 00000000..1549f7d2 --- /dev/null +++ b/src/FrontEnd/BinLifter/Python/PythonLifter.fs @@ -0,0 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Python.Lifter + +// TODO diff --git a/src/FrontEnd/BinLifter/Python/PythonParser.fs b/src/FrontEnd/BinLifter/Python/PythonParser.fs new file mode 100644 index 00000000..1005bafb --- /dev/null +++ b/src/FrontEnd/BinLifter/Python/PythonParser.fs @@ -0,0 +1,46 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Python + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Parser for Python instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type Python64Parser (isa: ISA) = + let wordSize = int isa.WordSize + let reader = BinReader.Init isa.Endian + + interface IInstructionParsable with + member __.Parse (span: ByteSpan, addr: Addr) = + Utils.futureFeature (): Instruction + + member __.Parse (bs: byte[], addr: Addr) = + Utils.futureFeature (): Instruction + + member __.MaxInstructionSize = 4 + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/Python/PythonParsingMain.fs b/src/FrontEnd/BinLifter/Python/PythonParsingMain.fs new file mode 100644 index 00000000..852ce4d7 --- /dev/null +++ b/src/FrontEnd/BinLifter/Python/PythonParsingMain.fs @@ -0,0 +1,148 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.Python.ParsingMain + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter + +let private parseOpcode (span: ReadOnlySpan) (reader: IBinReader) = + let bin = reader.ReadUInt8 (span, 0) + (* Opcode of Python 3.11 *) + match bin with + | 0x0uy -> CACHE + | 0x1uy -> POP_TOP + | 0x2uy -> PUSH_NULL + | 0x9uy -> NOP + | 0xauy -> UNARY_POSITIVE + | 0xbuy -> UNARY_NEGATIVE + | 0xcuy -> UNARY_NOT + | 0xfuy -> UNARY_INVERT + | 0x19uy -> BINARY_SUBSCR + | 0x1euy -> GET_LEN + | 0x1fuy -> MATCH_MAPPING + | 0x20uy -> MATCH_SEQUENCE + | 0x21uy -> MATCH_KEYS + | 0x23uy -> PUSH_EXC_INFO + | 0x24uy -> CHECK_EXC_MATCH + | 0x25uy -> CHECK_EG_MATCH + | 0x31uy -> WITH_EXCEPT_START + | 0x32uy -> GET_AITER + | 0x33uy -> GET_ANEXT + | 0x34uy -> BEFORE_ASYNC_WITH + | 0x35uy -> BEFORE_WITH + | 0x36uy -> END_ASYNC_FOR + | 0x3cuy -> STORE_SUBSCR + | 0x3duy -> DELETE_SUBSCR + | 0x44uy -> GET_ITER + | 0x45uy -> GET_YIELD_FROM_ITER + | 0x46uy -> PRINT_EXPR + | 0x47uy -> LOAD_BUILD_CLASS + | 0x4auy -> LOAD_ASSERTION_ERROR + | 0x4buy -> RETURN_GENERATOR + | 0x52uy -> LIST_TO_TUPLE + | 0x53uy -> RETURN_VALUE + | 0x54uy -> IMPORT_STAR + | 0x55uy -> SETUP_ANNOTATIONS + | 0x56uy -> YIELD_VALUE + | 0x57uy -> ASYNC_GEN_WRAP + | 0x58uy -> PREP_RERAISE_STAR + | 0x59uy -> POP_EXCEPT + | 0x5auy -> STORE_NAME + | 0x5buy -> DELETE_NAME + | 0x5cuy -> UNPACK_SEQUENCE + | 0x5duy -> FOR_ITER + | 0x5euy -> UNPACK_EX + | 0x5fuy -> STORE_ATTR + | 0x60uy -> DELETE_ATTR + | 0x61uy -> STORE_GLOBAL + | 0x62uy -> DELETE_GLOBAL + | 0x63uy -> SWAP + | 0x64uy -> LOAD_CONST + | 0x65uy -> LOAD_NAME + | 0x66uy -> BUILD_TUPLE + | 0x67uy -> BUILD_LIST + | 0x68uy -> BUILD_SET + | 0x69uy -> BUILD_MAP + | 0x6auy -> LOAD_ATTR + | 0x6buy -> COMPARE_OP + | 0x6cuy -> IMPORT_NAME + | 0x6duy -> IMPORT_FROM + | 0x6euy -> JUMP_FORWARD + | 0x6fuy -> JUMP_IF_FALSE_OR_POP + | 0x70uy -> JUMP_IF_TRUE_OR_POP + | 0x72uy -> POP_JUMP_FORWARD_IF_FALSE + | 0x73uy -> POP_JUMP_FORWARD_IF_TRUE + | 0x74uy -> LOAD_GLOBAL + | 0x75uy -> IS_OP + | 0x76uy -> CONTAINS_OP + | 0x77uy -> RERAISE + | 0x78uy -> COPY + | 0x7auy -> BINARY_OP + | 0x7buy -> SEND + | 0x7cuy -> LOAD_FAST + | 0x7duy -> STORE_FAST + | 0x7euy -> DELETE_FAST + | 0x80uy -> POP_JUMP_FORWARD_IF_NOT_NONE + | 0x81uy -> POP_JUMP_FORWARD_IF_NONE + | 0x82uy -> RAISE_VARARGS + | 0x83uy -> GET_AWAITABLE + | 0x84uy -> MAKE_FUNCTION + | 0x85uy -> BUILD_SLICE + | 0x86uy -> JUMP_BACKWARD_NO_INTERRUPT + | 0x87uy -> MAKE_CELL + | 0x88uy -> LOAD_CLOSURE + | 0x89uy -> LOAD_DEREF + | 0x8auy -> STORE_DEREF + | 0x8buy -> DELETE_DEREF + | 0x8cuy -> JUMP_BACKWARD + | 0x8euy -> CALL_FUNCTION_EX + | 0x90uy -> EXTENDED_ARG + | 0x91uy -> LIST_APPEND + | 0x92uy -> SET_ADD + | 0x93uy -> MAP_ADD + | 0x94uy -> LOAD_CLASSDEREF + | 0x95uy -> COPY_FREE_VARS + | 0x97uy -> RESUME + | 0x98uy -> MATCH_CLASS + | 0x9buy -> FORMAT_VALUE + | 0x9cuy -> BUILD_CONST_KEY_MAP + | 0x9duy -> BUILD_STRING + | 0xa0uy -> LOAD_METHOD + | 0xa2uy -> LIST_EXTEND + | 0xa3uy -> SET_UPDATE + | 0xa4uy -> DICT_MERGE + | 0xa5uy -> DICT_UPDATE + | 0xa6uy -> PRECALL + | 0xabuy -> CALL + | 0xacuy -> KW_NAMES + | 0xaduy -> POP_JUMP_BACKWARD_IF_NOT_NONE + | 0xaeuy -> POP_JUMP_BACKWARD_IF_NONE + | 0xafuy -> POP_JUMP_BACKWARD_IF_FALSE + | 0xb0uy -> POP_JUMP_BACKWARD_IF_TRUE + | _ -> raise ParsingFailureException + +let parse (span: ByteSpan) (reader: IBinReader) wordSize addr = + Utils.futureFeature () diff --git a/src/MiddleEnd/ControlFlowGraph/InstructionInfo.fs b/src/FrontEnd/BinLifter/Python/PythonTranslationContext.fs similarity index 77% rename from src/MiddleEnd/ControlFlowGraph/InstructionInfo.fs rename to src/FrontEnd/BinLifter/Python/PythonTranslationContext.fs index 368f1eeb..d8b75661 100644 --- a/src/MiddleEnd/ControlFlowGraph/InstructionInfo.fs +++ b/src/FrontEnd/BinLifter/Python/PythonTranslationContext.fs @@ -22,19 +22,19 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.ControlFlowGraph +namespace B2R2.FrontEnd.BinLifter.Python open B2R2 -open B2R2.BinIR.LowUIR open B2R2.FrontEnd.BinLifter -/// Abstract information about the instruction and its corresponding IR -/// statements. -type InstructionInfo = { - /// Instruction. - Instruction: Instruction - /// IR. - Stmts: Stmt [] - /// Corresponding BBL's address. - BBLAddr: Addr -} +/// Translation context for Python instructions. +type PythonTranslationContext (isa) = + inherit TranslationContext (isa) + + member __.RegExprs with get() = Utils.futureFeature () + + override __.GetRegVar id = + Utils.futureFeature () + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/Python/PythonTypes.fs b/src/FrontEnd/BinLifter/Python/PythonTypes.fs new file mode 100644 index 00000000..a3d931dd --- /dev/null +++ b/src/FrontEnd/BinLifter/Python/PythonTypes.fs @@ -0,0 +1,187 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.Python + +open B2R2 +open System.Runtime.CompilerServices + +[] +do () + +/// +/// Python opcodes. +/// +type Opcode = + | CACHE + | POP_TOP + | PUSH_NULL + | NOP + | UNARY_POSITIVE + | UNARY_NEGATIVE + | UNARY_NOT + | UNARY_INVERT + | BINARY_SUBSCR + | GET_LEN + | MATCH_MAPPING + | MATCH_SEQUENCE + | MATCH_KEYS + | PUSH_EXC_INFO + | CHECK_EXC_MATCH + | CHECK_EG_MATCH + | WITH_EXCEPT_START + | GET_AITER + | GET_ANEXT + | BEFORE_ASYNC_WITH + | BEFORE_WITH + | END_ASYNC_FOR + | STORE_SUBSCR + | DELETE_SUBSCR + | GET_ITER + | GET_YIELD_FROM_ITER + | PRINT_EXPR + | LOAD_BUILD_CLASS + | LOAD_ASSERTION_ERROR + | RETURN_GENERATOR + | LIST_TO_TUPLE + | RETURN_VALUE + | IMPORT_STAR + | SETUP_ANNOTATIONS + | YIELD_VALUE + | ASYNC_GEN_WRAP + | PREP_RERAISE_STAR + | POP_EXCEPT + | STORE_NAME + | DELETE_NAME + | UNPACK_SEQUENCE + | FOR_ITER + | UNPACK_EX + | STORE_ATTR + | DELETE_ATTR + | STORE_GLOBAL + | DELETE_GLOBAL + | SWAP + | LOAD_CONST + | LOAD_NAME + | BUILD_TUPLE + | BUILD_LIST + | BUILD_SET + | BUILD_MAP + | LOAD_ATTR + | COMPARE_OP + | IMPORT_NAME + | IMPORT_FROM + | JUMP_FORWARD + | JUMP_IF_FALSE_OR_POP + | JUMP_IF_TRUE_OR_POP + | POP_JUMP_FORWARD_IF_FALSE + | POP_JUMP_FORWARD_IF_TRUE + | LOAD_GLOBAL + | IS_OP + | CONTAINS_OP + | RERAISE + | COPY + | BINARY_OP + | SEND + | LOAD_FAST + | STORE_FAST + | DELETE_FAST + | POP_JUMP_FORWARD_IF_NOT_NONE + | POP_JUMP_FORWARD_IF_NONE + | RAISE_VARARGS + | GET_AWAITABLE + | MAKE_FUNCTION + | BUILD_SLICE + | JUMP_BACKWARD_NO_INTERRUPT + | MAKE_CELL + | LOAD_CLOSURE + | LOAD_DEREF + | STORE_DEREF + | DELETE_DEREF + | JUMP_BACKWARD + | CALL_FUNCTION_EX + | EXTENDED_ARG + | LIST_APPEND + | SET_ADD + | MAP_ADD + | LOAD_CLASSDEREF + | COPY_FREE_VARS + | RESUME + | MATCH_CLASS + | FORMAT_VALUE + | BUILD_CONST_KEY_MAP + | BUILD_STRING + | LOAD_METHOD + | LIST_EXTEND + | SET_UPDATE + | DICT_MERGE + | DICT_UPDATE + | PRECALL + | CALL + | KW_NAMES + | POP_JUMP_BACKWARD_IF_NOT_NONE + | POP_JUMP_BACKWARD_IF_NONE + | POP_JUMP_BACKWARD_IF_FALSE + | POP_JUMP_BACKWARD_IF_TRUE + +type internal Op = Opcode + +type Operand = + | MyOpr // FIXME + +type Operands = + | NoOperand + | OneOperand of Operand + | TwoOperands of Operand * Operand + +/// Basic information obtained by parsing a Python instruction. +[] +type InsInfo = { + /// Address. + Address: Addr + /// Instruction length. + NumBytes: uint32 + /// Opcode. + Opcode: Opcode + /// Operands. + Operands: Operands + /// Operation Size. + OperationSize: RegType +} +with + override __.GetHashCode () = + hash (__.Address, + __.NumBytes, + __.Opcode, + __.Operands, + __.OperationSize) + override __.Equals (i) = + match i with + | :? InsInfo as i -> + i.Address = __.Address + && i.NumBytes = __.NumBytes + && i.Opcode = __.Opcode + && i.Operands = __.Operands + && i.OperationSize = __.OperationSize + | _ -> false diff --git a/src/MiddleEnd/BinGraph/README.md b/src/FrontEnd/BinLifter/Python/README.md similarity index 53% rename from src/MiddleEnd/BinGraph/README.md rename to src/FrontEnd/BinLifter/Python/README.md index 0655c758..e82895cc 100644 --- a/src/MiddleEnd/BinGraph/README.md +++ b/src/FrontEnd/BinLifter/Python/README.md @@ -1,4 +1,4 @@ -# B2R2.MiddleEnd.BinGraph +# B2R2.FrontEnd.BinLifter.Python ### B2R2? @@ -6,7 +6,6 @@ B2R2 is a binary analysis and reversing framework written purely in F#. Since it does not rely on any native (unmanaged) code, it is readily usable in any platform or OS that .NET runs on. -### B2R2.MiddleEnd.BinGraph Package? +### B2R2.FrontEnd.BinLifter.Python Package? -`B2R2.MiddleEnd.BinGraph` defines basic graph types and values. Our CFG analyses -are dependent on this package. +`B2R2.FrontEnd.BinLifter.Python` includes Python parsers and lifters. diff --git a/src/FrontEnd/BinLifter/RISCV/B2R2.FrontEnd.BinLifter.RISCV.fsproj b/src/FrontEnd/BinLifter/RISCV/B2R2.FrontEnd.BinLifter.RISCV.fsproj index 62fc1ef6..2a4b0eed 100644 --- a/src/FrontEnd/BinLifter/RISCV/B2R2.FrontEnd.BinLifter.RISCV.fsproj +++ b/src/FrontEnd/BinLifter/RISCV/B2R2.FrontEnd.BinLifter.RISCV.fsproj @@ -1,31 +1,29 @@ - - + LICENSE.md b2r2-240x240.png README.md B2R2 RISCV frontend. - - - + + + + - + - - - + \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/RISCV/Library.fs b/src/FrontEnd/BinLifter/RISCV/Library.fs deleted file mode 100644 index 6c870ac3..00000000 --- a/src/FrontEnd/BinLifter/RISCV/Library.fs +++ /dev/null @@ -1,5 +0,0 @@ -namespace B2R2.FrontEnd.BinLifter.RISCV - -module Say = - let hello name = - printfn "Hello %s" name diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64.fs deleted file mode 100644 index 7b0318f7..00000000 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64.fs +++ /dev/null @@ -1,65 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.RISCV - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for RISCV instructions. -type RISCV64TranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for RISCV64 instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type RISCV64Parser (isa: ISA) = - inherit Parser () - - let reader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader addr :> Instruction - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader addr :> Instruction - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - RISCV64TranslationContext (isa, regexprs) :> TranslationContext, - RISCV64RegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Disasm.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Disasm.fs index fe03ff5d..744d0e66 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64Disasm.fs +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Disasm.fs @@ -26,31 +26,310 @@ module B2R2.FrontEnd.BinLifter.RISCV.Disasm open B2R2 open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData let opCodeToString = function + | Op.LUI -> "lui" + | Op.AUIPC -> "auipc" + | Op.JAL -> "jal" + | Op.JALR -> "jalr" + | Op.BEQ -> "beq" + | Op.BNE -> "bne" + | Op.BLT -> "blt" + | Op.BGE -> "bge" + | Op.BLTU -> "bltu" + | Op.BGEU -> "bgeu" + | Op.LB -> "lb" + | Op.LH -> "lh" + | Op.LW -> "lw" + | Op.LBU -> "lbu" + | Op.LHU -> "lhu" + | Op.SB -> "sb" + | Op.SH -> "sh" + | Op.SW -> "sw" + | Op.ADDI -> "addi" + | Op.SLTI -> "slti" + | Op.SLTIU -> "sltiu" + | Op.XORI -> "xori" + | Op.ORI -> "ori" + | Op.ANDI -> "andi" + | Op.SLLI -> "slli" + | Op.SRLI -> "srli" + | Op.SRAI -> "srai" | Op.ADD -> "add" + | Op.SUB -> "sub" + | Op.SLL -> "sll" + | Op.SLT -> "slt" + | Op.SLTU -> "sltu" + | Op.XOR -> "xor" + | Op.SRL -> "srl" + | Op.SRA -> "sra" + | Op.OR -> "or" + | Op.AND -> "and" + | Op.FENCE -> "fence" + | Op.FENCEdotI -> "fence.i" + | Op.ECALL -> "ecall" + | Op.EBREAK -> "ebreak" + | Op.CSRRW -> "csrrw" + | Op.CSRRS -> "csrrs" + | Op.CSRRC -> "csrrc" + | Op.CSRRWI -> "csrrwi" + | Op.CSRRSI -> "csrrsi" + | Op.CSRRCI -> "csrrci" + (* RV64I Base Instruction Set *) + | Op.LWU -> "lwu" + | Op.LD -> "ld" + | Op.SD -> "sd" + | Op.ADDIW -> "addiw" + | Op.SLLIW -> "slliw" + | Op.SRLIW -> "srliw" + | Op.SRAIW -> "sraiw" + | Op.ADDW -> "addw" + | Op.SUBW -> "subw" + | Op.SLLW -> "sllw" + | Op.SRLW -> "srlw" + | Op.SRAW -> "sraw" + (* RV32M Standard Extension *) + | Op.MUL -> "mul" + | Op.MULH -> "mulh" + | Op.MULHSU -> "mulhsu" + | Op.MULHU -> "mulhu" + | Op.DIV -> "div" + | Op.DIVU -> "divu" + | Op.REM -> "rem" + | Op.REMU -> "remu" + (* RV64M Standard Extension *) + | Op.MULW -> "mulw" + | Op.DIVW -> "divw" + | Op.DIVUW -> "divuw" + | Op.REMW -> "remw" + | Op.REMUW -> "remuw" + (* RV32A Standard Extension *) + | Op.LRdotW -> "lr.w" + | Op.SCdotW -> "sc.w" + | Op.AMOSWAPdotW -> "amoswap.w" + | Op.AMOADDdotW -> "amoadd.w" + | Op.AMOXORdotW -> "amoxor.w" + | Op.AMOANDdotW -> "amoand.w" + | Op.AMOORdotW -> "amoor.w" + | Op.AMOMINdotW -> "amomin.w" + | Op.AMOMAXdotW -> "amomax.w" + | Op.AMOMINUdotW -> "amomin.w" + | Op.AMOMAXUdotW -> "amomax.w" + (* RV64A Standard Extension *) + | Op.LRdotD -> "lr.d" + | Op.SCdotD -> "sc.d" + | Op.AMOSWAPdotD -> "amoswap.d" + | Op.AMOADDdotD -> "amoadd.d" + | Op.AMOXORdotD -> "amoxor.d" + | Op.AMOANDdotD -> "amoand.d" + | Op.AMOORdotD -> "amoor.d" + | Op.AMOMINdotD -> "amomin.d" + | Op.AMOMAXdotD -> "amomax.d" + | Op.AMOMINUdotD -> "amominu.d" + | Op.AMOMAXUdotD -> "amomaxu.d" + (* RV32F Standard Extension *) + | Op.FLW -> "flw" + | Op.FSW -> "fsw" + | Op.FMADDdotS -> "fmadd.s" + | Op.FMSUBdotS -> "fmsub.s" + | Op.FNMSUBdotS -> "fnmsub.s" + | Op.FNMADDdotS -> "fnmadd.s" + | Op.FADDdotS -> "fadd.s" + | Op.FSUBdotS -> "fsub.s" + | Op.FMULdotS -> "fmul.s" + | Op.FDIVdotS -> "fdiv.s" + | Op.FSQRTdotS -> "fsqrt.s" + | Op.FSGNJdotS -> "fsgnj.s" + | Op.FSGNJNdotS -> "fsgnjn.s" + | Op.FSGNJXdotS -> "fsgnjx.s" + | Op.FMINdotS -> "fmin.s" + | Op.FMAXdotS -> "fmax.s" + | Op.FCVTdotWdotS -> "fcvt.w.s" + | Op.FCVTdotWUdotS -> "fcvt.wu.s" + | Op.FMVdotXdotW -> "fmv.x.w" + | Op.FEQdotS -> "feq.s" + | Op.FLTdotS -> "flt.s" + | Op.FLEdotS -> "fle.s" + | Op.FCLASSdotS -> "fclass.s" + | Op.FCVTdotSdotW -> "fcvt.w.s" + | Op.FCVTdotSdotWU -> "fcvt.s.wu" + | Op.FMVdotWdotX -> "fmv.w.x" + (* RV64F Standard Extension *) + | Op.FCVTdotLdotS -> "fcvt.l.s" + | Op.FCVTdotLUdotS -> "fcvt.lu.s" + | Op.FCVTdotSdotL -> "fcvt.s.l" + | Op.FCVTdotSdotLU -> "fcvt.s.lu" + (* RV32D Standard Extension *) + | Op.FLD -> "fld" + | Op.FSD -> "fsd" + | Op.FMADDdotD -> "fmadd.d" + | Op.FMSUBdotD -> "fmsub.d" + | Op.FNMSUBdotD -> "fnmsub.d" + | Op.FNMADDdotD -> "fnmadd.d" + | Op.FADDdotD -> "fadd.d" + | Op.FSUBdotD -> "fsub.d" + | Op.FMULdotD -> "fmul.d" + | Op.FDIVdotD -> "fdiv.d" + | Op.FSQRTdotD -> "fsqrt.d" + | Op.FSGNJdotD -> "fsgnj.d" + | Op.FSGNJNdotD -> "fsgnjn.d" + | Op.FSGNJXdotD -> "fsgnjx.d" + | Op.FMINdotD -> "fmin.d" + | Op.FMAXdotD -> "fmax.d" + | Op.FCVTdotSdotD -> "fcvt.s.d" + | Op.FCVTdotDdotS -> "fcvt.d.s" + | Op.FEQdotD -> "feq.d" + | Op.FLTdotD -> "flt.d" + | Op.FLEdotD -> "fle.d" + | Op.FCLASSdotD -> "fclass.d" + | Op.FCVTdotWdotD -> "fcvt.w.d" + | Op.FCVTdotWUdotD -> "fcvt.wu.d" + | Op.FCVTdotDdotW -> "fcvt.d.w" + | Op.FCVTdotDdotWU -> "fcvt.d.wu" + (* RV64D Standard Extension *) + | Op.FCVTdotLdotD -> "fcvt.l.d" + | Op.FCVTdotLUdotD -> "fcvt.lu.d" + | Op.FMVdotXdotD -> "fmv.x.d" + | Op.FCVTdotDdotL -> "fcvt.d.l" + | Op.FCVTdotDdotLU -> "fcvt.d.lu" + | Op.FMVdotDdotX -> "fmv.d.x" + | Op.FENCEdotTSO -> "fence.tso" + | Op.CdotADDI4SPN -> "addi" + | Op.CdotFLD -> "fld" + | Op.CdotLW -> "lw" + | Op.CdotLD -> "ld" + | Op.CdotFSD -> "fsd" + | Op.CdotSW -> "sw" + | Op.CdotSD -> "sd" + | Op.CdotNOP -> "nop" + | Op.CdotADDI -> "addi" + | Op.CdotADDIW -> "addiw" + | Op.CdotLI -> "addi" + | Op.CdotADDI16SP -> "addi" + | Op.CdotLUI -> "lui" + | Op.CdotSRLI -> "srli" + | Op.CdotSRAI -> "srai" + | Op.CdotANDI -> "andi" + | Op.CdotSUB -> "sub" + | Op.CdotXOR -> "xor" + | Op.CdotOR -> "or" + | Op.CdotAND -> "and" + | Op.CdotSUBW -> "subw" + | Op.CdotADDW -> "addw" + | Op.CdotJ -> "jal" + | Op.CdotBEQZ -> "beq" + | Op.CdotBNEZ -> "bne" + | Op.CdotSLLI -> "slli" + | Op.CdotFLDSP -> "fld" + | Op.CdotLWSP -> "lw" + | Op.CdotLDSP -> "ld" + | Op.CdotJR -> "jalr" + | Op.CdotMV -> "add" + | Op.CdotEBREAK -> "ebreak" + | Op.CdotJALR -> "jalr" + | Op.CdotADD -> "add" + | Op.CdotFSDSP -> "fsd" + | Op.CdotSWSP -> "sw" + | Op.CdotSDSP -> "sd" | _ -> Utils.impossible () -let inline buildOpcode ins (builder: DisasmBuilder<_>) = +let roundModeToString = function + | RoundMode.RNE -> "rne" + | RoundMode.RTZ -> "rtz" + | RoundMode.RDN -> "rdn" + | RoundMode.RUP -> "rup" + | RoundMode.RMM -> "rmm" + | RoundMode.DYN -> "" + | _ -> Utils.impossible () + +let fenceMaskToString x = + let bin = x |> uint32 + let i = if pickBit bin 3u = 1u then "i" else "" + let o = if pickBit bin 2u = 1u then "o" else "" + let r = if pickBit bin 1u = 1u then "r" else "" + let w = if pickBit bin 0u = 1u then "w" else "" + i + o + r + w + +let inline buildOpcode ins (builder: DisasmBuilder) = let str = opCodeToString ins.Opcode builder.Accumulate AsmWordKind.Mnemonic str -let oprToString opr delim (builder: DisasmBuilder<_>) = +let inline relToString pc offset (builder: DisasmBuilder) = + let targetAddr = pc + uint64 offset + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 targetAddr) + +let oprToString insInfo opr delim (builder: DisasmBuilder) = match opr with | OpReg reg -> builder.Accumulate AsmWordKind.String delim builder.Accumulate AsmWordKind.Variable (Register.toString reg) + | OpImm imm + | OpShiftAmount imm -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 imm) + | OpMem (b, None, _) -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.String "(" + builder.Accumulate AsmWordKind.Variable (Register.toString b) + builder.Accumulate AsmWordKind.String ")" + | OpMem (b, Some (Imm off), _) -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (off.ToString ("D")) + builder.Accumulate AsmWordKind.String "(" + builder.Accumulate AsmWordKind.Variable (Register.toString b) + builder.Accumulate AsmWordKind.String ")" + | OpAddr (Relative offset) -> + builder.Accumulate AsmWordKind.String delim + relToString insInfo.Address offset builder + | OpAddr (RelativeBase (b, off)) -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (off.ToString ("D")) + builder.Accumulate AsmWordKind.String "(" + builder.Accumulate AsmWordKind.Variable (Register.toString b) + builder.Accumulate AsmWordKind.String ")" + | OpAtomMemOper (aq, rl) -> + if aq then builder.Accumulate AsmWordKind.String "aq" + if rl then builder.Accumulate AsmWordKind.String "rl" + | OpFenceMask (pred, succ) -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.String (fenceMaskToString pred) + builder.Accumulate AsmWordKind.String "," + builder.Accumulate AsmWordKind.String (fenceMaskToString succ) + | OpRoundMode (rm) -> + if rm <> RoundMode.DYN then + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.String (roundModeToString rm) + else () + | OpCSR (csr) -> + builder.Accumulate AsmWordKind.String delim + builder.Accumulate AsmWordKind.Value (HexString.ofUInt16 csr) let buildOprs insInfo builder = match insInfo.Operands with | NoOperand -> () | OneOperand opr -> - oprToString opr " " builder + oprToString insInfo opr " " builder | TwoOperands (opr1, opr2) -> - oprToString opr1 " " builder - oprToString opr2 ", " builder + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + | ThreeOperands (opr1, opr2, opr3) -> + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder + | FourOperands (opr1, opr2, opr3, opr4) -> + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder + oprToString insInfo opr4 ", " builder + | FiveOperands (opr1, opr2, opr3, opr4, opr5) -> + oprToString insInfo opr1 " " builder + oprToString insInfo opr2 ", " builder + oprToString insInfo opr3 ", " builder + oprToString insInfo opr4 ", " builder + oprToString insInfo opr5 ", " builder -let disasm insInfo (builder: DisasmBuilder<_>) = +let disasm insInfo (builder: DisasmBuilder) = if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode insInfo builder buildOprs insInfo builder diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Helper.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Helper.fs new file mode 100644 index 00000000..0864389f --- /dev/null +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Helper.fs @@ -0,0 +1,254 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.RISCV.Helper + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData + +let getRm = function + | 0u -> RoundMode.RNE + | 1u -> RoundMode.RTZ + | 2u -> RoundMode.RDN + | 3u -> RoundMode.RUP + | 4u -> RoundMode.RMM + | 7u -> RoundMode.DYN + | _ -> raise ParsingFailureException + +let getRegister = function + | 0x0uy -> R.X0 + | 0x1uy -> R.X1 + | 0x2uy -> R.X2 + | 0x3uy -> R.X3 + | 0x4uy -> R.X4 + | 0x5uy -> R.X5 + | 0x6uy -> R.X6 + | 0x7uy -> R.X7 + | 0x8uy -> R.X8 + | 0x9uy -> R.X9 + | 0xAuy -> R.X10 + | 0xBuy -> R.X11 + | 0xCuy -> R.X12 + | 0xDuy -> R.X13 + | 0xEuy -> R.X14 + | 0xFuy -> R.X15 + | 0x10uy -> R.X16 + | 0x11uy -> R.X17 + | 0x12uy -> R.X18 + | 0x13uy -> R.X19 + | 0x14uy -> R.X20 + | 0x15uy -> R.X21 + | 0x16uy -> R.X22 + | 0x17uy -> R.X23 + | 0x18uy -> R.X24 + | 0x19uy -> R.X25 + | 0x1Auy -> R.X26 + | 0x1Buy -> R.X27 + | 0x1Cuy -> R.X28 + | 0x1Duy -> R.X29 + | 0x1Euy -> R.X30 + | 0x1Fuy -> R.X31 + | _ -> raise InvalidRegisterException + +let getFRegister = function + | 0x0uy -> R.F0 + | 0x1uy -> R.F1 + | 0x2uy -> R.F2 + | 0x3uy -> R.F3 + | 0x4uy -> R.F4 + | 0x5uy -> R.F5 + | 0x6uy -> R.F6 + | 0x7uy -> R.F7 + | 0x8uy -> R.F8 + | 0x9uy -> R.F9 + | 0xAuy -> R.F10 + | 0xBuy -> R.F11 + | 0xCuy -> R.F12 + | 0xDuy -> R.F13 + | 0xEuy -> R.F14 + | 0xFuy -> R.F15 + | 0x10uy -> R.F16 + | 0x11uy -> R.F17 + | 0x12uy -> R.F18 + | 0x13uy -> R.F19 + | 0x14uy -> R.F20 + | 0x15uy -> R.F21 + | 0x16uy -> R.F22 + | 0x17uy -> R.F23 + | 0x18uy -> R.F24 + | 0x19uy -> R.F25 + | 0x1Auy -> R.F26 + | 0x1Buy -> R.F27 + | 0x1Cuy -> R.F28 + | 0x1Duy -> R.F29 + | 0x1Euy -> R.F30 + | 0x1Fuy -> R.F31 + | _ -> raise InvalidRegisterException + +let getCompRegister = function + | 0x0uy -> R.X8 + | 0x1uy -> R.X9 + | 0x2uy -> R.X10 + | 0x3uy -> R.X11 + | 0x4uy -> R.X12 + | 0x5uy -> R.X13 + | 0x6uy -> R.X14 + | 0x7uy -> R.X15 + | _ -> Utils.impossible () + +let getFCompRegister = function + | 0x0uy -> R.F8 + | 0x1uy -> R.F9 + | 0x2uy -> R.F10 + | 0x3uy -> R.F11 + | 0x4uy -> R.F12 + | 0x5uy -> R.F13 + | 0x6uy -> R.F14 + | 0x7uy -> R.F15 + | _ -> Utils.impossible () + +let getRegFrom117 b = getRegister (extract b 11u 7u |> byte) +let getFRegFrom117 b = getFRegister (extract b 11u 7u |> byte) +let getRegFrom1915 b = getRegister (extract b 19u 15u |> byte) +let getFRegFrom1915 b = getFRegister (extract b 19u 15u |> byte) +let getRegFrom2420 b = getRegister (extract b 24u 20u |> byte) +let getFRegFrom2420 b = getFRegister (extract b 24u 20u |> byte) +let getRegFrom3127 b = getRegister (extract b 31u 27u |> byte) +let getFRegFrom3127 b = getFRegister (extract b 31u 27u |> byte) +let getRegFrom62 b = getRegister (extract b 6u 2u |> byte) +let getFRegFrom62 b = getFRegister (extract b 6u 2u |> byte) +let getCompRegFrom42 b = getCompRegister (extract b 4u 2u |> byte) +let getFCompRegFrom42 b = getFCompRegister (extract b 4u 2u |> byte) +let getCompRegFrom97 b = getCompRegister (extract b 9u 7u |> byte) + +let getUImm b wordSize = + let imm = extract b 31u 12u |> uint64 + signExtend 20 wordSize imm + +let getBImm b wordSize = + let from4to1 = (extract b 11u 8u) <<< 1 + let from10to5 = (extract b 30u 25u) <<< 5 + let from11to11 = (pickBit b 7u) <<< 11 + let from12to12 = (pickBit b 31u) <<< 12 + let imm = from12to12 ||| from11to11 ||| from10to5 ||| from4to1 ||| 0b0u + |> uint64 + signExtend 13 wordSize imm + +let getIImm b wordSize = + let imm = extract b 31u 20u |> uint64 + signExtend 12 wordSize imm + +let getSImm b wordSize = + let from4to0 = extract b 11u 7u + let from11to5 = extract b 31u 25u <<< 5 + let imm = from11to5 ||| from4to0 |> uint64 + signExtend 12 wordSize imm + +let getJImm bin wordSize = + let from10to1 = (extract bin 30u 21u) <<< 1 + let from11to11 = (pickBit bin 20u) <<< 11 + let from19to12 = (extract bin 19u 12u) <<< 12 + let from20to20 = (pickBit bin 31u) <<< 20 + let imm = 0b0u ||| from10to1 ||| from11to11 ||| from19to12 ||| from20to20 + |> uint64 + signExtend 21 wordSize imm |> int64 + +let rd b = getRegFrom117 b |> OpReg +let frd b = getFRegFrom117 b |> OpReg +let rs1 b = getRegFrom1915 b |> OpReg +let frs1 b = getFRegFrom1915 b |> OpReg +let rs2 b = getRegFrom2420 b |> OpReg +let frs2 b = getFRegFrom2420 b |> OpReg +let rs3 b = getRegFrom3127 b |> OpReg +let frs3 b = getFRegFrom3127 b |> OpReg +let rm b = getRm (extract b 14u 12u) |> OpRoundMode +let csr b = extract b 31u 20u |> uint16 |> OpCSR +let uimm b = extract b 19u 15u |> uint64 |> OpImm +let shamt b = extract b 25u 20u |> uint64 |> OpShiftAmount +let crd b = getRegFrom117 b |> OpReg +let cfrd b = getFRegFrom117 b |> OpReg +let crs2 b = getRegFrom62 b |> OpReg +let crs2Comp b = getCompRegFrom42 b |> OpReg +let cfrs2 b = getFRegFrom62 b |> OpReg +let cfrs2Comp b = getFCompRegFrom42 b |> OpReg +let crdComp b = getCompRegFrom42 b |> OpReg +let cfrdComp b = getFCompRegFrom42 b |> OpReg +let crs1Comp b = getCompRegFrom97 b |> OpReg + +let getPred bin = extract bin 27u 24u |> uint8 +let getSucc bin = extract bin 23u 20u |> uint8 +let getAqRl bin = OpAtomMemOper(pickBit bin 26u > 0u, pickBit bin 25u > 0u) +let getRdImm20 b wordSz = TwoOperands (rd b, getUImm b wordSz |> OpImm) +let getPCRdImm20 b wordSz = TwoOperands (rd b, getUImm b wordSz |> OpImm) +let getRs1Rs2BImm b wordSz = + ThreeOperands (rs1 b, rs2 b, getBImm b wordSz |> int64 |> Relative |> OpAddr) +let getRdRs1IImmAcc b acc wordSize = + let mem = (getRegFrom1915 b, getIImm b wordSize |> int64 |> Imm |> Some, acc) + TwoOperands (rd b, mem |> OpMem) +let getRdRs1IImm b wordSize = + ThreeOperands (rd b, rs1 b, getIImm b wordSize |> uint64 |> OpImm) +let getFRdRs1Addr b acc wordSize = + let imm = getIImm b wordSize |> int64 |> Imm |> Some + TwoOperands(frd b, OpMem (getRegFrom1915 b, imm, acc)) +let getRs2Rs1SImm b acc wordSize = + let mem = (getRegFrom1915 b, getSImm b wordSize |> int64 |> Imm |> Some, acc) + TwoOperands (rs2 b, mem |> OpMem) +let getFRs2Rs1Addr b acc wordSize = + let imm = getSImm b wordSize |> int64 |> Imm |> Some + TwoOperands (frs2 b, OpMem (getRegFrom1915 b, imm, acc)) +let getRdRs1Shamt b = ThreeOperands(rd b, rs1 b, shamt b) +let getRdRs1Rs2 b = ThreeOperands(rd b, rs1 b, rs2 b) +let getFRdRs1Rs2 b = ThreeOperands(frd b, frs1 b, frs2 b) +let getFNRdRs1Rs2 b = ThreeOperands(rd b, frs1 b, frs2 b) +let getPredSucc b = OneOperand ((getPred b, getSucc b) |> OpFenceMask) +let getFunc3 b = extract b 14u 12u +let getFunc7 b = extract b 31u 25u +let getRs2 b = extract b 24u 20u +let getRdRs1AqRlAcc b acc = + ThreeOperands (rd b, OpMem (getRegFrom1915 b, None, acc), getAqRl b) +let getRdRs1Rs2AqRlAcc b acc = + let mem = OpMem (getRegFrom1915 b, None, acc) + FourOperands (rd b, mem, rs2 b, getAqRl b) +let getRdRs2Rs1AqRlAcc b acc = + let mem = OpMem (getRegFrom1915 b, None, acc) + FourOperands (rd b, rs2 b, mem, getAqRl b) +let getRdJImm b wordSize = + TwoOperands (rd b, getJImm b wordSize |> int64 |> Relative |> OpAddr) +let getRdRs1JImm b wordSize = + let off = RelativeBase (getRegFrom1915 b, getIImm b wordSize |> uint64) + TwoOperands (rd b, off |> OpAddr) +let getFRdRs1Rs2Rs3Rm b = FiveOperands (frd b, frs1 b, frs2 b, frs3 b, rm b) +let getRdRs1Rs2Rm b = FourOperands (rd b, rs1 b, rs2 b, rm b) +let getFRdRs1Rs2Rm b = FourOperands (frd b, frs1 b, frs2 b, rm b) +let getRdRs1Rm b = ThreeOperands (rd b, rs1 b, rm b) +let getFRdRs1Rm b = ThreeOperands (frd b, rs1 b, rm b) +let getFRdFRs1Rm b = ThreeOperands (frd b, frs1 b, rm b) +let getRdFRs1Rm b = ThreeOperands (rd b, frs1 b, rm b) +let getRdRs1 b = TwoOperands (rd b, rs1 b) +let getRdFRs1 b = TwoOperands (rd b, frs1 b) +let getFRdFRs1 b = TwoOperands (frd b, frs1 b) +let getFRdRs1 b = TwoOperands (frd b, rs1 b) +let getRdCSRRs1 b = ThreeOperands (rd b, csr b, rs1 b) +let getRdCSRUImm b = ThreeOperands (rd b, csr b, uimm b) diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Instruction.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Instruction.fs index 049939b8..9df4fd87 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64Instruction.fs +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Instruction.fs @@ -78,27 +78,29 @@ type RISCV64Instruction (addr, numBytes, insInfo) = override __.IsNop () = Utils.futureFeature () - override __.Translate _ctxt = Utils.futureFeature () + override __.Translate ctxt = + (Lifter.translate __.Info numBytes ctxt).ToStmts () - override __.TranslateToList _ctxt = Utils.futureFeature () + override __.TranslateToList ctxt = + Lifter.translate __.Info numBytes ctxt - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = - DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) + DisasmStringBuilder (showAddr, false, WordSize.Bit64, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = - DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) + DisasmStringBuilder (false, false, WordSize.Bit64, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = - DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) + DisasmWordBuilder (showAddr, false, WordSize.Bit64, addr, numBytes, 8) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Lifter.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Lifter.fs new file mode 100644 index 00000000..9a6a7af5 --- /dev/null +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Lifter.fs @@ -0,0 +1,2553 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.RISCV.Lifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingUtils +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.RISCV + +let inline getRegVar (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let inline (:=) dst src = + match dst with + | { E = Var (_, rid, _) } when rid = Register.toRegID Register.X0 -> + dst := dst (* Prevent setting x0. Our optimizer will remove this anyways. *) + | _ -> + dst := src + +let inline getCSRReg (ctxt: TranslationContext) csr = + let csrReg = + match csr with + | 0001us -> Register.FFLAGS + | 0002us -> Register.FRM + | 0003us -> Register.FCSR + | 0768us -> Register.CSR0768 + | 0769us -> Register.CSR0769 + | 0770us -> Register.CSR0770 + | 0771us -> Register.CSR0771 + | 0772us -> Register.CSR0772 + | 0773us -> Register.CSR0773 + | 0784us -> Register.CSR0784 + | 0832us -> Register.CSR0832 + | 0833us -> Register.CSR0833 + | 0834us -> Register.CSR0834 + | 0835us -> Register.CSR0835 + | 0836us -> Register.CSR0836 + | 0842us -> Register.CSR0842 + | 0843us -> Register.CSR0843 + | 3114us -> Register.CSR3114 + | 3787us -> Register.CSR3787 + | 3857us -> Register.CSR3857 + | 3858us -> Register.CSR3858 + | 3859us -> Register.CSR3859 + | 3860us -> Register.CSR3860 + | 0928us -> Register.CSR0928 + | 0930us -> Register.CSR0930 + | 0932us -> Register.CSR0932 + | 0934us -> Register.CSR0934 + | 0936us -> Register.CSR0936 + | 0938us -> Register.CSR0938 + | 0940us -> Register.CSR0940 + | 0942us -> Register.CSR0942 + | 0944us -> Register.CSR0944 + | 0945us -> Register.CSR0945 + | 0946us -> Register.CSR0946 + | 0947us -> Register.CSR0947 + | 0948us -> Register.CSR0948 + | 0949us -> Register.CSR0949 + | 0950us -> Register.CSR0950 + | 0951us -> Register.CSR0951 + | 0952us -> Register.CSR0952 + | 0953us -> Register.CSR0953 + | 0954us -> Register.CSR0954 + | 0955us -> Register.CSR0955 + | 0956us -> Register.CSR0956 + | 0957us -> Register.CSR0957 + | 0958us -> Register.CSR0958 + | 0959us -> Register.CSR0959 + | 0960us -> Register.CSR0960 + | 0961us -> Register.CSR0961 + | 0962us -> Register.CSR0962 + | 0963us -> Register.CSR0963 + | 0964us -> Register.CSR0964 + | 0965us -> Register.CSR0965 + | 0966us -> Register.CSR0966 + | 0967us -> Register.CSR0967 + | 0968us -> Register.CSR0968 + | 0969us -> Register.CSR0969 + | 0970us -> Register.CSR0970 + | 0971us -> Register.CSR0971 + | 0972us -> Register.CSR0972 + | 0973us -> Register.CSR0973 + | 0974us -> Register.CSR0974 + | 0975us -> Register.CSR0975 + | 0976us -> Register.CSR0976 + | 0977us -> Register.CSR0977 + | 0978us -> Register.CSR0978 + | 0979us -> Register.CSR0979 + | 0980us -> Register.CSR0980 + | 0981us -> Register.CSR0981 + | 0982us -> Register.CSR0982 + | 0983us -> Register.CSR0983 + | 0984us -> Register.CSR0984 + | 0985us -> Register.CSR0985 + | 0986us -> Register.CSR0986 + | 0987us -> Register.CSR0987 + | 0988us -> Register.CSR0988 + | 0989us -> Register.CSR0989 + | 0990us -> Register.CSR0990 + | 0991us -> Register.CSR0991 + | 0992us -> Register.CSR0992 + | 0993us -> Register.CSR0993 + | 0994us -> Register.CSR0994 + | 0995us -> Register.CSR0995 + | 0996us -> Register.CSR0996 + | 0997us -> Register.CSR0997 + | 0998us -> Register.CSR0998 + | 0999us -> Register.CSR0999 + | 1000us -> Register.CSR1000 + | 1001us -> Register.CSR1001 + | 1002us -> Register.CSR1002 + | 1003us -> Register.CSR1003 + | 1004us -> Register.CSR1004 + | 1005us -> Register.CSR1005 + | 1006us -> Register.CSR1006 + | 1007us -> Register.CSR1007 + | 2145us -> Register.CSR2145 + | 2617us -> Register.CSR2617 + | 2816us -> Register.CSR2816 + | 2818us -> Register.CSR2818 + | 2819us -> Register.CSR2819 + | 2820us -> Register.CSR2820 + | 2821us -> Register.CSR2821 + | 2822us -> Register.CSR2822 + | 2823us -> Register.CSR2823 + | 2824us -> Register.CSR2824 + | 2825us -> Register.CSR2825 + | 2826us -> Register.CSR2826 + | 2827us -> Register.CSR2827 + | 2828us -> Register.CSR2828 + | 2829us -> Register.CSR2829 + | 2830us -> Register.CSR2830 + | 2831us -> Register.CSR2831 + | 2832us -> Register.CSR2832 + | 2833us -> Register.CSR2833 + | 2834us -> Register.CSR2834 + | 2835us -> Register.CSR2835 + | 2836us -> Register.CSR2836 + | 2837us -> Register.CSR2837 + | 2838us -> Register.CSR2838 + | 2839us -> Register.CSR2839 + | 2840us -> Register.CSR2840 + | 2841us -> Register.CSR2841 + | 2842us -> Register.CSR2842 + | 2843us -> Register.CSR2843 + | 2844us -> Register.CSR2844 + | 2845us -> Register.CSR2845 + | 2846us -> Register.CSR2846 + | 2847us -> Register.CSR2847 + | 2945us -> Register.CSR2945 + | 0800us -> Register.CSR0800 + | 0803us -> Register.CSR0803 + | 0804us -> Register.CSR0804 + | 0805us -> Register.CSR0805 + | 0806us -> Register.CSR0806 + | 0807us -> Register.CSR0807 + | 0808us -> Register.CSR0808 + | 0809us -> Register.CSR0809 + | 0810us -> Register.CSR0810 + | 0811us -> Register.CSR0811 + | 0812us -> Register.CSR0812 + | 0813us -> Register.CSR0813 + | 0814us -> Register.CSR0814 + | 0815us -> Register.CSR0815 + | 0816us -> Register.CSR0816 + | 0817us -> Register.CSR0817 + | 0818us -> Register.CSR0818 + | 0819us -> Register.CSR0819 + | 0820us -> Register.CSR0820 + | 0821us -> Register.CSR0821 + | 0822us -> Register.CSR0822 + | 0823us -> Register.CSR0823 + | 0824us -> Register.CSR0824 + | 0825us -> Register.CSR0825 + | 0826us -> Register.CSR0826 + | 0827us -> Register.CSR0827 + | 0828us -> Register.CSR0828 + | 0829us -> Register.CSR0829 + | 0830us -> Register.CSR0830 + | 0831us -> Register.CSR0831 + | 1952us -> Register.CSR1952 + | 1953us -> Register.CSR1953 + | 1954us -> Register.CSR1954 + | 1955us -> Register.CSR1955 + | 1968us -> Register.CSR1968 + | 1969us -> Register.CSR1969 + | 1970us -> Register.CSR1970 + | 1971us -> Register.CSR1971 + | _ -> + eprintfn "%A" csr + raise InvalidRegisterException + Register.toRegID csrReg |> ctxt.GetRegVar + +let bvOfBaseAddr (ctxt: TranslationContext) addr = numU64 addr ctxt.WordBitSize + +let bvOfInstrLen (ctxt: TranslationContext) insInfo = + numU32 insInfo.NumBytes ctxt.WordBitSize + +let getOneOpr insInfo = + match insInfo.Operands with + | OneOperand opr -> opr + | _ -> raise InvalidOperandException + +let getTwoOprs insInfo = + match insInfo.Operands with + | TwoOperands (o1, o2) -> o1, o2 + | _ -> raise InvalidOperandException + +let getThreeOprs insInfo = + match insInfo.Operands with + | ThreeOperands (o1, o2, o3) -> o1, o2, o3 + | _ -> raise InvalidOperandException + +let getFourOprs insInfo = + match insInfo.Operands with + | FourOperands (o1, o2, o3, o4) -> o1, o2, o3, o4 + | _ -> raise InvalidOperandException + +let getFiveOprs insInfo = + match insInfo.Operands with + | FiveOperands (o1, o2, o3, o4, o5) -> o1, o2, o3, o4, o5 + | _ -> raise InvalidOperandException + +let transOprToExpr insInfo ctxt = function + | OpReg reg -> getRegVar ctxt reg + | OpImm imm + | OpShiftAmount imm -> numU64 imm ctxt.WordBitSize + | OpMem (b, Some (Imm o), sz) -> + let reg = getRegVar ctxt b + let offset = numI64 o ctxt.WordBitSize + AST.loadLE sz (reg .+ offset) + | OpAddr (Relative o) -> numI64 (int64 insInfo.Address + o) ctxt.WordBitSize + | OpAddr (RelativeBase (b, imm)) -> + if b = Register.X0 then + AST.num0 ctxt.WordBitSize + else + let target = getRegVar ctxt b .+ numI64 (int64 imm) ctxt.WordBitSize + let mask = numI64 0xFFFFFFFF_FFFFFFFEL 64 + target .& mask + | OpMem (b, None, sz) -> AST.loadLE sz (getRegVar ctxt b) + | OpAtomMemOper (_) -> numU32 0u 32 // FIXME: + | OpCSR (csr) -> getCSRReg ctxt csr + | _ -> raise InvalidOperandException + +let private maskForFCSR csr (opr1, opr2) = + let lowSrc = AST.xtlo 32 opr2 + let mask = + match csr with + | OpCSR csr when csr = 0001us -> lowSrc .& numU32 0b11111u 32 + | OpCSR csr when csr = 0002us -> lowSrc .& numU32 0b111u 32 + | _ -> opr2 + opr1, mask + +let private assignFCSR dst src ctxt ir = + match dst with + | { E = BinOp _ } -> + let lowSrc = AST.xtlo 32 src + !!ir (getRegVar ctxt R.FRM := + (lowSrc .& numU32 0b11100000u 32) >> numI32 5 32) + !!ir (getRegVar ctxt R.FFLAGS := lowSrc .& numU32 0b11111u 32) + | _ -> !!ir (dst := src) + +let roundingToCastFloat x = + match x with + | OpRoundMode (rm) -> + match rm with + | RoundMode.RNE + | RoundMode.RMM -> CastKind.FtoFRound + | RoundMode.RTZ -> CastKind.FtoFTrunc + | RoundMode.RDN -> CastKind.FtoFFloor + | RoundMode.RUP -> CastKind.FtoFCeil + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandException + +let roundingToCastInt x = + match x with + | OpRoundMode (rm) -> + match rm with + | RoundMode.RNE + | RoundMode.RMM -> CastKind.FtoIRound + | RoundMode.RTZ -> CastKind.FtoITrunc + | RoundMode.RDN -> CastKind.FtoIFloor + | RoundMode.RUP -> CastKind.FtoICeil + | _ -> raise InvalidOperandException + | _ -> raise InvalidOperandException + +let dynamicRoundingFl ir ctxt rt res = + let tmpVar = !+ir rt + let frm = (getRegVar ctxt Register.FRM) .& (numI32 7 32) + let condRNERMM = (frm == numI32 0 32) .| (frm == numI32 4 32) + let condRTZ = frm == numI32 1 32 + let condRDN = frm == numI32 2 32 + let condRUP = frm == numI32 3 32 + let lblD0 = !%ir "DF0" + let lblD1 = !%ir "DF1" + let lblD2 = !%ir "DF2" + let lblD3 = !%ir "DF3" + let lblD4 = !%ir "DF4" + let lblD5 = !%ir "DF6" + let lblD6 = !%ir "DF7" + let lblDException = !%ir "DFException" + let lblDEnd = !%ir "DFEnd" + !!ir (AST.cjmp condRNERMM (AST.name lblD0) (AST.name lblD1)) + !!ir (AST.lmark lblD0) + !!ir (tmpVar := AST.cast CastKind.FtoFRound rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblD1) + !!ir (AST.cjmp condRTZ (AST.name lblD2) (AST.name lblD3)) + !!ir (AST.lmark lblD2) + !!ir (tmpVar := AST.cast CastKind.FtoFTrunc rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblD3) + !!ir (AST.cjmp condRDN (AST.name lblD4) (AST.name lblD5)) + !!ir (AST.lmark lblD4) + !!ir (tmpVar := AST.cast CastKind.FtoFFloor rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblD5) + !!ir (AST.cjmp condRUP (AST.name lblD6) (AST.name lblDException)) + !!ir (AST.lmark lblD6) + !!ir (tmpVar := AST.cast CastKind.FtoFCeil rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblDException) + !!ir (AST.sideEffect (Exception "illegal instruction")) + !!ir (AST.lmark lblDEnd) + tmpVar + +let dynamicRoundingInt ir ctxt rt res = + let tmpVar = !+ir rt + let frm = (getRegVar ctxt Register.FRM) .& (numI32 7 32) + let condRNERMM = (frm == numI32 0 32) .| (frm == numI32 4 32) + let condRTZ = frm == numI32 1 32 + let condRDN = frm == numI32 2 32 + let condRUP = frm == numI32 3 32 + let lblD0 = !%ir "DI0" + let lblD1 = !%ir "DI1" + let lblD2 = !%ir "DI2" + let lblD3 = !%ir "DI3" + let lblD4 = !%ir "DI4" + let lblD5 = !%ir "DI6" + let lblD6 = !%ir "DI7" + let lblDException = !%ir "DIException" + let lblDEnd = !%ir "DIEnd" + !!ir (AST.cjmp condRNERMM (AST.name lblD0) (AST.name lblD1)) + !!ir (AST.lmark lblD0) + !!ir (tmpVar := AST.cast (CastKind.FtoIRound) rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblD1) + !!ir (AST.cjmp condRTZ (AST.name lblD2) (AST.name lblD3)) + !!ir (AST.lmark lblD2) + !!ir (tmpVar := AST.cast (CastKind.FtoITrunc) rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblD3) + !!ir (AST.cjmp condRDN (AST.name lblD4) (AST.name lblD5)) + !!ir (AST.lmark lblD4) + !!ir (tmpVar := AST.cast (CastKind.FtoIFloor) rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblD5) + !!ir (AST.cjmp condRUP (AST.name lblD6) (AST.name lblDException)) + !!ir (AST.lmark lblD6) + !!ir (tmpVar := AST.cast (CastKind.FtoICeil) rt res) + !!ir (AST.jmp (AST.name lblDEnd)) + !!ir (AST.lmark lblDException) + !!ir (AST.sideEffect (Exception "illegal instruction")) + !!ir (AST.lmark lblDEnd) + tmpVar + +let transOneOpr insInfo ctxt opr = transOprToExpr insInfo ctxt opr + +let transTwoOprs insInfo ctxt (o1, o2) = + transOprToExpr insInfo ctxt o1, transOprToExpr insInfo ctxt o2 + +let transThreeOprs insInfo ctxt (o1, o2, o3) = + transOprToExpr insInfo ctxt o1, + transOprToExpr insInfo ctxt o2, + transOprToExpr insInfo ctxt o3 + +let transFourOprs insInfo ctxt (o1, o2, o3, o4) = + transOprToExpr insInfo ctxt o1, + transOprToExpr insInfo ctxt o2, + transOprToExpr insInfo ctxt o3, + transOprToExpr insInfo ctxt o4 + +let getNanBoxed e = (numU64 0xFFFFFFFF_00000000uL 64) .| (AST.zext 64 e) + +let dstAssignSingleWithRound dst src rm ctxt ir = + let rtVal = getNanBoxed src + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + !!ir (dst := AST.cast rounding 64 rtVal) + else + !!ir (dst := dynamicRoundingFl ir ctxt 64 rtVal) + +let dstAssignDoubleWithRound dst src rm ctxt ir = + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + !!ir (dst := AST.cast rounding 64 src) + else + !!ir (dst := dynamicRoundingFl ir ctxt 64 src) + +let getAddrFromMem x = + match x.E with + | Load (_, _, addr) -> addr + | _ -> raise InvalidExprException + +let getAddrFromMemAndSize x = + match x.E with + | Load (_, rt, addr) -> addr, numI32 (RegType.toByteWidth rt) 64 + | _ -> raise InvalidExprException + +let isAligned rt expr = + match rt with + | 32 -> ((expr .& (numU32 0x3u 64)) == AST.num0 64) + | 64 -> ((expr .& (numU32 0x7u 64)) == AST.num0 64) + | _ -> raise InvalidRegTypeException + +let getAccessLength = function + | OpMem (_, _, sz) -> sz + | _ -> raise InvalidOperandException + +let fpDefaultNan oprSz = + match oprSz with + | 64 -> numU64 0x7ff8000000000000UL 64 + | 32 -> numU64 0x7fc00000UL 32 + | _ -> raise InvalidOperandException + +let isInf rt e = + match rt with + | 32 -> + let fullExponent = numU32 0x7F800000u 32 + let fullMantissa = numU32 0x7FFFFFu 32 + ((e .& fullExponent) == fullExponent) .& + ((e .& fullMantissa) == AST.num0 32) + | 64 -> + let fullExponent = numU64 0x7FF0000000000000uL 64 + let fullMantissa = numU64 0xFFFFFFFFFFFFFuL 64 + ((e .& fullExponent) == fullExponent) .& + ((e .& fullMantissa) == AST.num0 64) + | _ -> raise InvalidRegTypeException + +let isNan rt e = + match rt with + | 32 -> + let fullExponent = numU32 0x7F800000u 32 + let fullMantissa = numU32 0x7FFFFFu 32 + ((e .& fullExponent) == fullExponent) .& + ((e .& fullMantissa) != AST.num0 32) + | 64 -> + let fullExponent = numU64 0x7FF0000000000000uL 64 + let fullMantissa = numU64 0xFFFFFFFFFFFFFuL 64 + ((e .& fullExponent) == fullExponent) .& + ((e .& fullMantissa) != AST.num0 64) + | _ -> raise InvalidRegTypeException + +let isSNan rt e = + match rt with + | 32 -> + let signalBit = numU32 (1u <<< 22) 32 + (isNan rt e) .& ((e .& signalBit) == AST.num0 32) + | 64 -> + let signalBit = numU64 (1uL <<< 51) 64 + (isNan rt e) .& ((e .& signalBit) == AST.num0 64) + | _ -> raise InvalidRegTypeException + +let isQNan rt e = + match rt with + | 32 -> + let signalBit = numU32 (1u <<< 22) 32 + (isNan rt e) .& ((e .& signalBit) != AST.num0 32) + | 64 -> + let signalBit = numU64 (1uL <<< 51) 64 + (isNan rt e) .& ((e .& signalBit) != AST.num0 64) + | _ -> raise InvalidRegTypeException + +let isZero rt e = + match rt with + | 32 -> + let mask = numU32 0x7fffffffu 32 + AST.eq (e .& mask) (AST.num0 32) + | 64 -> + let mask = numU64 0x7fffffff_ffffffffUL 64 + AST.eq (e .& mask) (AST.num0 64) + | _ -> Utils.impossible () + +let fpNeg rt expr = + let mask = + match rt with + | 32 -> numU64 0x80000000UL rt + | 64 -> numU64 0x8000000000000000UL rt + | _ -> raise InvalidOperandSizeException + expr <+> mask + +let getSignFloat rt e = + match rt with + | 32 -> e .& (numU32 0x80000000u 32) + | 64 -> e .& (numU64 0x8000000000000000uL 64) + | _ -> raise InvalidRegTypeException + +let getFloat32FromReg e = + let mask = numU64 0xFFFFFFFF_00000000uL 64 + AST.ite (e .& mask == mask) (AST.xtlo 32 e) (numI32 0x7fc00000 32) + +let isSubnormal rt e = + match rt with + | 32 -> + let fullExponent = numU32 0x7F800000u 32 + let fullMantissa = numU32 0x7FFFFFu 32 + ((e .& fullExponent) == AST.num0 32) .& + (e .& fullMantissa != AST.num0 32) + | 64 -> + let fullExponent = numU64 0x7FF0000000000000uL 64 + let fullMantissa = numU64 0xFFFFFFFFFFFFFuL 64 + ((e .& fullExponent) == AST.num0 64) .& + (e .& fullMantissa != AST.num0 64) + | _ -> raise InvalidRegTypeException + +let private checkOverflowOnDMul e1 e2 = + let mask64 = numI64 0xFFFFFFFFFFFFFFFFL 64 + let bit32 = numI64 0x100000000L 64 + let cond = mask64 .- e1 .< e2 + AST.ite cond bit32 (AST.num0 64) + +let private mulWithOverflow src1 src2 ir (isSign, isUnsign) isLow = + let src1IsNeg = !+ir 1 + let struct (tSrc1, tSrc2, hiSrc1, loSrc1) = tmpVars4 ir 64 + let struct (hiSrc2, loSrc2, pMid1, pMid2) = tmpVars4 ir 64 + let struct (pMid, pLow) = tmpVars2 ir 64 + let struct (low, high) = tmpVars2 ir 64 + let struct (src2IsNeg, signBit) = tmpVars2 ir 1 + let struct (tLow, tHigh) = tmpVars2 ir 64 + let n32 = numI32 32 64 + let mask32 = numI64 0xFFFFFFFFL 64 + let zero = numI32 0 64 + let one = numI32 1 64 + match isSign, isUnsign with + | true, true -> + !!ir (src1IsNeg := AST.xthi 1 src1) + !!ir (src2IsNeg := AST.xthi 1 src2) + !!ir (tSrc1 := AST.ite src1IsNeg (AST.neg src1) src1) + !!ir (tSrc2 := AST.ite src2IsNeg (AST.neg src2) src2) + | true, false -> + !!ir (src1IsNeg := AST.xthi 1 src1) + !!ir (tSrc1 := AST.ite src1IsNeg (AST.neg src1) src1) + !!ir (tSrc2 := src2) + | _ -> + !!ir (tSrc1 := src1) + !!ir (tSrc2 := src2) + !!ir (hiSrc1 := (tSrc1 >> n32) .& mask32) (* SRC1[63:32] *) + !!ir (loSrc1 := tSrc1 .& mask32) (* SRC1[31:0] *) + !!ir (hiSrc2 := (tSrc2 >> n32) .& mask32) (* SRC2[63:32] *) + !!ir (loSrc2 := tSrc2 .& mask32) (* SRC2[31:0] *) + !!ir (pMid1 := hiSrc1 .* loSrc2) + !!ir (pMid2 := loSrc1 .* hiSrc2) + !!ir (pMid := pMid1 .+ pMid2) + !!ir (pLow := loSrc1 .* loSrc2) + !!ir (low := pLow .+ ((pMid .& mask32) << n32)) + if not isLow then + let overFlowBit = checkOverflowOnDMul pMid1 pMid2 + !! ir (high := + hiSrc1 .* hiSrc2 .+ ((pMid .+ (pLow >> n32)) >> n32) .+ overFlowBit) + if isSign then + !!ir (signBit := src1IsNeg <+> src2IsNeg) + !!ir (tLow := AST.ite signBit (AST.neg low) low) + if not isLow then + let carry = AST.ite (AST.``and`` signBit (tLow == zero)) one zero + !!ir (tHigh := AST.ite signBit (AST.not high) high .+ carry) + else + if not isLow then + !!ir (tHigh := high) + !!ir (tLow := low) + if isLow then tLow + else tHigh + +let add insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let addw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + ! rs1 + let rs2 = AST.xtlo 32 rs2 + !!ir (rd := AST.sext 64 (rs1 .+ rs2)) + !>ir insLen + +let subw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + ! rs1 + let rs2 = AST.xtlo 32 rs2 + !!ir (rd := AST.sext 64 (rs1 .- rs2)) + !>ir insLen + +let sub insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let ``and`` insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let ``or`` insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let xor insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + ! rs2) + !>ir insLen + +let slt insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 ?< rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + !ir insLen + +let sltu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 .< rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + !ir insLen + +let sll insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let shiftAmm = rs2 .& numU64 0x3fUL 64 + !ir insLen + +let sllw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let shiftAmm = rs2 .& numU32 0x1fu 32 + ! (rs1 << shiftAmm)) + !>ir insLen + +let srl insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let shiftAmm = rs2 .& numU64 0x3fUL 64 + !> shiftAmm) + !>ir insLen + +let srlw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let shiftAmm = rs2 .& numU32 0x1fu 32 + ! (rs1 >> shiftAmm)) + !>ir insLen + +let sra insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let shiftAmm = rs2 .& numU64 0x3fUL 64 + !> shiftAmm) + !>ir insLen + +let sraw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let shiftAmm = rs2 .& numU32 0x1fu 32 + ! (rs1 ?>> shiftAmm)) + !>ir insLen + +let srai insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, shiftAmm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !> shiftAmm) + !>ir insLen + +let srli insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, shiftAmm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !> shiftAmm) + !>ir insLen + +let slli insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, shiftAmm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let andi insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let addi insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let ori insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let xori insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + ! imm) + !>ir insLen + +let slti insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 ?< imm + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + !ir insLen + +let sltiu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 .< imm + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + !ir insLen + +let nop insLen ctxt = + let ir = !*ctxt + !ir insLen + +let jal insInfo insLen ctxt = + let ir = !*ctxt + let rd, jumpTarget = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let r = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let jalr insInfo insLen ctxt = + let ir = !*ctxt + let rd, jumpTarget = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let r = bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + let target = !+ir 64 + let actualTarget = if target = AST.num0 ctxt.WordBitSize then rd else target + !ir insLen + +let beq insInfo insLen ctxt = + let ir = !*ctxt + let rs1, rs2, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 == rs2 + let fallThrough = + bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let bne insInfo insLen ctxt = + let ir = !*ctxt + let rs1, rs2, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 != rs2 + let fallThrough = + bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let blt insInfo insLen ctxt = + let ir = !*ctxt + let rs1, rs2, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 ?< rs2 + let fallThrough = + bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let bge insInfo insLen ctxt = + let ir = !*ctxt + let rs1, rs2, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 ?>= rs2 + let fallThrough = + bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let bltu insInfo insLen ctxt = + let ir = !*ctxt + let rs1, rs2, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 .< rs2 + let fallThrough = + bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let bgeu insInfo insLen ctxt = + let ir = !*ctxt + let rs1, rs2, offset = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let cond = rs1 .>= rs2 + let fallThrough = + bvOfBaseAddr ctxt insInfo.Address .+ bvOfInstrLen ctxt insInfo + !ir insLen + +let load insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + !ir insLen + +let loadu insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + !ir insLen + +let store insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let accessLength = getAccessLength (snd (getTwoOprs insInfo)) + ! then !!ir (mem := rd) + else !!ir (mem := AST.xtlo accessLength rd) + !>ir insLen + +let sideEffects insLen ctxt name = + let ir = !*ctxt + !ir insLen + +let lui insInfo insLen ctxt = + let ir = !*ctxt + let rd, imm = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + !ir insLen + +let auipc insInfo insLen ctxt = + let ir = !*ctxt + let rd, imm = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let pc = bvOfBaseAddr ctxt insInfo.Address + !ir insLen + +let addiw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, imm = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let lowBitsRs1 = AST.xtlo 32 rs1 + ! (lowBitsRs1 .+ AST.xtlo 32 imm)) + !>ir insLen + +let slliw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, shamt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let lowBitsRs1 = AST.xtlo 32 rs1 + ! (lowBitsRs1 << AST.xtlo 32 shamt)) + !>ir insLen + +let srliw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, shamt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let lowBitsRs1 = AST.xtlo 32 rs1 + ! (lowBitsRs1 >> AST.xtlo 32 shamt)) + !>ir insLen + +let sraiw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, shamt = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let lowBitsRs1 = AST.xtlo 32 rs1 + ! (lowBitsRs1 ?>> AST.xtlo 32 shamt)) + !>ir insLen + +let mul insInfo insLen ctxt (isSign, isUnsign) = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let mulhSignOrUnsign insInfo insLen ctxt (isSign, isUnsign) = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + !ir insLen + +let mulw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let lowBitsRs1 = AST.xtlo 32 rs1 + let lowBitsRs2 = AST.xtlo 32 rs2 + ! (lowBitsRs1 .* lowBitsRs2)) + !>ir insLen + +let div insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let condZero = rs2 == AST.num0 64 + let condOverflow = + ((rs2 == numI32 -1 64) .& (rs1 == numI64 0x8000000000000000L 64)) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblEnd = !%ir "End" + !) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp condOverflow (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir (rd := rs1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (rd := rs1 ?/ rs2) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let divw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let condZero = rs2 == AST.num0 32 + let condOverflow = + ((rs2 == numI32 -1 32) .& (rs1 == numI32 0x80000000 32)) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblEnd = !%ir "End" + !) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp condOverflow (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir (rd := AST.sext 64 rs1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (rd := AST.sext 64 (rs1 ?/ rs2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let divuw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let condZero = rs2 == AST.num0 32 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + !) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (rd := AST.sext 64 (rs1 ./ rs2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let divu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let condZero = rs2 == AST.num0 64 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + !) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (rd := rs1 ./ rs2) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let remu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let condZero = rs2 == AST.num0 64 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + !ir insLen + +let rem insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let condZero = rs2 == AST.num0 64 + let condOverflow = + ((rs2 == numI32 -1 64) .& (rs1 == numI64 0x8000000000000000L 64)) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblEnd = !%ir "End" + !) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (rd := rs1 ?% rs2) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let remw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let condZero = rs2 == AST.num0 32 + let condOverflow = + ((rs2 == numI32 -1 32) .& (rs1 == numI32 0x80000000 32)) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblEnd = !%ir "End" + ! rs1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp condOverflow (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir (rd := AST.num0 64) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (rd := AST.sext 64 (rs1 ?% rs2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let remuw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rs2 = AST.xtlo 32 rs2 + let condZero = rs2 == AST.num0 32 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + ! rs1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (rd := AST.sext 64 (rs1 .% rs2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fld insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let condAlign = isAligned 64 (getAddrFromMem mem) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + !ir insLen + +let fsd insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let condAlign = isAligned 64 (getAddrFromMem mem) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + !ir insLen + +let fltdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let checkNan = isNan 32 rs1 .| isNan 32 rs2 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = AST.flt rs1 rs2 + let rtVal = + AST.ite cond (AST.num1 ctxt.WordBitSize) (AST.num0 ctxt.WordBitSize) + let fflags = getRegVar ctxt R.FFLAGS + !) + !!ir (fflags := fflags .| numU32 16u 32) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fledots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let checkNan = isNan 32 rs1 .| isNan 32 rs2 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = AST.fle rs1 rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + let fflags = getRegVar ctxt R.FFLAGS + !) + !!ir (fflags := fflags .| numU32 16u 32) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let feqdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let isSNan = isSNan 32 rs1 .| isSNan 32 rs2 + let checkNan = isNan 32 rs1 .| isNan 32 rs2 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = rs1 == rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + let fflags = getRegVar ctxt R.FFLAGS + let flagFscr = AST.ite (isSNan) (numU32 16u 32) (AST.num0 32) + !) + !!ir (fflags := fflags .| flagFscr) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fclassdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let plusZero = numU32 0u 32 + let negZero = numU32 0x80000000u 32 + let sign = AST.extract rs1 1 31 + let lblPos = !%ir "Pos" + let lblNeg = !%ir "Neg" + let lblEnd = !%ir "End" + let condZero = (rs1 == plusZero) .| (rs1 == negZero) + let condInf = isInf 32 rs1 + let condSubnormal = isSubnormal 32 rs1 + let condSNan = isSNan 32 rs1 + let condQNan = isQNan 32 rs1 + !) + !!ir (AST.cjmp sign (AST.name lblNeg) (AST.name lblPos)) + !!ir (AST.lmark lblPos) + !!ir (rd := AST.ite condInf (numU32 (1u <<< 7) 64) rd) + !!ir (rd := AST.ite condZero (numU32 (1u <<< 4) 64) rd) + !!ir (rd := AST.ite condSubnormal (numU32 (1u <<< 5) 64) rd) + !!ir (rd := AST.ite condQNan (numU32 (1u <<< 9) 64) rd) + !!ir (rd := AST.ite condSNan (numU32 (1u <<< 8) 64) rd) + !!ir (rd := AST.ite (rd == AST.num0 64) (numU32 (1u <<< 6) 64) rd) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblNeg) + !!ir (rd := AST.ite condInf (numU32 (1u <<< 0) 64) rd) + !!ir (rd := AST.ite condZero (numU32 (1u <<< 3) 64) rd) + !!ir (rd := AST.ite condSubnormal (numU32 (1u <<< 2) 64) rd) + !!ir (rd := AST.ite (rd == AST.num0 64) (numU32 (1u <<< 1) 64) rd) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fclassdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let plusZero = numU64 0uL 64 + let negZero = numU64 0x8000000000000000uL 64 + let sign = AST.extract rs1 1 63 + let lblPos = !%ir "Pos" + let lblNeg = !%ir "Neg" + let lblEnd = !%ir "End" + let condZero = (rs1 == plusZero) .| (rs1 == negZero) + let condInf = isInf 64 rs1 + let condSubnormal = isSubnormal 64 rs1 + let condSNan = isSNan 64 rs1 + let condQNan = isQNan 64 rs1 + !) + !!ir (AST.cjmp sign (AST.name lblNeg) (AST.name lblPos)) + !!ir (AST.lmark lblPos) + !!ir (rd := AST.ite condInf (numU32 (1u <<< 7) 64) rd) + !!ir (rd := AST.ite condZero (numU32 (1u <<< 4) 64) rd) + !!ir (rd := AST.ite condSubnormal (numU32 (1u <<< 5) 64) rd) + !!ir (rd := AST.ite condQNan (numU32 (1u <<< 9) 64) rd) + !!ir (rd := AST.ite condSNan (numU32 (1u <<< 8) 64) rd) + !!ir (rd := AST.ite (rd == AST.num0 64) (numU32 (1u <<< 6) 64) rd) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblNeg) + !!ir (rd := AST.ite condInf (numU32 (1u <<< 0) 64) rd) + !!ir (rd := AST.ite condZero (numU32 (1u <<< 3) 64) rd) + !!ir (rd := AST.ite condSubnormal (numU32 (1u <<< 2) 64) rd) + !!ir (rd := AST.ite (rd == AST.num0 64) (numU32 (1u <<< 1) 64) rd) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let flw insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let tmp = !+ir 32 + let condAlign = isAligned 32 (getAddrFromMem mem) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + !ir insLen + +let fsw insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let condAlign = isAligned 32 (getAddrFromMem mem) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + ! rd) + !!ir (AST.sideEffect Unlock) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (mem := AST.xtlo 32 rd) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fltdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let checkNan = isNan 64 rs1 .| isNan 64 rs2 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = AST.flt rs1 rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + let fflags = getRegVar ctxt R.FFLAGS + !) + !!ir (fflags := fflags .| numU32 16u 32) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fledotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let checkNan = isNan 64 rs1 .| isNan 64 rs2 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = AST.fle rs1 rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + let fflags = getRegVar ctxt R.FFLAGS + !) + !!ir (fflags := fflags .| numU32 16u 32) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let feqdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let isSNan = isSNan 64 rs1 .| isSNan 64 rs2 + let checkNan = isNan 64 rs1 .| isNan 64 rs2 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let cond = rs1 == rs2 + let rtVal = AST.ite cond (AST.num1 64) (AST.num0 64) + let fflags = getRegVar ctxt R.FFLAGS + let flagFscr = AST.ite isSNan (numU32 16u 32) (AST.num0 32) + !) + !!ir (fflags := fflags .| flagFscr) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fpArithmeticSingle insInfo insLen ctxt operator = + let ir = !*ctxt + let rd, rs1, rs2, _ = getFourOprs insInfo + let rd, rs1, rs2 = (rd, rs1, rs2) |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + ! operation) (fpDefaultNan 32) operation + !!ir (rd := getNanBoxed rtVal) + !>ir insLen + +let fpArithmeticDouble insInfo insLen ctxt operator = + let ir = !*ctxt + let rd, rs1, rs2, _ = getFourOprs insInfo + let rd, rs1, rs2 = (rd, rs1, rs2) |> transThreeOprs insInfo ctxt + ! operation) (fpDefaultNan 64) operation + !!ir (rd := rtVal) + !>ir insLen + +let fsqrtdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, _ = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + !ir insLen + +let fsqrtdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, _ = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + !ir insLen + +let fmindots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rtVal = !+ir 32 + let cond = AST.flt rs1 rs2 + !ir insLen + +let fmindotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rtVal = !+ir 64 + let cond = AST.flt rs1 rs2 + !ir insLen + +let fmaxdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rtVal = !+ir 32 + let cond = AST.flt rs1 rs2 + !ir insLen + +let fmaxdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rtVal = !+ir 64 + let cond = AST.flt rs1 rs2 + !ir insLen + +let fmadddots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rs3 = getFloat32FromReg rs3 + !ir insLen + +let fmadddotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + !ir insLen + +let fmsubdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rs3 = getFloat32FromReg rs3 + !ir insLen + +let fmsubdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + !ir insLen + +let fnmsubdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rs3 = getFloat32FromReg rs3 + ! <| AST.fmul rs1 rs2) rs3 + !!ir (rd := getNanBoxed rtVal) + !>ir insLen + +let fnmsubdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + ! <| AST.fmul rs1 rs2) rs3) + !>ir insLen + +let fnmadddots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + let lblValid = !%ir "Valid" + let lblInvalid = !%ir "Invalid operation" + let lblEnd = !%ir "End" + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rs3 = getFloat32FromReg rs3 + let condOfNV1 = isInf 32 rs1 .| isZero 32 rs2 + let condOfNV2 = isZero 32 rs1 .| isInf 32 rs2 + let setNV = (condOfNV1 .| condOfNV2) .& isQNan 32 rs3 + let fflags = getRegVar ctxt R.FFLAGS + ! <| AST.fmul rs1 rs2) rs3 + !!ir (rd := getNanBoxed rtVal) + !!ir (AST.cjmp setNV (AST.name lblInvalid) (AST.name lblValid)) + !!ir (AST.lmark lblValid) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblInvalid) + !!ir (fflags := fflags .| numU32 16u 32) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fnmadddotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2, rs3, _ = getFiveOprs insInfo + let rd, rs1, rs2, rs3 = (rd, rs1, rs2, rs3) |> transFourOprs insInfo ctxt + let lblValid = !%ir "Valid" + let lblInvalid = !%ir "Invalid operation" + let lblEnd = !%ir "End" + let condOfNV1 = isInf 64 rs1 .| isZero 64 rs2 + let condOfNV2 = isZero 64 rs1 .| isInf 64 rs2 + let setNV = (condOfNV1 .| condOfNV2) .& isQNan 64 rs3 + let fflags = getRegVar ctxt R.FFLAGS + ! <| AST.fmul rs1 rs2) rs3) + !!ir (AST.cjmp setNV (AST.name lblInvalid) (AST.name lblValid)) + !!ir (AST.lmark lblValid) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblInvalid) + !!ir (fflags := fflags .| numU32 16u 32) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fsgnjdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rtVal = !+ir 32 + let mask = numU32 0x7fffffffu 32 + let sign = getSignFloat 32 rs2 + !ir insLen + +let fsgnjdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rtVal = !+ir 64 + let mask = numU64 0x7FFFFFFFFFFFFFFFuL 64 + let sign = getSignFloat 64 rs2 + !ir insLen + +let fsgnjndots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rtVal = !+ir 32 + let mask = numU32 0x7fffffffu 32 + let sign = getSignFloat 32 rs2 <+> numU32 0x80000000u 32 + !ir insLen + +let fsgnjndotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rtVal = !+ir 64 + let mask = numU64 0x7FFFFFFFFFFFFFFFuL 64 + let sign = getSignFloat 64 rs2 <+> numU64 0x8000000000000000uL 64 + !ir insLen + +let fsgnjxdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let rs2 = getFloat32FromReg rs2 + let rtVal = !+ir 32 + let mask = numU32 0x7fffffffu 32 + let sign = (getSignFloat 32 rs2) <+> (getSignFloat 32 rs1) + !ir insLen + +let fsgnjxdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rs2 = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let rtVal = !+ir 64 + let mask = numU64 0x7FFFFFFFFFFFFFFFuL 64 + let sign = getSignFloat 64 rs2 <+> getSignFloat 64 rs1 + !ir insLen + +(* FIX ME: AQRL *) +let amod insInfo insLen ctxt op = + let ir = !*ctxt + let rd, rs2, mem, _ = getFourOprs insInfo |> transFourOprs insInfo ctxt + let cond = isAligned 64 (getAddrFromMem mem) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let tmp = !+ir 64 + !ir insLen + +let amow insInfo insLen ctxt op = + let ir = !*ctxt + let rd, rs2, mem, _ = getFourOprs insInfo |> transFourOprs insInfo ctxt + let rs2 = AST.xtlo 32 rs2 + let cond = isAligned 32 (getAddrFromMem mem) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let tmp = !+ir 32 + ! tmp) + !!ir (AST.sideEffect Unlock) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.sideEffect (Exception "Address-misaligned exception")) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fmvdotxdotw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + ! rs1) + !>ir insLen + +let fmvdotwdotx insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + ! rs1)) + !>ir insLen + +let fmvdotxdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + !ir insLen + +let fmvdotddotx insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + !ir insLen + +let csrrw insInfo insLen ctxt = + let ir = !*ctxt + let rd, csr, src = getThreeOprs insInfo + let csr, src = transTwoOprs insInfo ctxt (csr, src) |> maskForFCSR csr + ! assignFCSR csr src ctxt ir + | _ -> + let rd = transOneOpr insInfo ctxt rd + let tmpVar = !+ir 64 + !!ir (tmpVar := AST.zext 64 csr) + assignFCSR csr src ctxt ir + !!ir (rd := tmpVar) + !!ir (AST.sideEffect Unlock) + !>ir insLen + +let csrrs insInfo insLen ctxt = + let ir = !*ctxt + let rd, csr, src = getThreeOprs insInfo + let rd = transOprToExpr insInfo ctxt rd + ! + let csr = transOprToExpr insInfo ctxt csr + !!ir (rd := AST.zext 64 csr) + | _ -> + let csr, src = transTwoOprs insInfo ctxt (csr, src) |> maskForFCSR csr + let tmpVar = !+ir 64 + !!ir (tmpVar := AST.zext 64 csr) + assignFCSR csr (csr .| src) ctxt ir + !!ir (rd := tmpVar) + !!ir (AST.sideEffect Unlock) + !>ir insLen + +let csrrc insInfo insLen ctxt = + let ir = !*ctxt + let rd, csr, src = getThreeOprs insInfo + let rd = transOprToExpr insInfo ctxt rd + ! + let csr = transOprToExpr insInfo ctxt csr + !!ir (rd := AST.zext 64 csr) + | _ -> + let csr, src = transTwoOprs insInfo ctxt (csr, src) |> maskForFCSR csr + let tmpVar = !+ir 64 + !!ir (tmpVar := AST.zext 64 csr) + assignFCSR csr (csr .& AST.neg src) ctxt ir + !!ir (rd := tmpVar) + !!ir (AST.sideEffect Unlock) + !>ir insLen + +let fcvtdotldotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let llMaxInFloat = numU64 0x43e0000000000000uL 64 + let llMinInFloat = numU64 0xc3e0000000000000uL 64 + let llMax = numU64 0x7fffffffffffffffuL 64 + let llMin = numU64 0x8000000000000000uL 64 + let condInf = isInf 64 rs1 + let condNaN = isNan 64 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let rtVal = !+ir 64 + ! rs1) + !!ir (rd := AST.cast roundingInt 64 rtVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal llMinInFloat) llMin rd) + !!ir (rd := AST.ite (AST.fge rtVal llMaxInFloat) llMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN llMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) llMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) llMin rd) + !>ir insLen + else + ! rs1 + let rdVal = dynamicRoundingInt ir ctxt 64 rtVal + !!ir (rd := rdVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal llMinInFloat) llMin rd) + !!ir (rd := AST.ite (AST.fge rtVal llMaxInFloat) llMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN llMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) llMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) llMin rd) + !>ir insLen + +let fcvtdotludotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let ullMaxInFloat = numU64 0x43f0000000000000uL 64 + let ullMinInFloat = numU64 0uL 64 + let ullMax = numU64 0xffffffffffffffffuL 64 + let ullMin = numI32 0 64 + let condInf = isInf 64 rs1 + let condNaN = isNan 64 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let rtVal = !+ir 64 + ! rs1) + !!ir (rd := AST.cast roundingInt 64 rtVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal ullMinInFloat) ullMin rd) + !!ir (rd := AST.ite (AST.fge rtVal ullMaxInFloat) ullMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN ullMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) ullMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) ullMin rd) + !>ir insLen + else + ! rs1 + let rdVal = dynamicRoundingInt ir ctxt 64 rtVal + !!ir (rd := rdVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal ullMinInFloat) ullMin rd) + !!ir (rd := AST.ite (AST.fge rtVal ullMaxInFloat) ullMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN ullMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) ullMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) ullMin rd) + !>ir insLen + +let fcvtdotwdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let intMaxInFloat = numU64 0x41dfffffffc00000uL 64 + let intMinInFloat = numU64 0xc1e0000000000000uL 64 + let intMax = AST.sext 64 (numU32 0x7fffffffu 32) + let intMin = AST.sext 64 (numU32 0x80000000u 32) + let condInf = isInf 64 rs1 + let condNaN = isNan 64 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let rtVal = !+ir 64 + ! rs1) + !!ir (rd := AST.sext 64 (AST.cast roundingInt 32 rtVal)) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal intMinInFloat) intMin rd) + !!ir (rd := AST.ite (AST.fge rtVal intMaxInFloat) intMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN intMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) intMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) intMin rd) + !>ir insLen + else + ! rs1 + let rdVal = dynamicRoundingInt ir ctxt 32 rtVal + !!ir (rd := AST.sext 64 rdVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal intMinInFloat) intMin rd) + !!ir (rd := AST.ite (AST.fge rtVal intMaxInFloat) intMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN intMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) intMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) intMin rd) + !>ir insLen + +let fcvtdotwudotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let uintMaxInFloat = numU64 0x41efffffffe00000uL 64 + let uintMinInFloat = numU64 0uL 64 + let uintMax = numU64 0xffffffffffffffffuL 64 + let uintMin = numU64 0uL 64 + let condInf = isInf 64 rs1 + let condNaN = isNan 64 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let rtVal = !+ir 64 + ! rs1) + !!ir (rd := AST.sext 64 (AST.cast roundingInt 32 rtVal)) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal uintMinInFloat) uintMin rd) + !!ir (rd := AST.ite (AST.fge rtVal uintMaxInFloat) uintMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN uintMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) uintMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) uintMin rd) + !>ir insLen + else + ! rs1 + let rdVal = dynamicRoundingInt ir ctxt 32 rtVal + !!ir (rd := AST.sext 64 rdVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal uintMinInFloat) uintMin rd) + !!ir (rd := AST.ite (AST.fge rtVal uintMaxInFloat) uintMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN uintMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) uintMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) uintMin rd) + !>ir insLen + +let fcvtdotwdots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let intMaxInFloat = numU32 0x4f000000u 32 + let intMinInFloat = numU32 0xcf000000u 32 + let intMax = numU32 0x7fffffffu 64 + let intMin = numU64 0xffffffff80000000uL 64 + let condInf = isInf 32 rs1 + let condNaN = isNan 32 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let rtVal = !+ir 32 + ! rs1) + !!ir (rd := AST.sext 64 (AST.cast roundingInt 32 rtVal)) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal intMinInFloat) intMin rd) + !!ir (rd := AST.ite (AST.fge rtVal intMaxInFloat) intMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN intMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) intMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) intMin rd) + !>ir insLen + else + ! rs1 + let rdVal = dynamicRoundingInt ir ctxt 32 rtVal + !!ir (rd := AST.sext 64 rdVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal intMinInFloat) intMin rd) + !!ir (rd := AST.ite (AST.fge rtVal intMaxInFloat) intMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN intMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) intMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) intMin rd) + !>ir insLen + +let fcvtdotwudots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let uintMaxInFloat = numU32 0x4f800000u 32 + let uintMinInFloat = numU32 0x0u 32 + let uintMax = numU64 0xffffffffffffffffUL 64 + let uintMin = numU32 0x0u 64 + let condInf = isInf 32 rs1 + let condNaN = isNan 32 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let rtVal = !+ir 32 + ! rs1) + !!ir (rd := AST.cast roundingInt 32 rtVal) + !!ir (rd := AST.sext 64 rd) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal uintMinInFloat) uintMin rd) + !!ir (rd := AST.ite (AST.fge rtVal uintMaxInFloat) uintMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN uintMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) uintMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) uintMin rd) + !>ir insLen + else + ! rs1 + let rdVal = dynamicRoundingInt ir ctxt 32 rtVal + !!ir (rd := AST.sext 64 rdVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal uintMinInFloat) uintMin rd) + !!ir (rd := AST.ite (AST.fge rtVal uintMaxInFloat) uintMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN uintMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) uintMax rd) + !!ir (rd := AST.ite (condInf .& sign) uintMin rd) + (* -inf *) + !>ir insLen + +let fcvtdotldots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let llMaxInFloat = numU64 0x43e0000000000000uL 64 + let llMinInFloat = numU64 0xc3e0000000000000uL 64 + let condInf = isInf 32 rs1 + let condNaN = isNan 32 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let t0 = !+ir 32 + let rtVal = !+ir 64 + ! rs1) + !!ir (rtVal := AST.cast CastKind.FloatCast 64 t0) + (* check for out-of-range *) + !!ir (rtVal := AST.ite (AST.fle rtVal llMinInFloat) llMinInFloat rtVal) + !!ir (rtVal := AST.ite (AST.fge rtVal llMaxInFloat) llMaxInFloat rtVal) + (* NaN Check *) + !!ir (rtVal := AST.ite condNaN llMaxInFloat rtVal) + (* +inf *) + !!ir (rtVal := AST.ite (condInf .& (AST.not sign)) llMaxInFloat rtVal) + (* -inf *) + !!ir (rtVal := AST.ite (condInf .& sign) llMinInFloat rtVal) + !!ir (rd := AST.cast roundingInt 64 rtVal) + !>ir insLen + else + ! rs1 + let rtVal = !+ir 64 + (* check for out-of-range *) + !!ir (rtVal := AST.cast CastKind.FloatCast 64 t0) + !!ir (rtVal := AST.ite (AST.fle rtVal llMinInFloat) llMinInFloat rtVal) + !!ir (rtVal := AST.ite (AST.fge rtVal llMaxInFloat) llMaxInFloat rtVal) + (* NaN Check *) + !!ir (rtVal := AST.ite condNaN llMaxInFloat rtVal) + (* +inf *) + !!ir (rtVal := AST.ite (condInf .& (AST.not sign)) llMaxInFloat rtVal) + (* -inf *) + !!ir (rtVal := AST.ite (condInf .& sign) llMinInFloat rtVal) + let rdVal = dynamicRoundingInt ir ctxt 64 rtVal + !!ir (rd := rdVal) + !>ir insLen + +let fcvtdotludots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + let llMaxInFloat = numU64 0x43e0000000000000uL 64 + let llMinInFloat = numU64 0uL 64 + let llMax = numU64 0xffffffffffffffffuL 64 + let llMin = numU64 0uL 64 + let condInf = isInf 32 rs1 + let condNaN = isNan 32 rs1 + let sign = AST.xthi 1 rs1 + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + let roundingInt = roundingToCastInt rm + let t0 = !+ir 32 + let rtVal = !+ir 64 + ! rs1) + !!ir (rtVal := AST.cast CastKind.FloatCast 64 t0) + !!ir (rd := AST.cast roundingInt 64 rtVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal llMinInFloat) llMin rd) + !!ir (rd := AST.ite (AST.fge rtVal llMaxInFloat) llMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN llMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) llMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) llMin rd) + !>ir insLen + else + ! rs1 + let rtVal = !+ir 64 + (* check for out-of-range *) + !!ir (rtVal := AST.cast CastKind.FloatCast 64 t0) + !!ir (rd := AST.cast CastKind.FloatCast 64 rtVal) + (* check for out-of-range *) + !!ir (rd := AST.ite (AST.fle rtVal llMinInFloat) llMin rd) + !!ir (rd := AST.ite (AST.fge rtVal llMaxInFloat) llMax rd) + (* NaN Check *) + !!ir (rd := AST.ite condNaN llMax rd) + (* +inf *) + !!ir (rd := AST.ite (condInf .& (AST.not sign)) llMax rd) + (* -inf *) + !!ir (rd := AST.ite (condInf .& sign) llMin rd) + !>ir insLen + +let fcvtdotsdotw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rtVal = !+ir 32 + ! rs1) + dstAssignSingleWithRound rd rtVal rm ctxt ir + !>ir insLen + +let fcvtdotsdotwu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = AST.xtlo 32 rs1 + let rtVal = !+ir 32 + ! rs1) + dstAssignSingleWithRound rd rtVal rm ctxt ir + !>ir insLen + +let fcvtdotsdotl insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rtVal = !+ir 32 + ! rs1) + dstAssignSingleWithRound rd rtVal rm ctxt ir + !>ir insLen + +let fcvtdotsdotlu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rtVal = !+ir 32 + ! rs1) + dstAssignSingleWithRound rd rtVal rm ctxt ir + !>ir insLen + +let fcvtdotddotw insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + ! (AST.xtlo 32 rs1)) + !>ir insLen + +let fcvtdotddotwu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1 = getTwoOprs insInfo |> transTwoOprs insInfo ctxt + ! (AST.xtlo 32 rs1)) + !>ir insLen + +let fcvtdotddotl insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + ! rs1 + dstAssignDoubleWithRound rd rtVal rm ctxt ir + !>ir insLen + +let fcvtdotddotlu insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + ! rs1 + dstAssignDoubleWithRound rd rtVal rm ctxt ir + !>ir insLen + +let fcvtdotsdotd insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, rm = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rtVal = !+ir 64 + ! rs1 + |> fun single -> AST.ite (isNan 32 single) (fpDefaultNan 32) single + !!ir (rtVal := getNanBoxed rs1) + if rm <> OpRoundMode (RoundMode.DYN) then + let rounding = roundingToCastFloat rm + !!ir (rd := AST.cast rounding 64 rtVal) + else + !!ir (rd := dynamicRoundingFl ir ctxt 64 rtVal) + !>ir insLen + +let fcvtdotddots insInfo insLen ctxt = + let ir = !*ctxt + let rd, rs1, _ = getThreeOprs insInfo + let rd, rs1 = (rd, rs1) |> transTwoOprs insInfo ctxt + let rs1 = getFloat32FromReg rs1 + ! rs1) + !>ir insLen + +let lr insInfo insLen ctxt = + let ir = !*ctxt + let rd, mem, _ = getThreeOprs insInfo |> transThreeOprs insInfo ctxt + let addr, size = getAddrFromMemAndSize mem + !) + !!ir (rd := AST.sext 64 mem) + !>ir insLen + +let sc insInfo insLen ctxt oprSz = + let ir = !*ctxt + let rd, rs2, mem, _ = getFourOprs insInfo |> transFourOprs insInfo ctxt + let addr, size = getAddrFromMemAndSize mem + let rc = getRegVar ctxt R.RC + let lblRelease = !%ir "Release" + let lblEnd = !%ir "End" + !) + !!ir (AST.extCall <| AST.app "IsAcquired" [addr; size] 64) + !!ir (AST.cjmp rc (AST.name lblRelease) (AST.name lblEnd)) + !!ir (AST.lmark lblRelease) + !!ir (AST.extCall <| AST.app "Release" [addr; size] 64) + !!ir (mem := AST.xtlo oprSz rs2) + !!ir (rd := AST.num0 64) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let translate insInfo insLen (ctxt: TranslationContext) = + match insInfo.Opcode with + | Op.CdotMV + | Op.CdotADD + | Op.ADD -> add insInfo insLen ctxt + | Op.CdotADDW + | Op.ADDW -> addw insInfo insLen ctxt + | Op.CdotSUBW + | Op.SUBW -> subw insInfo insLen ctxt + | Op.CdotAND + | Op.AND -> ``and`` insInfo insLen ctxt + | Op.CdotOR + | Op.OR -> ``or`` insInfo insLen ctxt + | Op.CdotXOR + | Op.XOR -> xor insInfo insLen ctxt + | Op.CdotSUB + | Op.SUB -> sub insInfo insLen ctxt + | Op.SLT -> slt insInfo insLen ctxt + | Op.SLTU -> sltu insInfo insLen ctxt + | Op.SLL -> sll insInfo insLen ctxt + | Op.SLLW -> sllw insInfo insLen ctxt + | Op.SRA -> sra insInfo insLen ctxt + | Op.SRAW -> sraw insInfo insLen ctxt + | Op.SRL -> srl insInfo insLen ctxt + | Op.SRLW -> srlw insInfo insLen ctxt + | Op.CdotANDI + | Op.ANDI -> andi insInfo insLen ctxt + | Op.CdotADDI16SP + | Op.CdotLI + | Op.CdotADDI + | Op.CdotADDI4SPN + | Op.ADDI -> addi insInfo insLen ctxt + | Op.ORI -> ori insInfo insLen ctxt + | Op.XORI -> xori insInfo insLen ctxt + | Op.SLTI -> slti insInfo insLen ctxt + | Op.SLTIU -> sltiu insInfo insLen ctxt + | Op.CdotJ + | Op.JAL -> jal insInfo insLen ctxt + | Op.CdotJR + | Op.CdotJALR + | Op.JALR -> jalr insInfo insLen ctxt + | Op.CdotBEQZ + | Op.BEQ -> beq insInfo insLen ctxt + | Op.CdotBNEZ + | Op.BNE -> bne insInfo insLen ctxt + | Op.BLT -> blt insInfo insLen ctxt + | Op.BGE -> bge insInfo insLen ctxt + | Op.BLTU -> bltu insInfo insLen ctxt + | Op.BGEU -> bgeu insInfo insLen ctxt + | Op.CdotLW + | Op.CdotLD + | Op.CdotLWSP + | Op.CdotLDSP + | Op.LB + | Op.LH + | Op.LW + | Op.LD -> load insInfo insLen ctxt + | Op.LBU + | Op.LHU + | Op.LWU -> loadu insInfo insLen ctxt + | Op.CdotSW + | Op.CdotSD + | Op.CdotSWSP + | Op.CdotSDSP + | Op.SB + | Op.SH + | Op.SW + | Op.SD -> store insInfo insLen ctxt + | Op.CdotEBREAK + | Op.EBREAK -> sideEffects insLen ctxt Breakpoint + | Op.ECALL -> sideEffects insLen ctxt SysCall + | Op.CdotSRAI + | Op.SRAI -> srai insInfo insLen ctxt + | Op.CdotSLLI + | Op.SLLI -> slli insInfo insLen ctxt + | Op.CdotSRLI + | Op.SRLI -> srli insInfo insLen ctxt + | Op.CdotLUI + | Op.LUI -> lui insInfo insLen ctxt + | Op.AUIPC -> auipc insInfo insLen ctxt + | Op.CdotADDIW + | Op.ADDIW -> addiw insInfo insLen ctxt + | Op.SLLIW -> slliw insInfo insLen ctxt + | Op.SRLIW -> srliw insInfo insLen ctxt + | Op.SRAIW -> sraiw insInfo insLen ctxt + | Op.MUL -> mul insInfo insLen ctxt (true, true) + | Op.MULH -> mulhSignOrUnsign insInfo insLen ctxt (true, true) + | Op.MULHU -> mulhSignOrUnsign insInfo insLen ctxt (false, true) + | Op.MULHSU -> mulhSignOrUnsign insInfo insLen ctxt (true, false) + | Op.MULW -> mulw insInfo insLen ctxt + | Op.CdotNOP -> nop insLen ctxt + | Op.CdotFLD + | Op.CdotFLDSP + | Op.FLD -> fld insInfo insLen ctxt + | Op.CdotFSD + | Op.CdotFSDSP + | Op.FSD -> fsd insInfo insLen ctxt + | Op.FLTdotS -> fltdots insInfo insLen ctxt + | Op.FLTdotD -> fltdotd insInfo insLen ctxt + | Op.FLEdotS -> fledots insInfo insLen ctxt + | Op.FLEdotD -> fledotd insInfo insLen ctxt + | Op.FEQdotS -> feqdots insInfo insLen ctxt + | Op.FEQdotD -> feqdotd insInfo insLen ctxt + | Op.FLW -> flw insInfo insLen ctxt + | Op.FSW -> fsw insInfo insLen ctxt + | Op.FADDdotS -> fpArithmeticSingle insInfo insLen ctxt AST.fadd + | Op.FADDdotD -> fpArithmeticDouble insInfo insLen ctxt AST.fadd + | Op.FSUBdotS -> fpArithmeticSingle insInfo insLen ctxt AST.fsub + | Op.FSUBdotD -> fpArithmeticDouble insInfo insLen ctxt AST.fsub + | Op.FDIVdotS -> fpArithmeticSingle insInfo insLen ctxt AST.fdiv + | Op.FDIVdotD -> fpArithmeticDouble insInfo insLen ctxt AST.fdiv + | Op.FMULdotS -> fpArithmeticSingle insInfo insLen ctxt AST.fmul + | Op.FMULdotD -> fpArithmeticDouble insInfo insLen ctxt AST.fmul + | Op.FMINdotS -> fmindots insInfo insLen ctxt + | Op.FMINdotD -> fmindotd insInfo insLen ctxt + | Op.FMAXdotS -> fmaxdots insInfo insLen ctxt + | Op.FMAXdotD -> fmaxdotd insInfo insLen ctxt + | Op.FNMADDdotS -> fnmadddots insInfo insLen ctxt + | Op.FNMADDdotD -> fnmadddotd insInfo insLen ctxt + | Op.FNMSUBdotS -> fnmsubdots insInfo insLen ctxt + | Op.FNMSUBdotD -> fnmsubdotd insInfo insLen ctxt + | Op.FMADDdotS -> fmadddots insInfo insLen ctxt + | Op.FMADDdotD -> fmadddotd insInfo insLen ctxt + | Op.FMSUBdotS -> fmsubdots insInfo insLen ctxt + | Op.FMSUBdotD -> fmsubdotd insInfo insLen ctxt + | Op.FSQRTdotS -> fsqrtdots insInfo insLen ctxt + | Op.FSQRTdotD -> fsqrtdotd insInfo insLen ctxt + | Op.FCLASSdotS -> fclassdots insInfo insLen ctxt + | Op.FCLASSdotD -> fclassdotd insInfo insLen ctxt + | Op.FSGNJdotS -> fsgnjdots insInfo insLen ctxt + | Op.FSGNJdotD -> fsgnjdotd insInfo insLen ctxt + | Op.FSGNJNdotS -> fsgnjndots insInfo insLen ctxt + | Op.FSGNJNdotD -> fsgnjndotd insInfo insLen ctxt + | Op.FSGNJXdotS -> fsgnjxdots insInfo insLen ctxt + | Op.FSGNJXdotD -> fsgnjxdotd insInfo insLen ctxt + | Op.AMOADDdotW -> amow insInfo insLen ctxt (.+) + | Op.AMOADDdotD -> amod insInfo insLen ctxt (.+) + | Op.AMOANDdotW -> amow insInfo insLen ctxt (.&) + | Op.AMOANDdotD -> amod insInfo insLen ctxt (.&) + | Op.AMOXORdotW -> amow insInfo insLen ctxt (<+>) + | Op.AMOXORdotD -> amod insInfo insLen ctxt (<+>) + | Op.AMOORdotW -> amow insInfo insLen ctxt (.|) + | Op.AMOORdotD -> amod insInfo insLen ctxt (.|) + | Op.AMOMINdotW -> + amow insInfo insLen ctxt (fun a b -> AST.ite (a ?< b) (a) (b)) + | Op.AMOMINdotD -> + amod insInfo insLen ctxt (fun a b -> AST.ite (a ?< b) (a) (b)) + | Op.AMOMINUdotW -> + amow insInfo insLen ctxt (fun a b -> AST.ite (a .< b) (a) (b)) + | Op.AMOMINUdotD -> + amod insInfo insLen ctxt (fun a b -> AST.ite (a .< b) (a) (b)) + | Op.AMOMAXdotW -> + amow insInfo insLen ctxt (fun a b -> AST.ite (a ?> b) (a) (b)) + | Op.AMOMAXdotD -> + amod insInfo insLen ctxt (fun a b -> AST.ite (a ?> b) (a) (b)) + | Op.AMOMAXUdotW -> + amow insInfo insLen ctxt (fun a b -> AST.ite (a .> b) (a) (b)) + | Op.AMOMAXUdotD -> + amod insInfo insLen ctxt (fun a b -> AST.ite (a .> b) (a) (b)) + | Op.AMOSWAPdotW -> amow insInfo insLen ctxt (fun _ b -> b) + | Op.AMOSWAPdotD -> amod insInfo insLen ctxt (fun _ b -> b) + | Op.FMVdotXdotW -> fmvdotxdotw insInfo insLen ctxt + | Op.FMVdotXdotD -> fmvdotxdotd insInfo insLen ctxt + | Op.FMVdotWdotX -> fmvdotwdotx insInfo insLen ctxt + | Op.FMVdotDdotX -> fmvdotddotx insInfo insLen ctxt + | Op.DIVW -> divw insInfo insLen ctxt + | Op.DIV -> div insInfo insLen ctxt + | Op.DIVU -> divu insInfo insLen ctxt + | Op.REM -> rem insInfo insLen ctxt + | Op.REMU -> remu insInfo insLen ctxt + | Op.REMW -> remw insInfo insLen ctxt + | Op.DIVUW -> divuw insInfo insLen ctxt + | Op.REMUW -> remuw insInfo insLen ctxt + | Op.FCVTdotWdotD -> fcvtdotwdotd insInfo insLen ctxt + | Op.FCVTdotWUdotD -> fcvtdotwudotd insInfo insLen ctxt + | Op.FCVTdotLdotD -> fcvtdotldotd insInfo insLen ctxt + | Op.FCVTdotLUdotD -> fcvtdotludotd insInfo insLen ctxt + | Op.FCVTdotWdotS -> fcvtdotwdots insInfo insLen ctxt + | Op.FCVTdotWUdotS -> fcvtdotwudots insInfo insLen ctxt + | Op.FCVTdotLdotS -> fcvtdotldots insInfo insLen ctxt + | Op.FCVTdotLUdotS -> fcvtdotludots insInfo insLen ctxt + | Op.FENCE + | Op.FENCEdotI + | Op.FENCEdotTSO -> nop insLen ctxt + | Op.LRdotW + | Op.LRdotD -> lr insInfo insLen ctxt + | Op.SCdotW -> sc insInfo insLen ctxt 32 + | Op.SCdotD -> sc insInfo insLen ctxt 64 + | Op.CSRRW + | Op.CSRRWI -> csrrw insInfo insLen ctxt + | Op.CSRRS + | Op.CSRRSI -> csrrs insInfo insLen ctxt + | Op.CSRRC + | Op.CSRRCI -> csrrc insInfo insLen ctxt + | Op.FCVTdotSdotW -> fcvtdotsdotw insInfo insLen ctxt + | Op.FCVTdotSdotL -> fcvtdotsdotl insInfo insLen ctxt + | Op.FCVTdotSdotD -> fcvtdotsdotd insInfo insLen ctxt + | Op.FCVTdotDdotS -> fcvtdotddots insInfo insLen ctxt + | Op.FCVTdotDdotW -> fcvtdotddotw insInfo insLen ctxt + | Op.FCVTdotDdotL -> fcvtdotddotl insInfo insLen ctxt + | Op.FCVTdotDdotWU -> fcvtdotddotwu insInfo insLen ctxt + | Op.FCVTdotDdotLU -> fcvtdotddotlu insInfo insLen ctxt + | Op.FCVTdotSdotWU -> fcvtdotsdotwu insInfo insLen ctxt + | Op.FCVTdotSdotLU -> fcvtdotsdotlu insInfo insLen ctxt + | o -> +#if DEBUG + eprintfn "%A" o +#endif + raise <| NotImplementedIRException (Disasm.opCodeToString o) diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Parser.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Parser.fs index 1acbc560..5bff4f7a 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64Parser.fs +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Parser.fs @@ -22,28 +22,26 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.RISCV.Parser +namespace B2R2.FrontEnd.BinLifter.RISCV +open System open B2R2 open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinLifter.BitData - -let getRegister = function - | _ -> raise ParsingFailureException - -let private parseInstruction bin = - match bin with - | _ -> raise ParsingFailureException - -let parse (span: ByteSpan) (reader: IBinReader) addr = - let bin = reader.ReadUInt32 (span, 0) - let struct (opcode, operands) = parseInstruction bin - let insInfo = - { Address = addr - NumBytes = 4u - Opcode = opcode - Operands = operands - OperationSize = 32 } - RISCV64Instruction (addr, 4u, insInfo) - -// vim: set tw=80 sts=2 sw=2: + +/// Parser for RISCV64 instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type RISCV64Parser (isa: ISA) = + let wordSize = int isa.WordSize + let reader = BinReader.Init isa.Endian + + interface IInstructionParsable with + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader wordSize addr :> Instruction + + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader wordSize addr :> Instruction + + member __.MaxInstructionSize = 4 + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64ParsingMain.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64ParsingMain.fs new file mode 100644 index 00000000..f88e1676 --- /dev/null +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64ParsingMain.fs @@ -0,0 +1,714 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.RISCV.ParsingMain + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData +open B2R2.FrontEnd.BinLifter.RISCV.Helper + +let isTwoBytes b = + b &&& 3us <> 3us + +let getRegister = function + | _ -> raise ParsingFailureException + +let parseLUI bin wordSize = + struct (Op.LUI, getRdImm20 bin wordSize) + +let parseAUIPC bin wordSize = + struct (Op.AUIPC, getPCRdImm20 bin wordSize) + +let parseBranch bin wordSize = + let opcode = + match getFunc3 bin with + | 0b000u -> Op.BEQ + | 0b001u -> Op.BNE + | 0b100u -> Op.BLT + | 0b101u -> Op.BGE + | 0b110u -> Op.BLTU + | 0b111u -> Op.BGEU + | _ -> raise ParsingFailureException + struct (opcode, getRs1Rs2BImm bin wordSize) + +let parseLoad bin wordSize = + match getFunc3 bin with + | 0b000u -> struct (Op.LB, getRdRs1IImmAcc bin 8 wordSize) + | 0b001u -> struct (Op.LH, getRdRs1IImmAcc bin 16 wordSize) + | 0b010u -> struct (Op.LW, getRdRs1IImmAcc bin 32 wordSize) + | 0b011u -> struct (Op.LD, getRdRs1IImmAcc bin 64 wordSize) + | 0b100u -> struct (Op.LBU, getRdRs1IImmAcc bin 8 wordSize) + | 0b110u -> struct (Op.LWU, getRdRs1IImmAcc bin 32 wordSize) + | 0b101u -> struct (Op.LHU, getRdRs1IImmAcc bin 16 wordSize) + | _ -> raise ParsingFailureException + +let parseStore bin wordSize = + match getFunc3 bin with + | 0b000u -> struct (Op.SB, getRs2Rs1SImm bin 8 wordSize) + | 0b001u -> struct (Op.SH, getRs2Rs1SImm bin 16 wordSize) + | 0b010u -> struct (Op.SW, getRs2Rs1SImm bin 32 wordSize) + | 0b011u -> struct (Op.SD, getRs2Rs1SImm bin 64 wordSize) + | _ -> raise ParsingFailureException + +let parseOpImm bin wordSize = + let opcode = + match getFunc3 bin with + | 0b000u -> Op.ADDI + | 0b010u -> Op.SLTI + | 0b011u -> Op.SLTIU + | 0b100u -> Op.XORI + | 0b110u -> Op.ORI + | 0b111u -> Op.ANDI + (* Shifts *) + | 0b001u -> Op.SLLI + | 0b101u -> + if extract bin 31u 26u = 0b000000u then Op.SRLI + elif extract bin 31u 26u = 0b010000u then Op.SRAI + else raise ParsingFailureException + | _ -> raise ParsingFailureException + match opcode with + | Op.ADDI | Op.SLTI | Op.SLTIU | Op.XORI + | Op.ORI | Op.ANDI -> struct (opcode, getRdRs1IImm bin wordSize) + | _ -> struct (opcode, getRdRs1Shamt bin) + +let parseOp bin = + let opcode = + match getFunc3 bin with + | 0b000u -> + match getFunc7 bin with + | 0b0000001u -> Op.MUL + | 0b0000000u -> Op.ADD + | 0b0100000u -> Op.SUB + | _ -> raise ParsingFailureException + | 0b001u -> + match getFunc7 bin with + | 0b0000001u -> Op.MULH + | 0b0000000u -> Op.SLL + | _ -> raise ParsingFailureException + | 0b010u -> + match getFunc7 bin with + | 0b0000001u -> Op.MULHSU + | 0b0000000u -> Op.SLT + | _ -> raise ParsingFailureException + | 0b011u -> + match getFunc7 bin with + | 0b0000001u -> Op.MULHU + | 0b0000000u -> Op.SLTU + | _ -> raise ParsingFailureException + | 0b101u -> + match getFunc7 bin with + | 0b0000001u -> Op.DIVU + | 0b0000000u -> Op.SRL + | 0b0100000u -> Op.SRA + | _ -> raise ParsingFailureException + | 0b110u -> + match getFunc7 bin with + | 0b0000001u -> Op.REM + | 0b0000000u -> Op.OR + | _ -> raise ParsingFailureException + | 0b111u -> + match getFunc7 bin with + | 0b0000001u -> Op.REMU + | 0b0000000u -> Op.AND + | _ -> raise ParsingFailureException + | 0b100u -> + match getFunc7 bin with + | 0b0000001u -> Op.DIV + | 0b0000000u -> Op.XOR + | _ -> raise ParsingFailureException + | _ -> raise ParsingFailureException + struct (opcode, getRdRs1Rs2 bin) + +let parseEnvCall bin = + let opcode = if pickBit bin 20u = 1u then Op.EBREAK else Op.ECALL + struct (opcode, NoOperand) + +let parseFence bin = + let opcode = if pickBit bin 12u = 0u then Op.FENCE else Op.FENCEdotI + if opcode = Op.FENCEdotI then + struct (opcode, NoOperand) + else + if getPred bin = 0b0011uy && getSucc bin = 0b0011uy then + struct (Op.FENCEdotTSO, NoOperand) + else + struct (opcode, getPredSucc bin) + +let parseFloatArith bin = + match extract bin 31u 25u with + | 0b0000000u -> struct (Op.FADDdotS, getFRdRs1Rs2Rm bin) + | 0b0000100u -> struct (Op.FSUBdotS, getFRdRs1Rs2Rm bin) + | 0b0001000u -> struct (Op.FMULdotS, getFRdRs1Rs2Rm bin) + | 0b0001100u -> struct (Op.FDIVdotS, getFRdRs1Rs2Rm bin) + | 0b0101100u -> + if extract bin 24u 20u = 0u then struct (Op.FSQRTdotS, getFRdFRs1Rm bin) + else raise ParsingFailureException + | 0b0010000u -> + match getFunc3 bin with + | 0b000u -> struct (Op.FSGNJdotS, getFRdRs1Rs2 bin) + | 0b001u -> struct (Op.FSGNJNdotS, getFRdRs1Rs2 bin) + | 0b010u -> struct (Op.FSGNJXdotS, getFRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | 0b0010100u -> + match getFunc3 bin with + | 0b000u -> struct (Op.FMINdotS, getFRdRs1Rs2 bin) + | 0b001u -> struct (Op.FMAXdotS, getFRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | 0b1100000u -> + match getRs2 bin with + | 0b00000u -> struct (Op.FCVTdotWdotS, getRdFRs1Rm bin) + | 0b00001u -> struct (Op.FCVTdotWUdotS, getRdFRs1Rm bin) + | 0b00010u -> struct (Op.FCVTdotLdotS, getRdFRs1Rm bin) + | 0b00011u -> struct (Op.FCVTdotLUdotS, getRdFRs1Rm bin) + | _ -> raise ParsingFailureException + | 0b1110000u -> + if getFunc3 bin = 0b000u && getRs2 bin = 0b00000u then + struct (Op.FMVdotXdotW, getRdFRs1 bin) + elif getFunc3 bin = 0b001u && getRs2 bin = 0b00000u then + struct (Op.FCLASSdotS, getRdFRs1 bin) + else + raise ParsingFailureException + | 0b1010000u -> + match getFunc3 bin with + | 0b010u -> struct (Op.FEQdotS, getFNRdRs1Rs2 bin) + | 0b001u -> struct (Op.FLTdotS, getFNRdRs1Rs2 bin) + | 0b000u -> struct (Op.FLEdotS, getFNRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | 0b1101000u -> + match getRs2 bin with + | 0b00000u -> struct (Op.FCVTdotSdotW, getFRdRs1Rm bin) + | 0b00001u -> struct (Op.FCVTdotSdotWU, getFRdRs1Rm bin) + | 0b00010u -> struct (Op.FCVTdotSdotL, getFRdRs1Rm bin) + | 0b00011u -> struct (Op.FCVTdotSdotLU, getFRdRs1Rm bin) + | _ -> raise ParsingFailureException + | 0b1111000u -> + if getRs2 bin = 0b00000u && getFunc3 bin = 0b000u then + struct (Op.FMVdotWdotX, getFRdRs1 bin) + else + raise ParsingFailureException + | 0b0000001u -> struct (Op.FADDdotD, getFRdRs1Rs2Rm bin) + | 0b0000101u -> struct (Op.FSUBdotD, getFRdRs1Rs2Rm bin) + | 0b0001001u -> struct (Op.FMULdotD, getFRdRs1Rs2Rm bin) + | 0b0001101u -> struct (Op.FDIVdotD, getFRdRs1Rs2Rm bin) + | 0b0101101u -> + if getRs2 bin = 0u then struct (Op.FSQRTdotD, getFRdFRs1Rm bin) + else raise ParsingFailureException + | 0b0010001u -> + match getFunc3 bin with + | 0b000u -> struct (Op.FSGNJdotD, getFRdRs1Rs2 bin) + | 0b001u -> struct (Op.FSGNJNdotD, getFRdRs1Rs2 bin) + | 0b010u -> struct (Op.FSGNJXdotD, getFRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | 0b0010101u -> + if getFunc3 bin = 0b000u then struct (Op.FMINdotD, getFRdRs1Rs2 bin) + elif getFunc3 bin = 0b001u then struct (Op.FMAXdotD, getFRdRs1Rs2 bin) + else raise ParsingFailureException + | 0b0100000u -> + if getRs2 bin = 0b00001u then struct (Op.FCVTdotSdotD, getFRdFRs1Rm bin) + else raise ParsingFailureException + | 0b0100001u -> + if getRs2 bin = 0b00000u then struct (Op.FCVTdotDdotS, getFRdFRs1Rm bin) + else raise ParsingFailureException + | 0b1010001u -> + match getFunc3 bin with + | 0b010u -> struct (Op.FEQdotD, getFNRdRs1Rs2 bin) + | 0b000u -> struct (Op.FLEdotD, getFNRdRs1Rs2 bin) + | 0b001u -> struct (Op.FLTdotD, getFNRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | 0b1110001u -> + if getRs2 bin = 0b00000u && getFunc3 bin = 0b001u then + struct (Op.FCLASSdotD, getRdFRs1 bin) + elif getRs2 bin = 0b00000u && getFunc3 bin = 0b000u then + struct (Op.FMVdotXdotD, getRdFRs1 bin) + else + raise ParsingFailureException + | 0b1100001u -> + match getRs2 bin with + | 0b00000u -> struct (Op.FCVTdotWdotD, getRdFRs1Rm bin) + | 0b00001u -> struct (Op.FCVTdotWUdotD, getRdFRs1Rm bin) + | 0b00010u -> struct (Op.FCVTdotLdotD, getRdFRs1Rm bin) + | 0b00011u -> struct (Op.FCVTdotLUdotD, getRdFRs1Rm bin) + | _ -> raise ParsingFailureException + | 0b1101001u -> + match getRs2 bin with + | 0b00000u -> struct (Op.FCVTdotDdotW, getFRdRs1 bin) + | 0b00001u -> struct (Op.FCVTdotDdotWU, getFRdRs1 bin) + | 0b00010u -> struct (Op.FCVTdotDdotL, getFRdRs1Rm bin) + | 0b00011u -> struct (Op.FCVTdotDdotLU, getFRdRs1Rm bin) + | _ -> raise ParsingFailureException + | 0b1111001u -> + if getRs2 bin = 0b00000u && getFunc3 bin = 0b000u then + struct (Op.FMVdotDdotX, getFRdRs1 bin) + else + raise ParsingFailureException + | _ -> raise ParsingFailureException + +let parseAtomic bin = + if extract bin 14u 12u = 0b010u then + match extract bin 31u 27u with + | 0b00010u -> struct (Op.LRdotW, getRdRs1AqRlAcc bin 32) + | 0b00011u -> struct (Op.SCdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b00001u -> struct (Op.AMOSWAPdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b00000u -> struct (Op.AMOADDdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b00100u -> struct (Op.AMOXORdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b01100u -> struct (Op.AMOANDdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b01000u -> struct (Op.AMOORdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b10000u -> struct (Op.AMOMINdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b10100u -> struct (Op.AMOMAXdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b11000u -> struct (Op.AMOMINUdotW, getRdRs2Rs1AqRlAcc bin 32) + | 0b11100u -> struct (Op.AMOMAXUdotW, getRdRs2Rs1AqRlAcc bin 32) + | _ -> raise ParsingFailureException + elif extract bin 14u 12u = 0b011u then + match extract bin 31u 27u with + | 0b00010u -> struct (Op.LRdotD, getRdRs1AqRlAcc bin 64) + | 0b00011u -> struct (Op.SCdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b00001u -> struct (Op.AMOSWAPdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b00000u -> struct (Op.AMOADDdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b00100u -> struct (Op.AMOXORdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b01100u -> struct (Op.AMOANDdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b01000u -> struct (Op.AMOORdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b10000u -> struct (Op.AMOMINdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b10100u -> struct (Op.AMOMAXdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b11000u -> struct (Op.AMOMINUdotD, getRdRs2Rs1AqRlAcc bin 64) + | 0b11100u -> struct (Op.AMOMAXUdotD, getRdRs2Rs1AqRlAcc bin 64) + | _ -> raise ParsingFailureException + else + raise ParsingFailureException + +let parseJAL bin wordSize = struct (Op.JAL, getRdJImm bin wordSize) + +let parseJALR bin wordSize = struct (Op.JALR, getRdRs1JImm bin wordSize) + +let parseFused bin = + if extract bin 26u 25u = 0b00u then + match extract bin 6u 0u with + | 0b1000011u -> struct (Op.FMADDdotS, getFRdRs1Rs2Rs3Rm bin) + | 0b1000111u -> struct (Op.FMSUBdotS, getFRdRs1Rs2Rs3Rm bin) + | 0b1001011u -> struct (Op.FNMSUBdotS, getFRdRs1Rs2Rs3Rm bin) + | 0b1001111u -> struct (Op.FNMADDdotS, getFRdRs1Rs2Rs3Rm bin) + | _ -> raise ParsingFailureException + elif extract bin 26u 25u = 0b01u then + match extract bin 6u 0u with + | 0b1000011u -> struct (Op.FMADDdotD, getFRdRs1Rs2Rs3Rm bin) + | 0b1000111u -> struct (Op.FMSUBdotD, getFRdRs1Rs2Rs3Rm bin) + | 0b1001011u -> struct (Op.FNMSUBdotD, getFRdRs1Rs2Rs3Rm bin) + | 0b1001111u -> struct (Op.FNMADDdotD, getFRdRs1Rs2Rs3Rm bin) + | _ -> raise ParsingFailureException + else + raise ParsingFailureException + +let parseFloatLoad bin wordSize = + match extract bin 14u 12u with + | 0b011u -> struct (Op.FLD, getFRdRs1Addr bin 64 wordSize) + | 0b010u -> struct (Op.FLW, getFRdRs1Addr bin 32 wordSize) + | _ -> raise ParsingFailureException + +let parseFloatStore bin wordSize = + match extract bin 14u 12u with + | 0b011u -> struct (Op.FSD, getFRs2Rs1Addr bin 64 wordSize) + | 0b010u -> struct (Op.FSW, getFRs2Rs1Addr bin 32 wordSize) + | _ -> raise ParsingFailureException + +let parseOp32 bin = + match extract bin 31u 25u with + | 0b0000000u -> + match getFunc3 bin with + | 0b000u -> struct (Op.ADDW, getRdRs1Rs2 bin) + | 0b001u -> struct (Op.SLLW, getRdRs1Rs2 bin) + | 0b101u -> struct (Op.SRLW, getRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | 0b0100000u -> + if getFunc3 bin = 0b000u then struct (Op.SUBW, getRdRs1Rs2 bin) + elif getFunc3 bin = 0b101u then struct (Op.SRAW, getRdRs1Rs2 bin) + else raise ParsingFailureException + | 0b0000001u -> + match getFunc3 bin with + | 0b000u -> struct (Op.MULW, getRdRs1Rs2 bin) + | 0b100u -> struct (Op.DIVW, getRdRs1Rs2 bin) + | 0b101u -> struct (Op.DIVUW, getRdRs1Rs2 bin) + | 0b110u -> struct (Op.REMW, getRdRs1Rs2 bin) + | 0b111u -> struct (Op.REMUW, getRdRs1Rs2 bin) + | _ -> raise ParsingFailureException + | _ -> raise ParsingFailureException + +let parseOpImm32 bin wordSize = + match getFunc3 bin with + | 0b000u -> struct (Op.ADDIW, getRdRs1IImm bin wordSize) + | 0b001u -> struct (Op.SLLIW, getRdRs1Shamt bin) + | 0b101u -> + if extract bin 31u 25u = 0b0000000u then + struct (Op.SRLIW, getRdRs1Shamt bin) + elif extract bin 31u 25u = 0b0100000u then + struct (Op.SRAIW, getRdRs1Shamt bin) + else + raise ParsingFailureException + | _ -> raise ParsingFailureException + +let parseCSR bin = + match getFunc3 bin with + | 0b001u -> struct (Op.CSRRW, getRdCSRRs1 bin) + | 0b010u -> struct (Op.CSRRS, getRdCSRRs1 bin) + | 0b011u -> struct (Op.CSRRC, getRdCSRRs1 bin) + | 0b101u -> struct (Op.CSRRWI, getRdCSRUImm bin) + | 0b110u -> struct (Op.CSRRSI, getRdCSRUImm bin) + | 0b111u -> struct (Op.CSRRCI, getRdCSRUImm bin) + | _ -> raise ParsingFailureException + +let parseRegisterBasedLoadStore bin = + match extract bin 15u 13u with + | 0b010u -> + let dest = crdComp bin + let from2to2 = pickBit bin 6u <<< 2 + let from3to5 = extract bin 12u 10u <<< 3 + let from6to6 = pickBit bin 5u <<< 6 + let imm = from2to2 ||| from3to5 ||| from6to6 |> int64 |> Imm |> Some + let b = getCompRegFrom97 bin + struct (Op.CdotLW, TwoOperands (dest, OpMem (b, imm, 32))) + | 0b011u -> + let dest = crdComp bin + let from3to5 = extract bin 12u 10u <<< 3 + let from6to7 = extract bin 6u 5u <<< 6 + let imm = from3to5 ||| from6to7 |> int64 |> Imm |> Some + let b = getCompRegFrom97 bin + struct (Op.CdotLD, TwoOperands (dest, OpMem (b, imm, 64))) + | 0b001u -> + let dest = cfrdComp bin + let from3to5 = extract bin 12u 10u <<< 3 + let from6to7 = extract bin 6u 5u <<< 6 + let imm = from3to5 ||| from6to7 |> int64 |> Imm |> Some + let b = getCompRegFrom97 bin + struct (Op.CdotFLD, TwoOperands (dest, OpMem (b, imm, 64))) + | 0b110u -> + let src = crs2Comp bin + let b = getCompRegFrom97 bin + let from2to2 = pickBit bin 6u <<< 2 + let from3to5 = extract bin 10u 12u <<< 3 + let from6to6 = pickBit bin 5u <<< 6 + let imm = from2to2 ||| from3to5 ||| from6to6 |> int64 |> Imm |> Some + struct (Op.CdotSW, TwoOperands (src, OpMem (b, imm, 32))) + | 0b111u -> + let src = crs2Comp bin + let b = getCompRegFrom97 bin + let from3to5 = extract bin 10u 12u <<< 3 + let from6to7 = extract bin 6u 5u <<< 6 + let imm = from3to5 ||| from6to7 |> int64 |> Imm |> Some + struct (Op.CdotSD, TwoOperands (src, OpMem (b, imm, 64))) + | 0b101u -> + let src = cfrs2Comp bin + let b = getCompRegFrom97 bin + let from3to5 = extract bin 10u 12u <<< 3 + let from6to7 = extract bin 6u 5u <<< 6 + let imm = from3to5 ||| from6to7 |> int64 |> Imm |> Some + struct (Op.CdotFSD, TwoOperands (src, OpMem (b, imm, 64))) + | _ -> Utils.impossible () + +let parseStackBasedLoadStore bin = + match extract bin 15u 13u with + | 0b010u -> + let from2to4 = extract bin 4u 6u <<< 2 + let from5to5 = pickBit bin 12u <<< 5 + let from6to7 = extract bin 2u 3u <<< 6 + let imm = from2to4 ||| from5to5 ||| from6to7 |> int64 |> Imm |> Some + let dest = crd bin + if extract bin 11u 7u = 0u then raise ParsingFailureException + else () + struct (Op.CdotLWSP, TwoOperands (dest, OpMem (R.X2, imm, 32))) + | 0b011u -> + let from3to4 = extract bin 6u 5u <<< 3 + let from5to5 = pickBit bin 12u <<< 5 + let from6to8 = extract bin 2u 4u <<< 6 + let imm = from3to4 ||| from5to5 ||| from6to8 |> int64 |> Imm |> Some + let dest = crd bin + if extract bin 11u 7u = 0u then raise ParsingFailureException + else () + struct (Op.CdotLDSP, TwoOperands (dest, OpMem (R.X2, imm, 64))) + | 0b001u -> + let from3to4 = extract bin 6u 5u <<< 3 + let from5to5 = pickBit bin 12u <<< 5 + let from6to8 = extract bin 2u 4u <<< 6 + let imm = from3to4 ||| from5to5 ||| from6to8 |> int64 |> Imm |> Some + let dest = cfrd bin + struct (Op.CdotFLDSP, TwoOperands (dest, OpMem (R.X2, imm, 64))) + | 0b110u -> + let rs2 = crs2 bin + let from2to5 = extract bin 12u 9u <<< 2 + let from6to7 = extract bin 8u 7u <<< 6 + let imm = from2to5 ||| from6to7 |> int64 |> Imm |> Some + struct (Op.CdotSWSP, TwoOperands (rs2, OpMem (R.X2, imm, 32))) + | 0b111u -> + let rs2 = crs2 bin + let from3to5 = extract bin 12u 10u <<< 3 + let from6to8 = extract bin 9u 7u <<< 6 + let imm = from3to5 ||| from6to8 |> int64 |> Imm |> Some + struct (Op.CdotSDSP, TwoOperands (rs2, OpMem (R.X2, imm, 64))) + | 0b101u -> + let rs2 = cfrs2 bin + let from3to5 = extract bin 12u 10u <<< 3 + let from6to8 = extract bin 9u 7u <<< 6 + let imm = from3to5 ||| from6to8 |> int64 |> Imm |> Some + struct (Op.CdotFSDSP, TwoOperands (rs2, OpMem (R.X2, imm, 64))) + | _ -> Utils.impossible () + +let parseCdotADDI4SPN bin = + let from2to2 = pickBit bin 6u <<< 2 + let from3to3 = pickBit bin 5u <<< 3 + let from4to5 = extract bin 12u 11u <<< 4 + let from6to9 = extract bin 10u 7u <<< 6 + let imm = from2to2 ||| from3to3 ||| from4to5 ||| from6to9 |> uint64 + let dest = crs2Comp bin + if imm = 0UL then raise ParsingFailureException + else () + struct (Op.CdotADDI4SPN, ThreeOperands (dest, R.X2 |> OpReg, imm |> OpImm)) + +let parseCdotJ bin wordSize = + let from1to3 = extract bin 5u 3u <<< 1 + let from5to5 = pickBit bin 2u <<< 5 + let from7to7 = pickBit bin 6u <<< 7 + let from6to6 = pickBit bin 7u <<< 6 + let from10to10 = pickBit bin 8u <<< 10 + let from8to9 = extract bin 10u 9u <<< 8 + let from4to4 = pickBit bin 11u <<< 4 + let from11to11 = pickBit bin 12u <<< 11 + let imm = 0b0u ||| from1to3 ||| from4to4 ||| from5to5 ||| from6to6 + ||| from7to7 ||| from8to9 ||| from10to10 ||| from11to11 |> uint64 + |> signExtend 12 wordSize |> int64 |> Relative |> OpAddr + struct (Op.CdotJ, TwoOperands (R.X0 |> OpReg, imm)) + +let parseCdotBranch bin wordSize = + let opcode = if extract bin 15u 13u = 0b111u then Op.CdotBNEZ + else Op.CdotBEQZ + let src = crs1Comp bin + let from1to2 = extract bin 3u 4u <<< 1 + let from3to4 = extract bin 10u 11u <<< 3 + let from5to5 = pickBit bin 2u <<< 5 + let from6to7 = extract bin 6u 5u <<< 6 + let from8to8 = pickBit bin 12u <<< 8 + let imm = 0b0u ||| from1to2 ||| from3to4 ||| from5to5 ||| from6to7 + ||| from8to8 |> uint64 |> signExtend 9 wordSize + |> int64 |> Relative |> OpAddr + struct (opcode, ThreeOperands (src, R.X0 |> OpReg, imm)) + +let parseCdotADDIW bin wordSize = + if extract bin 11u 7u = 0u then raise ParsingFailureException + else () + let imm = (extract bin 6u 2u) ||| (pickBit bin 12u <<< 5) |> uint64 + let signExtended = signExtend 6 wordSize imm |> uint64 |> OpImm + let dest = crd bin + struct (Op.CdotADDIW, ThreeOperands (dest, dest, signExtended)) + +let parseCdotLI bin wordSize = + let dest = crd bin + let imm = (extract bin 6u 2u) ||| (pickBit bin 12u <<< 5) |> uint64 + let signExtended = signExtend 6 wordSize imm |> uint64 + struct (Op.CdotLI, ThreeOperands (dest, R.X0 |> OpReg, signExtended |> OpImm)) + +let parseCdotANDI bin wordSize = + let dest = crs1Comp bin + let from0to4 = extract bin 6u 2u + let from5to5 = pickBit bin 12u <<< 5 + let imm = from0to4 ||| from5to5 |> uint64 + let signExtended = signExtend 6 wordSize imm |> uint64 + struct (Op.CdotANDI, ThreeOperands (dest, dest, signExtended |> OpImm)) + +let parseCdotSLLI bin = + let from0to4 = extract bin 6u 2u + let from5to5 = pickBit bin 12u <<< 5 + let imm = from0to4 ||| from5to5 |> uint64 + let dest = crd bin + struct (Op.CdotSLLI, ThreeOperands (dest, dest, imm |> OpShiftAmount)) + +let parseCdotSR bin = + let dest = crs1Comp bin + let from0to4 = extract bin 6u 2u + let from5to5 = pickBit bin 12u <<< 5 + let imm = from0to4 ||| from5to5 |> uint64 + let opcode = if extract bin 11u 10u = 0u then Op.CdotSRLI else Op.CdotSRAI + struct (opcode, ThreeOperands (dest, dest, imm |> OpShiftAmount)) + +let parseCdotLUIADDI16SP bin wordSize= + if extract bin 11u 7u = 2u then + let from4to4 = pickBit bin 6u <<< 4 + let from5to5 = pickBit bin 2u <<< 5 + let from6to6 = pickBit bin 5u <<< 6 + let from7to8 = extract bin 4u 3u <<< 7 + let from9to9 = pickBit bin 12u <<< 9 + let imm = from4to4 ||| from5to5 ||| from6to6 ||| from7to8 ||| from9to9 + |> uint64 +#if DEBUG + if imm = 0uL then raise ParsingFailureException else () +#endif + let signExtended = signExtend 10 wordSize imm |> uint64 |> OpImm + struct (Op.CdotADDI16SP, + ThreeOperands (R.X2 |> OpReg, R.X2 |> OpReg, signExtended)) + else + let imm = (extract bin 6u 2u) ||| (pickBit bin 12u <<< 5) |> uint64 + let signExtended = signExtend 6 wordSize imm |> uint64 + if imm = 0uL then raise ParsingFailureException + else () + let dest = crd bin + struct (Op.CdotLUI, TwoOperands (dest, signExtended |> OpImm)) + +let parseCdotArith bin = + let opcode = + match (pickBit bin 12u) <<< 2 ||| extract bin 6u 5u with + | 0b000u -> Op.CdotSUB + | 0b001u -> Op.CdotXOR + | 0b010u -> Op.CdotOR + | 0b011u -> Op.CdotAND + | 0b100u -> Op.CdotSUBW + | 0b101u -> Op.CdotADDW + | _ -> raise ParsingFailureException + let dest = crs1Comp bin + let src = crdComp bin + struct (opcode, ThreeOperands (dest, dest, src)) + +let parseCdotJrMvEBREAKJalrAdd bin = + if pickBit bin 12u = 0u then + if extract bin 6u 2u = 0u then + if extract bin 11u 7u = 0u then raise ParsingFailureException + else struct (Op.CdotJR, TwoOperands (R.X0 |> OpReg, + RelativeBase (getRegFrom117 bin, 0UL) |> OpAddr)) + else + let dest = crd bin + let src = crs2 bin + struct (Op.CdotMV, ThreeOperands (dest, R.X0 |> OpReg, src)) + else + if extract bin 6u 2u = 0u then + if extract bin 11u 7u = 0u then + struct (Op.CdotEBREAK, NoOperand) + else + struct (Op.CdotJALR, TwoOperands (R.X1 |> OpReg, + RelativeBase (getRegFrom117 bin, 0UL) |> OpAddr)) + else + let dest = crd bin + let src = crs2 bin + struct (Op.CdotADD, ThreeOperands (dest, dest, src)) + +let parseCdotNOPADDI bin wordSize = + if extract bin 11u 7u = 0u then + struct (Op.CdotNOP, NoOperand) + else + let imm = (extract bin 6u 2u) ||| (pickBit bin 12u <<< 5) |> uint64 + let signExtended = signExtend 6 wordSize imm |> uint64 |> OpImm + let dest = crd bin + struct (Op.CdotADDI, ThreeOperands (dest, dest, signExtended)) + +let parseQuadrant0 bin wordSize = + match extract bin 15u 13u with + | 0b000u -> parseCdotADDI4SPN bin + | 0b001u + | 0b010u + | 0b011u + | 0b101u + | 0b110u + | 0b111u -> parseRegisterBasedLoadStore bin + | _ -> raise ParsingFailureException + +let parseQuadrant1 bin wordSize = + match extract bin 15u 13u with + | 0b000u -> parseCdotNOPADDI bin wordSize + | 0b001u -> parseCdotADDIW bin wordSize + | 0b010u -> parseCdotLI bin wordSize + | 0b011u -> parseCdotLUIADDI16SP bin wordSize + | 0b100u -> + match extract bin 11u 10u with + | 0b00u + | 0b01u -> parseCdotSR bin + | 0b10u -> parseCdotANDI bin wordSize + | 0b11u -> parseCdotArith bin + | _ -> Utils.impossible () + | 0b101u -> parseCdotJ bin wordSize + | 0b110u + | 0b111u -> parseCdotBranch bin wordSize + | _ -> raise ParsingFailureException + +let parseQuadrant2 bin wordSize = + match extract bin 15u 13u with + | 0b000u -> parseCdotSLLI bin + | 0b001u + | 0b010u + | 0b011u + | 0b101u + | 0b110u + | 0b111u -> parseStackBasedLoadStore bin + | 0b100u -> parseCdotJrMvEBREAKJalrAdd bin + | _ -> Utils.impossible () + +let private parseCompressedInstruction wordSize bin = + match extract bin 0u 1u with + | 0b00u -> parseQuadrant0 bin wordSize + | 0b01u -> parseQuadrant1 bin wordSize + | 0b10u -> parseQuadrant2 bin wordSize + | _ -> Utils.impossible () + +let private parseInstruction wordSize bin = + match extract bin 6u 0u with + | 0b0110111u -> parseLUI bin wordSize + | 0b0010111u -> parseAUIPC bin wordSize + | 0b1101111u -> parseJAL bin wordSize + | 0b1100111u -> parseJALR bin wordSize + | 0b1100011u -> parseBranch bin wordSize + | 0b0000011u -> parseLoad bin wordSize + | 0b0100011u -> parseStore bin wordSize + | 0b0010011u -> parseOpImm bin wordSize + | 0b0110011u -> parseOp bin + | 0b0001111u -> parseFence bin + | 0b1110011u -> + if getFunc3 bin = 0u then parseEnvCall bin + else parseCSR bin + | 0b0011011u -> parseOpImm32 bin wordSize + | 0b0111011u -> parseOp32 bin + | 0b0101111u -> parseAtomic bin + | 0b0000111u -> parseFloatLoad bin wordSize + | 0b0100111u -> parseFloatStore bin wordSize + | 0b1000011u + | 0b1000111u + | 0b1001011u + | 0b1001111u -> parseFused bin + | 0b1010011u -> parseFloatArith bin + | _ -> raise ParsingFailureException + +let parse (span: ByteSpan) (reader: IBinReader) wordSize addr = + let bin = reader.ReadUInt16 (span, 0) + let wordSz = int wordSize + let struct (op, operands, instrLen) = + match isTwoBytes bin with + | true -> + let bin = uint32 bin + let struct (op, operands) = bin |> parseCompressedInstruction wordSz + struct (op, operands, 2u) + | false -> + let b2 = reader.ReadUInt16 (span, 2) + let bin = ((uint32 b2) <<< 16) + (uint32 bin) + let struct (op, operands) = bin |> parseInstruction wordSz + struct (op, operands, 4u) + let insInfo = + { Address = addr + NumBytes = instrLen + Opcode = op + Operands = operands + OperationSize = 32 } + RISCV64Instruction (addr, instrLen, insInfo) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64RegExprs.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64RegExprs.fs index 0a117972..78769cde 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64RegExprs.fs +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64RegExprs.fs @@ -25,16 +25,657 @@ namespace B2R2.FrontEnd.BinLifter.RISCV open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingUtils open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (RISCV64RegisterSet.singleton t) +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name (* Registers *) let regType = WordSize.toRegType wordSize + let fflags = var 32 (Register.toRegID Register.FFLAGS) "FFLAGS" + let frm = var 32 (Register.toRegID Register.FRM) "FRM" + + member val X0 = var regType (Register.toRegID Register.X0) "X0" with get + member val X1 = var regType (Register.toRegID Register.X1) "X1" with get + member val X2 = var regType (Register.toRegID Register.X2) "X2" with get + member val X3 = var regType (Register.toRegID Register.X3) "X3" with get + member val X4 = var regType (Register.toRegID Register.X4) "X4" with get + member val X5 = var regType (Register.toRegID Register.X5) "X5" with get + member val X6 = var regType (Register.toRegID Register.X6) "X6" with get + member val X7 = var regType (Register.toRegID Register.X7) "X7" with get + member val X8 = var regType (Register.toRegID Register.X8) "X8" with get + member val X9 = var regType (Register.toRegID Register.X9) "X9" with get + member val X10 = var regType (Register.toRegID Register.X10) "X10" with get + member val X11 = var regType (Register.toRegID Register.X11) "X11" with get + member val X12 = var regType (Register.toRegID Register.X12) "X12" with get + member val X13 = var regType (Register.toRegID Register.X13) "X13" with get + member val X14 = var regType (Register.toRegID Register.X14) "X14" with get + member val X15 = var regType (Register.toRegID Register.X15) "X15" with get + member val X16 = var regType (Register.toRegID Register.X16) "X16" with get + member val X17 = var regType (Register.toRegID Register.X17) "X17" with get + member val X18 = var regType (Register.toRegID Register.X18) "X18" with get + member val X19 = var regType (Register.toRegID Register.X19) "X19" with get + member val X20 = var regType (Register.toRegID Register.X20) "X20" with get + member val X21 = var regType (Register.toRegID Register.X21) "X21" with get + member val X22 = var regType (Register.toRegID Register.X22) "X22" with get + member val X23 = var regType (Register.toRegID Register.X23) "X23" with get + member val X24 = var regType (Register.toRegID Register.X24) "X24" with get + member val X25 = var regType (Register.toRegID Register.X25) "X25" with get + member val X26 = var regType (Register.toRegID Register.X26) "X26" with get + member val X27 = var regType (Register.toRegID Register.X27) "X27" with get + member val X28 = var regType (Register.toRegID Register.X28) "X28" with get + member val X29 = var regType (Register.toRegID Register.X29) "X29" with get + member val X30 = var regType (Register.toRegID Register.X30) "X30" with get + member val X31 = var regType (Register.toRegID Register.X31) "X31" with get + + member val F0 = var regType (Register.toRegID Register.F0) "F0" with get + member val F1 = var regType (Register.toRegID Register.F1) "F1" with get + member val F2 = var regType (Register.toRegID Register.F2) "F2" with get + member val F3 = var regType (Register.toRegID Register.F3) "F3" with get + member val F4 = var regType (Register.toRegID Register.F4) "F4" with get + member val F5 = var regType (Register.toRegID Register.F5) "F5" with get + member val F6 = var regType (Register.toRegID Register.F6) "F6" with get + member val F7 = var regType (Register.toRegID Register.F7) "F7" with get + member val F8 = var regType (Register.toRegID Register.F8) "F8" with get + member val F9 = var regType (Register.toRegID Register.F9) "F9" with get + member val F10 = var regType (Register.toRegID Register.F10) "F10" with get + member val F11 = var regType (Register.toRegID Register.F11) "F11" with get + member val F12 = var regType (Register.toRegID Register.F12) "F12" with get + member val F13 = var regType (Register.toRegID Register.F13) "F13" with get + member val F14 = var regType (Register.toRegID Register.F14) "F14" with get + member val F15 = var regType (Register.toRegID Register.F15) "F15" with get + member val F16 = var regType (Register.toRegID Register.F16) "F16" with get + member val F17 = var regType (Register.toRegID Register.F17) "F17" with get + member val F18 = var regType (Register.toRegID Register.F18) "F18" with get + member val F19 = var regType (Register.toRegID Register.F19) "F19" with get + member val F20 = var regType (Register.toRegID Register.F20) "F20" with get + member val F21 = var regType (Register.toRegID Register.F21) "F21" with get + member val F22 = var regType (Register.toRegID Register.F22) "F22" with get + member val F23 = var regType (Register.toRegID Register.F23) "F23" with get + member val F24 = var regType (Register.toRegID Register.F24) "F24" with get + member val F25 = var regType (Register.toRegID Register.F25) "F25" with get + member val F26 = var regType (Register.toRegID Register.F26) "F26" with get + member val F27 = var regType (Register.toRegID Register.F27) "F27" with get + member val F28 = var regType (Register.toRegID Register.F28) "F28" with get + member val F29 = var regType (Register.toRegID Register.F29) "F29" with get + member val F30 = var regType (Register.toRegID Register.F30) "F30" with get + member val F31 = var regType (Register.toRegID Register.F31) "F31" with get + + member val PC = AST.pcvar regType "PC" with get + member val RC = var 1 (Register.toRegID Register.RC) "RC" with get + member val FFLAGS = fflags with get + member val FRM = frm with get + member val FCSR = + (fflags .& (numI32 0b11111 32)) + .| ((frm .& (numI32 0b111 32)) << numI32 5 32) with get + + member val CSR0768 = + var regType (Register.toRegID Register.CSR0768) "CSR0768" with get + member val CSR0769 = + var regType (Register.toRegID Register.CSR0769) "CSR0769" with get + member val CSR0770 = + var regType (Register.toRegID Register.CSR0770) "CSR0770" with get + member val CSR0771 = + var regType (Register.toRegID Register.CSR0771) "CSR0771" with get + member val CSR0772 = + var regType (Register.toRegID Register.CSR0772) "CSR0772" with get + member val CSR0773 = + var regType (Register.toRegID Register.CSR0773) "CSR0773" with get + member val CSR0784 = + var regType (Register.toRegID Register.CSR0784) "CSR0784" with get + member val CSR0832 = + var regType (Register.toRegID Register.CSR0832) "CSR0832" with get + member val CSR0833 = + var regType (Register.toRegID Register.CSR0833) "CSR0833" with get + member val CSR0834 = + var regType (Register.toRegID Register.CSR0834) "CSR0834" with get + member val CSR0835 = + var regType (Register.toRegID Register.CSR0835) "CSR0835" with get + member val CSR0836 = + var regType (Register.toRegID Register.CSR0836) "CSR0836" with get + member val CSR0842 = + var regType (Register.toRegID Register.CSR0842) "CSR0842" with get + member val CSR0843 = + var regType (Register.toRegID Register.CSR0843) "CSR0843" with get + member val CSR3114 = + var regType (Register.toRegID Register.CSR3114) "CSR3114" with get + member val CSR3787 = + var regType (Register.toRegID Register.CSR3787) "CSR3787" with get + member val CSR3857 = + var regType (Register.toRegID Register.CSR3857) "CSR3857" with get + member val CSR3858 = + var regType (Register.toRegID Register.CSR3858) "CSR3858" with get + member val CSR3859 = + var regType (Register.toRegID Register.CSR3859) "CSR3859" with get + member val CSR3860 = + var regType (Register.toRegID Register.CSR3860) "CSR3860" with get + member val CSR0928 = + var regType (Register.toRegID Register.CSR0928) "CSR0928" with get + member val CSR0930 = + var regType (Register.toRegID Register.CSR0930) "CSR0930" with get + member val CSR0932 = + var regType (Register.toRegID Register.CSR0932) "CSR0932" with get + member val CSR0934 = + var regType (Register.toRegID Register.CSR0934) "CSR0934" with get + member val CSR0936 = + var regType (Register.toRegID Register.CSR0936) "CSR0936" with get + member val CSR0938 = + var regType (Register.toRegID Register.CSR0938) "CSR0938" with get + member val CSR0940 = + var regType (Register.toRegID Register.CSR0940) "CSR0940" with get + member val CSR0942 = + var regType (Register.toRegID Register.CSR0942) "CSR0942" with get + member val CSR0944 = + var regType (Register.toRegID Register.CSR0944) "CSR0944" with get + member val CSR0945 = + var regType (Register.toRegID Register.CSR0945) "CSR0945" with get + member val CSR0946 = + var regType (Register.toRegID Register.CSR0946) "CSR0946" with get + member val CSR0947 = + var regType (Register.toRegID Register.CSR0947) "CSR0947" with get + member val CSR0948 = + var regType (Register.toRegID Register.CSR0948) "CSR0948" with get + member val CSR0949 = + var regType (Register.toRegID Register.CSR0949) "CSR0949" with get + member val CSR0950 = + var regType (Register.toRegID Register.CSR0950) "CSR0950" with get + member val CSR0951 = + var regType (Register.toRegID Register.CSR0951) "CSR0951" with get + member val CSR0952 = + var regType (Register.toRegID Register.CSR0952) "CSR0952" with get + member val CSR0953 = + var regType (Register.toRegID Register.CSR0953) "CSR0953" with get + member val CSR0954 = + var regType (Register.toRegID Register.CSR0954) "CSR0954" with get + member val CSR0955 = + var regType (Register.toRegID Register.CSR0955) "CSR0955" with get + member val CSR0956 = + var regType (Register.toRegID Register.CSR0956) "CSR0956" with get + member val CSR0957 = + var regType (Register.toRegID Register.CSR0957) "CSR0957" with get + member val CSR0958 = + var regType (Register.toRegID Register.CSR0958) "CSR0958" with get + member val CSR0959 = + var regType (Register.toRegID Register.CSR0959) "CSR0959" with get + member val CSR0960 = + var regType (Register.toRegID Register.CSR0960) "CSR0960" with get + member val CSR0961 = + var regType (Register.toRegID Register.CSR0961) "CSR0961" with get + member val CSR0962 = + var regType (Register.toRegID Register.CSR0962) "CSR0962" with get + member val CSR0963 = + var regType (Register.toRegID Register.CSR0963) "CSR0963" with get + member val CSR0964 = + var regType (Register.toRegID Register.CSR0964) "CSR0964" with get + member val CSR0965 = + var regType (Register.toRegID Register.CSR0965) "CSR0965" with get + member val CSR0966 = + var regType (Register.toRegID Register.CSR0966) "CSR0966" with get + member val CSR0967 = + var regType (Register.toRegID Register.CSR0967) "CSR0967" with get + member val CSR0968 = + var regType (Register.toRegID Register.CSR0968) "CSR0968" with get + member val CSR0969 = + var regType (Register.toRegID Register.CSR0969) "CSR0969" with get + member val CSR0970 = + var regType (Register.toRegID Register.CSR0970) "CSR0970" with get + member val CSR0971 = + var regType (Register.toRegID Register.CSR0971) "CSR0971" with get + member val CSR0972 = + var regType (Register.toRegID Register.CSR0972) "CSR0972" with get + member val CSR0973 = + var regType (Register.toRegID Register.CSR0973) "CSR0973" with get + member val CSR0974 = + var regType (Register.toRegID Register.CSR0974) "CSR0974" with get + member val CSR0975 = + var regType (Register.toRegID Register.CSR0975) "CSR0975" with get + member val CSR0976 = + var regType (Register.toRegID Register.CSR0976) "CSR0976" with get + member val CSR0977 = + var regType (Register.toRegID Register.CSR0977) "CSR0977" with get + member val CSR0978 = + var regType (Register.toRegID Register.CSR0978) "CSR0978" with get + member val CSR0979 = + var regType (Register.toRegID Register.CSR0979) "CSR0979" with get + member val CSR0980 = + var regType (Register.toRegID Register.CSR0980) "CSR0980" with get + member val CSR0981 = + var regType (Register.toRegID Register.CSR0981) "CSR0981" with get + member val CSR0982 = + var regType (Register.toRegID Register.CSR0982) "CSR0982" with get + member val CSR0983 = + var regType (Register.toRegID Register.CSR0983) "CSR0983" with get + member val CSR0984 = + var regType (Register.toRegID Register.CSR0984) "CSR0984" with get + member val CSR0985 = + var regType (Register.toRegID Register.CSR0985) "CSR0985" with get + member val CSR0986 = + var regType (Register.toRegID Register.CSR0986) "CSR0986" with get + member val CSR0987 = + var regType (Register.toRegID Register.CSR0987) "CSR0987" with get + member val CSR0988 = + var regType (Register.toRegID Register.CSR0988) "CSR0988" with get + member val CSR0989 = + var regType (Register.toRegID Register.CSR0989) "CSR0989" with get + member val CSR0990 = + var regType (Register.toRegID Register.CSR0990) "CSR0990" with get + member val CSR0991 = + var regType (Register.toRegID Register.CSR0991) "CSR0991" with get + member val CSR0992 = + var regType (Register.toRegID Register.CSR0992) "CSR0992" with get + member val CSR0993 = + var regType (Register.toRegID Register.CSR0993) "CSR0993" with get + member val CSR0994 = + var regType (Register.toRegID Register.CSR0994) "CSR0994" with get + member val CSR0995 = + var regType (Register.toRegID Register.CSR0995) "CSR0995" with get + member val CSR0996 = + var regType (Register.toRegID Register.CSR0996) "CSR0996" with get + member val CSR0997 = + var regType (Register.toRegID Register.CSR0997) "CSR0997" with get + member val CSR0998 = + var regType (Register.toRegID Register.CSR0998) "CSR0998" with get + member val CSR0999 = + var regType (Register.toRegID Register.CSR0999) "CSR0999" with get + member val CSR1000 = + var regType (Register.toRegID Register.CSR1000) "CSR1000" with get + member val CSR1001 = + var regType (Register.toRegID Register.CSR1001) "CSR1001" with get + member val CSR1002 = + var regType (Register.toRegID Register.CSR1002) "CSR1002" with get + member val CSR1003 = + var regType (Register.toRegID Register.CSR1003) "CSR1003" with get + member val CSR1004 = + var regType (Register.toRegID Register.CSR1004) "CSR1004" with get + member val CSR1005 = + var regType (Register.toRegID Register.CSR1005) "CSR1005" with get + member val CSR1006 = + var regType (Register.toRegID Register.CSR1006) "CSR1006" with get + member val CSR1007 = + var regType (Register.toRegID Register.CSR1007) "CSR1007" with get + member val CSR2145 = + var regType (Register.toRegID Register.CSR2145) "CSR2145" with get + member val CSR2617 = + var regType (Register.toRegID Register.CSR2617) "CSR2617" with get + member val CSR2816 = + var regType (Register.toRegID Register.CSR2816) "CSR2816" with get + member val CSR2818 = + var regType (Register.toRegID Register.CSR2818) "CSR2818" with get + member val CSR2819 = + var regType (Register.toRegID Register.CSR2819) "CSR2819" with get + member val CSR2820 = + var regType (Register.toRegID Register.CSR2820) "CSR2820" with get + member val CSR2821 = + var regType (Register.toRegID Register.CSR2821) "CSR2821" with get + member val CSR2822 = + var regType (Register.toRegID Register.CSR2822) "CSR2822" with get + member val CSR2823 = + var regType (Register.toRegID Register.CSR2823) "CSR2823" with get + member val CSR2824 = + var regType (Register.toRegID Register.CSR2824) "CSR2824" with get + member val CSR2825 = + var regType (Register.toRegID Register.CSR2825) "CSR2825" with get + member val CSR2826 = + var regType (Register.toRegID Register.CSR2826) "CSR2826" with get + member val CSR2827 = + var regType (Register.toRegID Register.CSR2827) "CSR2827" with get + member val CSR2828 = + var regType (Register.toRegID Register.CSR2828) "CSR2828" with get + member val CSR2829 = + var regType (Register.toRegID Register.CSR2829) "CSR2829" with get + member val CSR2830 = + var regType (Register.toRegID Register.CSR2830) "CSR2830" with get + member val CSR2831 = + var regType (Register.toRegID Register.CSR2831) "CSR2831" with get + member val CSR2832 = + var regType (Register.toRegID Register.CSR2832) "CSR2832" with get + member val CSR2833 = + var regType (Register.toRegID Register.CSR2833) "CSR2833" with get + member val CSR2834 = + var regType (Register.toRegID Register.CSR2834) "CSR2834" with get + member val CSR2835 = + var regType (Register.toRegID Register.CSR2835) "CSR2835" with get + member val CSR2836 = + var regType (Register.toRegID Register.CSR2836) "CSR2836" with get + member val CSR2837 = + var regType (Register.toRegID Register.CSR2837) "CSR2837" with get + member val CSR2838 = + var regType (Register.toRegID Register.CSR2838) "CSR2838" with get + member val CSR2839 = + var regType (Register.toRegID Register.CSR2839) "CSR2839" with get + member val CSR2840 = + var regType (Register.toRegID Register.CSR2840) "CSR2840" with get + member val CSR2841 = + var regType (Register.toRegID Register.CSR2841) "CSR2841" with get + member val CSR2842 = + var regType (Register.toRegID Register.CSR2842) "CSR2842" with get + member val CSR2843 = + var regType (Register.toRegID Register.CSR2843) "CSR2843" with get + member val CSR2844 = + var regType (Register.toRegID Register.CSR2844) "CSR2844" with get + member val CSR2845 = + var regType (Register.toRegID Register.CSR2845) "CSR2845" with get + member val CSR2846 = + var regType (Register.toRegID Register.CSR2846) "CSR2846" with get + member val CSR2847 = + var regType (Register.toRegID Register.CSR2847) "CSR2847" with get + member val CSR2945 = + var regType (Register.toRegID Register.CSR2945) "CSR2945" with get + member val CSR0800 = + var regType (Register.toRegID Register.CSR0800) "CSR0800" with get + member val CSR0803 = + var regType (Register.toRegID Register.CSR0803) "CSR0803" with get + member val CSR0804 = + var regType (Register.toRegID Register.CSR0804) "CSR0804" with get + member val CSR0805 = + var regType (Register.toRegID Register.CSR0805) "CSR0805" with get + member val CSR0806 = + var regType (Register.toRegID Register.CSR0806) "CSR0806" with get + member val CSR0807 = + var regType (Register.toRegID Register.CSR0807) "CSR0807" with get + member val CSR0808 = + var regType (Register.toRegID Register.CSR0808) "CSR0808" with get + member val CSR0809 = + var regType (Register.toRegID Register.CSR0809) "CSR0809" with get + member val CSR0810 = + var regType (Register.toRegID Register.CSR0810) "CSR0810" with get + member val CSR0811 = + var regType (Register.toRegID Register.CSR0811) "CSR0811" with get + member val CSR0812 = + var regType (Register.toRegID Register.CSR0812) "CSR0812" with get + member val CSR0813 = + var regType (Register.toRegID Register.CSR0813) "CSR0813" with get + member val CSR0814 = + var regType (Register.toRegID Register.CSR0814) "CSR0814" with get + member val CSR0815 = + var regType (Register.toRegID Register.CSR0815) "CSR0815" with get + member val CSR0816 = + var regType (Register.toRegID Register.CSR0816) "CSR0816" with get + member val CSR0817 = + var regType (Register.toRegID Register.CSR0817) "CSR0817" with get + member val CSR0818 = + var regType (Register.toRegID Register.CSR0818) "CSR0818" with get + member val CSR0819 = + var regType (Register.toRegID Register.CSR0819) "CSR0819" with get + member val CSR0820 = + var regType (Register.toRegID Register.CSR0820) "CSR0820" with get + member val CSR0821 = + var regType (Register.toRegID Register.CSR0821) "CSR0821" with get + member val CSR0822 = + var regType (Register.toRegID Register.CSR0822) "CSR0822" with get + member val CSR0823 = + var regType (Register.toRegID Register.CSR0823) "CSR0823" with get + member val CSR0824 = + var regType (Register.toRegID Register.CSR0824) "CSR0824" with get + member val CSR0825 = + var regType (Register.toRegID Register.CSR0825) "CSR0825" with get + member val CSR0826 = + var regType (Register.toRegID Register.CSR0826) "CSR0826" with get + member val CSR0827 = + var regType (Register.toRegID Register.CSR0827) "CSR0827" with get + member val CSR0828 = + var regType (Register.toRegID Register.CSR0828) "CSR0828" with get + member val CSR0829 = + var regType (Register.toRegID Register.CSR0829) "CSR0829" with get + member val CSR0830 = + var regType (Register.toRegID Register.CSR0830) "CSR0830" with get + member val CSR0831 = + var regType (Register.toRegID Register.CSR0831) "CSR0831" with get + member val CSR1952 = + var regType (Register.toRegID Register.CSR1952) "CSR1952" with get + member val CSR1953 = + var regType (Register.toRegID Register.CSR1953) "CSR1953" with get + member val CSR1954 = + var regType (Register.toRegID Register.CSR1954) "CSR1954" with get + member val CSR1955 = + var regType (Register.toRegID Register.CSR1955) "CSR1955" with get + member val CSR1968 = + var regType (Register.toRegID Register.CSR1968) "CSR1968" with get + member val CSR1969 = + var regType (Register.toRegID Register.CSR1969) "CSR1969" with get + member val CSR1970 = + var regType (Register.toRegID Register.CSR1970) "CSR1970" with get + member val CSR1971 = + var regType (Register.toRegID Register.CSR1971) "CSR1971" with get member __.GetRegVar (name) = match name with - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | R.PC -> __.PC + | R.RC -> __.RC + | R.X0 -> __.X0 + | R.X1 -> __.X1 + | R.X2 -> __.X2 + | R.X3 -> __.X3 + | R.X4 -> __.X4 + | R.X5 -> __.X5 + | R.X6 -> __.X6 + | R.X7 -> __.X7 + | R.X8 -> __.X8 + | R.X9 -> __.X9 + | R.X10 -> __.X10 + | R.X11 -> __.X11 + | R.X12 -> __.X12 + | R.X13 -> __.X13 + | R.X14 -> __.X14 + | R.X15 -> __.X15 + | R.X16 -> __.X16 + | R.X17 -> __.X17 + | R.X18 -> __.X18 + | R.X19 -> __.X19 + | R.X20 -> __.X20 + | R.X21 -> __.X21 + | R.X22 -> __.X22 + | R.X23 -> __.X23 + | R.X24 -> __.X24 + | R.X25 -> __.X25 + | R.X26 -> __.X26 + | R.X27 -> __.X27 + | R.X28 -> __.X28 + | R.X29 -> __.X29 + | R.X30 -> __.X30 + | R.X31 -> __.X31 + | R.F0 -> __.F0 + | R.F1 -> __.F1 + | R.F2 -> __.F2 + | R.F3 -> __.F3 + | R.F4 -> __.F4 + | R.F5 -> __.F5 + | R.F6 -> __.F6 + | R.F7 -> __.F7 + | R.F8 -> __.F8 + | R.F9 -> __.F9 + | R.F10 -> __.F10 + | R.F11 -> __.F11 + | R.F12 -> __.F12 + | R.F13 -> __.F13 + | R.F14 -> __.F14 + | R.F15 -> __.F15 + | R.F16 -> __.F16 + | R.F17 -> __.F17 + | R.F18 -> __.F18 + | R.F19 -> __.F19 + | R.F20 -> __.F20 + | R.F21 -> __.F21 + | R.F22 -> __.F22 + | R.F23 -> __.F23 + | R.F24 -> __.F24 + | R.F25 -> __.F25 + | R.F26 -> __.F26 + | R.F27 -> __.F27 + | R.F28 -> __.F28 + | R.F29 -> __.F29 + | R.F30 -> __.F30 + | R.F31 -> __.F31 + | R.FFLAGS -> __.FFLAGS + | R.FRM -> __.FRM + | R.FCSR -> __.FCSR + | R.CSR0768 -> __.CSR0768 + | R.CSR0769 -> __.CSR0769 + | R.CSR0770 -> __.CSR0770 + | R.CSR0771 -> __.CSR0771 + | R.CSR0772 -> __.CSR0772 + | R.CSR0773 -> __.CSR0773 + | R.CSR0784 -> __.CSR0784 + | R.CSR0832 -> __.CSR0832 + | R.CSR0833 -> __.CSR0833 + | R.CSR0834 -> __.CSR0834 + | R.CSR0835 -> __.CSR0835 + | R.CSR0836 -> __.CSR0836 + | R.CSR0842 -> __.CSR0842 + | R.CSR0843 -> __.CSR0843 + | R.CSR3114 -> __.CSR3114 + | R.CSR3787 -> __.CSR3787 + | R.CSR3857 -> __.CSR3857 + | R.CSR3858 -> __.CSR3858 + | R.CSR3859 -> __.CSR3859 + | R.CSR3860 -> __.CSR3860 + | R.CSR0928 -> __.CSR0928 + | R.CSR0930 -> __.CSR0930 + | R.CSR0932 -> __.CSR0932 + | R.CSR0934 -> __.CSR0934 + | R.CSR0936 -> __.CSR0936 + | R.CSR0938 -> __.CSR0938 + | R.CSR0940 -> __.CSR0940 + | R.CSR0942 -> __.CSR0942 + | R.CSR0944 -> __.CSR0944 + | R.CSR0945 -> __.CSR0945 + | R.CSR0946 -> __.CSR0946 + | R.CSR0947 -> __.CSR0947 + | R.CSR0948 -> __.CSR0948 + | R.CSR0949 -> __.CSR0949 + | R.CSR0950 -> __.CSR0950 + | R.CSR0951 -> __.CSR0951 + | R.CSR0952 -> __.CSR0952 + | R.CSR0953 -> __.CSR0953 + | R.CSR0954 -> __.CSR0954 + | R.CSR0955 -> __.CSR0955 + | R.CSR0956 -> __.CSR0956 + | R.CSR0957 -> __.CSR0957 + | R.CSR0958 -> __.CSR0958 + | R.CSR0959 -> __.CSR0959 + | R.CSR0960 -> __.CSR0960 + | R.CSR0961 -> __.CSR0961 + | R.CSR0962 -> __.CSR0962 + | R.CSR0963 -> __.CSR0963 + | R.CSR0964 -> __.CSR0964 + | R.CSR0965 -> __.CSR0965 + | R.CSR0966 -> __.CSR0966 + | R.CSR0967 -> __.CSR0967 + | R.CSR0968 -> __.CSR0968 + | R.CSR0969 -> __.CSR0969 + | R.CSR0970 -> __.CSR0970 + | R.CSR0971 -> __.CSR0971 + | R.CSR0972 -> __.CSR0972 + | R.CSR0973 -> __.CSR0973 + | R.CSR0974 -> __.CSR0974 + | R.CSR0975 -> __.CSR0975 + | R.CSR0976 -> __.CSR0976 + | R.CSR0977 -> __.CSR0977 + | R.CSR0978 -> __.CSR0978 + | R.CSR0979 -> __.CSR0979 + | R.CSR0980 -> __.CSR0980 + | R.CSR0981 -> __.CSR0981 + | R.CSR0982 -> __.CSR0982 + | R.CSR0983 -> __.CSR0983 + | R.CSR0984 -> __.CSR0984 + | R.CSR0985 -> __.CSR0985 + | R.CSR0986 -> __.CSR0986 + | R.CSR0987 -> __.CSR0987 + | R.CSR0988 -> __.CSR0988 + | R.CSR0989 -> __.CSR0989 + | R.CSR0990 -> __.CSR0990 + | R.CSR0991 -> __.CSR0991 + | R.CSR0992 -> __.CSR0992 + | R.CSR0993 -> __.CSR0993 + | R.CSR0994 -> __.CSR0994 + | R.CSR0995 -> __.CSR0995 + | R.CSR0996 -> __.CSR0996 + | R.CSR0997 -> __.CSR0997 + | R.CSR0998 -> __.CSR0998 + | R.CSR0999 -> __.CSR0999 + | R.CSR1000 -> __.CSR1000 + | R.CSR1001 -> __.CSR1001 + | R.CSR1002 -> __.CSR1002 + | R.CSR1003 -> __.CSR1003 + | R.CSR1004 -> __.CSR1004 + | R.CSR1005 -> __.CSR1005 + | R.CSR1006 -> __.CSR1006 + | R.CSR1007 -> __.CSR1007 + | R.CSR2145 -> __.CSR2145 + | R.CSR2617 -> __.CSR2617 + | R.CSR2816 -> __.CSR2816 + | R.CSR2818 -> __.CSR2818 + | R.CSR2819 -> __.CSR2819 + | R.CSR2820 -> __.CSR2820 + | R.CSR2821 -> __.CSR2821 + | R.CSR2822 -> __.CSR2822 + | R.CSR2823 -> __.CSR2823 + | R.CSR2824 -> __.CSR2824 + | R.CSR2825 -> __.CSR2825 + | R.CSR2826 -> __.CSR2826 + | R.CSR2827 -> __.CSR2827 + | R.CSR2828 -> __.CSR2828 + | R.CSR2829 -> __.CSR2829 + | R.CSR2830 -> __.CSR2830 + | R.CSR2831 -> __.CSR2831 + | R.CSR2832 -> __.CSR2832 + | R.CSR2833 -> __.CSR2833 + | R.CSR2834 -> __.CSR2834 + | R.CSR2835 -> __.CSR2835 + | R.CSR2836 -> __.CSR2836 + | R.CSR2837 -> __.CSR2837 + | R.CSR2838 -> __.CSR2838 + | R.CSR2839 -> __.CSR2839 + | R.CSR2840 -> __.CSR2840 + | R.CSR2841 -> __.CSR2841 + | R.CSR2842 -> __.CSR2842 + | R.CSR2843 -> __.CSR2843 + | R.CSR2844 -> __.CSR2844 + | R.CSR2845 -> __.CSR2845 + | R.CSR2846 -> __.CSR2846 + | R.CSR2847 -> __.CSR2847 + | R.CSR2945 -> __.CSR2945 + | R.CSR0800 -> __.CSR0800 + | R.CSR0803 -> __.CSR0803 + | R.CSR0804 -> __.CSR0804 + | R.CSR0805 -> __.CSR0805 + | R.CSR0806 -> __.CSR0806 + | R.CSR0807 -> __.CSR0807 + | R.CSR0808 -> __.CSR0808 + | R.CSR0809 -> __.CSR0809 + | R.CSR0810 -> __.CSR0810 + | R.CSR0811 -> __.CSR0811 + | R.CSR0812 -> __.CSR0812 + | R.CSR0813 -> __.CSR0813 + | R.CSR0814 -> __.CSR0814 + | R.CSR0815 -> __.CSR0815 + | R.CSR0816 -> __.CSR0816 + | R.CSR0817 -> __.CSR0817 + | R.CSR0818 -> __.CSR0818 + | R.CSR0819 -> __.CSR0819 + | R.CSR0820 -> __.CSR0820 + | R.CSR0821 -> __.CSR0821 + | R.CSR0822 -> __.CSR0822 + | R.CSR0823 -> __.CSR0823 + | R.CSR0824 -> __.CSR0824 + | R.CSR0825 -> __.CSR0825 + | R.CSR0826 -> __.CSR0826 + | R.CSR0827 -> __.CSR0827 + | R.CSR0828 -> __.CSR0828 + | R.CSR0829 -> __.CSR0829 + | R.CSR0830 -> __.CSR0830 + | R.CSR0831 -> __.CSR0831 + | R.CSR1952 -> __.CSR1952 + | R.CSR1953 -> __.CSR1953 + | R.CSR1954 -> __.CSR1954 + | R.CSR1955 -> __.CSR1955 + | R.CSR1968 -> __.CSR1968 + | R.CSR1969 -> __.CSR1969 + | R.CSR1970 -> __.CSR1970 + | R.CSR1971 -> __.CSR1971 + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Register.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Register.fs index 6829ada2..cb7bd66d 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64Register.fs +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Register.fs @@ -27,7 +27,308 @@ namespace B2R2.FrontEnd.BinLifter.RISCV open B2R2 type Register = - | R0 = 0x0 (* FIXME *) + /// zero - Hard-wired zero. + | X0 = 0x0 + /// ra - Return address. + | X1 = 0x1 + /// sp - Stack pointer. + | X2 = 0x2 + /// gp - Global pointer. + | X3 = 0x3 + /// tp - Thread pointer. + | X4 = 0x4 + /// t0 - Temporary/alternate link register. + | X5 = 0x5 + /// t1 - Temporary register. + | X6 = 0x6 + /// t2 - Temporary register. + | X7 = 0x7 + /// s0 or fp - Saved register/frame pointer. + | X8 = 0x8 + /// s1 - Saved register. + | X9 = 0x9 + /// a0 - Function argument/return value. + | X10 = 0xA + /// a1 - Function argument/return value. + | X11 = 0xB + /// a2 - Function argument. + | X12 = 0xC + /// a3 - Function argument. + | X13 = 0xD + /// a4 - Function argument. + | X14 = 0xE + /// a5 - Function argument. + | X15 = 0xF + /// a6 - Function argument. + | X16 = 0x10 + /// a7 - Function argument. + | X17 = 0x11 + /// s2 - Saved register. + | X18 = 0x12 + /// s3 - Saved register. + | X19 = 0x13 + /// s4 - Saved register. + | X20 = 0x14 + /// s5 - Saved register. + | X21 = 0x15 + /// s6 - Saved register. + | X22 = 0x16 + /// s7 - Saved register. + | X23 = 0x17 + /// s8 - Saved register. + | X24 = 0x18 + /// s9 - Saved register. + | X25 = 0x19 + /// s10 - Saved register. + | X26 = 0x1A + /// s11 - Saved registers + | X27 = 0x1B + /// t3 - Temporary register. + | X28 = 0x1C + /// t4 - Temporary register. + | X29 = 0x1D + /// t5 - Temporary register. + | X30 = 0x1E + /// t6 - Temporary register. + | X31 = 0x1F + /// ft0 - FP temporary register. + | F0 = 0x20 + /// ft1 - FP temporary register. + | F1 = 0x21 + /// ft2 - FP temporary register. + | F2 = 0x22 + /// ft3 - FP temporary register. + | F3 = 0x23 + /// ft4 - FP temporary register. + | F4 = 0x24 + /// ft5 - FP temporary register. + | F5 = 0x25 + /// ft6 - FP temporary register. + | F6 = 0x26 + /// ft7 - FP temporary register. + | F7 = 0x27 + /// fs0 - FP saved register. + | F8 = 0x28 + /// fs1 - FP saved register. + | F9 = 0x29 + /// fa0 - FP argument/return value. + | F10 = 0x2A + /// fa1 - FP argument/return value. + | F11 = 0x2B + /// fa2 - FP argument. + | F12 = 0x2C + /// fa3 - FP argument. + | F13 = 0x2D + /// fa4 - FP argument. + | F14 = 0x2E + /// fa5 - FP argument. + | F15 = 0x2F + /// fa6 - FP argument. + | F16 = 0x30 + /// fa7 - FP argument. + | F17 = 0x31 + /// fs2 - FP saved register. + | F18 = 0x32 + /// fs3 - FP saved register. + | F19 = 0x33 + /// fs4 - FP saved register. + | F20 = 0x34 + /// fs5 - FP saved register. + | F21 = 0x35 + /// fs6 - FP saved register. + | F22 = 0x36 + /// fs7 - FP saved register. + | F23 = 0x37 + /// fs8 - FP saved register. + | F24 = 0x38 + /// fs9 - FP saved register. + | F25 = 0x39 + /// fs10 - FP saved register. + | F26 = 0x3A + /// fs11 - FP saved register. + | F27 = 0x3B + /// ft8 - FP temporary register. + | F28 = 0x3C + /// ft9 - FP temporary register. + | F29 = 0x3D + /// ft10 - FP temporary register. + | F30 = 0x3E + /// ft11 - FP temporary register. + | F31 = 0x3F + /// Program Counter. + | PC = 0x40 + /// Floating point control and status register. + | FCSR = 0x41 + /// Floating-Point Accrued Exceptions. + | FFLAGS = 0x42 + | CSR0768 = 0x43 + | CSR0769 = 0x44 + | CSR0770 = 0x45 + | CSR0771 = 0x46 + | CSR0772 = 0x47 + | CSR0773 = 0x48 + | CSR0784 = 0x49 + | CSR0832 = 0x4A + | CSR0833 = 0x4B + | CSR0834 = 0x4C + | CSR0835 = 0x4D + | CSR0836 = 0x4E + | CSR0842 = 0x4F + | CSR0843 = 0x50 + | CSR3857 = 0x51 + | CSR3858 = 0x52 + | CSR3859 = 0x53 + | CSR3860 = 0x54 + | CSR0928 = 0x55 + | CSR0930 = 0x56 + | CSR0932 = 0x57 + | CSR0934 = 0x58 + | CSR0936 = 0x59 + | CSR0938 = 0x5A + | CSR0940 = 0x5B + | CSR0942 = 0x5C + | CSR0944 = 0x5D + | CSR0945 = 0x5E + | CSR0946 = 0x5F + | CSR0947 = 0x60 + | CSR0948 = 0x61 + | CSR0949 = 0x62 + | CSR0950 = 0x63 + | CSR0951 = 0x64 + | CSR0952 = 0x65 + | CSR0953 = 0x66 + | CSR0954 = 0x67 + | CSR0955 = 0x68 + | CSR0956 = 0x69 + | CSR0957 = 0x6A + | CSR0958 = 0x6B + | CSR0959 = 0x6C + | CSR0960 = 0x6D + | CSR0961 = 0x6E + | CSR0962 = 0x6F + | CSR0963 = 0x70 + | CSR0964 = 0x71 + | CSR0965 = 0x72 + | CSR0966 = 0x73 + | CSR0967 = 0x74 + | CSR0968 = 0x75 + | CSR0969 = 0x76 + | CSR0970 = 0x77 + | CSR0971 = 0x78 + | CSR0972 = 0x79 + | CSR0973 = 0x7A + | CSR0974 = 0x7B + | CSR0975 = 0x7C + | CSR0976 = 0x7D + | CSR0977 = 0x7E + | CSR0978 = 0x7F + | CSR0979 = 0x80 + | CSR0980 = 0x81 + | CSR0981 = 0x82 + | CSR0982 = 0x83 + | CSR0983 = 0x84 + | CSR0984 = 0x85 + | CSR0985 = 0x86 + | CSR0986 = 0x87 + | CSR0987 = 0x88 + | CSR0988 = 0x89 + | CSR0989 = 0x8A + | CSR0990 = 0x8B + | CSR0991 = 0x8C + | CSR0992 = 0x8D + | CSR0993 = 0x8E + | CSR0994 = 0x8F + | CSR0995 = 0x90 + | CSR0996 = 0x91 + | CSR0997 = 0x92 + | CSR0998 = 0x93 + | CSR0999 = 0x94 + | CSR1000 = 0x95 + | CSR1001 = 0x96 + | CSR1002 = 0x97 + | CSR1003 = 0x98 + | CSR1004 = 0x99 + | CSR1005 = 0x9A + | CSR1006 = 0x9B + | CSR1007 = 0x9C + | CSR2816 = 0x9D + | CSR2818 = 0x9E + | CSR2819 = 0x9F + | CSR2820 = 0xA0 + | CSR2821 = 0xA1 + | CSR2822 = 0xA2 + | CSR2823 = 0x103 + | CSR2824 = 0x104 + | CSR2825 = 0x105 + | CSR2826 = 0x106 + | CSR2827 = 0x107 + | CSR2828 = 0x108 + | CSR2829 = 0x109 + | CSR2830 = 0x10A + | CSR2831 = 0x10B + | CSR2832 = 0x10C + | CSR2833 = 0x10D + | CSR2834 = 0x10E + | CSR2835 = 0x10F + | CSR2836 = 0x110 + | CSR2837 = 0x111 + | CSR2838 = 0x112 + | CSR2839 = 0x113 + | CSR2840 = 0x114 + | CSR2841 = 0x115 + | CSR2842 = 0x116 + | CSR2843 = 0x117 + | CSR2844 = 0x118 + | CSR2845 = 0x119 + | CSR2846 = 0x11A + | CSR2847 = 0x11B + | CSR0800 = 0x11C + | CSR0803 = 0x11D + | CSR0804 = 0x11E + | CSR0805 = 0x11F + | CSR0806 = 0x120 + | CSR0807 = 0x121 + | CSR0808 = 0x122 + | CSR0809 = 0x123 + | CSR0810 = 0x124 + | CSR0811 = 0x125 + | CSR0812 = 0x126 + | CSR0813 = 0x127 + | CSR0814 = 0x128 + | CSR0815 = 0x129 + | CSR0816 = 0x12A + | CSR0817 = 0x12B + | CSR0818 = 0x12C + | CSR0819 = 0x12D + | CSR0820 = 0x12E + | CSR0821 = 0x12F + | CSR0822 = 0x130 + | CSR0823 = 0x131 + | CSR0824 = 0x132 + | CSR0825 = 0x133 + | CSR0826 = 0x134 + | CSR0827 = 0x135 + | CSR0828 = 0x136 + | CSR0829 = 0x137 + | CSR0830 = 0x138 + | CSR0831 = 0x139 + | CSR1952 = 0x13A + | CSR1953 = 0x13B + | CSR1954 = 0x13C + | CSR1955 = 0x13D + | CSR1968 = 0x13E + | CSR1969 = 0x13F + | CSR1970 = 0x140 + | CSR1971 = 0x141 + | CSR3787 = 0x142 + | CSR2617 = 0x143 + | CSR3114 = 0x144 + | CSR2145 = 0X145 + | CSR2945 = 0x146 + /// Floating-Point Dynamic Rounding Mode. + | FRM = 0x147 + /// Pseudo register for reservation check and follows the same format as ARM. + | RC = 0x148 /// Shortcut for Register type. type internal R = Register @@ -43,10 +344,157 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with - | "r0" -> R.R0 (* FIXME: Add Registers *) + match str.ToLowerInvariant () with + | "x0" -> R.X0 + | "x1" -> R.X1 + | "x2" -> R.X2 + | "x3" -> R.X3 + | "x4" -> R.X4 + | "x5" -> R.X5 + | "x6" -> R.X6 + | "x7" -> R.X7 + | "x8" -> R.X8 + | "x9" -> R.X9 + | "x10" -> R.X10 + | "x11" -> R.X11 + | "x12" -> R.X12 + | "x13" -> R.X13 + | "x14" -> R.X14 + | "x15" -> R.X15 + | "x16" -> R.X16 + | "x17" -> R.X17 + | "x18" -> R.X18 + | "x19" -> R.X19 + | "x20" -> R.X20 + | "x21" -> R.X21 + | "x22" -> R.X22 + | "x23" -> R.X23 + | "x24" -> R.X24 + | "x25" -> R.X25 + | "x26" -> R.X26 + | "x27" -> R.X27 + | "x28" -> R.X28 + | "x29" -> R.X29 + | "x30" -> R.X30 + | "x31" -> R.X31 + | "f0" -> R.F0 + | "f1" -> R.F1 + | "f2" -> R.F2 + | "f3" -> R.F3 + | "f4" -> R.F4 + | "f5" -> R.F5 + | "f6" -> R.F6 + | "f7" -> R.F7 + | "f8" -> R.F8 + | "f9" -> R.F9 + | "f10" -> R.F10 + | "f11" -> R.F11 + | "f12" -> R.F12 + | "f13" -> R.F13 + | "f14" -> R.F14 + | "f15" -> R.F15 + | "f16" -> R.F16 + | "f17" -> R.F17 + | "f18" -> R.F18 + | "f19" -> R.F19 + | "f20" -> R.F20 + | "f21" -> R.F21 + | "f22" -> R.F22 + | "f23" -> R.F23 + | "f24" -> R.F24 + | "f25" -> R.F25 + | "f26" -> R.F26 + | "f27" -> R.F27 + | "f28" -> R.F28 + | "f29" -> R.F29 + | "f30" -> R.F30 + | "f31" -> R.F31 + | "pc" -> R.PC + | "fcsr" -> R.FCSR + | "fflags" -> R.FFLAGS + | "frm" -> R.FRM + | "rc" -> R.RC | _ -> Utils.impossible () let toString = function - | R.R0 -> "r0" (* FIXME: Add Registers *) - | _ -> Utils.impossible () \ No newline at end of file + | R.X0 -> "zero" + | R.X1 -> "ra" + | R.X2 -> "sp" + | R.X3 -> "gp" + | R.X4 -> "tp" + | R.X5 -> "t0" + | R.X6 -> "t1" + | R.X7 -> "t2" + | R.X8 -> "s0" + | R.X9 -> "s1" + | R.X10 -> "a0" + | R.X11 -> "a1" + | R.X12 -> "a2" + | R.X13 -> "a3" + | R.X14 -> "a4" + | R.X15 -> "a5" + | R.X16 -> "a6" + | R.X17 -> "a7" + | R.X18 -> "s2" + | R.X19 -> "s3" + | R.X20 -> "s4" + | R.X21 -> "s5" + | R.X22 -> "s6" + | R.X23 -> "s7" + | R.X24 -> "s8" + | R.X25 -> "s9" + | R.X26 -> "s10" + | R.X27 -> "s11" + | R.X28 -> "t3" + | R.X29 -> "t4" + | R.X30 -> "t5" + | R.X31 -> "t6" + | R.F0 -> "ft0" + | R.F1 -> "ft1" + | R.F2 -> "ft2" + | R.F3 -> "ft3" + | R.F4 -> "ft4" + | R.F5 -> "ft5" + | R.F6 -> "ft6" + | R.F7 -> "ft7" + | R.F8 -> "fs0" + | R.F9 -> "fs1" + | R.F10 -> "fa0" + | R.F11 -> "fa1" + | R.F12 -> "fa2" + | R.F13 -> "fa3" + | R.F14 -> "fa4" + | R.F15 -> "fa5" + | R.F16 -> "fa6" + | R.F17 -> "fa7" + | R.F18 -> "fs2" + | R.F19 -> "fs3" + | R.F20 -> "fs4" + | R.F21 -> "fs5" + | R.F22 -> "fs6" + | R.F23 -> "fs7" + | R.F24 -> "fs8" + | R.F25 -> "fs9" + | R.F26 -> "fs10" + | R.F27 -> "fs11" + | R.F28 -> "ft8" + | R.F29 -> "ft9" + | R.F30 -> "ft10" + | R.F31 -> "ft11" + | R.FCSR -> "fcsr" + | R.FFLAGS -> "fflags" + | R.FRM -> "frm" + | R.RC -> "rc" + | _ -> Utils.impossible () + + let toRegType wordSize = function + | R.PC | R.X0 | R.X1 | R.X2 | R.X3 | R.X4 | R.X5 | R.X6 | R.X7 | R.X8 + | R.X9 | R.X10 | R.X11 | R.X12 | R.X13 | R.X14 | R.X15 | R.X16 | R.X17 + | R.X18 | R.X19 | R.X20 | R.X21 | R.X22 | R.X23 | R.X24 | R.X25 | R.X26 + | R.X27 | R.X28 | R.X29 | R.X30 | R.X31 -> WordSize.toRegType wordSize + | R.F0 | R.F1 | R.F2 | R.F3 | R.F4 | R.F5 | R.F6 | R.F7 | R.F8 | R.F9 + | R.F10 | R.F11 | R.F12 | R.F13 | R.F14 | R.F15 | R.F16 | R.F17 | R.F18 + | R.F19 | R.F20 | R.F21 | R.F22 | R.F23 | R.F24 | R.F25 | R.F26 | R.F27 + | R.F28 | R.F29 | R.F30 | R.F31 -> 64 + | R.FCSR | R.FFLAGS | R.FRM -> 32 + | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterFactory.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterFactory.fs new file mode 100644 index 00000000..984ba2c9 --- /dev/null +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterFactory.fs @@ -0,0 +1,159 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.RISCV + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type RISCV64RegisterFactory (wordSize, r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + [ r.X0; r.X1; r.X2; r.X3; r.X4; r.X5; r.X6; r.X7; r.X8; r.X9; r.X10; r.X11 + r.X12; r.X13; r.X14; r.X15; r.X16; r.X17; r.X18; r.X19; r.X20; r.X21 + r.X22; r.X23; r.X24; r.X25; r.X26; r.X27; r.X28; r.X29; r.X30; r.X31 + r.F0; r.F1; r.F2; r.F3; r.F4; r.F5; r.F6; r.F7; r.F8; r.F9; r.F10; r.F11 + r.F12; r.F13; r.F14; r.F15; r.F16; r.F17; r.F18; r.F19; r.F20; r.F21 + r.F22; r.F23; r.F24; r.F25; r.F26; r.F27; r.F28; r.F29; r.F30; r.F31 + r.PC; r.FCSR ] + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + [ r.X0; r.X1; r.X2; r.X3; r.X4; r.X5; r.X6; r.X7; r.X8; r.X9; r.X10; r.X11 + r.X12; r.X13; r.X14; r.X15; r.X16; r.X17; r.X18; r.X19; r.X20; r.X21 + r.X22; r.X23; r.X24; r.X25; r.X26; r.X27; r.X28; r.X29; r.X30; r.X31 ] + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_, id, _) -> id + | PCVar (_) -> Register.toRegID Register.PC + | _ -> raise InvalidRegisterException + + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> r.GetRegVar + + override __.StrToRegExpr s = + match s.ToLowerInvariant () with + | "x0" -> r.X0 + | "x1" -> r.X1 + | "x2" -> r.X2 + | "x3" -> r.X3 + | "x4" -> r.X4 + | "x5" -> r.X5 + | "x6" -> r.X6 + | "x7" -> r.X7 + | "x8" -> r.X8 + | "x9" -> r.X9 + | "x10" -> r.X10 + | "x11" -> r.X11 + | "x12" -> r.X12 + | "x13" -> r.X13 + | "x14" -> r.X14 + | "x15" -> r.X15 + | "x16" -> r.X16 + | "x17" -> r.X17 + | "x18" -> r.X18 + | "x19" -> r.X19 + | "x20" -> r.X20 + | "x21" -> r.X21 + | "x22" -> r.X22 + | "x23" -> r.X23 + | "x24" -> r.X24 + | "x25" -> r.X25 + | "x26" -> r.X26 + | "x27" -> r.X27 + | "x28" -> r.X28 + | "x29" -> r.X29 + | "x30" -> r.X30 + | "x31" -> r.X31 + | "f0" -> r.F0 + | "f1" -> r.F1 + | "f2" -> r.F2 + | "f3" -> r.F3 + | "f4" -> r.F4 + | "f5" -> r.F5 + | "f6" -> r.F6 + | "f7" -> r.F7 + | "f8" -> r.F8 + | "f9" -> r.F9 + | "f10" -> r.F10 + | "f11" -> r.F11 + | "f12" -> r.F12 + | "f13" -> r.F13 + | "f14" -> r.F14 + | "f15" -> r.F15 + | "f16" -> r.F16 + | "f17" -> r.F17 + | "f18" -> r.F18 + | "f19" -> r.F19 + | "f20" -> r.F20 + | "f21" -> r.F21 + | "f22" -> r.F22 + | "f23" -> r.F23 + | "f24" -> r.F24 + | "f25" -> r.F25 + | "f26" -> r.F26 + | "f27" -> r.F27 + | "f28" -> r.F28 + | "f29" -> r.F29 + | "f30" -> r.F30 + | "f31" -> r.F31 + | "pc" -> r.PC + | "fcsr" -> r.FCSR + | _ -> raise UnhandledRegExprException + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + Register.ofRegID rid |> Register.toRegType wordSize + + override __.GetRegisterAliases _rid = + Utils.futureFeature () + + override __.ProgramCounter = + Register.PC |> Register.toRegID + + override __.StackPointer = + Register.X30 |> Register.toRegID |> Some + + override __.FramePointer = + Register.X29 |> Register.toRegID |> Some + + override __.IsProgramCounter rid = + __.ProgramCounter = rid + + override __.IsStackPointer rid = + (__.StackPointer |> Option.get) = rid + + override __.IsFramePointer rid = + (__.FramePointer |> Option.get) = rid diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterSet.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterSet.fs deleted file mode 100644 index 64b0c82c..00000000 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterSet.fs +++ /dev/null @@ -1,59 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.RISCV - -open B2R2 - -module private RegisterSetLiteral = - let [] arrLen = 2 - -open RegisterSetLiteral - -type RISCV64RegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = - RISCV64RegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) - - override __.Tag = RegisterSetTag.RISCV64 - - override __.ArrSize = arrLen - - override __.New arr s = new RISCV64RegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | _ -> Utils.futureFeature () - - override __.IndexToRegID _index: RegisterID = - Utils.futureFeature () - - override __.ToString () = - sprintf "RISCV64RegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] - -[] -module RISCV64RegisterSet = - let singleton rid = RISCV64RegisterSet().Add(rid) - let empty = RISCV64RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64TranslationContext.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64TranslationContext.fs new file mode 100644 index 00000000..8920e9c7 --- /dev/null +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64TranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.RISCV + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for RISCV instructions. +type RISCV64TranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64Types.fs b/src/FrontEnd/BinLifter/RISCV/RISCV64Types.fs index c2cbf0eb..44cb8c40 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64Types.fs +++ b/src/FrontEnd/BinLifter/RISCV/RISCV64Types.fs @@ -36,18 +36,258 @@ do () /// file. /// type Opcode = - | ADD = 0 (* FIXME: Add Opcodes *) - | InvalOP = 500 + | LUI = 0 + | AUIPC = 1 + | JAL = 2 + | JALR = 3 + | BEQ = 4 + | BNE = 5 + | BLT = 6 + | BGE = 7 + | BLTU = 8 + | BGEU = 9 + | LB = 10 + | LH = 11 + | LW = 12 + | LBU = 13 + | LHU = 14 + | SB = 15 + | SH = 16 + | SW = 17 + | ADDI = 18 + | SLTI = 19 + | SLTIU = 20 + | XORI = 21 + | ORI = 22 + | ANDI = 23 + | ADD = 24 + | SUB = 25 + | SLL = 26 + | SLT = 27 + | SLTU = 28 + | XOR = 29 + | SRL = 30 + | SRA = 31 + | OR = 32 + | AND = 33 + | FENCE = 34 + | FENCEdotI = 35 + | ECALL = 36 + | EBREAK = 37 + | CSRRW = 38 + | CSRRS = 39 + | CSRRC = 40 + | CSRRWI = 41 + | CSRRSI = 42 + | CSRRCI = 43 + (* RV64I Base Instruction Set *) + | LWU = 44 + | LD = 45 + | SD = 46 + | SLLI = 47 + | SRLI = 48 + | SRAI = 49 + | ADDIW = 50 + | SLLIW = 51 + | SRLIW = 52 + | SRAIW = 53 + | ADDW = 54 + | SUBW = 55 + | SLLW = 56 + | SRLW = 57 + | SRAW = 58 + (* RV32M Standard Extension *) + | MUL = 59 + | MULH = 60 + | MULHSU = 61 + | MULHU = 62 + | DIV = 63 + | DIVU = 64 + | REM = 65 + | REMU = 66 + (* RV64M Standard Extension *) + | MULW = 67 + | DIVW = 68 + | DIVUW = 69 + | REMW = 70 + | REMUW = 71 + (* RV32A Standard Extension *) + | LRdotW = 72 + | SCdotW = 73 + | AMOSWAPdotW = 74 + | AMOADDdotW = 75 + | AMOXORdotW = 76 + | AMOANDdotW = 77 + | AMOORdotW = 78 + | AMOMINdotW = 79 + | AMOMAXdotW = 80 + | AMOMINUdotW = 81 + | AMOMAXUdotW = 82 + (* RV64A Standard Extension *) + | LRdotD = 83 + | SCdotD = 84 + | AMOSWAPdotD = 85 + | AMOADDdotD = 86 + | AMOXORdotD = 87 + | AMOANDdotD = 88 + | AMOORdotD = 89 + | AMOMINdotD = 90 + | AMOMAXdotD = 91 + | AMOMINUdotD = 92 + | AMOMAXUdotD = 93 + (* RV32F Standard Extension *) + | FLW = 94 + | FSW = 95 + | FMADDdotS = 96 + | FMSUBdotS = 97 + | FNMSUBdotS = 98 + | FNMADDdotS = 99 + | FADDdotS = 100 + | FSUBdotS = 101 + | FMULdotS = 102 + | FDIVdotS = 103 + | FSQRTdotS = 104 + | FSGNJdotS = 105 + | FSGNJNdotS = 106 + | FSGNJXdotS = 107 + | FMINdotS = 108 + | FMAXdotS = 109 + | FCVTdotWdotS = 110 + | FCVTdotWUdotS = 111 + | FMVdotXdotW = 112 + | FEQdotS = 113 + | FLTdotS = 114 + | FLEdotS = 115 + | FCLASSdotS = 116 + | FCVTdotSdotW = 117 + | FCVTdotSdotWU = 118 + | FMVdotWdotX = 119 + (* RV64F Standard Extension *) + | FCVTdotLdotS = 120 + | FCVTdotLUdotS = 121 + | FCVTdotSdotL = 122 + | FCVTdotSdotLU = 123 + (* RV32D Standard Extension *) + | FLD = 124 + | FSD = 125 + | FMADDdotD = 126 + | FMSUBdotD = 127 + | FNMSUBdotD = 128 + | FNMADDdotD = 129 + | FADDdotD = 130 + | FSUBdotD = 131 + | FMULdotD = 132 + | FDIVdotD = 133 + | FSQRTdotD = 134 + | FSGNJdotD = 135 + | FSGNJNdotD = 136 + | FSGNJXdotD = 137 + | FMINdotD = 138 + | FMAXdotD = 139 + | FCVTdotSdotD = 140 + | FCVTdotDdotS = 141 + | FEQdotD = 142 + | FLTdotD = 143 + | FLEdotD = 144 + | FCLASSdotD = 145 + | FCVTdotWdotD = 146 + | FCVTdotWUdotD = 147 + | FCVTdotDdotW = 148 + | FCVTdotDdotWU = 149 + (* RV64D Standard Extension *) + | FCVTdotLdotD = 150 + | FCVTdotLUdotD = 151 + | FMVdotXdotD = 152 + | FCVTdotDdotL = 153 + | FCVTdotDdotLU = 154 + | FMVdotDdotX = 155 + | FENCEdotTSO = 156 + (* RV64C Standard Extension *) + | CdotADDI4SPN = 157 + | CdotFLD = 158 + | CdotLW = 159 + | CdotLD = 160 + | CdotFSD = 161 + | CdotSW = 162 + | CdotSD = 163 + | CdotNOP = 164 + | CdotADDI = 165 + | CdotADDIW = 166 + | CdotLI = 167 + | CdotADDI16SP = 168 + | CdotLUI = 169 + | CdotSRLI = 170 + | CdotSRAI = 171 + | CdotANDI = 172 + | CdotSUB = 173 + | CdotXOR = 174 + | CdotOR = 175 + | CdotAND = 176 + | CdotSUBW = 177 + | CdotADDW = 178 + | CdotJ = 179 + | CdotBEQZ = 180 + | CdotBNEZ = 181 + | CdotSLLI = 182 + | CdotFLDSP = 183 + | CdotLWSP = 184 + | CdotLDSP = 185 + | CdotJR = 186 + | CdotMV = 187 + | CdotEBREAK = 188 + | CdotJALR = 189 + | CdotADD = 190 + | CdotFSDSP = 191 + | CdotSWSP = 192 + | CdotSDSP = 193 + | InvalOP = 194 type internal Op = Opcode +type RoundMode = + // Round to Nearest, ties to Even + | RNE = 0 + // Round towards Zero + | RTZ = 1 + // Round Down + | RDN = 2 + // Round Up + | RUP = 3 + // Round to Nearest, ties to Max Magnitude + | RMM = 4 + // In instruction's rm field selects dynamic mode; + // In Rounding Mode register, Invalid + | DYN = 7 + type Operand = | OpReg of Register + | OpImm of Imm + | OpMem of Base * Offset option * AccessLength + | OpAddr of JumpTarget + | OpShiftAmount of Imm + | OpFenceMask of FenceMask * FenceMask + | OpRoundMode of RoundMode + | OpAtomMemOper of Aq * Rl + | OpCSR of uint16 +and Aq = bool +and Rl = bool +and Imm = uint64 +and FenceMask = uint8 +and JumpTarget = + | Relative of int64 + | RelativeBase of Base * Imm +and Offset = + | Imm of int64 +and AccessLength = RegType +and Base = Register type Operands = | NoOperand | OneOperand of Operand | TwoOperands of Operand * Operand + | ThreeOperands of Operand * Operand * Operand + | FourOperands of Operand * Operand * Operand * Operand + | FiveOperands of Operand * Operand * Operand * Operand * Operand type internal Instruction = Opcode * Operands diff --git a/src/FrontEnd/BinLifter/S390/B2R2.FrontEnd.BinLifter.S390.fsproj b/src/FrontEnd/BinLifter/S390/B2R2.FrontEnd.BinLifter.S390.fsproj new file mode 100644 index 00000000..a0a5c493 --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/B2R2.FrontEnd.BinLifter.S390.fsproj @@ -0,0 +1,28 @@ + + + LICENSE.md + b2r2-240x240.png + README.md + B2R2 S390 frontend. + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MiddleEnd/DataFlow/README.md b/src/FrontEnd/BinLifter/S390/README.md similarity index 58% rename from src/MiddleEnd/DataFlow/README.md rename to src/FrontEnd/BinLifter/S390/README.md index a6c15799..0939bd18 100644 --- a/src/MiddleEnd/DataFlow/README.md +++ b/src/FrontEnd/BinLifter/S390/README.md @@ -1,4 +1,4 @@ -# B2R2.MiddleEnd.DataFlow +# B2R2.FrontEnd.BinLifter.S390 ### B2R2? @@ -6,7 +6,6 @@ B2R2 is a binary analysis and reversing framework written purely in F#. Since it does not rely on any native (unmanaged) code, it is readily usable in any platform or OS that .NET runs on. -### B2R2.MiddleEnd.DataFlow Package? +### B2R2.FrontEnd.BinLifter.S390 Package? -`B2R2.MiddleEnd.DataFlow` provides a fixpoint-based data-flow analysis -framework. +`B2R2.FrontEnd.BinLifter.S390` includes S390 parsers and lifters. diff --git a/src/FrontEnd/BinLifter/S390/S390Disasm.fs b/src/FrontEnd/BinLifter/S390/S390Disasm.fs new file mode 100644 index 00000000..3e9edc71 --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390Disasm.fs @@ -0,0 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.S390.Disasm + +// TODO Implement disasm logic diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64Instruction.fs b/src/FrontEnd/BinLifter/S390/S390Instruction.fs similarity index 85% rename from src/FrontEnd/BinLifter/Sparc64/Sparc64Instruction.fs rename to src/FrontEnd/BinLifter/S390/S390Instruction.fs index bfafdaf8..454b55f5 100644 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64Instruction.fs +++ b/src/FrontEnd/BinLifter/S390/S390Instruction.fs @@ -22,20 +22,22 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.Sparc64 +namespace B2R2.FrontEnd.BinLifter.S390 open B2R2 open B2R2.FrontEnd.BinLifter -/// The internal representation for a Sparc64 instruction used by our +/// The internal representation for a S390 instruction used by our /// disassembler and lifter. -type Sparc64Instruction (addr, insInfo) = - inherit Instruction (addr, 4u, WordSize.Bit32) +type S390Instruction (addr, numBytes, insInfo) = + inherit Instruction (addr, numBytes, WordSize.Bit32) /// Basic instruction information. member val Info: InsInfo = insInfo - override __.IsBranch () = Utils.futureFeature () + override __.IsBranch () = + match __.Info.Opcode with + | _ -> false override __.IsModeChanging () = false @@ -76,11 +78,13 @@ type Sparc64Instruction (addr, insInfo) = override __.IsNop () = Utils.futureFeature () - override __.Translate _ctxt = Utils.futureFeature () + override __.Translate ctxt = + Utils.futureFeature () - override __.TranslateToList _ctxt = Utils.futureFeature () + override __.TranslateToList ctxt = + Utils.futureFeature () - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = Utils.futureFeature () override __.Disasm () = diff --git a/src/FrontEnd/BinLifter/S390/S390Lifter.fs b/src/FrontEnd/BinLifter/S390/S390Lifter.fs new file mode 100644 index 00000000..43ecbdac --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390Lifter.fs @@ -0,0 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.S390.Lifter + +// TODO diff --git a/src/FrontEnd/BinLifter/S390/S390Parser.fs b/src/FrontEnd/BinLifter/S390/S390Parser.fs new file mode 100644 index 00000000..23725bcd --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390Parser.fs @@ -0,0 +1,46 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.S390 + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Parser for S390 instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type S39064Parser (isa: ISA) = + let wordSize = int isa.WordSize + let reader = BinReader.Init isa.Endian + + interface IInstructionParsable with + member __.Parse (span: ByteSpan, addr: Addr) = + Utils.futureFeature (): Instruction + + member __.Parse (bs: byte[], addr: Addr) = + Utils.futureFeature (): Instruction + + member __.MaxInstructionSize = 4 + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64Types.fs b/src/FrontEnd/BinLifter/S390/S390ParsingMain.fs similarity index 85% rename from src/FrontEnd/BinLifter/Sparc64/Sparc64Types.fs rename to src/FrontEnd/BinLifter/S390/S390ParsingMain.fs index be346f17..0fa0583c 100644 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64Types.fs +++ b/src/FrontEnd/BinLifter/S390/S390ParsingMain.fs @@ -22,18 +22,11 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.Sparc64 +module internal B2R2.FrontEnd.BinLifter.S390.ParsingMain open B2R2 -open System.Runtime.CompilerServices -[] -do () - - -type InsInfo = { - /// Address. - Address: Addr -} +let parse (span: ByteSpan) (reader: IBinReader) wordSize addr = + Utils.futureFeature () // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/S390/S390RegExprs.fs b/src/FrontEnd/BinLifter/S390/S390RegExprs.fs new file mode 100644 index 00000000..3929fb8d --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390RegExprs.fs @@ -0,0 +1,34 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.S390 + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingUtils +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp + +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64Register.fs b/src/FrontEnd/BinLifter/S390/S390Register.fs similarity index 85% rename from src/FrontEnd/BinLifter/Sparc64/Sparc64Register.fs rename to src/FrontEnd/BinLifter/S390/S390Register.fs index 11da7ce9..99912abb 100644 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64Register.fs +++ b/src/FrontEnd/BinLifter/S390/S390Register.fs @@ -22,17 +22,17 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.Sparc64 +namespace B2R2.FrontEnd.BinLifter.S390 open B2R2 type Register = - | G0 = 0x0 + | R0 = 0 // FIXME /// Shortcut for Register type. type internal R = Register -/// This module exposes several useful functions to handle Sparc64 +/// This module exposes several useful functions to handle s390/s390x /// registers. [] module Register = @@ -43,6 +43,9 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with - | "G0" -> R.G0 + match str.ToLowerInvariant () with + | "r0" -> R.R0 + | _ -> Utils.impossible () + + let toRegType wordSize = function | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinLifter/S390/S390RegisterFactory.fs b/src/FrontEnd/BinLifter/S390/S390RegisterFactory.fs new file mode 100644 index 00000000..f291802b --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390RegisterFactory.fs @@ -0,0 +1,81 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.S390 + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type S39064RegisterFactory (wordSize, r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + Utils.futureFeature () + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + Utils.futureFeature () + + override __.RegIDFromRegExpr (e) = + Utils.futureFeature () + + override __.RegIDToRegExpr (id) = + Utils.futureFeature () + + override __.StrToRegExpr s = + Utils.futureFeature () + + override __.RegIDFromString str = + Utils.futureFeature () + + override __.RegIDToString rid = + Utils.futureFeature () + + override __.RegIDToRegType rid = + Utils.futureFeature () + + override __.GetRegisterAliases _rid = + Utils.futureFeature () + + override __.ProgramCounter = + Utils.futureFeature () + + override __.StackPointer = + Utils.futureFeature () + + override __.FramePointer = + Utils.futureFeature () + + override __.IsProgramCounter rid = + Utils.futureFeature () + + override __.IsStackPointer rid = + Utils.futureFeature () + + override __.IsFramePointer rid = + Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/S390/S390TranslationContext.fs b/src/FrontEnd/BinLifter/S390/S390TranslationContext.fs new file mode 100644 index 00000000..a57727f3 --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390TranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.S390 + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for S390 instructions. +type S390TranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Utils.futureFeature () + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/S390/S390Types.fs b/src/FrontEnd/BinLifter/S390/S390Types.fs new file mode 100644 index 00000000..32bd301a --- /dev/null +++ b/src/FrontEnd/BinLifter/S390/S390Types.fs @@ -0,0 +1,82 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.S390 + +open B2R2 +open System.Runtime.CompilerServices + +[] +do () + +/// +/// S390 opcodes. This type should be generated using +/// scripts/genOpcode.fsx from the `S39064SupportedOpcode.txt` +/// file. +/// +type Opcode = + | MyOp = 0 // FIXME + +type internal Op = Opcode + +type Operand = + | MyOpr // FIXME + +type Operands = + | NoOperand + | OneOperand of Operand + | TwoOperands of Operand * Operand + +/// Basic information obtained by parsing a S390 instruction. +[] +type InsInfo = { + /// Address. + Address: Addr + /// Instruction length. + NumBytes: uint32 + /// Opcode. + Opcode: Opcode + /// Operands. + Operands: Operands + /// Operation Size. + OperationSize: RegType +} +with + override __.GetHashCode () = + hash (__.Address, + __.NumBytes, + __.Opcode, + __.Operands, + __.OperationSize) + override __.Equals (i) = + match i with + | :? InsInfo as i -> + i.Address = __.Address + && i.NumBytes = __.NumBytes + && i.Opcode = __.Opcode + && i.Operands = __.Operands + && i.OperationSize = __.OperationSize + | _ -> false + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.fsproj b/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.fsproj index 952db71a..e7351cf3 100644 --- a/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.fsproj +++ b/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.fsproj @@ -9,15 +9,15 @@ - - - + + + - + diff --git a/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.sln b/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.sln deleted file mode 100644 index 6067d1c9..00000000 --- a/src/FrontEnd/BinLifter/SH4/B2R2.FrontEnd.BinLifter.SH4.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32210.238 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "B2R2.FrontEnd.BinLifter.SH4", "B2R2.FrontEnd.BinLifter.SH4.fsproj", "{1E28F796-09C4-4463-9AF7-BA33C50D987E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1E28F796-09C4-4463-9AF7-BA33C50D987E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E28F796-09C4-4463-9AF7-BA33C50D987E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E28F796-09C4-4463-9AF7-BA33C50D987E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E28F796-09C4-4463-9AF7-BA33C50D987E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EAED6D63-F30E-4207-9DDA-C93415B82232} - EndGlobalSection -EndGlobal diff --git a/src/FrontEnd/BinLifter/SH4/SH4.fs b/src/FrontEnd/BinLifter/SH4/SH4.fs deleted file mode 100644 index 6a9e8f6d..00000000 --- a/src/FrontEnd/BinLifter/SH4/SH4.fs +++ /dev/null @@ -1,63 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.SH4 - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -type SH4TranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - - override __.GetPseudoRegVar _id _pos = Utils.impossible () - -type SH4Parser (isa: ISA) = - inherit Parser () - - let reader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - - override __.Parse (span: ByteSpan, addr: Addr) = - Parser.parse span reader addr :> Instruction - - override __.Parse (bs: byte[], addr: Addr) = - let span = ReadOnlySpan bs - __.Parse (span, addr) - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - -module Basis = - let init isa = - let regexprs = RegExprs (isa.WordSize) - struct ( - SH4TranslationContext (isa, regexprs) :> TranslationContext, - SH4RegisterBay () :> RegisterBay - ) diff --git a/src/FrontEnd/BinLifter/SH4/SH4Disassembly.fs b/src/FrontEnd/BinLifter/SH4/SH4Disasm.fs similarity index 93% rename from src/FrontEnd/BinLifter/SH4/SH4Disassembly.fs rename to src/FrontEnd/BinLifter/SH4/SH4Disasm.fs index 3619346b..4f51a02c 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4Disassembly.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4Disasm.fs @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.SH4.Disassembly +module B2R2.FrontEnd.BinLifter.SH4.Disasm open B2R2 open B2R2.FrontEnd.BinLifter @@ -159,28 +159,28 @@ let opCodeToString = function | Opcode.InvalidOp -> "(invalid)" | _ -> Utils.impossible() -let prepDelim delim (builder: DisasmBuilder<_>) = +let prepDelim delim (builder: DisasmBuilder) = match delim with | None -> () | Some delimiter -> builder.Accumulate AsmWordKind.String delimiter -let immToStr imm (builder: DisasmBuilder<_>) = - builder.Accumulate AsmWordKind.Value (String.i32ToHex imm) +let immToStr imm (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 imm) -let addrToStr shift addr (builder: DisasmBuilder<_>) = +let addrToStr shift addr (builder: DisasmBuilder) = let relAddr = int(addr) + shift + 4 if shift >= 0 then builder.Accumulate AsmWordKind.String ".+" builder.Accumulate AsmWordKind.Value (string shift) builder.Accumulate AsmWordKind.String " ; " - builder.Accumulate AsmWordKind.Value (String.i32ToHex relAddr) + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 relAddr) else builder.Accumulate AsmWordKind.String "." builder.Accumulate AsmWordKind.Value (string shift) builder.Accumulate AsmWordKind.String " ; " - builder.Accumulate AsmWordKind.Value (String.i32ToHex relAddr) + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 relAddr) -let memToStr addrMode (builder: DisasmBuilder<_>) = +let memToStr addrMode (builder: DisasmBuilder) = match addrMode with | Regdir reg -> let reg = Register.toString reg @@ -248,7 +248,7 @@ let memToStr addrMode (builder: DisasmBuilder<_>) = builder.Accumulate AsmWordKind.Value (string imm) | _ -> raise InvalidOperandException -let buildReg ins reg (builder: DisasmBuilder<_>) = +let buildReg ins reg (builder: DisasmBuilder) = let reg = Register.toString reg builder.Accumulate AsmWordKind.Variable reg @@ -277,7 +277,7 @@ let buildOp ins pc builder = opToStr ins pc opr2 (Some ",") builder opToStr ins pc opr3 (Some ",") builder -let inline buildOpcode ins (builder: DisasmBuilder<_>) = +let inline buildOpcode ins (builder: DisasmBuilder) = let str = opCodeToString ins.Opcode builder.Accumulate AsmWordKind.Mnemonic str if String.length str = 2 then builder.Accumulate AsmWordKind.String " " @@ -287,7 +287,7 @@ let inline buildOpcode ins (builder: DisasmBuilder<_>) = elif String.length str = 6 then builder.Accumulate AsmWordKind.String " " else builder.Accumulate AsmWordKind.String "" -let disas insInfo (builder: DisasmBuilder<_>) = +let disas insInfo (builder: DisasmBuilder) = let pc = insInfo.Address if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode insInfo builder diff --git a/src/FrontEnd/BinLifter/SH4/SH4GeneralLifter.fs b/src/FrontEnd/BinLifter/SH4/SH4GeneralLifter.fs index c61367b0..dce04157 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4GeneralLifter.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4GeneralLifter.fs @@ -34,13 +34,13 @@ open B2R2.FrontEnd.BinLifter open B2R2.FrontEnd.BinLifter.LiftingOperators open B2R2.FrontEnd.BinLifter.SH4 -let delaySlot = new List() +let delaySlot = List() -let numI32 n = BitVector.ofInt32 n 32 |> AST.num +let numI32 n = BitVector.OfInt32 n 32 |> AST.num -let numI32PC n = BitVector.ofInt32 n 32 |> AST.num +let numI32PC n = BitVector.OfInt32 n 32 |> AST.num -let numI64 n = BitVector.ofInt64 n 16 |> AST.num +let numI64 n = BitVector.OfInt64 n 16 |> AST.num let exprToInt (n: Expr) = match n.E with @@ -48,7 +48,7 @@ let exprToInt (n: Expr) = | _ -> Utils.impossible() let bv1Check s = - exprToInt s |> BitVector.isOne + exprToInt s |> BitVector.IsOne let inline (!.) (ctxt: TranslationContext) reg = Register.toRegID reg |> ctxt.GetRegVar @@ -113,13 +113,13 @@ let trsMemOpr4toExpr ins ctxt = | _ -> Utils.impossible() let inline tmpVars2 ir t = - struct (!*ir t, !*ir t) + struct (!+ir t, !+ir t) let inline tmpVars3 ir t = - struct (!*ir t, !*ir t, !*ir t) + struct (!+ir t, !+ir t, !+ir t) let inline tmpVars4 ir t = - struct (!*ir t, !*ir t, !*ir t, !*ir t) + struct (!+ir t, !+ir t, !+ir t, !+ir t) let illSlot1 ir len ctxt = !) (n)) then true else false + bv1Check (AST.extract (fps) (1) (n)) let signedSaturate r = - AST.ite ((r ?< numI32 (int ((-2.0)**32))) .| (r ?> numI32 (int ((2.0)**32)))) ( - AST.ite ((r ?< numI32 (int ((-2.0)**32)))) (numI32 (int ((-2.0)**32))) ( - numI32 (int ((2.0)**32)))) (r) + AST.ite ((r ?< numI32 (int ((-2.0)**32))) .| (r ?> numI32 (int ((2.0)**32)))) + (AST.ite ((r ?< numI32 (int ((-2.0)**32)))) + (numI32 (int ((-2.0)**32))) (numI32 (int ((2.0)**32)))) + (r) /// Carry Forward check let cfonAdd e1 e2 r = @@ -234,15 +235,15 @@ let add ins len ctxt = match src.E with | Num n -> let ir = IRBuilder (8) - let t1 = !*ir 8 - let t2 = !*ir 32 + let t1 = !+ir 8 + let t2 = !+ir 32 ! AST.num |> AST.sext 8) !!ir (t2 := dst |> AST.sext 32) !!ir (t2 := t2 .+ t1) !!ir (dst := t2) !>ir len - | Var (_,_,s,_) -> + | Var (_, _, s) -> let oprSize = 32 let ir = IRBuilder (8) let struct (t1, t2) = tmpVars2 ir oprSize @@ -259,7 +260,7 @@ let addc ins len ctxt = let oprSize = 32 let ir = IRBuilder (16) let struct (t1,t2) = tmpVars2 ir oprSize - let t = !*ir 1 + let t = !+ir 1 ! (!.ctxt R.T)) !!ir (t1 := AST.zext 32 <| AST.sext 32 src) @@ -275,7 +276,7 @@ let addv ins len ctxt = let oprSize = 32 let ir = IRBuilder (8) let struct (t1,t2) = tmpVars2 ir oprSize - let t = !*ir 1 + let t = !+ir 1 ! src) !!ir (t2 := AST.sext 32 dst) @@ -290,15 +291,15 @@ let ``and`` ins len ctxt = match src.E with | Num n -> let ir = IRBuilder (8) - let t1 = !*ir 8 - let t2 = !*ir 32 + let t1 = !+ir 8 + let t2 = !+ir 32 ! AST.num |> AST.zext 8) !!ir (t2 := AST.zext 32 dst) !!ir (t2 := t2 .& t1) !!ir (dst := AST.xtlo 32 t2) !>ir len - | Var (_,_,s,_) -> + | Var (_, _, s) -> let oprSize = 32 let ir = IRBuilder (8) let struct (t1,t2) = tmpVars2 ir oprSize @@ -328,9 +329,9 @@ let andb ins len ctxt = let bfHelper ir ins len ctxt = let disp = trsOneOpr ins ctxt let struct (pc, newPC, delayedPC) = tmpVars3 ir 32 - let t = !*ir 1 - let label = !*ir 8 - let temp = !*ir 32 + let t = !+ir 1 + let label = !+ir 8 + let temp = !+ir 32 ! AST.zext 1) !!ir (pc := !.ctxt R.PC |> AST.sext 32) @@ -352,9 +353,9 @@ let bf ins len ctxt = let bfsHelper ir ins len ctxt = let disp = trsOneOpr ins ctxt let struct (pc, delayedPC) = tmpVars2 ir 32 - let t = !*ir 1 - let label = !*ir 8 - let temp = !*ir 32 + let t = !+ir 1 + let label = !+ir 8 + let temp = !+ir 32 ! AST.zext 1) !!ir (pc := !.ctxt R.PC |> AST.sext 32) @@ -377,7 +378,7 @@ let bfs ins len ctxt = let braHelper ir ins len ctxt = let disp = trsOneOpr ins ctxt let struct (pc, temp, delayedPC) = tmpVars3 ir 32 - let label = !*ir 12 + let label = !+ir 12 ! pc) !!ir (label := AST.sext 12 disp) @@ -418,7 +419,7 @@ let braf ins len ctxt = let bsrHelper ir ins len ctxt = let disp = trsOneOpr ins ctxt let struct (pc, delayedPR, temp, delayedPC) = tmpVars4 ir 32 - let label = !*ir 12 + let label = !+ir 12 ! AST.sext 32) !!ir (label := (AST.sext 32 disp) << AST.b1) @@ -441,7 +442,7 @@ let bsr ins len ctxt = let bsrfHelper ir ins len ctxt = let dst = trsOneOpr ins ctxt let struct (pc, delayedPR, op1, delayedPC) = tmpVars4 ir 32 - let target = !*ir 32 + let target = !+ir 32 ! AST.sext 32) !!ir (op1 := AST.sext 32 dst) @@ -464,8 +465,8 @@ let bsrf ins len ctxt = let btHelper ir ins len ctxt = let disp = trsOneOpr ins ctxt let struct (pc, newPC, delayedPC, temp) = tmpVars4 ir 32 - let t = !*ir 1 - let label = !*ir 8 + let t = !+ir 1 + let label = !+ir 8 ! AST.zext 1) !!ir (pc := !.ctxt R.PC |> AST.sext 32) @@ -487,8 +488,8 @@ let bt ins len ctxt = let btsHelper ir ins len ctxt = let disp = trsOneOpr ins ctxt let struct (pc, delayedPC, temp) = tmpVars3 ir 32 - let t = !*ir 1 - let label = !*ir 8 + let t = !+ir 1 + let label = !+ir 8 ! AST.zext 1) !!ir (pc := !.ctxt R.PC |> AST.sext 32) @@ -520,7 +521,7 @@ let clrmac ins len ctxt = let clrs len ctxt = let ir = IRBuilder (4) - let s = !*ir 1 + let s = !+ir 1 ! 1) @@ -528,7 +529,7 @@ let clrs len ctxt = let clrt len ctxt = let ir = IRBuilder (4) - let t = !*ir 1 + let t = !+ir 1 ! 1) @@ -539,19 +540,19 @@ let cmpeq ins len ctxt = match src.E with | Num n -> let ir = IRBuilder (8) - let r0 = !*ir 32 - let imm = !*ir 8 - let t = !*ir 1 + let r0 = !+ir 32 + let imm = !+ir 8 + let t = !+ir 1 ! (!.ctxt R.R0)) !!ir (imm := AST.sext 8 (AST.num n)) !!ir (t := r0 == imm) !!ir (!.ctxt R.T := AST.extract t 1 1) !>ir len - | Var (_,_,r,_) -> + | Var (_, _, r) -> let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! Register.ofString |> !.ctxt |> AST.sext 32)) !!ir (op2 := AST.sext 32 dst) @@ -564,7 +565,7 @@ let cmpge ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! AST.sext 32) !!ir (op2 := AST.sext 32 dst) @@ -576,7 +577,7 @@ let cmpgt ins len ctxt= let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! AST.sext 32) !!ir (op2 := AST.sext 32 dst) @@ -588,7 +589,7 @@ let cmphi ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! AST.zext 32) !!ir (op2 := AST.zext 32 dst) @@ -600,7 +601,7 @@ let cmphs ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! AST.zext 32) !!ir (op2 := AST.zext 32 dst) @@ -611,8 +612,8 @@ let cmphs ins len ctxt = let cmppl ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (4) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (t := op1 ?> AST.b0) @@ -622,8 +623,8 @@ let cmppl ins len ctxt = let cmppz ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (t := op1 ?>= AST.b0) @@ -634,7 +635,7 @@ let cmpstr ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (op1, op2, temp) = tmpVars3 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! src) !!ir (op2 := AST.sext 32 dst) @@ -678,7 +679,7 @@ let div1 ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (q, m, t) = tmpVars3 ir 1 - let oldq = !*ir 1 + let oldq = !+ir 1 let struct (op1, op2) = tmpVars2 ir 32 ! AST.zext 1) @@ -701,7 +702,7 @@ let dmulsl ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (op1, op2) = tmpVars2 ir 32 - let mac = !*ir 64 + let mac = !+ir 64 let struct (macl, mach) = tmpVars2 ir 32 ! src) @@ -717,7 +718,7 @@ let dmulul ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (op1, op2) = tmpVars2 ir 32 - let mac = !*ir 64 + let mac = !+ir 64 let struct (macl, mach) = tmpVars2 ir 32 ! src |> AST.zext 32) @@ -732,8 +733,8 @@ let dmulul ins len ctxt = let dt ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (op1 := op1 .- AST.b1) @@ -786,7 +787,7 @@ let fabs ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (16) match dst.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> if s.StartsWith "fr" then let struct (sr, op1) = tmpVars2 ir 32 !ir len else - let sr = !*ir 32 - let op1 = !*ir 64 + let sr = !+ir 32 + let op1 = !+ir 64 ! AST.zext 32) !!ir (op1 := dst) @@ -812,7 +813,7 @@ let fadd ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) match src.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> if s.StartsWith "fr" then let struct (sr, fps, op1, op2) = tmpVars4 ir 32 ! + let t = !+ir 1 match src.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> if s.StartsWith "fr" then let struct (sr, fps, op1, op2) = tmpVars4 ir 32 ! + let t = !+ir 1 match src.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> if s.StartsWith "fr" then let struct (sr, fps, op1, op2) = tmpVars4 ir 32 ! - let op1 = !*ir 64 + let op1 = !+ir 64 ! AST.zext 32) !!ir (fps := !.ctxt R.FPSCR |> AST.zext 32) @@ -949,7 +950,7 @@ let fcnvsd ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (sr, fps, fpul) = tmpVars3 ir 32 - let op1 = !*ir 64 + let op1 = !+ir 64 ! AST.zext 32) !!ir (fps := !.ctxt R.FPSCR |> AST.zext 32) @@ -966,7 +967,7 @@ let fdiv ins len ctxt = let struct (sr, fps) = tmpVars2 ir 32 let struct (op1, op2) = match src.E with - | Var (_,_,r,_) -> + | Var (_, _, r) -> if r.StartsWith "dr" then tmpVars2 ir 64 else @@ -1031,7 +1032,7 @@ let ``float`` ins len ctxt = let ir = IRBuilder (16) let mode = match dst.E with - | Var (_,_,r,_) -> + | Var (_, _, r) -> if r.StartsWith "DR" then 64 else 32 | _ -> Utils.impossible() let struct (fpul, sr, fps, op1) = tmpVars4 ir 32 @@ -1040,7 +1041,7 @@ let ``float`` ins len ctxt = !!ir (sr := !.ctxt R.SR |> AST.zext 32) !!ir (fps := !.ctxt R.FPSCR |> AST.zext 32) fpudisChecker ir ctxt - !!ir (op1 := AST.cast CastKind.IntToFloat mode fpul) + !!ir (op1 := AST.cast CastKind.SIntToFloat mode fpul) !!ir (dst := op1) !>ir len @@ -1117,7 +1118,7 @@ let fmul ins len ctxt = let struct (sr, fps) = tmpVars2 ir 32 let struct (op1, op2) = match src.E with - | Var (_,_,r,_) -> + | Var (_, _, r) -> if r.StartsWith "FR" then tmpVars2 ir 32 else tmpVars2 ir 64 @@ -1141,14 +1142,13 @@ let fmul ins len ctxt = let fneg ins len ctxt = let (dst) = trsOneOpr ins ctxt let ir = IRBuilder (16) - let sr = !*ir 32 - let fps = !*ir 32 + let sr = !+ir 32 + let fps = !+ir 32 let mode = match dst.E with - | Var (_,_,r,_) -> - if r.StartsWith "DR" then true else false + | Var (_, _, r) -> r.StartsWith "DR" | _ -> Utils.impossible() - let op1 = if mode then !*ir 64 else !*ir 32 + let op1 = if mode then !+ir 64 else !+ir 32 ! AST.zext 32) if mode then () else (!!ir (fps := !.ctxt R.FPSCR |> AST.zext 32)) @@ -1160,8 +1160,8 @@ let fneg ins len ctxt = let frchg ins len ctxt = let ir = IRBuilder (16) - let sr = !*ir 32 - let fr = !*ir 1 + let sr = !+ir 32 + let fr = !+ir 1 ! AST.zext 32) !!ir (fr := !.ctxt R.FPSCR_FR |> AST.zext 1) @@ -1172,8 +1172,8 @@ let frchg ins len ctxt = let fschg ins len ctxt = let ir = IRBuilder (16) - let sr = !*ir 32 - let fr = !*ir 1 + let sr = !+ir 32 + let fr = !+ir 1 ! AST.zext 32) !!ir (fr := !.ctxt R.FPSCR_SZ |> AST.zext 1) @@ -1188,10 +1188,9 @@ let fsqrt ins len ctxt = let struct (sr, fps) = tmpVars2 ir 32 let mode = match dst.E with - | Var (_,_,r,_) -> - if r.StartsWith "DR" then true else false + | Var (_, _, r) -> r.StartsWith "DR" | _ -> Utils.impossible() - let op1 = if mode then !*ir 64 else !*ir 32 + let op1 = if mode then !+ir 64 else !+ir 32 ! AST.zext 32) !!ir (fps := !.ctxt R.FPSCR |> AST.zext 32) @@ -1222,7 +1221,7 @@ let fsub ins len ctxt = let ir = IRBuilder (16) let mode = match dst.E with - | Var (_,_,r,_) -> r.StartsWith "DR" + | Var (_, _, r) -> r.StartsWith "DR" | _ -> Utils.impossible() let struct (sr, fps) = tmpVars2 ir 32 let struct (op1, op2) = @@ -1249,10 +1248,9 @@ let ftrc ins len ctxt = let struct (sr, fps, fpul) = tmpVars3 ir 32 let mode = match dst.E with - | Var (_,_,r,_) -> - if r.StartsWith "DR" then true else false + | Var (_, _, r) -> r.StartsWith "DR" | _ -> Utils.impossible() - let op1 = if mode then !*ir 64 else !*ir 32 + let op1 = if mode then !+ir 64 else !+ir 32 ! AST.zext 32) !!ir (fps := !.ctxt R.FPSCR |> AST.zext 32) @@ -1315,7 +1313,7 @@ let ldc ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) match dst.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> match s with | "gbr" -> let struct (op1, gbr) = tmpVars2 ir 32 @@ -1326,7 +1324,7 @@ let ldc ins len ctxt = !>ir len | "sr" -> let struct (op1, sr) = tmpVars2 ir 32 - let md = !*ir 1 + let md = !+ir 1 ! !.ctxt |> AST.zext 1) if bv1Check md then () else resinst ir ctxt @@ -1336,7 +1334,7 @@ let ldc ins len ctxt = !>ir len | "vbr" -> let struct (op1, vbr) = tmpVars2 ir 32 - let md = !*ir 1 + let md = !+ir 1 ! !.ctxt |> AST.zext 1) if bv1Check md then () else resinst ir ctxt @@ -1346,7 +1344,7 @@ let ldc ins len ctxt = !>ir len | "ssr" -> let struct (op1, ssr) = tmpVars2 ir 32 - let md = !*ir 1 + let md = !+ir 1 ! !.ctxt |> AST.zext 1) if bv1Check md then () else resinst ir ctxt @@ -1356,7 +1354,7 @@ let ldc ins len ctxt = !>ir len | "spc" -> let struct (op1, spc) = tmpVars2 ir 32 - let md = !*ir 1 + let md = !+ir 1 ! !.ctxt |> AST.zext 1) if bv1Check md then () else resinst ir ctxt @@ -1366,7 +1364,7 @@ let ldc ins len ctxt = !>ir len | "dbr" -> let struct (op1, dbr) = tmpVars2 ir 32 - let md = !*ir 1 + let md = !+ir 1 ! !.ctxt |> AST.zext 1) if bv1Check md then () else resinst ir ctxt @@ -1375,14 +1373,14 @@ let ldc ins len ctxt = !!ir (!.ctxt R.DBR := AST.xtlo 32 dbr) !>ir len | _ -> - let struct (op1, rn_Bank) = tmpVars2 ir 32 - let md = !*ir 1 + let struct (op1, rnBank) = tmpVars2 ir 32 + let md = !+ir 1 ! !.ctxt |> AST.zext 1) if bv1Check md then () else resinst ir ctxt !!ir (op1 := AST.sext 32 src) - !!ir (rn_Bank := op1) - !!ir (dst := AST.xtlo 32 rn_Bank) + !!ir (rnBank := op1) + !!ir (dst := AST.xtlo 32 rnBank) !>ir len | _ -> Utils.impossible() @@ -1390,7 +1388,7 @@ let ldcl ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) match src.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> match s with | "gbr" -> let struct (op1, address, gbr) = tmpVars3 ir 32 @@ -1403,7 +1401,7 @@ let ldcl ins len ctxt = !!ir (!.ctxt R.GBR := AST.xtlo 32 gbr) !>ir len | "sr" -> - let md = !*ir 1 + let md = !+ir 1 let struct (op1, address, sr) = tmpVars3 ir 32 ! AST.zext 1) @@ -1416,7 +1414,7 @@ let ldcl ins len ctxt = !!ir (!.ctxt R.SR := AST.xtlo 32 sr) !>ir len | "vbr" -> - let md = !*ir 1 + let md = !+ir 1 let struct (op1, address, vbr) = tmpVars3 ir 32 ! AST.zext 1) @@ -1429,7 +1427,7 @@ let ldcl ins len ctxt = !!ir (!.ctxt R.VBR := AST.xtlo 32 vbr) !>ir len | "ssr" -> - let md = !*ir 1 + let md = !+ir 1 let struct (op1, address, ssr) = tmpVars3 ir 32 ! AST.zext 1) @@ -1442,7 +1440,7 @@ let ldcl ins len ctxt = !!ir (!.ctxt R.SSR := AST.xtlo 32 ssr) !>ir len | "spc" -> - let md = !*ir 1 + let md = !+ir 1 let struct (op1, address, spc) = tmpVars3 ir 32 ! AST.zext 1) @@ -1455,7 +1453,7 @@ let ldcl ins len ctxt = !!ir (!.ctxt R.SPC := AST.xtlo 32 spc) !>ir len | "dbr" -> - let md = !*ir 1 + let md = !+ir 1 let struct (op1, address, dbr) = tmpVars3 ir 32 ! AST.zext 1) @@ -1468,24 +1466,24 @@ let ldcl ins len ctxt = !!ir (!.ctxt R.DBR := AST.xtlo 32 dbr) !>ir len | _ -> - let md = !*ir 1 - let struct (op1, address, rn_Bank) = tmpVars3 ir 32 + let md = !+ir 1 + let struct (op1, address, rnBank) = tmpVars3 ir 32 ! AST.zext 1) if bv1Check md then () else resinst ir ctxt !!ir (op1 := AST.sext 32 src) !!ir (address := AST.zext 32 op1) - !!ir (rn_Bank := AST.loadLE 32 address |> AST.sext 32) + !!ir (rnBank := AST.loadLE 32 address |> AST.sext 32) !!ir (op1 := op1 .+ numI32 4) !!ir (src := AST.xtlo 32 op1) - !!ir (dst := AST.xtlo 32 rn_Bank) + !!ir (dst := AST.xtlo 32 rnBank) !>ir len | _ -> Utils.impossible() let lds ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt match dst.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> match s with | "fpscr" -> let ir = IRBuilder (16) @@ -1546,7 +1544,7 @@ let lds ins len ctxt = let ldsl ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt match dst.E with - | Var (_,_,s,_) -> + | Var (_, _, s) -> match s with | "fpscr" -> let ir = IRBuilder (16) @@ -1627,35 +1625,35 @@ let macl ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (64) let struct (macl, mach, temp) = tmpVars3 ir 32 - let struct (m_field, n_field) = tmpVars2 ir 4 - let struct (m_address, n_address, mul) = tmpVars3 ir 32 - let s = !*ir 1 + let struct (mField, nField) = tmpVars2 ir 4 + let struct (mAddr, nAddr, mul) = tmpVars3 ir 32 + let s = !+ir 1 let struct (value1, value2) = tmpVars2 ir 16 - let result = !*ir 32 - let mac = !*ir 32 + let result = !+ir 32 + let mac = !+ir 32 let struct (m, n) = match src.E, dst.E with - | Var (_,_,n1,_), Var (_,_,n2,_) -> + | Var (_, _, n1), Var (_, _, n2) -> struct (numI32 (int (n1[1..2])), numI32 (int (n2[1..2]))) | _ -> Utils.impossible() ! AST.zext 32) !!ir (mach := !.ctxt R.MACH |> AST.zext 32) !!ir (s := !.ctxt R.S |> AST.zext 1) - !!ir (m_field := AST.zext 4 m) - !!ir (n_field := AST.zext 4 n) - !!ir (m_address := AST.zext 32 src) - !!ir (n_address := AST.zext 32 dst) - !!ir (value2 := AST.zext 32 n_address |> AST.loadLE 32 + !!ir (mField := AST.zext 4 m) + !!ir (nField := AST.zext 4 n) + !!ir (mAddr := AST.zext 32 src) + !!ir (nAddr := AST.zext 32 dst) + !!ir (value2 := AST.zext 32 nAddr |> AST.loadLE 32 |> AST.sext 32) - !!ir (n_address := n_address .+ numI32 4) - !!ir (m_address := AST.ite (m_field == n_field) - (m_address .+ numI32 4) (m_address)) - !!ir (n_address := AST.ite (m_field == n_field) - (n_address .+ numI32 4) (n_address)) - !!ir (value1 := AST.zext 32 m_address |> AST.loadLE 32 + !!ir (nAddr := nAddr .+ numI32 4) + !!ir (mAddr := AST.ite (mField == nField) + (mAddr .+ numI32 4) (mAddr)) + !!ir (nAddr := AST.ite (mField == nField) + (nAddr .+ numI32 4) (nAddr)) + !!ir (value1 := AST.zext 32 mAddr |> AST.loadLE 32 |> AST.sext 32) - !!ir (m_address := m_address .+ numI32 4) + !!ir (mAddr := mAddr .+ numI32 4) !!ir (mul := value2 .* value1) !!ir (mac := macl .+ (mach << numI32 32)) !!ir (result := mac .+ mul) @@ -1667,8 +1665,8 @@ let macl ins len ctxt = (result)) !!ir (macl := result) !!ir (mach := result >> numI32 32) - !!ir (src := AST.xtlo 32 m_address) - !!ir (dst := AST.xtlo 32 n_address) + !!ir (src := AST.xtlo 32 mAddr) + !!ir (dst := AST.xtlo 32 nAddr) !!ir (!.ctxt R.MACL := AST.zext 32 macl) !!ir (!.ctxt R.MACH := AST.zext 32 mach) !>ir len @@ -1677,34 +1675,34 @@ let macw ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (64) let struct (macl, mach, temp) = tmpVars3 ir 32 - let struct (m_field, n_field) = tmpVars2 ir 4 - let struct (m_address, n_address, mul) = tmpVars3 ir 32 - let s = !*ir 1 + let struct (mField, nField) = tmpVars2 ir 4 + let struct (mAddr, nAddr, mul) = tmpVars3 ir 32 + let s = !+ir 1 let struct (value1, value2) = tmpVars2 ir 16 - let result = !*ir 32 + let result = !+ir 32 let struct (m, n) = match src.E, dst.E with - | Var (_,_,n1,_), Var (_,_,n2,_) -> + | Var (_, _, n1), Var (_, _, n2) -> struct (numI32 (int (n1[1..2])), numI32 (int (n2[1..2]))) | _ -> Utils.impossible() ! AST.zext 32) !!ir (mach := !.ctxt R.MACH |> AST.zext 32) !!ir (s := !.ctxt R.S |> AST.zext 1) - !!ir (m_field := AST.zext 4 m) - !!ir (n_field := AST.zext 4 n) - !!ir (m_address := AST.zext 32 src) - !!ir (n_address := AST.zext 32 dst) - !!ir (value2 := AST.zext 32 n_address |> AST.loadLE 16 + !!ir (mField := AST.zext 4 m) + !!ir (nField := AST.zext 4 n) + !!ir (mAddr := AST.zext 32 src) + !!ir (nAddr := AST.zext 32 dst) + !!ir (value2 := AST.zext 32 nAddr |> AST.loadLE 16 |> AST.sext 16) - !!ir (n_address := n_address .+ numI32 2) - !!ir (m_address := AST.ite (m_field == n_field) - (m_address .+ numI32 2) (m_address)) - !!ir (n_address := AST.ite (m_field == n_field) - (n_address .+ numI32 2) (n_address)) - !!ir (value1 := AST.zext 32 m_address |> AST.loadLE 16 + !!ir (nAddr := nAddr .+ numI32 2) + !!ir (mAddr := AST.ite (mField == nField) + (mAddr .+ numI32 2) (mAddr)) + !!ir (nAddr := AST.ite (mField == nField) + (nAddr .+ numI32 2) (nAddr)) + !!ir (value1 := AST.zext 32 mAddr |> AST.loadLE 16 |> AST.sext 16) - !!ir (m_address := m_address .+ numI32 2) + !!ir (mAddr := mAddr .+ numI32 2) !!ir (mul := value2 .* value1) !!ir (macl := AST.ite (s == AST.b1) (mul .+ AST.sext 32 macl) (macl)) !!ir (temp := AST.ite (signedSaturate macl) (macl) (temp)) @@ -1714,8 +1712,8 @@ let macw ins len ctxt = (mul .+ macl .+ (mach << numI32 32))) !!ir (macl := result) !!ir (mach := result >> numI32 32) - !!ir (src := AST.xtlo 32 m_address) - !!ir (dst := AST.xtlo 32 n_address) + !!ir (src := AST.xtlo 32 mAddr) + !!ir (dst := AST.xtlo 32 nAddr) !!ir (!.ctxt R.MACL := AST.zext 32 macl) !!ir (!.ctxt R.MACH := AST.zext 32 mach) !>ir len @@ -1731,7 +1729,7 @@ let mov ins len ctxt = !!ir (op2 := imm) !!ir (dst := AST.xtlo 32 op2) !>ir len - | Var (_,_,r,_) -> + | Var (_, _, r) -> let struct (op1, op2) = tmpVars2 ir 32 ! src) @@ -1744,7 +1742,7 @@ let mova ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (pc, r0) = tmpVars2 ir 32 - let disp = !*ir 8 + let disp = !+ir 8 ! AST.sext 32) !!ir (disp := (AST.zext 8 src) << numI32 2) @@ -1777,7 +1775,7 @@ let movb ins len ctxt = !!ir (op2 := address) !!ir (dst := AST.xtlo 32 op2) !>ir len - | TwoOperands (OpReg (Regdir _), OpReg (IdxIndir (_,_))) -> + | TwoOperands (OpReg (Regdir _), OpReg (IdxIndir (_))) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (r0, op1, op2, address) = tmpVars4 ir 32 ! let struct (src, dst) = trsTwoOpr ins ctxt let struct (gbr, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let r0 = !*ir 32 + let disp = !+ir 8 + let r0 = !+ir 32 ! AST.sext 32) !!ir (r0 := !.ctxt R.R0 |> AST.sext 32) @@ -1802,7 +1800,7 @@ let movb ins len ctxt = | TwoOperands (OpReg (Regdir _), OpReg (RegDisp _)) -> let struct (src, dst, imm) = trsMemOpr4toExpr ins ctxt let struct (op2, address, r0) = tmpVars3 ir 32 - let disp = !*ir 4 + let disp = !+ir 4 ! AST.sext 32) !!ir (disp := AST.zext 4 imm) @@ -1813,7 +1811,7 @@ let movb ins len ctxt = | TwoOperands (OpReg (RegIndir _), OpReg (Regdir _)) -> //0100 0100 0100 0000 let struct (src, dst) = trsTwoOpr ins ctxt let struct (op1, address) = tmpVars2 ir 32 - let op2 = !*ir 32 + let op2 = !+ir 32 ! src) !!ir (address := AST.zext 32 op1) @@ -1822,29 +1820,29 @@ let movb ins len ctxt = !>ir len | TwoOperands (OpReg (PostInc _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt - let struct (m_field, n_field) = tmpVars2 ir 4 - let op1 = !*ir 32 - let address = !*ir 32 - let op2 = !*ir 16 + let struct (mField, nField) = tmpVars2 ir 4 + let op1 = !+ir 32 + let address = !+ir 32 + let op2 = !+ir 16 let struct (m, n) = match src.E, dst.E with - | Var (_,_,n1,_), Var (_,_,n2,_) -> + | Var (_, _, n1), Var (_, _, n2) -> struct (numI32 (int (n1[1..2])), numI32 (int (n2[1..2]))) | _ -> Utils.impossible() ! m) - !!ir (n_field := AST.zext 4 n) + !!ir (mField := AST.zext 4 m) + !!ir (nField := AST.zext 4 n) !!ir (op1 := AST.sext 32 src) !!ir (address := AST.zext 32 op1) !!ir (op2 := AST.loadLE 32 address |> AST.sext 32) - !!ir (op1 := AST.ite (m_field == n_field) (op2) (op1 .+ numI32 4)) + !!ir (op1 := AST.ite (mField == nField) (op2) (op1 .+ numI32 4)) !!ir (src := AST.xtlo 32 op1) !!ir (dst := AST.xtlo 32 op2) !>ir len | TwoOperands (OpReg (IdxIndir _), OpReg (Regdir (_))) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (r0, op1, address) = tmpVars3 ir 32 - let op2 = !*ir 8 + let op2 = !+ir 8 ! AST.sext 32) !!ir (op1 := AST.sext 32 src) @@ -1855,8 +1853,8 @@ let movb ins len ctxt = | TwoOperands (OpReg (GbrDisp _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (gbr, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let r0 = !*ir 8 + let disp = !+ir 8 + let r0 = !+ir 8 ! AST.sext 32) !!ir (disp := AST.zext 8 src) @@ -1867,8 +1865,8 @@ let movb ins len ctxt = | TwoOperands (OpReg (RegDisp _), OpReg (Regdir _)) -> let struct (src, dst, imm) = trsMemOpr3toExpr ins ctxt let struct (op2, address) = tmpVars2 ir 32 - let disp = !*ir 4 - let r0 = !*ir 8 + let disp = !+ir 4 + let r0 = !+ir 8 ! imm) !!ir (op2 := AST.sext 32 src) @@ -1901,7 +1899,7 @@ let movl ins len ctxt = !!ir (op2 := address) !!ir (dst := AST.xtlo 32 op2) !>ir len - | TwoOperands (OpReg (Regdir _), OpReg (IdxIndir (_,_))) -> + | TwoOperands (OpReg (Regdir _), OpReg (IdxIndir (_))) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (r0, op1, op2, address) = tmpVars4 ir 32 ! let struct (src, dst) = trsTwoOpr ins ctxt let struct (gbr, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let r0 = !*ir 32 + let disp = !+ir 8 + let r0 = !+ir 32 ! AST.sext 32) !!ir (r0 := !.ctxt R.R0 |> AST.sext 32) @@ -1926,7 +1924,7 @@ let movl ins len ctxt = | TwoOperands (OpReg (Regdir _), OpReg (RegDisp _)) -> let struct (src, dst, imm) = trsMemOpr4toExpr ins ctxt let struct (op3, address, op1) = tmpVars3 ir 32 - let disp = !*ir 4 + let disp = !+ir 4 ! imm << numI32 2) !!ir (op1 := AST.sext 32 src) @@ -1937,7 +1935,7 @@ let movl ins len ctxt = | TwoOperands (OpReg (RegIndir _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (op1, address) = tmpVars2 ir 32 - let op2 = !*ir 32 + let op2 = !+ir 32 ! src) !!ir (address := AST.zext 32 op1) @@ -1946,29 +1944,29 @@ let movl ins len ctxt = !>ir len | TwoOperands (OpReg (PostInc _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt - let struct (m_field, n_field) = tmpVars2 ir 4 - let op1 = !*ir 32 - let address = !*ir 32 - let op2 = !*ir 16 + let struct (mField, nField) = tmpVars2 ir 4 + let op1 = !+ir 32 + let address = !+ir 32 + let op2 = !+ir 16 let struct (m, n) = match src.E, dst.E with - | Var (_,_,n1,_), Var (_,_,n2,_) -> + | Var (_, _, n1), Var (_, _, n2) -> struct (numI32 (int (n1[1..2])), numI32 (int (n2[1..2]))) | _ -> Utils.impossible() ! m) - !!ir (n_field := AST.zext 4 n) + !!ir (mField := AST.zext 4 m) + !!ir (nField := AST.zext 4 n) !!ir (op1 := AST.sext 32 src) !!ir (address := AST.zext 32 op1) !!ir (op2 := AST.loadLE 32 address |> AST.sext 32) - !!ir (op1 := AST.ite (m_field == n_field) (op2) (op1 .+ numI32 4)) + !!ir (op1 := AST.ite (mField == nField) (op2) (op1 .+ numI32 4)) !!ir (src := AST.xtlo 32 op1) !!ir (dst := AST.xtlo 32 op2) !>ir len | TwoOperands (OpReg (IdxIndir _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (r0, op1, address) = tmpVars3 ir 32 - let op2 = !*ir 32 + let op2 = !+ir 32 ! AST.sext 32) !!ir (op1 := AST.sext 32 src) @@ -1979,8 +1977,8 @@ let movl ins len ctxt = | TwoOperands (OpReg (GbrDisp _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (gbr, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let r0 = !*ir 32 + let disp = !+ir 8 + let r0 = !+ir 32 ! AST.sext 32) !!ir (disp := AST.zext 8 src << numI32 2) @@ -1991,8 +1989,8 @@ let movl ins len ctxt = | TwoOperands (OpReg (PCrDisp _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (pc, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let op2 = !*ir 16 + let disp = !+ir 8 + let op2 = !+ir 16 ! AST.sext 32) !!ir (disp := AST.zext 8 src << numI32 2) @@ -2006,8 +2004,8 @@ let movl ins len ctxt = | TwoOperands (OpReg (RegDisp _), OpReg (Regdir _)) -> let struct (src, dst, imm) = trsMemOpr3toExpr ins ctxt let struct (op2, address) = tmpVars2 ir 32 - let disp = !*ir 4 - let op3 = !*ir 32 + let disp = !+ir 4 + let op3 = !+ir 32 ! imm << numI32 2) !!ir (op2 := AST.sext 32 src) @@ -2040,7 +2038,7 @@ let movw ins len ctxt = !!ir (op2 := address) !!ir (dst := AST.xtlo 32 op2) !>ir len - | TwoOperands (OpReg (Regdir _), OpReg (IdxIndir (_,_))) -> + | TwoOperands (OpReg (Regdir _), OpReg (IdxIndir (_))) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (r0, op1, op2, address) = tmpVars4 ir 32 ! AST.zext 32) !!ir (AST.store Endian.Little address op1) !>ir len - | TwoOperands (OpReg (Regdir _), OpReg (GbrDisp (_, _))) -> + | TwoOperands (OpReg (Regdir _), OpReg (GbrDisp (_))) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (gbr, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let r0 = !*ir 32 + let disp = !+ir 8 + let r0 = !+ir 32 ! AST.sext 32) !!ir (r0 := !.ctxt R.R0 |> AST.sext 32) @@ -2062,10 +2060,10 @@ let movw ins len ctxt = !!ir (address := (gbr .+ disp) |> AST.zext 32) !!ir (AST.store Endian.Little address r0) !>ir len - | TwoOperands (OpReg (Regdir _), OpReg (RegDisp (_, _))) -> + | TwoOperands (OpReg (Regdir _), OpReg (RegDisp (_))) -> let struct (src, dst, imm) = trsMemOpr4toExpr ins ctxt let struct (op2, address, r0) = tmpVars3 ir 32 - let disp = !*ir 4 + let disp = !+ir 4 ! AST.sext 32) !!ir (disp := AST.zext 4 imm << AST.b1) @@ -2076,7 +2074,7 @@ let movw ins len ctxt = | TwoOperands (OpReg (RegIndir _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (op1, address) = tmpVars2 ir 32 - let op2 = !*ir 16 + let op2 = !+ir 16 ! src) !!ir (address := AST.zext 32 op1) @@ -2085,29 +2083,29 @@ let movw ins len ctxt = !>ir len | TwoOperands (OpReg (PostInc _), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt - let struct (m_field, n_field) = tmpVars2 ir 4 - let op1 = !*ir 32 - let address = !*ir 32 - let op2 = !*ir 16 + let struct (mField, nField) = tmpVars2 ir 4 + let op1 = !+ir 32 + let address = !+ir 32 + let op2 = !+ir 16 let struct (m, n) = match src.E, dst.E with - | Var (_,_,n1,_), Var (_,_,n2,_) -> + | Var (_, _, n1), Var (_, _, n2) -> struct (numI32 (int (n1[1..2])), numI32 (int (n2[1..2]))) | _ -> Utils.impossible() ! m) - !!ir (n_field := AST.zext 4 n) + !!ir (mField := AST.zext 4 m) + !!ir (nField := AST.zext 4 n) !!ir (op1 := AST.sext 32 src) !!ir (address := AST.zext 32 op1) !!ir (op2 := AST.loadLE 16 address |> AST.sext 16) - !!ir (op1 := AST.ite (m_field == n_field) (op2) (op1 .+ numI32 2)) + !!ir (op1 := AST.ite (mField == nField) (op2) (op1 .+ numI32 2)) !!ir (src := AST.xtlo 32 op1) !!ir (dst := AST.xtlo 16 op2) !>ir len - | TwoOperands (OpReg (IdxIndir (_,_)), OpReg (Regdir (_))) -> + | TwoOperands (OpReg (IdxIndir (_)), OpReg (Regdir (_))) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (r0, op1, address) = tmpVars3 ir 32 - let op2 = !*ir 16 + let op2 = !+ir 16 ! AST.sext 32) !!ir (op1 := AST.sext 32 src) @@ -2115,11 +2113,11 @@ let movw ins len ctxt = !!ir (op2 := AST.loadLE 16 address |> AST.sext 16) !!ir (dst := AST.xtlo 16 op2) !>ir len - | TwoOperands (OpReg (GbrDisp (_, _)), OpReg (Regdir _)) -> + | TwoOperands (OpReg (GbrDisp (_)), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (gbr, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let r0 = !*ir 16 + let disp = !+ir 8 + let r0 = !+ir 16 ! AST.sext 32) !!ir (disp := AST.zext 8 src << AST.b1) @@ -2127,11 +2125,11 @@ let movw ins len ctxt = !!ir (r0 := AST.loadLE 16 address |> AST.sext 16) !!ir (dst := AST.xtlo 16 r0) !>ir len - | TwoOperands (OpReg (PCrDisp (_,_)), OpReg (Regdir _)) -> + | TwoOperands (OpReg (PCrDisp (_)), OpReg (Regdir _)) -> let struct (src, dst) = trsTwoOpr ins ctxt let struct (pc, address) = tmpVars2 ir 32 - let disp = !*ir 8 - let op2 = !*ir 16 + let disp = !+ir 8 + let op2 = !+ir 16 ! AST.sext 32) !!ir (disp := AST.zext 8 src << AST.b1) @@ -2141,11 +2139,11 @@ let movw ins len ctxt = !!ir (op2 := AST.loadLE 16 address |> AST.sext 16) !!ir (dst := AST.xtlo 16 op2) !>ir len - | TwoOperands (OpReg (RegDisp (_, _)), OpReg (Regdir _)) -> + | TwoOperands (OpReg (RegDisp (_)), OpReg (Regdir _)) -> let struct (src, dst, imm) = trsMemOpr3toExpr ins ctxt let struct (op2, address) = tmpVars2 ir 32 - let disp = !*ir 4 - let r0 = !*ir 16 + let disp = !+ir 4 + let r0 = !+ir 16 ! imm << AST.b1) !!ir (op2 := AST.sext 32 src) @@ -2180,7 +2178,7 @@ let mull ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let macl = !*ir 64 + let macl = !+ir 64 ! src) !!ir (op2 := AST.sext 32 dst) @@ -2192,7 +2190,7 @@ let mulsw ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 16 - let macl = !*ir 64 + let macl = !+ir 64 ! src |> AST.sext 16) !!ir (op2 := AST.sext 32 dst |> AST.sext 16) @@ -2204,7 +2202,7 @@ let muluw ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 16 - let macl = !*ir 64 + let macl = !+ir 64 ! src |> AST.zext 16) !!ir (op2 := AST.sext 32 dst |> AST.zext 16) @@ -2226,7 +2224,7 @@ let negc ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! AST.zext 1) !!ir (op1 := AST.zext 32 src) @@ -2271,15 +2269,15 @@ let ``or`` ins len ctxt = let ir = IRBuilder (8) match src.E with | Num _ -> - let r0 = !*ir 32 - let imm = !*ir 8 + let r0 = !+ir 32 + let imm = !+ir 8 ! AST.zext 32) !!ir (imm := AST.zext 8 src) !!ir (r0 := r0 .| imm) !!ir (!.ctxt R.R0 := AST.xtlo 32 r0) !>ir len - | Var (_,_,_,_) -> + | Var _ -> let struct (op1, op2) = tmpVars2 ir 32 ! src) @@ -2310,8 +2308,8 @@ let pref ins len = function let rotcl ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (16) - let t = !*ir 1 - let op1 = !*ir 32 + let t = !+ir 1 + let op1 = !+ir 32 ! AST.zext 32) !!ir (op1 := AST.zext 32 dst) @@ -2325,7 +2323,7 @@ let rotcr ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (16) let struct (oldt, t) = tmpVars2 ir 1 - let op1 = !*ir 32 + let op1 = !+ir 32 ! AST.zext 32) !!ir (op1 := AST.zext 32 dst) @@ -2339,8 +2337,8 @@ let rotcr ins len ctxt = let rotl ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (16) - let t = !*ir 1 - let op1 = !*ir 32 + let t = !+ir 1 + let op1 = !+ir 32 ! dst) !!ir (t := AST.extract op1 1 31) @@ -2352,8 +2350,8 @@ let rotl ins len ctxt = let rotr ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (16) - let t = !*ir 1 - let op1 = !*ir 32 + let t = !+ir 1 + let op1 = !+ir 32 ! dst) !!ir (t := AST.extract op1 1 1) @@ -2364,7 +2362,7 @@ let rotr ins len ctxt = let rte ins len ctxt = let ir = IRBuilder (16) - let md = !*ir 1 + let md = !+ir 1 let struct (ssr, pc, target, delayedPC) = tmpVars4 ir 32 ! AST.zext 1) @@ -2392,7 +2390,7 @@ let rts ins len ctxt = let sets ins len ctxt = let ir = IRBuilder (8) - let s = !*ir 1 + let s = !+ir 1 ! 1) @@ -2400,7 +2398,7 @@ let sets ins len ctxt = let sett ins len ctxt = let ir = IRBuilder (8) - let t = !*ir 1 + let t = !+ir 1 ! 1) @@ -2410,7 +2408,7 @@ let shad ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (op1, op2) = tmpVars2 ir 32 - let shift = !*ir 5 + let shift = !+ir 5 ! src) !!ir (op2 := AST.sext 32 dst) @@ -2424,8 +2422,8 @@ let shad ins len ctxt = let shal ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (t := AST.extract op1 1 32) @@ -2437,8 +2435,8 @@ let shal ins len ctxt = let shar ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (t := AST.extract op1 1 1) @@ -2451,7 +2449,7 @@ let shld ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) let struct (op1, op2) = tmpVars2 ir 32 - let shift = !*ir 32 + let shift = !+ir 32 ! src) !!ir (op2 := AST.sext 32 dst) @@ -2465,8 +2463,8 @@ let shld ins len ctxt = let shll ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (t := AST.extract op1 1 1) @@ -2478,7 +2476,7 @@ let shll ins len ctxt = let shll2 ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 + let op1 = !+ir 32 ! dst) !!ir (op1 := op1 << numI32 2) @@ -2488,7 +2486,7 @@ let shll2 ins len ctxt = let shll8 ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 + let op1 = !+ir 32 ! dst) !!ir (op1 := op1 << numI32 8) @@ -2498,7 +2496,7 @@ let shll8 ins len ctxt = let shll16 ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 + let op1 = !+ir 32 ! dst) !!ir (op1 := op1 << numI32 16) @@ -2508,8 +2506,8 @@ let shll16 ins len ctxt = let shlr ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 - let t = !*ir 1 + let op1 = !+ir 32 + let t = !+ir 1 ! dst) !!ir (t := AST.extract op1 1 1) @@ -2521,7 +2519,7 @@ let shlr ins len ctxt = let shlr2 ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 + let op1 = !+ir 32 ! dst) !!ir (op1 := op1 >> numI32 2) @@ -2531,7 +2529,7 @@ let shlr2 ins len ctxt = let shlr8 ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 + let op1 = !+ir 32 ! dst) !!ir (op1 := op1 >> numI32 8) @@ -2541,7 +2539,7 @@ let shlr8 ins len ctxt = let shlr16 ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let op1 = !*ir 32 + let op1 = !+ir 32 ! dst) !!ir (op1 := op1 >> numI32 16) @@ -2556,7 +2554,7 @@ let sleep ins len ctxt = let stc ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) - let md = !*ir 1 + let md = !+ir 1 let struct (reg, op1) = tmpVars2 ir 32 ! AST.zext 1) @@ -2569,7 +2567,7 @@ let stc ins len ctxt = let stcl ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) - let md = !*ir 1 + let md = !+ir 1 let struct (reg, op1, address) = tmpVars3 ir 32 ! AST.zext 1) @@ -2586,7 +2584,7 @@ let sts ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) match src.E with - | Var (_,_,r,_) -> + | Var (_, _, r) -> if (r = "fpscr" || r = "fpul") then let struct (sr, fps, op1) = tmpVars3 ir 32 ! + | Var (_, _, r) -> if (r = "fpscr" || r = "fpul") then let struct (sr, reg, op1, address) = tmpVars4 ir 32 ! - let t = !*ir 1 + let t = !+ir 1 ! AST.zext 1) !!ir (op1 := AST.sext 32 src |> AST.zext 32) @@ -2663,7 +2661,7 @@ let subv ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (8) let struct (op1, op2) = tmpVars2 ir 32 - let t = !*ir 1 + let t = !+ir 1 ! src) !!ir (op2 := AST.sext 32 dst) @@ -2701,8 +2699,8 @@ let tasb ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (16) let struct (op1, address) = tmpVars2 ir 32 - let value = !*ir 8 - let t = !*ir 1 + let value = !+ir 8 + let t = !+ir 1 ! dst) !!ir (address := AST.zext 32 op1) @@ -2718,7 +2716,7 @@ let tasb ins len ctxt = let trapa ins len ctxt = let dst = trsOneOpr ins ctxt let ir = IRBuilder (8) - let imm = !*ir 8 + let imm = !+ir 8 ! dst) if (delaySlot.Count = 1) then illSlot2 ir len ctxt @@ -2729,9 +2727,9 @@ let trapa ins len ctxt = let tst ins len ctxt = let struct (src, dst) = trsTwoOpr ins ctxt let ir = IRBuilder (16) - let r0 = !*ir 32 - let imm = !*ir 8 - let t = !*ir 1 + let r0 = !+ir 32 + let imm = !+ir 8 + let t = !+ir 1 ! AST.sext 32) !!ir (imm := AST.zext 8 src) @@ -2744,7 +2742,7 @@ let tstb ins len ctxt = let ir = IRBuilder (16) let struct (r0, gbr, address) = tmpVars3 ir 32 let struct (imm, value) = tmpVars2 ir 8 - let t = !*ir 1 + let t = !+ir 1 ! AST.sext 32) !!ir (gbr := !.ctxt R.GBR |> AST.sext 32) diff --git a/src/FrontEnd/BinLifter/SH4/SH4Instruction.fs b/src/FrontEnd/BinLifter/SH4/SH4Instruction.fs index ea336d8c..83f99c5a 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4Instruction.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4Instruction.fs @@ -58,24 +58,23 @@ type SH4Instruction (addr, numBytes, insInfo) = override __.TranslateToList ctxt = Lifter.translate __.Info numBytes ctxt - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = - + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) - Disassembly.disas __.Info builder - builder.Finalize () + Disasm.disas __.Info builder + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) - Disassembly.disas __.Info builder - builder.Finalize () + Disasm.disas __.Info builder + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) - Disassembly.disas __.Info builder - builder.Finalize () + Disasm.disas __.Info builder + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/SH4/SH4Lifter.fs b/src/FrontEnd/BinLifter/SH4/SH4Lifter.fs index 55d08f25..483516f4 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4Lifter.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4Lifter.fs @@ -24,7 +24,6 @@ module B2R2.FrontEnd.BinLifter.SH4.Lifter -open B2R2.BinIR open B2R2.FrontEnd.BinLifter open B2R2.FrontEnd.BinLifter.SH4 open B2R2.FrontEnd.BinLifter.SH4.GeneralLifter diff --git a/src/FrontEnd/BinLifter/SH4/SH4Parser.fs b/src/FrontEnd/BinLifter/SH4/SH4Parser.fs index 0e0cafe9..1b350164 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4Parser.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4Parser.fs @@ -22,1055 +22,24 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.SH4.Parser +namespace B2R2.FrontEnd.BinLifter.SH4 +open System open B2R2 +open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinLifter.SH4.OperandHelper +type SH4Parser (isa: ISA) = + let reader = BinReader.Init isa.Endian -let getState = function - | _ -> Utils.futureFeature() + interface IInstructionParsable with + member __.Parse (bs: byte[], addr: Addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader addr :> Instruction -/// 0000 0000 ---- ---- with no operands -let noOpParse0000 b16 = - match getBits b16 8 1 with - | 0b00011001us -> Opcode.DIV0U, NoOperand - | 0b00001011us -> Opcode.RTS, NoOperand - | 0b00101000us -> Opcode.CLRMAC, NoOperand - | 0b01001000us -> Opcode.CLRS, NoOperand - | 0b00001000us -> Opcode.CLRT, NoOperand - | 0b00111000us -> Opcode.LDTLB, NoOperand - | 0b00001001us -> Opcode.NOP, NoOperand - | 0b00101011us -> Opcode.RTE, NoOperand - | 0b01011000us -> Opcode.SETS, NoOperand - | 0b00011000us -> Opcode.SETT, NoOperand - | 0b00011011us -> Opcode.SLEEP, NoOperand - | _ -> Opcode.InvalidOp, NoOperand + member __.Parse (span: ByteSpan, addr: Addr) = + ParsingMain.parse span reader addr :> Instruction -/// 1111 ---- 1111 1101 with no operands. -let noOpParse1111 b16 = - match getBits b16 12 9 with - | 0b1011us -> Opcode.FRCHG, NoOperand - | 0b0011us -> Opcode.FSCHG, NoOperand - | _ -> Opcode.InvalidOp, NoOperand + member __.MaxInstructionSize = 2 -/// 0100 ---- ---- ---- with destination operand only. -let oneOpParse0100 b16 = - match getBits b16 8 5 with - | 0b0010us -> - match getBits b16 4 1 with - | 0b1001us -> Opcode.MOVT, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0100us -> Opcode.ROTCL, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0101us -> Opcode.ROTCR, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0000us -> Opcode.SHAL, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0001us -> Opcode.SHAR, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b1000us -> Opcode.SHLL16, OneOperand (OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - | 0b0001us -> - match getBits b16 4 1 with - | 0b0001us -> Opcode.CMPPZ, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0101us -> Opcode.CMPPL, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0000us -> Opcode.DT, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b1000us -> Opcode.SHLL8, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b1001us -> Opcode.SHLR8, OneOperand (OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - | 0b0000us -> - match getBits b16 4 1 with - | 0b0100us -> Opcode.ROTL, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0101us -> Opcode.ROTR, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0000us -> Opcode.SHLL, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0001us -> Opcode.SHLR, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b1000us -> Opcode.SHLL2, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b1001us -> Opcode.SHLR2, OneOperand (OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () -/// 1111 ---- ---- 1101 with destination operand only. -let oneOpParse1111 b16 = - match getBits b16 8 5 with - | 0b0101us -> - if get1Bit b16 9 then - Opcode.FABS, OneOperand(OpReg(Regdir(getReg1dFR b16))) - else if getState() - then Opcode.FABS, OneOperand(OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FABS, OneOperand(OpReg(Regdir(getReg1dFR b16))) - | 0b0100us -> - if get1Bit b16 9 then - Opcode.FNEG, OneOperand(OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FNEG, OneOperand(OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FNEG, OneOperand(OpReg(Regdir(getReg1dFR b16))) - | 0b0110us -> - if get1Bit b16 9 then - Opcode.FSQRT, OneOperand(OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FSQRT, OneOperand(OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FSQRT, OneOperand(OpReg(Regdir(getReg1dFR b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// 0011 ---- ---- ---- with source and destination operands. -let twoOpParse0011 b16 = - match getBits b16 4 1 with - | 0b1100us -> - Opcode.ADD, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1110us -> - Opcode.ADDC, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1111us -> - Opcode.ADDV, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0000us -> - Opcode.CMPEQ, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0010us -> - Opcode.CMPHS, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0011us -> - Opcode.CMPGE, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0110us -> - Opcode.CMPHI, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0111us -> - Opcode.CMPGT, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0100us -> - Opcode.DIV1, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1101us -> - Opcode.DMULSL, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0101us -> - Opcode.DMULUL, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1000us -> - Opcode.SUB, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1010us -> - Opcode.SUBC, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1011us -> - Opcode.SUBV, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// 0110 ---- ---- ---- with source and destination operands. -let twoOpParse0110 b16 = - match getBits b16 4 1 with - | 0b0011us -> - Opcode.MOV, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1000us -> - Opcode.SWAPB, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1001us -> - Opcode.SWAPW, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1110us -> - Opcode.EXTSB, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1111us -> - Opcode.EXTSW, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1100us -> - Opcode.EXTUB, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1101us -> - Opcode.EXTUW, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1011us -> - Opcode.NEG, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1010us -> - Opcode.NEGC, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0111us -> - Opcode.NOT, - TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// 0010 ---- ---- ---- with source and destination operands. -let twoOpParse0010 b16 = - match getBits b16 4 1 with - | 0b1101us -> - Opcode.XTRCT, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1100us -> - Opcode.CMPSTR, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0111us -> - Opcode.DIV0S, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1111us -> - Opcode.MULSW, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1110us -> - Opcode.MULUW, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1001us -> - Opcode.AND, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1011us -> - Opcode.OR, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1000us -> - Opcode.TST, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1010us -> - Opcode.XOR, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// 0100 ---- ---- ---- with source and destination operands. -let twoOpParse0100 b16 = - match getBits b16 4 1 with - | 0b1100us -> - Opcode.SHAD, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1101us -> - Opcode.SHLD, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b1110us -> - match getBits b16 8 5 with - | 0b0000us -> - Opcode.LDC, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.SR))) - | 0b0001us -> - Opcode.LDC, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.GBR))) - | 0b0010us -> - Opcode.LDC, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.VBR))) - | 0b0011us -> - Opcode.LDC, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.SSR))) - | 0b0100us -> - Opcode.LDC, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.SPC))) - | 0b1000us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1001us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1010us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1011us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1100us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1101us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1110us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | 0b1111us -> - Opcode.LDC, - TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) - | _ -> Opcode.InvalidOp, NoOperand - | 0b1010us -> - match getBits b16 8 5 with - | 0b1111us -> - Opcode.LDC, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.DBR))) - | 0b0000us -> - Opcode.LDS, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.MACH))) - | 0b0001us -> - Opcode.LDS, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.MACL))) - | 0b0010us -> - Opcode.LDS, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.PR))) - | 0b0110us -> - Opcode.LDS, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.FPSCR))) - | 0b0101us -> - Opcode.LDS, - TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.FPUL))) - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// 0000 ---- ---- ---- with source and destination operand. -let twoOpParse0000 b16 = - match getBits b16 4 1 with - | 0b0111us -> - Opcode.MULL, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0010us -> - match getBits b16 8 5 with - | 0b0000us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.SR)), OpReg(Regdir(getReg1d b16))) - | 0b0001us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.GBR)), OpReg(Regdir(getReg1d b16))) - | 0b0010us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.VBR)), OpReg(Regdir(getReg1d b16))) - | 0b0011us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.SSR)), OpReg(Regdir(getReg1d b16))) - | 0b0100us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.SPC)), OpReg(Regdir(getReg1d b16))) - | 0b1000us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1001us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1010us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1011us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1100us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1101us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1110us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | 0b1111us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - | 0b1010us -> - match getBits b16 8 5 with - | 0b0011us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.SGR)), OpReg(Regdir(getReg1d b16))) - | 0b1111us -> - Opcode.STC, - TwoOperands(OpReg(Regdir(R.DBR)), OpReg(Regdir(getReg1d b16))) - | 0b0000us -> - Opcode.STS, - TwoOperands(OpReg(Regdir(R.MACH)), OpReg(Regdir(getReg1d b16))) - | 0b0001us -> - Opcode.STS, - TwoOperands(OpReg(Regdir(R.MACL)), OpReg(Regdir(getReg1d b16))) - | 0b0010us -> - Opcode.STS, - TwoOperands(OpReg(Regdir(R.PR)), OpReg(Regdir(getReg1d b16))) - | 0b0110us -> - Opcode.STS, - TwoOperands(OpReg(Regdir(R.FPSCR)), OpReg(Regdir(getReg1d b16))) - | 0b0101us -> - Opcode.STS, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// 1111 ---- ---- ---- with source and destination operands. -let twoOpParse1111 b16 = - match getBits b16 4 1 with - | 0b1110us -> - Opcode.FMAC, - ThreeOperands(OpReg(Regdir(R.FR0)), OpReg(Regdir(getReg1sFR b16)), - OpReg(Regdir(getReg1dFR b16))) - | 0b0000us -> - if get1Bit b16 5 then - Opcode.FADD, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FADD, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FADD, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - | 0b0100us -> - if get1Bit b16 5 then - Opcode.FCMPEQ, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FCMPEQ, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FCMPEQ, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - | 0b0101us -> - if get1Bit b16 5 then - Opcode.FCMPGT, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FCMPGT, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FCMPGT, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - | 0b0011us -> - if get1Bit b16 5 then - Opcode.FDIV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FDIV, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FDIV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - | 0b0010us -> - if get1Bit b16 5 then - Opcode.FMUL, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FMUL, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FMUL, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - | 0b0001us -> - if get1Bit b16 5 then - Opcode.FSUB, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FSUB, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FSUB, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) - | 0b1100us -> - if (get1Bit b16 5 && get1Bit b16 9) then - if getState() then - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sXD b16)), - OpReg(Regdir(getReg1dXD b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(Regdir(getReg1dFR b16))) - elif ((get1Bit b16 9) && not(get1Bit b16 5)) then - if getState() then - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), - OpReg(Regdir(getReg1dXD b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(Regdir(getReg1dFR b16))) - elif ((get1Bit b16 5) && not(get1Bit b16 9)) then - if getState() then - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sXD b16)), - OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(Regdir(getReg1dFR b16))) - else - if getState() then - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), - OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(Regdir(getReg1dFR b16))) - | 0b1101us -> - match getBits b16 8 5 with - | 0b1110us -> - Opcode.FIPR, - TwoOperands(OpReg(Regdir(getReg1sFV b16)), OpReg(Regdir(getReg1dFV b16))) - | 0b1111us -> - Opcode.FTRV, - TwoOperands(OpReg(Regdir(R.XMTRX)), OpReg(Regdir(getReg1dFV b16))) - | 0b0001us -> - Opcode.FLDS, - TwoOperands(OpReg(Regdir(getReg1dFR b16)), OpReg(Regdir(R.FPUL))) - | 0b1011us -> - Opcode.FCNVDS, - TwoOperands(OpReg(Regdir(getReg1dDR b16)), OpReg(Regdir(R.FPUL))) - | 0b0011us -> - if get1Bit b16 9 then - Opcode.FTRC, - TwoOperands(OpReg(Regdir(getReg1dFR b16)), OpReg(Regdir(R.FPUL))) - else if getState() then - Opcode.FTRC, - TwoOperands(OpReg(Regdir(getReg1dDR b16)), OpReg(Regdir(R.FPUL))) - else - Opcode.FTRC, - TwoOperands(OpReg(Regdir(getReg1dFR b16)), OpReg(Regdir (R.FPUL))) - | 0b0000us -> - Opcode.FSTS, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) - | 0b1010us -> - Opcode.FCNVSD, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dDR b16))) - | 0b0010us -> - if get1Bit b16 9 then - Opcode.FLOAT, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) - else if getState() then - Opcode.FLOAT, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) - else - Opcode.FLOAT, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect 0100 ---- ---- ---- with destination operand only. -let parseRegInd0100 b16 = - match getBits b16 8 5 with - | 0b0001us -> Opcode.TASB, OneOperand( OpReg(RegIndir(getReg1d b16))) - | 0b0010us -> Opcode.JMP, OneOperand( OpReg(RegIndir(getReg1d b16))) - | 0b0000us -> Opcode.JSR, OneOperand( OpReg(RegIndir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect 0000 ---- ---- ---- with destination operand only. -let parseRegInd0000 b16 = - match getBits b16 8 5 with - | 0b1001us -> Opcode.OCBI, OneOperand( OpReg(RegIndir(getReg1d b16))) - | 0b1010us -> Opcode.OCBP, OneOperand( OpReg(RegIndir(getReg1d b16))) - | 0b1011us -> Opcode.OCBWB, OneOperand( OpReg(RegIndir(getReg1d b16))) - | 0b1000us -> Opcode.PREF, OneOperand( OpReg(RegIndir(getReg1d b16))) - | 0b1100us -> - Opcode.MOVCAL, - TwoOperands(OpReg(Regdir(R.R0)), OpReg(RegIndir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect 0010 ---- ---- ---- with source and destination operands. -let parseRegInd0010 b16 = - match getBits b16 4 1 with - | 0b0000us -> - Opcode.MOVB, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(RegIndir(getReg1d b16))) - | 0b0001us -> - Opcode.MOVW, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(RegIndir(getReg1d b16))) - | 0b0010us -> - Opcode.MOVL, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(RegIndir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect 0110 ---- ---- ---- with source and destination operands. -let parseRegInd0110 b16 = - match getBits b16 4 1 with - | 0b0000us -> - Opcode.MOVB, - TwoOperands(OpReg(RegIndir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0001us -> - Opcode.MOVW, - TwoOperands(OpReg(RegIndir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0010us -> - Opcode.MOVL, - TwoOperands(OpReg(RegIndir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect 1111 ---- ---- ---- with source and destination operands. -let parseRegInd1111 b16 = - match getBits b16 4 1 with - | 0b1000us -> - if getState() then - if get1Bit b16 9 then - Opcode.FMOV, - TwoOperands(OpReg(RegIndir(getReg1s b16)), - OpReg(Regdir(getReg1dXD b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(RegIndir(getReg1s b16)), - OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FMOVS, - TwoOperands(OpReg(RegIndir(getReg1s b16)), - OpReg(Regdir(getReg1sFR b16))) - | 0b1010us -> - if getState() then - if get1Bit b16 5 then - Opcode.FMOV, - TwoOperands( OpReg(Regdir(getReg1sXD b16)), - OpReg(RegIndir(getReg1d b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), - OpReg(RegIndir(getReg1d b16))) - else - Opcode.FMOVS, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(RegIndir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Post-Increment) -/// 0000 ---- ---- ---- with source and destination operands. -let parsePostInc0000 b16 = - match getBits b16 4 1 with - | 0b1111us -> - Opcode.MACL, - TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(PostInc(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Post-Increment) -/// 0100 ---- ---- ---- with source and destination operands. -let parsePostInc0100 b16 = - match getBits b16 4 1 with - | 0b1111us -> - Opcode.MACW, - TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(PostInc(getReg1d b16))) - | 0b0111us -> - match getBits b16 8 5 with - | 0b0000us -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.SR))) - | 0b0001us -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.GBR))) - | 0b0010us -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.VBR))) - | 0b0011us -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.SSR))) - | 0b0100us -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.SPC))) - | _ -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), - OpReg(Regdir(getReg1dBank b16))) - | 0b0110us -> - match getBits b16 8 5 with - | 0b1111us -> - Opcode.LDCL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.DBR))) - | 0b0000us -> - Opcode.LDSL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.MACH))) - | 0b0001us -> - Opcode.LDSL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.MACL))) - | 0b0010us -> - Opcode.LDSL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.PR))) - | 0b0110us -> - Opcode.LDSL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.FPSCR))) - | 0b0101us -> - Opcode.LDSL, - TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.FPUL))) - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Post-Increment) -/// 0110 ---- ---- ---- with source and destination operands. -let parsePostInc0110 b16 = - match getBits b16 4 1 with - | 0b0100us -> - Opcode.MOVB, - TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0101us -> - Opcode.MOVW, - TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | 0b0110us -> - Opcode.MOVL, - TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Post-Increment) -/// 1111 ---- ---- ---- with source and destination operands. -let parsePostInc1111 b16 = - match getBits b16 4 1 with - | 0b1001us -> - if getState() then - if get1Bit b16 9 then - Opcode.FMOV, - TwoOperands(OpReg(PostInc(getReg1s b16)), - OpReg(Regdir(getReg1dXD b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(PostInc(getReg1s b16)), - OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FMOVS, - TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1dFR b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Pre-Decrement) -/// 0000 ---- ---- ---- with source and destination operands. -let parsePreDec0010 b16 = - match getBits b16 4 1 with - | 0b0100us -> - Opcode.MOVB, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(PreDec(getReg1d b16))) - | 0b0101us -> - Opcode.MOVW, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(PreDec(getReg1d b16))) - | 0b0110us -> - Opcode.MOVL, - TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(PreDec(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Pre-Decrement) -/// 1111 ---- ---- ---- with source and destination operands. -let parsePreDec1111 b16 = - match getBits b16 4 1 with - | 0b1011us -> - if getState() (*SZ*) then - if get1Bit b16 5 then - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(PreDec(getReg1d b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sXD b16)), OpReg(PreDec(getReg1d b16))) - else - Opcode.FMOVS, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(PreDec(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect (Pre-Decrement) -/// 0100 ---- ---- ---- with source and destination operands. -let parsePreDec0100 b16 = - match getBits b16 4 1 with - | 0b0011us -> - match getBits b16 8 5 with - | 0b0000us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.SR)), OpReg(PreDec(getReg1d b16))) - | 0b0001us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.GBR)), OpReg(PreDec(getReg1d b16))) - | 0b0010us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.VBR)), OpReg(PreDec(getReg1d b16))) - | 0b0011us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.SSR)), OpReg(PreDec(getReg1d b16))) - | 0b0100us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.SPC)), OpReg(PreDec(getReg1d b16))) - | _ -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(PreDec(getReg1d b16))) - | 0b0010us -> - match getBits b16 8 5 with - | 0b0011us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.SGR)), OpReg(PreDec(getReg1d b16))) - | 0b1111us -> - Opcode.STCL, - TwoOperands(OpReg(Regdir(R.DBR)), OpReg(PreDec(getReg1d b16))) - | 0b0000us -> - Opcode.STSL, - TwoOperands(OpReg(Regdir(R.MACH)), OpReg(PreDec(getReg1d b16))) - | 0b0001us -> - Opcode.STSL, - TwoOperands(OpReg(Regdir(R.MACL)), OpReg(PreDec(getReg1d b16))) - | 0b0010us -> - Opcode.STSL, - TwoOperands(OpReg(Regdir(R.PR)), OpReg(PreDec(getReg1d b16))) - | 0b0110us -> - Opcode.STSL, - TwoOperands(OpReg(Regdir(R.FPSCR)), OpReg(PreDec(getReg1d b16))) - | 0b0101us -> - Opcode.STSL, - TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(PreDec(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect with Displacement -/// 1000 ---- ---- ---- with source and destination operands. -let parseIndDisp1000 b16 = - match getBits b16 12 9 with - | 0b0000us -> - Opcode.MOVB, - TwoOperands(OpReg(Regdir(R.R0)), - OpReg(RegDisp(getDisp4b b16, getReg1s b16))) - | 0b0001us -> - Opcode.MOVW, - TwoOperands(OpReg(Regdir(R.R0)), - OpReg(RegDisp(getDisp4b b16, getReg1s b16))) - | 0b0100us -> - Opcode.MOVB, - TwoOperands(OpReg(RegDisp(getDisp4b b16, getReg1s b16)), - OpReg(Regdir(R.R0))) - | 0b0101us -> - Opcode.MOVW, - TwoOperands(OpReg(RegDisp(getDisp4b b16, getReg1s b16)), - OpReg(Regdir(R.R0))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Register Indirect with Displacement -/// 0001 ---- ---- ---- with source and destination operands. -let parseIndDisp0001 b16 = - Opcode.MOVL, - TwoOperands(OpReg(Regdir(getReg1s b16)), - OpReg(RegDisp(getDisp4b b16, getReg1d b16))) - -/// Register Indirect with Displacement -/// 0101 ---- ---- ---- with source and destination operands. -let parseIndDisp0101 b16 = - Opcode.MOVL, - TwoOperands(OpReg(RegDisp(getDisp4b b16, getReg1s b16)), - OpReg(Regdir(getReg1d b16))) - -/// Indexed Register Indirect -/// 0000 ---- ---- ---- with source and destination operands. -let parseIdxInd0000 b16 = - match getBits b16 4 1 with - | 0b0100us -> - Opcode.MOVB, - TwoOperands(OpReg(Regdir(getReg1s b16)), - OpReg(IdxIndir(R.R0, getReg1d b16))) - | 0b0101us -> - Opcode.MOVW, - TwoOperands(OpReg(Regdir(getReg1s b16)), - OpReg (IdxIndir(R.R0, getReg1d b16))) - | 0b0110us -> - Opcode.MOVL, - TwoOperands(OpReg(Regdir(getReg1s b16)), - OpReg (IdxIndir(R.R0, getReg1d b16))) - | 0b1100us -> - Opcode.MOVB, - TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), - OpReg(Regdir(getReg1d b16))) - | 0b1101us -> - Opcode.MOVW, - TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), - OpReg(Regdir(getReg1d b16))) - | 0b1110us -> - Opcode.MOVL, - TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), - OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Indexed Register Indirect -/// 1111 ---- ---- ---- with source and destination operands. -let parseIdxInd1111 b16 = - match getBits b16 4 1 with - | 0b0110us -> - if getState()(*SZ*) then - Opcode.FMOV, - TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), - OpReg(Regdir(getReg1dDR b16))) - else - Opcode.FMOVS, - TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), - OpReg(Regdir(getReg1dFR b16))) - | 0b0111us -> - if getState()(*SZ*) then - if get1Bit b16 5 then - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sXD b16)), - OpReg(IdxIndir(R.R0, getReg1d b16))) - else - Opcode.FMOV, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(IdxIndir(R.R0, getReg1d b16))) - else - Opcode.FMOVS, - TwoOperands(OpReg(Regdir(getReg1sFR b16)), - OpReg(IdxIndir(R.R0, getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// GBR Indirect with Displacement -/// 1100 ---- ---- ---- with source and destination operands. -let parseGBRIndDisp1100 b16 = - match getBits b16 12 9 with - | 0b0000us -> - Opcode.MOVB, - TwoOperands(OpReg(Regdir(R.R0)), OpReg(GbrDisp(getDisp8b b16, R.GBR))) - | 0b0001us -> - Opcode.MOVW, - TwoOperands(OpReg(Regdir(R.R0)), OpReg(GbrDisp(getDisp8b b16, R.GBR))) - | 0b0010us -> - Opcode.MOVL, - TwoOperands(OpReg(Regdir(R.R0)), OpReg(GbrDisp(getDisp8b b16, R.GBR))) - | 0b0100us -> - Opcode.MOVB, - TwoOperands(OpReg(GbrDisp(getDisp8b b16, R.GBR)), OpReg(Regdir(R.R0))) - | 0b0101us -> - Opcode.MOVW, - TwoOperands(OpReg(GbrDisp(getDisp8b b16, R.GBR)), OpReg(Regdir(R.R0))) - | 0b0110us -> - Opcode.MOVL, - TwoOperands(OpReg(GbrDisp(getDisp8b b16, R.GBR)), OpReg(Regdir(R.R0))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Indexed GBR Indirect -/// 1100 ---- ---- ---- with source and destination operands. -let parseIdxGBRInd1100 b16 = - match getBits b16 12 9 with - | 0b1101us -> - Opcode.ANDB, - TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) - | 0b1111us -> - Opcode.ORB, - TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) - | 0b1100us -> - Opcode.TSTB, - TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) - | 0b1110us -> - Opcode.XORB, - TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) - | _ -> Opcode.InvalidOp, NoOperand - -/// PC Relative with Displacement -/// 1001 ---- ---- ---- with source and destination operands. -let parsePCDisp1001 b16 = - Opcode.MOVW, - TwoOperands(OpReg(PCrDisp(getDisp8b b16, R.PC)), OpReg(Regdir(getReg1d b16))) - -/// PC Relative with Displacement -/// 1101 ---- ---- ---- with source and destination operands. -let parsePCDisp1101 b16 = - Opcode.MOVL, - TwoOperands(OpReg(PCrDisp(getDisp8b b16, R.PC)), OpReg(Regdir(getReg1d b16))) - -/// PC Relative with Displacement -/// 1100 ---- ---- ---- with source and destination operands. -let parsePCDisp1100 b16 = - Opcode.MOVA, - TwoOperands (OpReg (PCrDisp(getDisp8b b16, R.PC)), OpReg(Regdir(R.R0))) - -/// PC Relative using Rn -/// 0000 ---- ---- ---- destination operand only. -let parsePCReg0000 b16 = - match getBits b16 8 5 with - | 0b0010us -> Opcode.BRAF, OneOperand (OpReg(Regdir(getReg1d b16))) - | 0b0000us -> Opcode.BSRF, OneOperand (OpReg(Regdir(getReg1d b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// PC Relative 1000 ---- ---- ---- destination operand only. -let parsePC1000 b16 = - match getBits b16 8 5 with - | 0b1011us -> Opcode.BF, OneOperand(OpReg( PCr(getDisp8b b16))) - | 0b1111us -> Opcode.BFS, OneOperand(OpReg( PCr(getDisp8b b16))) - | 0b1001us -> Opcode.BT, OneOperand(OpReg( PCr(getDisp8b b16))) - | 0b1101us -> Opcode.BTS, OneOperand(OpReg( PCr(getDisp8b b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// PC Relative 1010 ---- ---- ---- destination operand only. -let parsePC1010 b16 = - Opcode.BRA, OneOperand(OpReg(PCr(getDisp12b b16))) - -/// PC Relative 1011 ---- ---- ---- destination operand only. -let parsePC1011 b16 = - Opcode.BSR, OneOperand(OpReg(PCr(getDisp12b b16))) - -/// Immediate -let parseImm1111 b16 = - match getBits b16 8 5 with - | 0b1000us -> Opcode.FLDI0, OneOperand (OpReg(Regdir(getReg1dFR b16))) - | 0b1001us -> Opcode.FLDI1, OneOperand (OpReg(Regdir(getReg1dFR b16))) - | _ -> Opcode.InvalidOp, NoOperand - -/// Immediate -let parseImm1110 b16 = - Opcode.MOV, - TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg(Regdir(getReg1d b16))) - -/// Immediate -let parseImm0111 b16 = - Opcode.ADD, - TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg(Regdir(getReg1d b16))) - -/// Immediate -let parseImm1000 b16 = - Opcode.CMPEQ, - TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) - -/// Immmediate -let parseImm1100 b16 = - match getBits b16 8 5 with - | 0b1001us -> - Opcode.AND, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) - | 0b1011us -> - Opcode.OR, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) - | 0b1000us -> - Opcode.TST, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) - | 0b1010us -> - Opcode.XOR, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) - | 0b0011us -> - Opcode.TRAPA, OneOperand (OpReg(Imm(getDisp8b b16))) - | _ -> Opcode.InvalidOp, NoOperand - -let parseNow b16 = - match getBits b16 16 13 with - | 0b0000us -> - match getBits b16 4 1 with - | 0b0111us | 0b0010us | 0b1010us -> twoOpParse0000 b16 - | 0b0011us -> - match getBits b16 8 5 with - | 0b0010us | 0b0000us -> parsePCReg0000 b16 - | _ -> parseRegInd0000 b16 - | 0b0100us | 0b0101us | 0b0110us | 0b1100us - | 0b1101us | 0b1110us -> parseIdxInd0000 b16 - | 0b1111us -> parsePostInc0000 b16 - | _ -> noOpParse0000 b16 - | 0b0100us -> - match getBits b16 4 1 with - | 0b1100us | 0b1110us | 0b1101us | 0b1010us -> twoOpParse0100 b16 - | 0b1011us -> parseRegInd0100 b16 - | 0b1111us | 0b0111us | 0b0110us -> parsePostInc0100 b16 - | 0b0011us | 0b0010us -> parsePreDec0100 b16 - | _ -> oneOpParse0100 b16 - | 0b0010us -> - match getBits b16 4 1 with - | 0b0000us | 0b0001us | 0b0010us -> parseRegInd0010 b16 - | 0b0100us | 0b0101us | 0b0110us -> parsePreDec0010 b16 - | _ -> twoOpParse0010 b16 - | 0b0110us -> - match getBits b16 4 1 with - | 0b0000us | 0b0001us | 0b0010us -> parseRegInd0010 b16 - | 0b0100us | 0b0101us | 0b0110us -> parsePostInc0110 b16 - | _ -> twoOpParse0110 b16 - | 0b0011us -> twoOpParse0011 b16 - | 0b1000us -> - match getBits b16 8 5 with - | 0b1011us | 0b1111us | 0b1001us | 0b1101us -> parsePC1000 b16 - | 0b1000us -> parseImm1000 b16 - | _ -> parseIndDisp1000 b16 - | 0b1001us -> parsePCDisp1001 b16 - | 0b1010us -> parsePC1010 b16 - | 0b1011us -> parsePC1011 b16 - | 0b1101us -> parsePCDisp1101 b16 - | 0b1110us -> parseImm1110 b16 - | 0b0111us -> parseImm0111 b16 - | 0b1100us -> - if get1Bit b16 12 then - match getBits b16 12 9 with - | 0b1001us | 0b1011us | 0b1000us | 0b1010us -> parseImm1100 b16 - | _ -> parseIdxGBRInd1100 b16 - else - if getBits b16 8 5 = 0b0111us then parsePCDisp1100 b16 - elif getBits b16 8 5 = 0b0011us then parseImm1100 b16 - else parseGBRIndDisp1100 b16 - | 0b0001us -> parseIndDisp0001 b16 - | 0b0101us -> parseIndDisp0101 b16 - | 0b1111us -> - if ((getBits b16 4 1 = 0b1101us) && (getBits b16 8 5 = 0b1111us)) then - match getBits b16 12 9 with - | 0b1011us | 0b0011us -> noOpParse1111 b16 - | _ -> twoOpParse1111 b16 - else - match getBits b16 4 1 with - | 0b1000us | 0b1010us -> parseRegInd1111 b16 - | 0b0110us | 0b0111us -> parseIdxInd1111 b16 - | 0b1001us -> parsePostInc1111 b16 - | 0b1011us -> parsePreDec1111 b16 - | 0b1101us -> parseImm1111 b16 - | _ -> - match getBits b16 8 5 with - | 0b0101us | 0b0100us | 0b0110us -> oneOpParse1111 b16 - | _ -> twoOpParse1111 b16 - | _ -> Utils.futureFeature() - -let parse (span: ByteSpan) (reader: IBinReader) addr = - let bin = reader.ReadUInt16 (span, 0) - let op, operands = parseNow bin - let insInfo = - { Address = addr - NumBytes = 2u - Opcode = op - Operands = operands } - SH4Instruction (addr, 2u, insInfo) diff --git a/src/FrontEnd/BinLifter/SH4/SH4ParsingMain.fs b/src/FrontEnd/BinLifter/SH4/SH4ParsingMain.fs new file mode 100644 index 00000000..a07e7c0f --- /dev/null +++ b/src/FrontEnd/BinLifter/SH4/SH4ParsingMain.fs @@ -0,0 +1,1076 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.SH4.ParsingMain + +open B2R2 + +open B2R2.FrontEnd.BinLifter.SH4.OperandHelper + +let getState = function + | _ -> Utils.futureFeature() + +/// 0000 0000 ---- ---- with no operands +let noOpParse0000 b16 = + match getBits b16 8 1 with + | 0b00011001us -> Opcode.DIV0U, NoOperand + | 0b00001011us -> Opcode.RTS, NoOperand + | 0b00101000us -> Opcode.CLRMAC, NoOperand + | 0b01001000us -> Opcode.CLRS, NoOperand + | 0b00001000us -> Opcode.CLRT, NoOperand + | 0b00111000us -> Opcode.LDTLB, NoOperand + | 0b00001001us -> Opcode.NOP, NoOperand + | 0b00101011us -> Opcode.RTE, NoOperand + | 0b01011000us -> Opcode.SETS, NoOperand + | 0b00011000us -> Opcode.SETT, NoOperand + | 0b00011011us -> Opcode.SLEEP, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 ---- 1111 1101 with no operands. +let noOpParse1111 b16 = + match getBits b16 12 9 with + | 0b1011us -> Opcode.FRCHG, NoOperand + | 0b0011us -> Opcode.FSCHG, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 0100 ---- ---- ---- with destination operand only. +let oneOpParse0100 b16 = + match getBits b16 8 5 with + | 0b0010us -> + match getBits b16 4 1 with + | 0b1001us -> Opcode.MOVT, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0100us -> Opcode.ROTCL, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0101us -> Opcode.ROTCR, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0000us -> Opcode.SHAL, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0001us -> Opcode.SHAR, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b1000us -> Opcode.SHLL16, OneOperand (OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + | 0b0001us -> + match getBits b16 4 1 with + | 0b0001us -> Opcode.CMPPZ, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0101us -> Opcode.CMPPL, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0000us -> Opcode.DT, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b1000us -> Opcode.SHLL8, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b1001us -> Opcode.SHLR8, OneOperand (OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + | 0b0000us -> + match getBits b16 4 1 with + | 0b0100us -> Opcode.ROTL, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0101us -> Opcode.ROTR, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0000us -> Opcode.SHLL, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0001us -> Opcode.SHLR, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b1000us -> Opcode.SHLL2, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b1001us -> Opcode.SHLR2, OneOperand (OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 ---- ---- 1101 with destination operand only. +let oneOpParse1111 b16 = + match getBits b16 8 5 with + | 0b0101us -> + if get1Bit b16 9 then + Opcode.FABS, OneOperand(OpReg(Regdir(getReg1dFR b16))) + else if getState() + then Opcode.FABS, OneOperand(OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FABS, OneOperand(OpReg(Regdir(getReg1dFR b16))) + | 0b0100us -> + if get1Bit b16 9 then + Opcode.FNEG, OneOperand(OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FNEG, OneOperand(OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FNEG, OneOperand(OpReg(Regdir(getReg1dFR b16))) + | 0b0110us -> + if get1Bit b16 9 then + Opcode.FSQRT, OneOperand(OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FSQRT, OneOperand(OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FSQRT, OneOperand(OpReg(Regdir(getReg1dFR b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// 0011 ---- ---- ---- with source and destination operands. +let twoOpParse0011 b16 = + match getBits b16 4 1 with + | 0b1100us -> + Opcode.ADD, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1110us -> + Opcode.ADDC, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1111us -> + Opcode.ADDV, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0000us -> + Opcode.CMPEQ, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0010us -> + Opcode.CMPHS, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0011us -> + Opcode.CMPGE, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0110us -> + Opcode.CMPHI, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0111us -> + Opcode.CMPGT, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0100us -> + Opcode.DIV1, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1101us -> + Opcode.DMULSL, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0101us -> + Opcode.DMULUL, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1000us -> + Opcode.SUB, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1010us -> + Opcode.SUBC, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1011us -> + Opcode.SUBV, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// 0110 ---- ---- ---- with source and destination operands. +let twoOpParse0110 b16 = + match getBits b16 4 1 with + | 0b0011us -> + Opcode.MOV, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1000us -> + Opcode.SWAPB, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1001us -> + Opcode.SWAPW, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1110us -> + Opcode.EXTSB, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1111us -> + Opcode.EXTSW, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1100us -> + Opcode.EXTUB, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1101us -> + Opcode.EXTUW, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1011us -> + Opcode.NEG, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1010us -> + Opcode.NEGC, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0111us -> + Opcode.NOT, + TwoOperands (OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// 0010 ---- ---- ---- with source and destination operands. +let twoOpParse0010 b16 = + match getBits b16 4 1 with + | 0b1101us -> + Opcode.XTRCT, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1100us -> + Opcode.CMPSTR, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0111us -> + Opcode.DIV0S, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1111us -> + Opcode.MULSW, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1110us -> + Opcode.MULUW, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1001us -> + Opcode.AND, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1011us -> + Opcode.OR, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1000us -> + Opcode.TST, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1010us -> + Opcode.XOR, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// 0100 ---- ---- ---- with source and destination operands. +let twoOpParse0100 b16 = + match getBits b16 4 1 with + | 0b1100us -> + Opcode.SHAD, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1101us -> + Opcode.SHLD, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b1110us -> + match getBits b16 8 5 with + | 0b0000us -> + Opcode.LDC, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.SR))) + | 0b0001us -> + Opcode.LDC, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.GBR))) + | 0b0010us -> + Opcode.LDC, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.VBR))) + | 0b0011us -> + Opcode.LDC, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.SSR))) + | 0b0100us -> + Opcode.LDC, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.SPC))) + | 0b1000us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1001us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1010us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1011us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1100us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1101us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1110us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | 0b1111us -> + Opcode.LDC, + TwoOperands(OpReg(Regdir(getReg1d b16)), OpReg(Regdir(getReg1dBank b16))) + | _ -> Opcode.InvalidOp, NoOperand + | 0b1010us -> + match getBits b16 8 5 with + | 0b1111us -> + Opcode.LDC, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.DBR))) + | 0b0000us -> + Opcode.LDS, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.MACH))) + | 0b0001us -> + Opcode.LDS, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.MACL))) + | 0b0010us -> + Opcode.LDS, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.PR))) + | 0b0110us -> + Opcode.LDS, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.FPSCR))) + | 0b0101us -> + Opcode.LDS, + TwoOperands( OpReg(Regdir(getReg1d b16)), OpReg(Regdir(R.FPUL))) + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 0000 ---- ---- ---- with source and destination operand. +let twoOpParse0000 b16 = + match getBits b16 4 1 with + | 0b0111us -> + Opcode.MULL, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0010us -> + match getBits b16 8 5 with + | 0b0000us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.SR)), OpReg(Regdir(getReg1d b16))) + | 0b0001us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.GBR)), OpReg(Regdir(getReg1d b16))) + | 0b0010us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.VBR)), OpReg(Regdir(getReg1d b16))) + | 0b0011us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.SSR)), OpReg(Regdir(getReg1d b16))) + | 0b0100us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.SPC)), OpReg(Regdir(getReg1d b16))) + | 0b1000us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1001us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1010us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1011us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1100us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1101us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1110us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | 0b1111us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + | 0b1010us -> + match getBits b16 8 5 with + | 0b0011us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.SGR)), OpReg(Regdir(getReg1d b16))) + | 0b1111us -> + Opcode.STC, + TwoOperands(OpReg(Regdir(R.DBR)), OpReg(Regdir(getReg1d b16))) + | 0b0000us -> + Opcode.STS, + TwoOperands(OpReg(Regdir(R.MACH)), OpReg(Regdir(getReg1d b16))) + | 0b0001us -> + Opcode.STS, + TwoOperands(OpReg(Regdir(R.MACL)), OpReg(Regdir(getReg1d b16))) + | 0b0010us -> + Opcode.STS, + TwoOperands(OpReg(Regdir(R.PR)), OpReg(Regdir(getReg1d b16))) + | 0b0110us -> + Opcode.STS, + TwoOperands(OpReg(Regdir(R.FPSCR)), OpReg(Regdir(getReg1d b16))) + | 0b0101us -> + Opcode.STS, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// 1111 ---- ---- ---- with source and destination operands. +let twoOpParse1111 b16 = + match getBits b16 4 1 with + | 0b1110us -> + Opcode.FMAC, + ThreeOperands(OpReg(Regdir(R.FR0)), OpReg(Regdir(getReg1sFR b16)), + OpReg(Regdir(getReg1dFR b16))) + | 0b0000us -> + if get1Bit b16 5 then + Opcode.FADD, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FADD, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FADD, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + | 0b0100us -> + if get1Bit b16 5 then + Opcode.FCMPEQ, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FCMPEQ, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FCMPEQ, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + | 0b0101us -> + if get1Bit b16 5 then + Opcode.FCMPGT, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FCMPGT, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FCMPGT, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + | 0b0011us -> + if get1Bit b16 5 then + Opcode.FDIV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FDIV, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FDIV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + | 0b0010us -> + if get1Bit b16 5 then + Opcode.FMUL, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FMUL, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FMUL, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + | 0b0001us -> + if get1Bit b16 5 then + Opcode.FSUB, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FSUB, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FSUB, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(Regdir(getReg1dFR b16))) + | 0b1100us -> + if (get1Bit b16 5 && get1Bit b16 9) then + if getState() then + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sXD b16)), + OpReg(Regdir(getReg1dXD b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(Regdir(getReg1dFR b16))) + elif ((get1Bit b16 9) && not(get1Bit b16 5)) then + if getState() then + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), + OpReg(Regdir(getReg1dXD b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(Regdir(getReg1dFR b16))) + elif ((get1Bit b16 5) && not(get1Bit b16 9)) then + if getState() then + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sXD b16)), + OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(Regdir(getReg1dFR b16))) + else + if getState() then + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), + OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(Regdir(getReg1dFR b16))) + | 0b1101us -> + match getBits b16 8 5 with + | 0b1110us -> + Opcode.FIPR, + TwoOperands(OpReg(Regdir(getReg1sFV b16)), OpReg(Regdir(getReg1dFV b16))) + | 0b1111us -> + Opcode.FTRV, + TwoOperands(OpReg(Regdir(R.XMTRX)), OpReg(Regdir(getReg1dFV b16))) + | 0b0001us -> + Opcode.FLDS, + TwoOperands(OpReg(Regdir(getReg1dFR b16)), OpReg(Regdir(R.FPUL))) + | 0b1011us -> + Opcode.FCNVDS, + TwoOperands(OpReg(Regdir(getReg1dDR b16)), OpReg(Regdir(R.FPUL))) + | 0b0011us -> + if get1Bit b16 9 then + Opcode.FTRC, + TwoOperands(OpReg(Regdir(getReg1dFR b16)), OpReg(Regdir(R.FPUL))) + else if getState() then + Opcode.FTRC, + TwoOperands(OpReg(Regdir(getReg1dDR b16)), OpReg(Regdir(R.FPUL))) + else + Opcode.FTRC, + TwoOperands(OpReg(Regdir(getReg1dFR b16)), OpReg(Regdir (R.FPUL))) + | 0b0000us -> + Opcode.FSTS, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) + | 0b1010us -> + Opcode.FCNVSD, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dDR b16))) + | 0b0010us -> + if get1Bit b16 9 then + Opcode.FLOAT, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) + else if getState() then + Opcode.FLOAT, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) + else + Opcode.FLOAT, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(Regdir(getReg1dFR b16))) + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect 0100 ---- ---- ---- with destination operand only. +let parseRegInd0100 b16 = + match getBits b16 8 5 with + | 0b0001us -> Opcode.TASB, OneOperand( OpReg(RegIndir(getReg1d b16))) + | 0b0010us -> Opcode.JMP, OneOperand( OpReg(RegIndir(getReg1d b16))) + | 0b0000us -> Opcode.JSR, OneOperand( OpReg(RegIndir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect 0000 ---- ---- ---- with destination operand only. +let parseRegInd0000 b16 = + match getBits b16 8 5 with + | 0b1001us -> Opcode.OCBI, OneOperand( OpReg(RegIndir(getReg1d b16))) + | 0b1010us -> Opcode.OCBP, OneOperand( OpReg(RegIndir(getReg1d b16))) + | 0b1011us -> Opcode.OCBWB, OneOperand( OpReg(RegIndir(getReg1d b16))) + | 0b1000us -> Opcode.PREF, OneOperand( OpReg(RegIndir(getReg1d b16))) + | 0b1100us -> + Opcode.MOVCAL, + TwoOperands(OpReg(Regdir(R.R0)), OpReg(RegIndir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect 0010 ---- ---- ---- with source and destination operands. +let parseRegInd0010 b16 = + match getBits b16 4 1 with + | 0b0000us -> + Opcode.MOVB, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(RegIndir(getReg1d b16))) + | 0b0001us -> + Opcode.MOVW, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(RegIndir(getReg1d b16))) + | 0b0010us -> + Opcode.MOVL, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(RegIndir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect 0110 ---- ---- ---- with source and destination operands. +let parseRegInd0110 b16 = + match getBits b16 4 1 with + | 0b0000us -> + Opcode.MOVB, + TwoOperands(OpReg(RegIndir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0001us -> + Opcode.MOVW, + TwoOperands(OpReg(RegIndir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0010us -> + Opcode.MOVL, + TwoOperands(OpReg(RegIndir(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect 1111 ---- ---- ---- with source and destination operands. +let parseRegInd1111 b16 = + match getBits b16 4 1 with + | 0b1000us -> + if getState() then + if get1Bit b16 9 then + Opcode.FMOV, + TwoOperands(OpReg(RegIndir(getReg1s b16)), + OpReg(Regdir(getReg1dXD b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(RegIndir(getReg1s b16)), + OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FMOVS, + TwoOperands(OpReg(RegIndir(getReg1s b16)), + OpReg(Regdir(getReg1sFR b16))) + | 0b1010us -> + if getState() then + if get1Bit b16 5 then + Opcode.FMOV, + TwoOperands( OpReg(Regdir(getReg1sXD b16)), + OpReg(RegIndir(getReg1d b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), + OpReg(RegIndir(getReg1d b16))) + else + Opcode.FMOVS, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(RegIndir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Post-Increment) +/// 0000 ---- ---- ---- with source and destination operands. +let parsePostInc0000 b16 = + match getBits b16 4 1 with + | 0b1111us -> + Opcode.MACL, + TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(PostInc(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Post-Increment) +/// 0100 ---- ---- ---- with source and destination operands. +let parsePostInc0100 b16 = + match getBits b16 4 1 with + | 0b1111us -> + Opcode.MACW, + TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(PostInc(getReg1d b16))) + | 0b0111us -> + match getBits b16 8 5 with + | 0b0000us -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.SR))) + | 0b0001us -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.GBR))) + | 0b0010us -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.VBR))) + | 0b0011us -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.SSR))) + | 0b0100us -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.SPC))) + | _ -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), + OpReg(Regdir(getReg1dBank b16))) + | 0b0110us -> + match getBits b16 8 5 with + | 0b1111us -> + Opcode.LDCL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.DBR))) + | 0b0000us -> + Opcode.LDSL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.MACH))) + | 0b0001us -> + Opcode.LDSL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.MACL))) + | 0b0010us -> + Opcode.LDSL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.PR))) + | 0b0110us -> + Opcode.LDSL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.FPSCR))) + | 0b0101us -> + Opcode.LDSL, + TwoOperands(OpReg(PostInc(getReg1d b16)), OpReg(Regdir(R.FPUL))) + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Post-Increment) +/// 0110 ---- ---- ---- with source and destination operands. +let parsePostInc0110 b16 = + match getBits b16 4 1 with + | 0b0100us -> + Opcode.MOVB, + TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0101us -> + Opcode.MOVW, + TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | 0b0110us -> + Opcode.MOVL, + TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Post-Increment) +/// 1111 ---- ---- ---- with source and destination operands. +let parsePostInc1111 b16 = + match getBits b16 4 1 with + | 0b1001us -> + if getState() then + if get1Bit b16 9 then + Opcode.FMOV, + TwoOperands(OpReg(PostInc(getReg1s b16)), + OpReg(Regdir(getReg1dXD b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(PostInc(getReg1s b16)), + OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FMOVS, + TwoOperands(OpReg(PostInc(getReg1s b16)), OpReg(Regdir(getReg1dFR b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Pre-Decrement) +/// 0000 ---- ---- ---- with source and destination operands. +let parsePreDec0010 b16 = + match getBits b16 4 1 with + | 0b0100us -> + Opcode.MOVB, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(PreDec(getReg1d b16))) + | 0b0101us -> + Opcode.MOVW, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(PreDec(getReg1d b16))) + | 0b0110us -> + Opcode.MOVL, + TwoOperands(OpReg(Regdir(getReg1s b16)), OpReg(PreDec(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Pre-Decrement) +/// 1111 ---- ---- ---- with source and destination operands. +let parsePreDec1111 b16 = + match getBits b16 4 1 with + | 0b1011us -> + if getState() (*SZ*) then + if get1Bit b16 5 then + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sDR b16)), OpReg(PreDec(getReg1d b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sXD b16)), OpReg(PreDec(getReg1d b16))) + else + Opcode.FMOVS, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), OpReg(PreDec(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect (Pre-Decrement) +/// 0100 ---- ---- ---- with source and destination operands. +let parsePreDec0100 b16 = + match getBits b16 4 1 with + | 0b0011us -> + match getBits b16 8 5 with + | 0b0000us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.SR)), OpReg(PreDec(getReg1d b16))) + | 0b0001us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.GBR)), OpReg(PreDec(getReg1d b16))) + | 0b0010us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.VBR)), OpReg(PreDec(getReg1d b16))) + | 0b0011us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.SSR)), OpReg(PreDec(getReg1d b16))) + | 0b0100us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.SPC)), OpReg(PreDec(getReg1d b16))) + | _ -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(getReg1dBank b16)), OpReg(PreDec(getReg1d b16))) + | 0b0010us -> + match getBits b16 8 5 with + | 0b0011us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.SGR)), OpReg(PreDec(getReg1d b16))) + | 0b1111us -> + Opcode.STCL, + TwoOperands(OpReg(Regdir(R.DBR)), OpReg(PreDec(getReg1d b16))) + | 0b0000us -> + Opcode.STSL, + TwoOperands(OpReg(Regdir(R.MACH)), OpReg(PreDec(getReg1d b16))) + | 0b0001us -> + Opcode.STSL, + TwoOperands(OpReg(Regdir(R.MACL)), OpReg(PreDec(getReg1d b16))) + | 0b0010us -> + Opcode.STSL, + TwoOperands(OpReg(Regdir(R.PR)), OpReg(PreDec(getReg1d b16))) + | 0b0110us -> + Opcode.STSL, + TwoOperands(OpReg(Regdir(R.FPSCR)), OpReg(PreDec(getReg1d b16))) + | 0b0101us -> + Opcode.STSL, + TwoOperands(OpReg(Regdir(R.FPUL)), OpReg(PreDec(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect with Displacement +/// 1000 ---- ---- ---- with source and destination operands. +let parseIndDisp1000 b16 = + match getBits b16 12 9 with + | 0b0000us -> + Opcode.MOVB, + TwoOperands(OpReg(Regdir(R.R0)), + OpReg(RegDisp(getDisp4b b16, getReg1s b16))) + | 0b0001us -> + Opcode.MOVW, + TwoOperands(OpReg(Regdir(R.R0)), + OpReg(RegDisp(getDisp4b b16, getReg1s b16))) + | 0b0100us -> + Opcode.MOVB, + TwoOperands(OpReg(RegDisp(getDisp4b b16, getReg1s b16)), + OpReg(Regdir(R.R0))) + | 0b0101us -> + Opcode.MOVW, + TwoOperands(OpReg(RegDisp(getDisp4b b16, getReg1s b16)), + OpReg(Regdir(R.R0))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Register Indirect with Displacement +/// 0001 ---- ---- ---- with source and destination operands. +let parseIndDisp0001 b16 = + Opcode.MOVL, + TwoOperands(OpReg(Regdir(getReg1s b16)), + OpReg(RegDisp(getDisp4b b16, getReg1d b16))) + +/// Register Indirect with Displacement +/// 0101 ---- ---- ---- with source and destination operands. +let parseIndDisp0101 b16 = + Opcode.MOVL, + TwoOperands(OpReg(RegDisp(getDisp4b b16, getReg1s b16)), + OpReg(Regdir(getReg1d b16))) + +/// Indexed Register Indirect +/// 0000 ---- ---- ---- with source and destination operands. +let parseIdxInd0000 b16 = + match getBits b16 4 1 with + | 0b0100us -> + Opcode.MOVB, + TwoOperands(OpReg(Regdir(getReg1s b16)), + OpReg(IdxIndir(R.R0, getReg1d b16))) + | 0b0101us -> + Opcode.MOVW, + TwoOperands(OpReg(Regdir(getReg1s b16)), + OpReg (IdxIndir(R.R0, getReg1d b16))) + | 0b0110us -> + Opcode.MOVL, + TwoOperands(OpReg(Regdir(getReg1s b16)), + OpReg (IdxIndir(R.R0, getReg1d b16))) + | 0b1100us -> + Opcode.MOVB, + TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), + OpReg(Regdir(getReg1d b16))) + | 0b1101us -> + Opcode.MOVW, + TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), + OpReg(Regdir(getReg1d b16))) + | 0b1110us -> + Opcode.MOVL, + TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), + OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Indexed Register Indirect +/// 1111 ---- ---- ---- with source and destination operands. +let parseIdxInd1111 b16 = + match getBits b16 4 1 with + | 0b0110us -> + if getState()(*SZ*) then + Opcode.FMOV, + TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), + OpReg(Regdir(getReg1dDR b16))) + else + Opcode.FMOVS, + TwoOperands(OpReg(IdxIndir(R.R0, getReg1s b16)), + OpReg(Regdir(getReg1dFR b16))) + | 0b0111us -> + if getState()(*SZ*) then + if get1Bit b16 5 then + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sXD b16)), + OpReg(IdxIndir(R.R0, getReg1d b16))) + else + Opcode.FMOV, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(IdxIndir(R.R0, getReg1d b16))) + else + Opcode.FMOVS, + TwoOperands(OpReg(Regdir(getReg1sFR b16)), + OpReg(IdxIndir(R.R0, getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// GBR Indirect with Displacement +/// 1100 ---- ---- ---- with source and destination operands. +let parseGBRIndDisp1100 b16 = + match getBits b16 12 9 with + | 0b0000us -> + Opcode.MOVB, + TwoOperands(OpReg(Regdir(R.R0)), OpReg(GbrDisp(getDisp8b b16, R.GBR))) + | 0b0001us -> + Opcode.MOVW, + TwoOperands(OpReg(Regdir(R.R0)), OpReg(GbrDisp(getDisp8b b16, R.GBR))) + | 0b0010us -> + Opcode.MOVL, + TwoOperands(OpReg(Regdir(R.R0)), OpReg(GbrDisp(getDisp8b b16, R.GBR))) + | 0b0100us -> + Opcode.MOVB, + TwoOperands(OpReg(GbrDisp(getDisp8b b16, R.GBR)), OpReg(Regdir(R.R0))) + | 0b0101us -> + Opcode.MOVW, + TwoOperands(OpReg(GbrDisp(getDisp8b b16, R.GBR)), OpReg(Regdir(R.R0))) + | 0b0110us -> + Opcode.MOVL, + TwoOperands(OpReg(GbrDisp(getDisp8b b16, R.GBR)), OpReg(Regdir(R.R0))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Indexed GBR Indirect +/// 1100 ---- ---- ---- with source and destination operands. +let parseIdxGBRInd1100 b16 = + match getBits b16 12 9 with + | 0b1101us -> + Opcode.ANDB, + TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) + | 0b1111us -> + Opcode.ORB, + TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) + | 0b1100us -> + Opcode.TSTB, + TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) + | 0b1110us -> + Opcode.XORB, + TwoOperands(OpReg(Imm(getDisp8b b16)), OpReg(IdxGbr(R.R0, R.GBR))) + | _ -> Opcode.InvalidOp, NoOperand + +/// PC Relative with Displacement +/// 1001 ---- ---- ---- with source and destination operands. +let parsePCDisp1001 b16 = + Opcode.MOVW, + TwoOperands(OpReg(PCrDisp(getDisp8b b16, R.PC)), OpReg(Regdir(getReg1d b16))) + +/// PC Relative with Displacement +/// 1101 ---- ---- ---- with source and destination operands. +let parsePCDisp1101 b16 = + Opcode.MOVL, + TwoOperands(OpReg(PCrDisp(getDisp8b b16, R.PC)), OpReg(Regdir(getReg1d b16))) + +/// PC Relative with Displacement +/// 1100 ---- ---- ---- with source and destination operands. +let parsePCDisp1100 b16 = + Opcode.MOVA, + TwoOperands (OpReg (PCrDisp(getDisp8b b16, R.PC)), OpReg(Regdir(R.R0))) + +/// PC Relative using Rn +/// 0000 ---- ---- ---- destination operand only. +let parsePCReg0000 b16 = + match getBits b16 8 5 with + | 0b0010us -> Opcode.BRAF, OneOperand (OpReg(Regdir(getReg1d b16))) + | 0b0000us -> Opcode.BSRF, OneOperand (OpReg(Regdir(getReg1d b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// PC Relative 1000 ---- ---- ---- destination operand only. +let parsePC1000 b16 = + match getBits b16 8 5 with + | 0b1011us -> Opcode.BF, OneOperand(OpReg( PCr(getDisp8b b16))) + | 0b1111us -> Opcode.BFS, OneOperand(OpReg( PCr(getDisp8b b16))) + | 0b1001us -> Opcode.BT, OneOperand(OpReg( PCr(getDisp8b b16))) + | 0b1101us -> Opcode.BTS, OneOperand(OpReg( PCr(getDisp8b b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// PC Relative 1010 ---- ---- ---- destination operand only. +let parsePC1010 b16 = + Opcode.BRA, OneOperand(OpReg(PCr(getDisp12b b16))) + +/// PC Relative 1011 ---- ---- ---- destination operand only. +let parsePC1011 b16 = + Opcode.BSR, OneOperand(OpReg(PCr(getDisp12b b16))) + +/// Immediate +let parseImm1111 b16 = + match getBits b16 8 5 with + | 0b1000us -> Opcode.FLDI0, OneOperand (OpReg(Regdir(getReg1dFR b16))) + | 0b1001us -> Opcode.FLDI1, OneOperand (OpReg(Regdir(getReg1dFR b16))) + | _ -> Opcode.InvalidOp, NoOperand + +/// Immediate +let parseImm1110 b16 = + Opcode.MOV, + TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg(Regdir(getReg1d b16))) + +/// Immediate +let parseImm0111 b16 = + Opcode.ADD, + TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg(Regdir(getReg1d b16))) + +/// Immediate +let parseImm1000 b16 = + Opcode.CMPEQ, + TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) + +/// Immmediate +let parseImm1100 b16 = + match getBits b16 8 5 with + | 0b1001us -> + Opcode.AND, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) + | 0b1011us -> + Opcode.OR, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) + | 0b1000us -> + Opcode.TST, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) + | 0b1010us -> + Opcode.XOR, TwoOperands (OpReg(Imm(getDisp8b b16)), OpReg (Regdir(R.R0))) + | 0b0011us -> + Opcode.TRAPA, OneOperand (OpReg(Imm(getDisp8b b16))) + | _ -> Opcode.InvalidOp, NoOperand + +let parseNow b16 = + match getBits b16 16 13 with + | 0b0000us -> + match getBits b16 4 1 with + | 0b0111us | 0b0010us | 0b1010us -> twoOpParse0000 b16 + | 0b0011us -> + match getBits b16 8 5 with + | 0b0010us | 0b0000us -> parsePCReg0000 b16 + | _ -> parseRegInd0000 b16 + | 0b0100us | 0b0101us | 0b0110us | 0b1100us + | 0b1101us | 0b1110us -> parseIdxInd0000 b16 + | 0b1111us -> parsePostInc0000 b16 + | _ -> noOpParse0000 b16 + | 0b0100us -> + match getBits b16 4 1 with + | 0b1100us | 0b1110us | 0b1101us | 0b1010us -> twoOpParse0100 b16 + | 0b1011us -> parseRegInd0100 b16 + | 0b1111us | 0b0111us | 0b0110us -> parsePostInc0100 b16 + | 0b0011us | 0b0010us -> parsePreDec0100 b16 + | _ -> oneOpParse0100 b16 + | 0b0010us -> + match getBits b16 4 1 with + | 0b0000us | 0b0001us | 0b0010us -> parseRegInd0010 b16 + | 0b0100us | 0b0101us | 0b0110us -> parsePreDec0010 b16 + | _ -> twoOpParse0010 b16 + | 0b0110us -> + match getBits b16 4 1 with + | 0b0000us | 0b0001us | 0b0010us -> parseRegInd0010 b16 + | 0b0100us | 0b0101us | 0b0110us -> parsePostInc0110 b16 + | _ -> twoOpParse0110 b16 + | 0b0011us -> twoOpParse0011 b16 + | 0b1000us -> + match getBits b16 8 5 with + | 0b1011us | 0b1111us | 0b1001us | 0b1101us -> parsePC1000 b16 + | 0b1000us -> parseImm1000 b16 + | _ -> parseIndDisp1000 b16 + | 0b1001us -> parsePCDisp1001 b16 + | 0b1010us -> parsePC1010 b16 + | 0b1011us -> parsePC1011 b16 + | 0b1101us -> parsePCDisp1101 b16 + | 0b1110us -> parseImm1110 b16 + | 0b0111us -> parseImm0111 b16 + | 0b1100us -> + if get1Bit b16 12 then + match getBits b16 12 9 with + | 0b1001us | 0b1011us | 0b1000us | 0b1010us -> parseImm1100 b16 + | _ -> parseIdxGBRInd1100 b16 + else + if getBits b16 8 5 = 0b0111us then parsePCDisp1100 b16 + elif getBits b16 8 5 = 0b0011us then parseImm1100 b16 + else parseGBRIndDisp1100 b16 + | 0b0001us -> parseIndDisp0001 b16 + | 0b0101us -> parseIndDisp0101 b16 + | 0b1111us -> + if ((getBits b16 4 1 = 0b1101us) && (getBits b16 8 5 = 0b1111us)) then + match getBits b16 12 9 with + | 0b1011us | 0b0011us -> noOpParse1111 b16 + | _ -> twoOpParse1111 b16 + else + match getBits b16 4 1 with + | 0b1000us | 0b1010us -> parseRegInd1111 b16 + | 0b0110us | 0b0111us -> parseIdxInd1111 b16 + | 0b1001us -> parsePostInc1111 b16 + | 0b1011us -> parsePreDec1111 b16 + | 0b1101us -> parseImm1111 b16 + | _ -> + match getBits b16 8 5 with + | 0b0101us | 0b0100us | 0b0110us -> oneOpParse1111 b16 + | _ -> twoOpParse1111 b16 + | _ -> Utils.futureFeature() + +let parse (span: ByteSpan) (reader: IBinReader) addr = + let bin = reader.ReadUInt16 (span, 0) + let op, operands = parseNow bin + let insInfo = + { Address = addr + NumBytes = 2u + Opcode = op + Operands = operands } + SH4Instruction (addr, 2u, insInfo) diff --git a/src/FrontEnd/BinLifter/SH4/SH4RegExprs.fs b/src/FrontEnd/BinLifter/SH4/SH4RegExprs.fs index 0238f5a6..3e04b099 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4RegExprs.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4RegExprs.fs @@ -25,149 +25,155 @@ namespace B2R2.FrontEnd.BinLifter.SH4 open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type internal RegExprs (wordSize) = +module R = Register - let var sz t name = AST.var sz t name (SH4RegisterSet.singleton t) +type RegExprs (wordSize) = + + let var sz t name = AST.var sz t name let regType = WordSize.toRegType wordSize - member val R0 = var (regType) (Register.toRegID Register.R0) "R0" with get - member val R1 = var (regType) (Register.toRegID Register.R1) "R1" with get - member val R2 = var (regType) (Register.toRegID Register.R2) "R2" with get - member val R3 = var (regType) (Register.toRegID Register.R3) "R3" with get - member val R4 = var (regType) (Register.toRegID Register.R4) "R4" with get - member val R5 = var (regType) (Register.toRegID Register.R5) "R5" with get - member val R6 = var (regType) (Register.toRegID Register.R6) "R6" with get - member val R7 = var (regType) (Register.toRegID Register.R7) "R7" with get - member val R8 = var (regType) (Register.toRegID Register.R8) "R8" with get - member val R9 = var (regType) (Register.toRegID Register.R9) "R9" with get - member val R10 = var (regType) (Register.toRegID Register.R10) "R10" with get - member val R11 = var (regType) (Register.toRegID Register.R11) "R11" with get - member val R12 = var (regType) (Register.toRegID Register.R12) "R12" with get - member val R13 = var (regType) (Register.toRegID Register.R13) "R13" with get - member val R14 = var (regType) (Register.toRegID Register.R14) "R14" with get - member val R15 = var (regType) (Register.toRegID Register.R15) "R15" with get - member val R0_BANK = var (regType) (Register.toRegID Register.R0_BANK) "R0_BANK" with get - member val R1_BANK = var (regType) (Register.toRegID Register.R1_BANK) "R1_BANK" with get - member val R2_BANK = var (regType) (Register.toRegID Register.R2_BANK) "R2_BANK" with get - member val R3_BANK = var (regType) (Register.toRegID Register.R3_BANK) "R3_BANK" with get - member val R4_BANK = var (regType) (Register.toRegID Register.R4_BANK) "R4_BANK" with get - member val R5_BANK = var (regType) (Register.toRegID Register.R5_BANK) "R5_BANK" with get - member val R6_BANK = var (regType) (Register.toRegID Register.R6_BANK) "R6_BANK" with get - member val R7_BANK = var (regType) (Register.toRegID Register.R7_BANK) "R7_BANK" with get - member val SR = var (regType) (Register.toRegID Register.SR) "SR" with get - member val GBR = var (regType) (Register.toRegID Register.GBR) "GBR" with get - member val SSR = var (regType) (Register.toRegID Register.SSR) "SSR" with get - member val SPC = var (regType) (Register.toRegID Register.SPC) "SPC" with get - member val SGR = var (regType) (Register.toRegID Register.SGR) "SGR" with get - member val DBR = var (regType) (Register.toRegID Register.DBR) "DBR" with get - member val VBR = var (regType) (Register.toRegID Register.VBR) "VBR" with get - member val MACH = var (regType) (Register.toRegID Register.MACH) "MACH" with get - member val MACL = var (regType) (Register.toRegID Register.MACL) "MACL" with get - member val PR = var (regType) (Register.toRegID Register.PR) "PR" with get - member val FPUL = var (regType) (Register.toRegID Register.FPUL) "FPUL" with get - member val PC = var (regType) (Register.toRegID Register.PC) "PC" with get - member val FPSCR = var (regType) (Register.toRegID Register.FPSCR) "FPSCR" with get - member val FPR0 = var (regType) (Register.toRegID Register.FPR0) "FPR0" with get - member val FPR1 = var (regType) (Register.toRegID Register.FPR1) "FPR1" with get - member val FPR2 = var (regType) (Register.toRegID Register.FPR2) "FPR2" with get - member val FPR3 = var (regType) (Register.toRegID Register.FPR3) "FPR3" with get - member val FPR4 = var (regType) (Register.toRegID Register.FPR4) "FPR4" with get - member val FPR5 = var (regType) (Register.toRegID Register.FPR5) "FPR5" with get - member val FPR6 = var (regType) (Register.toRegID Register.FPR6) "FPR6" with get - member val FPR7 = var (regType) (Register.toRegID Register.FPR7) "FPR7" with get - member val FPR8 = var (regType) (Register.toRegID Register.FPR8) "FPR8" with get - member val FPR9 = var (regType) (Register.toRegID Register.FPR9) "FPR9" with get - member val FPR10 = var (regType) (Register.toRegID Register.FPR10) "FPR10" with get - member val FPR11 = var (regType) (Register.toRegID Register.FPR11) "FPR11" with get - member val FPR12 = var (regType) (Register.toRegID Register.FPR12) "FPR12" with get - member val FPR13 = var (regType) (Register.toRegID Register.FPR13) "FPR13" with get - member val FPR14 = var (regType) (Register.toRegID Register.FPR14) "FPR14" with get - member val FPR15 = var (regType) (Register.toRegID Register.FPR15) "FPR15" with get - member val FR0 = var (regType) (Register.toRegID Register.FR0) "FR0" with get - member val FR1 = var (regType) (Register.toRegID Register.FR1) "FR1" with get - member val FR2 = var (regType) (Register.toRegID Register.FR2) "FR2" with get - member val FR3 = var (regType) (Register.toRegID Register.FR3) "FR3" with get - member val FR4 = var (regType) (Register.toRegID Register.FR4) "FR4" with get - member val FR5 = var (regType) (Register.toRegID Register.FR5) "FR5" with get - member val FR6 = var (regType) (Register.toRegID Register.FR6) "FR6" with get - member val FR7 = var (regType) (Register.toRegID Register.FR7) "FR7" with get - member val FR8 = var (regType) (Register.toRegID Register.FR8) "FR8" with get - member val FR9 = var (regType) (Register.toRegID Register.FR9) "FR9" with get - member val FR10 = var (regType) (Register.toRegID Register.FR10) "FR10" with get - member val FR11 = var (regType) (Register.toRegID Register.FR11) "FR11" with get - member val FR12 = var (regType) (Register.toRegID Register.FR12) "FR12" with get - member val FR13 = var (regType) (Register.toRegID Register.FR13) "FR13" with get - member val FR14 = var (regType) (Register.toRegID Register.FR14) "FR14" with get - member val FR15 = var (regType) (Register.toRegID Register.FR15) "FR15" with get - member val DR0 = var (regType) (Register.toRegID Register.DR0) "DR0" with get - member val DR2 = var (regType) (Register.toRegID Register.DR2) "DR2" with get - member val DR4 = var (regType) (Register.toRegID Register.DR4) "DR4" with get - member val DR6 = var (regType) (Register.toRegID Register.DR6) "DR6" with get - member val DR8 = var (regType) (Register.toRegID Register.DR8) "DR8" with get - member val DR10 = var (regType) (Register.toRegID Register.DR10) "DR10" with get - member val DR12 = var (regType) (Register.toRegID Register.DR12) "DR12" with get - member val DR14 = var (regType) (Register.toRegID Register.DR14) "DR14" with get - member val FV0 = var (regType) (Register.toRegID Register.FV0) "FV0" with get - member val FV4 = var (regType) (Register.toRegID Register.FV4) "FV4" with get - member val FV8 = var (regType) (Register.toRegID Register.FV8) "FV8" with get - member val FV12 = var (regType) (Register.toRegID Register.FV12) "FV12" with get - member val XD0 = var (regType) (Register.toRegID Register.XD0) "XD0" with get - member val XD2 = var (regType) (Register.toRegID Register.XD2) "XD2" with get - member val XD4 = var (regType) (Register.toRegID Register.XD4) "XD4" with get - member val XD6 = var (regType) (Register.toRegID Register.XD6) "XD6" with get - member val XD8 = var (regType) (Register.toRegID Register.XD8) "XD8" with get - member val XD10 = var (regType) (Register.toRegID Register.XD10) "XD10" with get - member val XD12 = var (regType) (Register.toRegID Register.XD12) "XD12" with get - member val XD14 = var (regType) (Register.toRegID Register.XD14) "XD14" with get - member val XF0 = var (regType) (Register.toRegID Register.XF0) "XF0" with get - member val XF1 = var (regType) (Register.toRegID Register.XF1) "XF1" with get - member val XF2 = var (regType) (Register.toRegID Register.XF2) "XF2" with get - member val XF3 = var (regType) (Register.toRegID Register.XF3) "XF3" with get - member val XF4 = var (regType) (Register.toRegID Register.XF4) "XF4" with get - member val XF5 = var (regType) (Register.toRegID Register.XF5) "XF5" with get - member val XF6 = var (regType) (Register.toRegID Register.XF6) "XF6" with get - member val XF7 = var (regType) (Register.toRegID Register.XF7) "XF7" with get - member val XF8 = var (regType) (Register.toRegID Register.XF8) "XF8" with get - member val XF9 = var (regType) (Register.toRegID Register.XF9) "XF9" with get - member val XF10 = var (regType) (Register.toRegID Register.XF10) "XF10" with get - member val XF11 = var (regType) (Register.toRegID Register.XF11) "XF11" with get - member val XF12 = var (regType) (Register.toRegID Register.XF12) "XF12" with get - member val XF13 = var (regType) (Register.toRegID Register.XF13) "XF13" with get - member val XF14 = var (regType) (Register.toRegID Register.XF14) "XF14" with get - member val XF15 = var (regType) (Register.toRegID Register.XF15) "XF15" with get - member val XMTRX = var (regType) (Register.toRegID Register.XMTRX) "XMTRX" with get - member val PTEH = var (regType) (Register.toRegID Register.PTEH) "PTEH" with get - member val PTEL = var (regType) (Register.toRegID Register.PTEL) "PTEL" with get - member val PTEA = var (regType) (Register.toRegID Register.PTEA) "PTEA" with get - member val TTB = var (regType) (Register.toRegID Register.TTB) "TTB" with get - member val TEA = var (regType) (Register.toRegID Register.TEA) "TEA" with get - member val MMUCR = var (regType) (Register.toRegID Register.MMUCR) "MMUCR" with get - member val CCR = var (regType) (Register.toRegID Register.CCR) "CCR" with get - member val QACR0 = var (regType) (Register.toRegID Register.QACR0) "QACR0" with get - member val QACR1 = var (regType) (Register.toRegID Register.QACR1) "QACR1" with get - member val TRA = var (regType) (Register.toRegID Register.TRA) "TRA" with get - member val EXPEVT = var (regType) (Register.toRegID Register.EXPEVT) "EXPEVT" with get - member val INTEVT = var (regType) (Register.toRegID Register.INTEVT) "INTEVT" with get - member val MD = var (regType) (Register.toRegID Register.MD) "MD" with get - member val RB = var (regType) (Register.toRegID Register.RB) "RB" with get - member val BL = var (regType) (Register.toRegID Register.BL) "BL" with get - member val FD = var (regType) (Register.toRegID Register.FD) "FD" with get - member val M = var (regType) (Register.toRegID Register.M) "M" with get - member val Q = var (regType) (Register.toRegID Register.Q) "Q" with get - member val IMASK = var (regType) (Register.toRegID Register.IMASK) "IMASK" with get - member val S = var (regType) (Register.toRegID Register.S) "S" with get - member val T = var (regType) (Register.toRegID Register.T) "T" with get - member val FPSCR_RM = var (regType) (Register.toRegID Register.FPSCR_RM) "FPSCR_RM" with get - member val FPSCR_FLAG = var (regType) (Register.toRegID Register.FPSCR_FLAG) "FPSCR_FLAG" with get - member val FPSCR_ENABLE = var (regType) (Register.toRegID Register.FPSCR_ENABLE) "FPSCR_ENABLE" with get - member val FPSCR_CAUSE = var (regType) (Register.toRegID Register.FPSCR_CAUSE) "FPSCR_CAUSE" with get - member val FPSCR_DN = var (regType) (Register.toRegID Register.FPSCR_DN) "FPSCR_DN" with get - member val FPSCR_PR = var (regType) (Register.toRegID Register.FPSCR_PR) "FPSCR_PR" with get - member val FPSCR_SZ = var (regType) (Register.toRegID Register.FPSCR_SZ) "FPSCR_SZ" with get - member val FPSCR_FR = var (regType) (Register.toRegID Register.FPSCR_FR) "FPSCR_FR" with get + member val R0 = var (regType) (R.toRegID R.R0) "R0" with get + member val R1 = var (regType) (R.toRegID R.R1) "R1" with get + member val R2 = var (regType) (R.toRegID R.R2) "R2" with get + member val R3 = var (regType) (R.toRegID R.R3) "R3" with get + member val R4 = var (regType) (R.toRegID R.R4) "R4" with get + member val R5 = var (regType) (R.toRegID R.R5) "R5" with get + member val R6 = var (regType) (R.toRegID R.R6) "R6" with get + member val R7 = var (regType) (R.toRegID R.R7) "R7" with get + member val R8 = var (regType) (R.toRegID R.R8) "R8" with get + member val R9 = var (regType) (R.toRegID R.R9) "R9" with get + member val R10 = var (regType) (R.toRegID R.R10) "R10" with get + member val R11 = var (regType) (R.toRegID R.R11) "R11" with get + member val R12 = var (regType) (R.toRegID R.R12) "R12" with get + member val R13 = var (regType) (R.toRegID R.R13) "R13" with get + member val R14 = var (regType) (R.toRegID R.R14) "R14" with get + member val R15 = var (regType) (R.toRegID R.R15) "R15" with get + member val R0_BANK = var (regType) (R.toRegID R.R0_BANK) "R0_BANK" with get + member val R1_BANK = var (regType) (R.toRegID R.R1_BANK) "R1_BANK" with get + member val R2_BANK = var (regType) (R.toRegID R.R2_BANK) "R2_BANK" with get + member val R3_BANK = var (regType) (R.toRegID R.R3_BANK) "R3_BANK" with get + member val R4_BANK = var (regType) (R.toRegID R.R4_BANK) "R4_BANK" with get + member val R5_BANK = var (regType) (R.toRegID R.R5_BANK) "R5_BANK" with get + member val R6_BANK = var (regType) (R.toRegID R.R6_BANK) "R6_BANK" with get + member val R7_BANK = var (regType) (R.toRegID R.R7_BANK) "R7_BANK" with get + member val SR = var (regType) (R.toRegID R.SR) "SR" with get + member val GBR = var (regType) (R.toRegID R.GBR) "GBR" with get + member val SSR = var (regType) (R.toRegID R.SSR) "SSR" with get + member val SPC = var (regType) (R.toRegID R.SPC) "SPC" with get + member val SGR = var (regType) (R.toRegID R.SGR) "SGR" with get + member val DBR = var (regType) (R.toRegID R.DBR) "DBR" with get + member val VBR = var (regType) (R.toRegID R.VBR) "VBR" with get + member val MACH = var (regType) (R.toRegID R.MACH) "MACH" with get + member val MACL = var (regType) (R.toRegID R.MACL) "MACL" with get + member val PR = var (regType) (R.toRegID R.PR) "PR" with get + member val FPUL = var (regType) (R.toRegID R.FPUL) "FPUL" with get + member val PC = var (regType) (R.toRegID R.PC) "PC" with get + member val FPSCR = var (regType) (R.toRegID R.FPSCR) "FPSCR" with get + member val FPR0 = var (regType) (R.toRegID R.FPR0) "FPR0" with get + member val FPR1 = var (regType) (R.toRegID R.FPR1) "FPR1" with get + member val FPR2 = var (regType) (R.toRegID R.FPR2) "FPR2" with get + member val FPR3 = var (regType) (R.toRegID R.FPR3) "FPR3" with get + member val FPR4 = var (regType) (R.toRegID R.FPR4) "FPR4" with get + member val FPR5 = var (regType) (R.toRegID R.FPR5) "FPR5" with get + member val FPR6 = var (regType) (R.toRegID R.FPR6) "FPR6" with get + member val FPR7 = var (regType) (R.toRegID R.FPR7) "FPR7" with get + member val FPR8 = var (regType) (R.toRegID R.FPR8) "FPR8" with get + member val FPR9 = var (regType) (R.toRegID R.FPR9) "FPR9" with get + member val FPR10 = var (regType) (R.toRegID R.FPR10) "FPR10" with get + member val FPR11 = var (regType) (R.toRegID R.FPR11) "FPR11" with get + member val FPR12 = var (regType) (R.toRegID R.FPR12) "FPR12" with get + member val FPR13 = var (regType) (R.toRegID R.FPR13) "FPR13" with get + member val FPR14 = var (regType) (R.toRegID R.FPR14) "FPR14" with get + member val FPR15 = var (regType) (R.toRegID R.FPR15) "FPR15" with get + member val FR0 = var (regType) (R.toRegID R.FR0) "FR0" with get + member val FR1 = var (regType) (R.toRegID R.FR1) "FR1" with get + member val FR2 = var (regType) (R.toRegID R.FR2) "FR2" with get + member val FR3 = var (regType) (R.toRegID R.FR3) "FR3" with get + member val FR4 = var (regType) (R.toRegID R.FR4) "FR4" with get + member val FR5 = var (regType) (R.toRegID R.FR5) "FR5" with get + member val FR6 = var (regType) (R.toRegID R.FR6) "FR6" with get + member val FR7 = var (regType) (R.toRegID R.FR7) "FR7" with get + member val FR8 = var (regType) (R.toRegID R.FR8) "FR8" with get + member val FR9 = var (regType) (R.toRegID R.FR9) "FR9" with get + member val FR10 = var (regType) (R.toRegID R.FR10) "FR10" with get + member val FR11 = var (regType) (R.toRegID R.FR11) "FR11" with get + member val FR12 = var (regType) (R.toRegID R.FR12) "FR12" with get + member val FR13 = var (regType) (R.toRegID R.FR13) "FR13" with get + member val FR14 = var (regType) (R.toRegID R.FR14) "FR14" with get + member val FR15 = var (regType) (R.toRegID R.FR15) "FR15" with get + member val DR0 = var (regType) (R.toRegID R.DR0) "DR0" with get + member val DR2 = var (regType) (R.toRegID R.DR2) "DR2" with get + member val DR4 = var (regType) (R.toRegID R.DR4) "DR4" with get + member val DR6 = var (regType) (R.toRegID R.DR6) "DR6" with get + member val DR8 = var (regType) (R.toRegID R.DR8) "DR8" with get + member val DR10 = var (regType) (R.toRegID R.DR10) "DR10" with get + member val DR12 = var (regType) (R.toRegID R.DR12) "DR12" with get + member val DR14 = var (regType) (R.toRegID R.DR14) "DR14" with get + member val FV0 = var (regType) (R.toRegID R.FV0) "FV0" with get + member val FV4 = var (regType) (R.toRegID R.FV4) "FV4" with get + member val FV8 = var (regType) (R.toRegID R.FV8) "FV8" with get + member val FV12 = var (regType) (R.toRegID R.FV12) "FV12" with get + member val XD0 = var (regType) (R.toRegID R.XD0) "XD0" with get + member val XD2 = var (regType) (R.toRegID R.XD2) "XD2" with get + member val XD4 = var (regType) (R.toRegID R.XD4) "XD4" with get + member val XD6 = var (regType) (R.toRegID R.XD6) "XD6" with get + member val XD8 = var (regType) (R.toRegID R.XD8) "XD8" with get + member val XD10 = var (regType) (R.toRegID R.XD10) "XD10" with get + member val XD12 = var (regType) (R.toRegID R.XD12) "XD12" with get + member val XD14 = var (regType) (R.toRegID R.XD14) "XD14" with get + member val XF0 = var (regType) (R.toRegID R.XF0) "XF0" with get + member val XF1 = var (regType) (R.toRegID R.XF1) "XF1" with get + member val XF2 = var (regType) (R.toRegID R.XF2) "XF2" with get + member val XF3 = var (regType) (R.toRegID R.XF3) "XF3" with get + member val XF4 = var (regType) (R.toRegID R.XF4) "XF4" with get + member val XF5 = var (regType) (R.toRegID R.XF5) "XF5" with get + member val XF6 = var (regType) (R.toRegID R.XF6) "XF6" with get + member val XF7 = var (regType) (R.toRegID R.XF7) "XF7" with get + member val XF8 = var (regType) (R.toRegID R.XF8) "XF8" with get + member val XF9 = var (regType) (R.toRegID R.XF9) "XF9" with get + member val XF10 = var (regType) (R.toRegID R.XF10) "XF10" with get + member val XF11 = var (regType) (R.toRegID R.XF11) "XF11" with get + member val XF12 = var (regType) (R.toRegID R.XF12) "XF12" with get + member val XF13 = var (regType) (R.toRegID R.XF13) "XF13" with get + member val XF14 = var (regType) (R.toRegID R.XF14) "XF14" with get + member val XF15 = var (regType) (R.toRegID R.XF15) "XF15" with get + member val XMTRX = var (regType) (R.toRegID R.XMTRX) "XMTRX" with get + member val PTEH = var (regType) (R.toRegID R.PTEH) "PTEH" with get + member val PTEL = var (regType) (R.toRegID R.PTEL) "PTEL" with get + member val PTEA = var (regType) (R.toRegID R.PTEA) "PTEA" with get + member val TTB = var (regType) (R.toRegID R.TTB) "TTB" with get + member val TEA = var (regType) (R.toRegID R.TEA) "TEA" with get + member val MMUCR = var (regType) (R.toRegID R.MMUCR) "MMUCR" with get + member val CCR = var (regType) (R.toRegID R.CCR) "CCR" with get + member val QACR0 = var (regType) (R.toRegID R.QACR0) "QACR0" with get + member val QACR1 = var (regType) (R.toRegID R.QACR1) "QACR1" with get + member val TRA = var (regType) (R.toRegID R.TRA) "TRA" with get + member val EXPEVT = var (regType) (R.toRegID R.EXPEVT) "EXPEVT" with get + member val INTEVT = var (regType) (R.toRegID R.INTEVT) "INTEVT" with get + member val MD = var (regType) (R.toRegID R.MD) "MD" with get + member val RB = var (regType) (R.toRegID R.RB) "RB" with get + member val BL = var (regType) (R.toRegID R.BL) "BL" with get + member val FD = var (regType) (R.toRegID R.FD) "FD" with get + member val M = var (regType) (R.toRegID R.M) "M" with get + member val Q = var (regType) (R.toRegID R.Q) "Q" with get + member val IMASK = var (regType) (R.toRegID R.IMASK) "IMASK" with get + member val S = var (regType) (R.toRegID R.S) "S" with get + member val T = var (regType) (R.toRegID R.T) "T" with get + member val FPSCR_RM = var (regType) (R.toRegID R.FPSCR_RM) "FPSCR_RM" with get + member val FPSCR_FLAG = + var (regType) (R.toRegID R.FPSCR_FLAG) "FPSCR_FLAG" with get + member val FPSCR_ENABLE = + var (regType) (R.toRegID R.FPSCR_ENABLE) "FPSCR_ENABLE" with get + member val FPSCR_CAUSE = + var (regType) (R.toRegID R.FPSCR_CAUSE) "FPSCR_CAUSE" with get + member val FPSCR_DN = var (regType) (R.toRegID R.FPSCR_DN) "FPSCR_DN" with get + member val FPSCR_PR = var (regType) (R.toRegID R.FPSCR_PR) "FPSCR_PR" with get + member val FPSCR_SZ = var (regType) (R.toRegID R.FPSCR_SZ) "FPSCR_SZ" with get + member val FPSCR_FR = var (regType) (R.toRegID R.FPSCR_FR) "FPSCR_FR" with get member __.GetRegVar (name) = match name with @@ -306,4 +312,4 @@ type internal RegExprs (wordSize) = | R.FPSCR_PR -> __.FPSCR_PR | R.FPSCR_SZ -> __.FPSCR_SZ | R.FPSCR_FR -> __.FPSCR_FR - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException diff --git a/src/FrontEnd/BinLifter/SH4/SH4RegisterFactory.fs b/src/FrontEnd/BinLifter/SH4/SH4RegisterFactory.fs new file mode 100644 index 00000000..3dc8b04b --- /dev/null +++ b/src/FrontEnd/BinLifter/SH4/SH4RegisterFactory.fs @@ -0,0 +1,104 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SH4 + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type SH4RegisterFactory (r: RegExprs) = + inherit RegisterFactory () + + override __.GetAllRegExprs () = + [ r.R0; r.R1; r.R2; r.R3; r.R4; r.R5; r.R6; r.R7; r.R8; r.R9; r.R10; r.R11 + r.R12; r.R13; r.R14; r.R15; r.PC ] + + override __.GetAllRegNames () = + __.GetAllRegExprs () + |> List.map (__.RegIDFromRegExpr >> __.RegIDToString) + + override __.GetGeneralRegExprs () = + [ r.R0; r.R1; r.R2; r.R3; r.R4; r.R5; r.R6; r.R7; r.R8; r.R9; r.R10; r.R11 + r.R12; r.R13; r.R14; r.R15 ] + + override __.RegIDFromRegExpr (e) = + match e.E with + | Var (_, id, _) -> id + | PCVar (_) -> Register.toRegID Register.PC + | _ -> raise InvalidRegisterException + + override __.RegIDToRegExpr (id) = + Register.ofRegID id |> r.GetRegVar + + override __.StrToRegExpr s = + match s.ToLowerInvariant () with + | "r0" -> r.R0 + | "r1" -> r.R1 + | "r2" -> r.R2 + | "r3" -> r.R3 + | "r4" -> r.R4 + | "r5" -> r.R5 + | "r6" -> r.R6 + | "r7" -> r.R7 + | "r8" -> r.R8 + | "r9" -> r.R9 + | "r10" -> r.R10 + | "r11" -> r.R11 + | "r12" -> r.R12 + | "r13" -> r.R13 + | "r14" -> r.R14 + | "r15" -> r.R15 + | "pc" -> r.PC + | _ -> raise UnhandledRegExprException + + override __.RegIDFromString str = + Register.ofString str |> Register.toRegID + + override __.RegIDToString rid = + Register.ofRegID rid |> Register.toString + + override __.RegIDToRegType rid = + Register.ofRegID rid |> Register.toRegType + + override __.GetRegisterAliases _ = + Utils.futureFeature () + + override __.ProgramCounter = + Register.PC |> Register.toRegID + + override __.StackPointer = + Register.R15 |> Register.toRegID |> Some + + override __.FramePointer = + Register.R14 |> Register.toRegID |> Some + + override __.IsProgramCounter rid = + __.ProgramCounter = rid + + override __.IsStackPointer rid = + (__.StackPointer |> Option.get) = rid + + override __.IsFramePointer rid = + (__.FramePointer |> Option.get) = rid diff --git a/src/FrontEnd/BinLifter/SH4/SH4RegisterSet.fs b/src/FrontEnd/BinLifter/SH4/SH4RegisterSet.fs deleted file mode 100644 index 60b1de83..00000000 --- a/src/FrontEnd/BinLifter/SH4/SH4RegisterSet.fs +++ /dev/null @@ -1,325 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.SH4 - -open B2R2 - -type SH4RegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = SH4RegisterSet (RegisterSet.MakeInternalBitArray 3, Set.empty) - - override __.Tag = RegisterSetTag.SH4 - - override __.ArrSize = 3 - - override __.New arr s = new SH4RegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | R.R0 -> 0 - | R.R1 -> 1 - | R.R2 -> 2 - | R.R3 -> 3 - | R.R4 -> 4 - | R.R5 -> 5 - | R.R6 -> 6 - | R.R7 -> 7 - | R.R8 -> 8 - | R.R9 -> 9 - | R.R10 -> 10 - | R.R11 -> 11 - | R.R12 -> 12 - | R.R13 -> 13 - | R.R14 -> 14 - | R.R15 -> 15 - | R.R0_BANK -> 16 - | R.R1_BANK -> 17 - | R.R2_BANK -> 18 - | R.R3_BANK -> 19 - | R.R4_BANK -> 20 - | R.R5_BANK -> 21 - | R.R6_BANK -> 22 - | R.R7_BANK -> 23 - | R.SR -> 24 - | R.GBR -> 25 - | R.SSR -> 26 - | R.SPC -> 27 - | R.SGR -> 28 - | R.DBR -> 29 - | R.VBR -> 30 - | R.MACH -> 31 - | R.MACL -> 32 - | R.PR -> 33 - | R.FPUL -> 34 - | R.PC -> 35 - | R.FPSCR -> 36 - | R.FPR0 -> 37 - | R.FPR1 -> 38 - | R.FPR2 -> 39 - | R.FPR3 -> 40 - | R.FPR4 -> 41 - | R.FPR5 -> 42 - | R.FPR6 -> 43 - | R.FPR7 -> 44 - | R.FPR8 -> 45 - | R.FPR9 -> 46 - | R.FPR10 -> 47 - | R.FPR11 -> 48 - | R.FPR12 -> 49 - | R.FPR13 -> 50 - | R.FPR14 -> 51 - | R.FPR15 -> 52 - | R.FR0 -> 53 - | R.FR1 -> 54 - | R.FR2 -> 55 - | R.FR3 -> 56 - | R.FR4 -> 57 - | R.FR5 -> 58 - | R.FR6 -> 59 - | R.FR7 -> 60 - | R.FR8 -> 61 - | R.FR9 -> 62 - | R.FR10 -> 63 - | R.FR11 -> 64 - | R.FR12 -> 65 - | R.FR13 -> 66 - | R.FR14 -> 67 - | R.FR15 -> 68 - | R.DR0 -> 69 - | R.DR2 -> 70 - | R.DR4 -> 71 - | R.DR6 -> 72 - | R.DR8 -> 73 - | R.DR10 -> 74 - | R.DR12 -> 75 - | R.DR14 -> 76 - | R.FV0 -> 77 - | R.FV4 -> 78 - | R.FV8 -> 79 - | R.FV12 -> 80 - | R.XD0 -> 81 - | R.XD2 -> 82 - | R.XD4 -> 83 - | R.XD6 -> 84 - | R.XD8 -> 85 - | R.XD10 -> 86 - | R.XD12 -> 87 - | R.XD14 -> 88 - | R.XF0 -> 89 - | R.XF1 -> 90 - | R.XF2 -> 91 - | R.XF3 -> 92 - | R.XF4 -> 93 - | R.XF5 -> 94 - | R.XF6 -> 95 - | R.XF7 -> 96 - | R.XF8 -> 97 - | R.XF9 -> 98 - | R.XF10 -> 99 - | R.XF11 -> 100 - | R.XF12 -> 101 - | R.XF13 -> 102 - | R.XF14 -> 103 - | R.XF15 -> 104 - | R.XMTRX -> 105 - | R.PTEH -> 106 - | R.PTEL -> 107 - | R.PTEA -> 108 - | R.TTB -> 109 - | R.TEA -> 110 - | R.MMUCR -> 111 - | R.CCR -> 112 - | R.QACR0 -> 113 - | R.QACR1 -> 114 - | R.TRA -> 115 - | R.EXPEVT -> 116 - | R.INTEVT -> 117 - | R.MD -> 118 - | R.RB -> 119 - | R.BL -> 120 - | R.FD -> 121 - | R.M -> 122 - | R.Q -> 123 - | R.IMASK -> 124 - | R.S -> 125 - | R.T -> 126 - | R.FPSCR_RM -> 127 - | R.FPSCR_FLAG -> 128 - | R.FPSCR_ENABLE -> 129 - | R.FPSCR_CAUSE -> 130 - | R.FPSCR_DN -> 131 - | R.FPSCR_PR -> 132 - | R.FPSCR_SZ -> 133 - | R.FPSCR_FR -> 134 - | _ -> Utils.impossible () - - override __.IndexToRegID index = - match index with - | 0 -> R.R0 - | 1 -> R.R1 - | 2 -> R.R2 - | 3 -> R.R3 - | 4 -> R.R4 - | 5 -> R.R5 - | 6 -> R.R6 - | 7 -> R.R7 - | 8 -> R.R8 - | 9 -> R.R9 - | 10 -> R.R10 - | 11 -> R.R11 - | 12 -> R.R12 - | 13 -> R.R13 - | 14 -> R.R14 - | 15 -> R.R15 - | 16 -> R.R0_BANK - | 17 -> R.R1_BANK - | 18 -> R.R2_BANK - | 19 -> R.R3_BANK - | 20 -> R.R4_BANK - | 21 -> R.R5_BANK - | 22 -> R.R6_BANK - | 23 -> R.R7_BANK - | 24 -> R.SR - | 25 -> R.GBR - | 26 -> R.SSR - | 27 -> R.SPC - | 28 -> R.SGR - | 29 -> R.DBR - | 30 -> R.VBR - | 31 -> R.MACH - | 32 -> R.MACL - | 33 -> R.PR - | 34 -> R.FPUL - | 35 -> R.PC - | 36 -> R.FPSCR - | 37 -> R.FPR0 - | 38 -> R.FPR1 - | 39 -> R.FPR2 - | 40 -> R.FPR3 - | 41 -> R.FPR4 - | 42 -> R.FPR5 - | 43 -> R.FPR6 - | 44 -> R.FPR7 - | 45 -> R.FPR8 - | 46 -> R.FPR9 - | 47 -> R.FPR10 - | 48 -> R.FPR11 - | 49 -> R.FPR12 - | 50 -> R.FPR13 - | 51 -> R.FPR14 - | 52 -> R.FPR15 - | 53 -> R.FR0 - | 54 -> R.FR1 - | 55 -> R.FR2 - | 56 -> R.FR3 - | 57 -> R.FR4 - | 58 -> R.FR5 - | 59 -> R.FR6 - | 60 -> R.FR7 - | 61 -> R.FR8 - | 62 -> R.FR9 - | 63 -> R.FR10 - | 64 -> R.FR11 - | 65 -> R.FR12 - | 66 -> R.FR13 - | 67 -> R.FR14 - | 68 -> R.FR15 - | 69 -> R.DR0 - | 70 -> R.DR2 - | 71 -> R.DR4 - | 72 -> R.DR6 - | 73 -> R.DR8 - | 74 -> R.DR10 - | 75 -> R.DR12 - | 76 -> R.DR14 - | 77 -> R.FV0 - | 78 -> R.FV4 - | 79 -> R.FV8 - | 80 -> R.FV12 - | 81 -> R.XD0 - | 82 -> R.XD2 - | 83 -> R.XD4 - | 84 -> R.XD6 - | 85 -> R.XD8 - | 86 -> R.XD10 - | 87 -> R.XD12 - | 88 -> R.XD14 - | 89 -> R.XF0 - | 90 -> R.XF1 - | 91 -> R.XF2 - | 92 -> R.XF3 - | 93 -> R.XF4 - | 94 -> R.XF5 - | 95 -> R.XF6 - | 96 -> R.XF7 - | 97 -> R.XF8 - | 98 -> R.XF9 - | 99 -> R.XF10 - | 100 -> R.XF11 - | 101 -> R.XF12 - | 102 -> R.XF13 - | 103 -> R.XF14 - | 104 -> R.XF15 - | 105 -> R.XMTRX - | 106 -> R.PTEH - | 107 -> R.PTEL - | 108 -> R.PTEA - | 109 -> R.TTB - | 110 -> R.TEA - | 111 -> R.MMUCR - | 112 -> R.CCR - | 113 -> R.QACR0 - | 114 -> R.QACR1 - | 115 -> R.TRA - | 116 -> R.EXPEVT - | 117 -> R.INTEVT - | 118 -> R.MD - | 119 -> R.RB - | 120 -> R.BL - | 121 -> R.FD - | 122 -> R.M - | 123 -> R.Q - | 124 -> R.IMASK - | 125 -> R.S - | 126 -> R.T - | 127 -> R.FPSCR_RM - | 128 -> R.FPSCR_FLAG - | 129 -> R.FPSCR_ENABLE - | 130 -> R.FPSCR_CAUSE - | 131 -> R.FPSCR_DN - | 132 -> R.FPSCR_PR - | 133 -> R.FPSCR_SZ - | 134 -> R.FPSCR_FR - | _ -> Utils.impossible () - |> Register.toRegID - - override __.ToString () = - sprintf "SH4ReisterSet<%x, %x>" __.BitArray[0] __.BitArray[1] - -[] -module SH4RegisterSet = - let singleton rid = SH4RegisterSet().Add(rid) - let empty = SH4RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64RegExprs.fs b/src/FrontEnd/BinLifter/SH4/SH4TranslationContext.fs similarity index 75% rename from src/FrontEnd/BinLifter/Sparc64/Sparc64RegExprs.fs rename to src/FrontEnd/BinLifter/SH4/SH4TranslationContext.fs index c61a6c99..8722fbe6 100644 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64RegExprs.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4TranslationContext.fs @@ -22,19 +22,21 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.Sparc64 +namespace B2R2.FrontEnd.BinLifter.SH4 open B2R2 -open B2R2.BinIR.LowUIR +open B2R2.FrontEnd.BinLifter -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (Sparc64RegisterSet.singleton t) +type SH4TranslationContext (isa) = + inherit TranslationContext (isa) - (* Registers *) - let regType = WordSize.toRegType wordSize + let regExprs = RegExprs isa.WordSize - member __.GetRegVar (name) = - match name with - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + /// Register expressions. + member __.RegExprs with get() = regExprs -// vim: set tw=80 sts=2 sw=2: + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/SH4/SH4Types.fs b/src/FrontEnd/BinLifter/SH4/SH4Types.fs index b704972a..700abac2 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4Types.fs +++ b/src/FrontEnd/BinLifter/SH4/SH4Types.fs @@ -27,7 +27,6 @@ namespace B2R2.FrontEnd.BinLifter.SH4 open B2R2 type Register = - // General Registers (32-bit) | R0 = 0x0 | R1 = 0x1 | R2 = 0x2 @@ -52,7 +51,6 @@ type Register = | R5_BANK = 0x15 | R6_BANK = 0x16 | R7_BANK = 0x17 - // Control Registers (32-bit) | SR = 0x18 | GBR = 0x19 | SSR = 0x1A @@ -60,14 +58,12 @@ type Register = | SGR = 0x1C | DBR = 0x1D | VBR = 0x1E - // System Registers (32-bit) | MACH = 0x1F | MACL = 0x20 | PR = 0x21 | FPUL = 0x22 | PC = 0x23 | FPSCR = 0x24 - // Single-Precision Floating-point Registers (32-bit) | FPR0 = 0x25 | FPR1 = 0x26 | FPR2 = 0x27 @@ -84,7 +80,6 @@ type Register = | FPR13 = 0X32 | FPR14 = 0x33 | FPR15 = 0x34 - // Floating-Point Registers (32-bit) | FR0 = 0x35 | FR1 = 0x36 | FR2 = 0x37 @@ -101,7 +96,6 @@ type Register = | FR13 = 0x42 | FR14 = 0x43 | FR15 = 0x44 - // Single-Precision Floating-Point Extended Registers (32-bit) | XF0 = 0x45 | XF1 = 0x46 | XF2 = 0x47 @@ -118,9 +112,7 @@ type Register = | XF13 = 0x52 | XF14 = 0x53 | XF15 = 0x54 - // Single-precision floating-point extended register matrix. (512-bit) | XMTRX = 0x55 - // Double-Precision Floating-point Registers (64-bit) | DR0 = 0x56 | DR2 = 0x57 | DR4 = 0x58 @@ -129,7 +121,6 @@ type Register = | DR10 = 0x5B | DR12 = 0x5C | DR14 = 0x5D - // Single-Precision Floatig-Point Extended Register Pairs (64-bit) | XD0 = 0x5E | XD2 = 0x5F | XD4 = 0x60 @@ -138,27 +129,22 @@ type Register = | XD10 = 0x63 | XD12 = 0x64 | XD14 = 0x65 - // Single-Precison Floating-point Vector Registers (128-bit) | FV0 = 0x66 | FV4 = 0x67 | FV8 = 0x68 | FV12 = 0x69 - // MMU-Related Registers (32-bit) | PTEH = 0x6A | PTEL = 0x6B | PTEA = 0x6C | TTB = 0x6D | TEA = 0x6E | MMUCR = 0x6F - // Cache and Store Queue Control Registers (32-bit) | CCR = 0x70 | QACR0 = 0x71 | QACR1 = 0x72 - // Exception-Related Registers (32-bit) | TRA = 0x73 | EXPEVT = 0x74 | INTEVT = 0x75 - // Flags in the SR (Status Register) (1-bit) | MD = 0x76 | RB = 0x77 | BL = 0x78 @@ -168,7 +154,6 @@ type Register = | IMASK = 0x7C | S = 0x7D | T = 0x7E - // Flags in the FPSCR (Floating-point Status Control Register) (1-bit) | FPSCR_RM = 0X7F | FPSCR_FLAG = 0x80 | FPSCR_ENABLE = 0x81 @@ -191,7 +176,7 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "r0" -> R.R0 | "r1" -> R.R1 | "r2" -> R.R2 diff --git a/src/FrontEnd/BinLifter/SPARC/B2R2.FrontEnd.BinLifter.SPARC.fsproj b/src/FrontEnd/BinLifter/SPARC/B2R2.FrontEnd.BinLifter.SPARC.fsproj new file mode 100644 index 00000000..3231036e --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/B2R2.FrontEnd.BinLifter.SPARC.fsproj @@ -0,0 +1,33 @@ + + + + LICENSE.md + b2r2-240x240.png + README.md + B2R2 SPARC frontend. + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MiddleEnd/ControlFlowAnalysis/README.md b/src/FrontEnd/BinLifter/SPARC/README.md similarity index 53% rename from src/MiddleEnd/ControlFlowAnalysis/README.md rename to src/FrontEnd/BinLifter/SPARC/README.md index f680625e..1e9af88d 100644 --- a/src/MiddleEnd/ControlFlowAnalysis/README.md +++ b/src/FrontEnd/BinLifter/SPARC/README.md @@ -1,4 +1,4 @@ -# B2R2.MiddleEnd.ControlFlowAnalysis +# B2R2.FrontEnd.BinLifter.SPARC ### B2R2? @@ -6,7 +6,6 @@ B2R2 is a binary analysis and reversing framework written purely in F#. Since it does not rely on any native (unmanaged) code, it is readily usable in any platform or OS that .NET runs on. -### B2R2.MiddleEnd.ControlFlowAnalysis Package? +### B2R2.FrontEnd.BinLifter.SPARC Package? -`B2R2.MiddleEnd.ControlFlowAnalysis` provides an interface for our CFG-recovery -algorithm. +`B2R2.FrontEnd.BinLifter.SPARC` includes SPARC parsers and lifters. diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCDisasm.fs b/src/FrontEnd/BinLifter/SPARC/SPARCDisasm.fs new file mode 100644 index 00000000..164821d6 --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCDisasm.fs @@ -0,0 +1,841 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.SPARC.Disasm + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.SPARC + +let opCodeToString = function + | Opcode.ADD -> "add" + | Opcode.ADDcc -> "addcc" + | Opcode.ADDC -> "addc" + | Opcode.ADDCcc -> "addccc" + | Opcode.AND -> "and" + | Opcode.ANDcc -> "andcc" + | Opcode.ANDN -> "andn" + | Opcode.ANDNcc -> "andncc" + | Opcode.BPA -> "ba" + | Opcode.BPN -> "bn" + | Opcode.BPNE -> "bne" + | Opcode.BPE -> "be" + | Opcode.BPG -> "bg" + | Opcode.BPLE -> "ble" + | Opcode.BPGE -> "bge" + | Opcode.BPL -> "bl" + | Opcode.BPGU -> "bgu" + | Opcode.BPLEU -> "bleu" + | Opcode.BPCC -> "bcc" + | Opcode.BPCS -> "bcs" + | Opcode.BPPOS -> "bpos" + | Opcode.BPNEG -> "bneg" + | Opcode.BPVC -> "bvc" + | Opcode.BPVS -> "bvs" + | Opcode.BA -> "ba" + | Opcode.BN -> "bn" + | Opcode.BNE -> "bne" + | Opcode.BE -> "be" + | Opcode.BG -> "bg" + | Opcode.BLE -> "ble" + | Opcode.BGE -> "bge" + | Opcode.BL -> "bl" + | Opcode.BGU -> "bgu" + | Opcode.BLEU -> "bleu" + | Opcode.BCC -> "bcc" + | Opcode.BCS -> "bcs" + | Opcode.BPOS -> "bpos" + | Opcode.BNEG -> "bneg" + | Opcode.BVC -> "bvc" + | Opcode.BRZ -> "brz" + | Opcode.BRLEZ -> "brlez" + | Opcode.BRLZ -> "brlz" + | Opcode.BRNZ -> "brnz" + | Opcode.BRGZ -> "brgz" + | Opcode.BRGEZ -> "brgez" + | Opcode.CALL -> "call" + | Opcode.CASA -> "casa" + | Opcode.CASXA -> "casxa" + | Opcode.DONE -> "done" + | Opcode.FABSs -> "fabss" + | Opcode.FABSd -> "fabsd" + | Opcode.FABSq -> "fabsq" + | Opcode.FADDs -> "fadds" + | Opcode.FADDd -> "faddd" + | Opcode.FADDq -> "faddq" + | Opcode.FBA -> "fba" + | Opcode.FBN -> "fbn" + | Opcode.FBU -> "fbu" + | Opcode.FBG -> "fbg" + | Opcode.FBUG -> "fbug" + | Opcode.FBL -> "fbl" + | Opcode.FBUL -> "fbul" + | Opcode.FBLG -> "fblg" + | Opcode.FBNE -> "fbne" + | Opcode.FBE -> "fbe" + | Opcode.FBUE -> "fbue" + | Opcode.FBGE -> "fbge" + | Opcode.FBUGE -> "fbuge" + | Opcode.FBLE -> "fble" + | Opcode.FBULE -> "fbule" + | Opcode.FBO -> "fbo" + | Opcode.FBPA -> "fba" + | Opcode.FBPN -> "fbn" + | Opcode.FBPU -> "fbu" + | Opcode.FBPG -> "fbg" + | Opcode.FBPUG -> "fbug" + | Opcode.FBPL -> "fbl" + | Opcode.FBPUL -> "fbul" + | Opcode.FBPLG -> "fblg" + | Opcode.FBPNE -> "fbne" + | Opcode.FBPE -> "fbe" + | Opcode.FBPUE -> "fbue" + | Opcode.FBPGE -> "fbge" + | Opcode.FBPUGE -> "fbuge" + | Opcode.FBPLE -> "fble" + | Opcode.FBPULE -> "fbule" + | Opcode.FBPO -> "fbo" + | Opcode.FCMPs -> "fcmps" + | Opcode.FCMPd -> "fcmpd" + | Opcode.FCMPq -> "fcmpq" + | Opcode.FCMPEs -> "fcmpes" + | Opcode.FCMPEd -> "fcmped" + | Opcode.FCMPEq -> "fcmpeq" + | Opcode.FDIVs -> "fdivs" + | Opcode.FDIVd -> "fdivd" + | Opcode.FDIVq -> "fdivq" + | Opcode.FiTOs -> "fitos" + | Opcode.FiTOd -> "fitod" + | Opcode.FiTOq -> "fitoq" + | Opcode.FLUSH -> "flush" + | Opcode.FLUSHW -> "flushw" + | Opcode.FMOVs -> "fmovs" + | Opcode.FMOVd -> "fmovd" + | Opcode.FMOVq -> "fmovq" + | Opcode.FMOVA -> "fmova" + | Opcode.FMOVsA -> "fmovsa" + | Opcode.FMOVdA -> "fmovda" + | Opcode.FMOVqA -> "fmovqa" + | Opcode.FMOVN -> "fmovn" + | Opcode.FMOVsN -> "fmovsn" + | Opcode.FMOVdN -> "fmovdn" + | Opcode.FMOVqN -> "fmovqn" + | Opcode.FMOVNE -> "fmovne" + | Opcode.FMOVsNE -> "fmovsne" + | Opcode.FMOVdNE -> "fmovdne" + | Opcode.FMOVqNE -> "fmovqne" + | Opcode.FMOVE -> "fmove" + | Opcode.FMOVsE -> "fmovse" + | Opcode.FMOVdE -> "fmovde" + | Opcode.FMOVqE -> "fmovqe" + | Opcode.FMOVG -> "fmovg" + | Opcode.FMOVsG -> "fmovsg" + | Opcode.FMOVdG -> "fmovdg" + | Opcode.FMOVqG -> "fmovqg" + | Opcode.FMOVLE -> "fmovle" + | Opcode.FMOVsLE -> "fmovsle" + | Opcode.FMOVdLE -> "fmovdle" + | Opcode.FMOVqLE -> "fmovqle" + | Opcode.FMOVGE -> "fmovge" + | Opcode.FMOVsGE -> "fmovsge" + | Opcode.FMOVdGE -> "fmovdge" + | Opcode.FMOVqGE -> "fmovqge" + | Opcode.FMOVL -> "fmovl" + | Opcode.FMOVsL -> "fmovsl" + | Opcode.FMOVdL -> "fmovdl" + | Opcode.FMOVqL -> "fmovql" + | Opcode.FMOVGU -> "fmovgu" + | Opcode.FMOVsGU -> "fmovsgu" + | Opcode.FMOVdGU -> "fmovdgu" + | Opcode.FMOVqGU -> "fmovqgu" + | Opcode.FMOVLEU -> "fmovleu" + | Opcode.FMOVsLEU -> "fmovsleu" + | Opcode.FMOVdLEU -> "fmovdleu" + | Opcode.FMOVqLEU -> "fmovqleu" + | Opcode.FMOVCC -> "fmovcc" + | Opcode.FMOVsCC -> "fmovscc" + | Opcode.FMOVdCC -> "fmovdcc" + | Opcode.FMOVqCC -> "fmovqcc" + | Opcode.FMOVCS -> "fmovcs" + | Opcode.FMOVsCS -> "fmovscs" + | Opcode.FMOVdCS -> "fmovdcs" + | Opcode.FMOVqCS -> "fmovqcs" + | Opcode.FMOVPOS -> "fmovpos" + | Opcode.FMOVsPOS -> "fmovspos" + | Opcode.FMOVdPOS -> "fmovspos" + | Opcode.FMOVqPOS -> "fmovqpos" + | Opcode.FMOVNEG -> "fmovneg" + | Opcode.FMOVsNEG -> "fmovsneg" + | Opcode.FMOVdNEG -> "fmovdneg" + | Opcode.FMOVqNEG -> "fmovqneg" + | Opcode.FMOVVC -> "fmovvc" + | Opcode.FMOVsVC -> "fmovsvc" + | Opcode.FMOVdVC -> "fmovdvc" + | Opcode.FMOVqVC -> "fmovqvc" + | Opcode.FMOVVS -> "fmovvs" + | Opcode.FMOVsVS -> "fmovsvs" + | Opcode.FMOVdVS -> "fmovdvs" + | Opcode.FMOVqVS -> "fmovqvs" + | Opcode.FMOVFsA -> "fmovsa" + | Opcode.FMOVFdA -> "fmovda" + | Opcode.FMOVFqA -> "fmovqa" + | Opcode.FMOVFsN -> "fmovsn" + | Opcode.FMOVFdN -> "fmovdn" + | Opcode.FMOVFqN -> "fmovqn" + | Opcode.FMOVFsU -> "fmovsu" + | Opcode.FMOVFdU -> "fmovdu" + | Opcode.FMOVFqU -> "fmovqu" + | Opcode.FMOVFsG -> "fmovsg" + | Opcode.FMOVFdG -> "fmovdg" + | Opcode.FMOVFqG -> "fmovqg" + | Opcode.FMOVFsUG -> "fmovsug" + | Opcode.FMOVFdUG -> "fmovdug" + | Opcode.FMOVFqUG -> "fmovqug" + | Opcode.FMOVFsL -> "fmovsl" + | Opcode.FMOVFdL -> "fmovdl" + | Opcode.FMOVFqL -> "fmovql" + | Opcode.FMOVFsUL -> "fmovsul" + | Opcode.FMOVFdUL -> "fmovdul" + | Opcode.FMOVFqUL -> "fmovqul" + | Opcode.FMOVFsLG -> "fmovslg" + | Opcode.FMOVFdLG -> "fmovdlg" + | Opcode.FMOVFqLG -> "fmovqlg" + | Opcode.FMOVFsNE -> "fmovsne" + | Opcode.FMOVFdNE -> "fmovdne" + | Opcode.FMOVFqNE -> "fmovqne" + | Opcode.FMOVFsE -> "fmovse" + | Opcode.FMOVFdE -> "fmovde" + | Opcode.FMOVFqE -> "fmovqe" + | Opcode.FMOVFsUE -> "fmovsue" + | Opcode.FMOVFdUE -> "fmovdue" + | Opcode.FMOVFqUE -> "fmovque" + | Opcode.FMOVFsGE -> "fmovsge" + | Opcode.FMOVFdGE -> "fmovdge" + | Opcode.FMOVFqGE -> "fmovqge" + | Opcode.FMOVFsUGE -> "fmovsuge" + | Opcode.FMOVFdUGE -> "fmovduge" + | Opcode.FMOVFqUGE -> "fmovquge" + | Opcode.FMOVFsLE -> "fmovsle" + | Opcode.FMOVFdLE -> "fmovdle" + | Opcode.FMOVFqLE -> "fmovqle" + | Opcode.FMOVFsULE -> "fmovsule" + | Opcode.FMOVFdULE -> "fmovdule" + | Opcode.FMOVFqULE -> "fmovqule" + | Opcode.FMOVFsO -> "fmovso" + | Opcode.FMOVFdO -> "fmovdo" + | Opcode.FMOVFqO -> "fmovqo" + | Opcode.FMOVFA -> "fmovfa" + | Opcode.FMOVFN -> "fmovfn" + | Opcode.FMOVFU -> "fmovfu" + | Opcode.FMOVFG -> "fmovfg" + | Opcode.FMOVFUG -> "fmovfug" + | Opcode.FMOVFL -> "fmovfl" + | Opcode.FMOVFUL -> "fmovful" + | Opcode.FMOVFLG -> "fmovflg" + | Opcode.FMOVFNE -> "fmovfne" + | Opcode.FMOVFE -> "fmovfe" + | Opcode.FMOVFUE -> "fmovfue" + | Opcode.FMOVFGE -> "fmovfge" + | Opcode.FMOVFUGE -> "fmovfuge" + | Opcode.FMOVFLE -> "fmovfle" + | Opcode.FMOVFULE -> "fmovfule" + | Opcode.FMOVFO -> "fmovfo" + | Opcode.FMOVRZ -> "fmovre" + | Opcode.FMOVRLEZ -> "fmovrlez" + | Opcode.FMOVRLZ -> "fmovrlz" + | Opcode.FMOVRNZ -> "fmovrne" + | Opcode.FMOVRGZ -> "fmovrgz" + | Opcode.FMOVRGEZ -> "fmovrgez" + | Opcode.FMOVRsZ -> "fmovrse" + | Opcode.FMOVRsLEZ -> "fmovrslez" + | Opcode.FMOVRsLZ -> "fmovrslz" + | Opcode.FMOVRsNZ -> "fmovrsne" + | Opcode.FMOVRsGZ -> "fmovrsgz" + | Opcode.FMOVRsGEZ -> "fmovrsgez" + | Opcode.FMOVRdZ -> "fmovrde" + | Opcode.FMOVRdLEZ -> "fmovrdlez" + | Opcode.FMOVRdLZ -> "fmovrdlz" + | Opcode.FMOVRdNZ -> "fmovrdne" + | Opcode.FMOVRdGZ -> "fmovrdgz" + | Opcode.FMOVRdGEZ -> "fmovrdgez" + | Opcode.FMOVRqZ -> "fmovrqe" + | Opcode.FMOVRqLEZ -> "fmovrqlez" + | Opcode.FMOVRqLZ -> "fmovrqlz" + | Opcode.FMOVRqNZ -> "fmovrqne" + | Opcode.FMOVRqGZ -> "fmovrqgz" + | Opcode.FMOVRqGEZ -> "fmovrqgez" + | Opcode.FMULs -> "fmuls" + | Opcode.FMULd -> "fmuld" + | Opcode.FMULq -> "fmulq" + | Opcode.FNEGs -> "fnegs" + | Opcode.FNEGd -> "fnegd" + | Opcode.FNEGq -> "fnegq" + | Opcode.FsMULd -> "fsmuld" + | Opcode.FdMULq -> "fdmulq" + | Opcode.FSQRTs -> "fsqrts" + | Opcode.FSQRTd -> "fsqrtd" + | Opcode.FSQRTq -> "fsqrtq" + | Opcode.FsTOi -> "fstoi" + | Opcode.FdTOi -> "fdtoi" + | Opcode.FqTOi -> "fqtoi" + | Opcode.FsTOd -> "fstod" + | Opcode.FsTOq -> "fstoq" + | Opcode.FdTOs -> "fdtos" + | Opcode.FdTOq -> "fdtoq" + | Opcode.FqTOs -> "fdtos" + | Opcode.FqTOd -> "fqtod" + | Opcode.FsTOx -> "fstox" + | Opcode.FdTOx -> "fdtox" + | Opcode.FqTOx -> "fqtox" + | Opcode.FSUBs -> "fsubs" + | Opcode.FSUBd -> "fsubd" + | Opcode.FSUBq -> "fsubq" + | Opcode.FxTOs -> "fxtos" + | Opcode.FxTOd -> "fxtod" + | Opcode.FxTOq -> "fxtoq" + | Opcode.ILLTRAP -> "illtrap" + | Opcode.IMPDEP1 -> "impdep1" + | Opcode.IMPDEP2 -> "impdep2" + | Opcode.JMPL -> "jmpl" + | Opcode.LDD -> "ldd" + | Opcode.LDDA -> "ldda" + | Opcode.LDDF -> "ldd" + | Opcode.LDDFA -> "ldda" + | Opcode.LDF -> "ld" + | Opcode.LDFA -> "lda" + | Opcode.LDFSR -> "ld" + | Opcode.LDQF -> "ldq" + | Opcode.LDQFA -> "ldqa" + | Opcode.LDSB -> "ldsb" + | Opcode.LDSBA -> "ldsba" + | Opcode.LDSH -> "ldsh" + | Opcode.LDSHA -> "ldsha" + | Opcode.LDSTUB -> "ldstub" + | Opcode.LDSTUBA -> "ldstuba" + | Opcode.LDSW -> "ldsw" + | Opcode.LDSWA -> "ldswa" + | Opcode.LDUB -> "ldub" + | Opcode.LDUBA -> "lduba" + | Opcode.LDUH -> "lduh" + | Opcode.LDUHA -> "lduha" + | Opcode.LDUW -> "lduw" + | Opcode.LDUWA -> "lduwa" + | Opcode.LDX -> "ldx" + | Opcode.LDXA -> "ldxa" + | Opcode.LDXFSR -> "ldx" + | Opcode.MEMBAR -> "membar" + | Opcode.MOVA -> "mova" + | Opcode.MOVN -> "movn" + | Opcode.MOVNE -> "movne" + | Opcode.MOVE -> "move" + | Opcode.MOVG -> "movg" + | Opcode.MOVLE -> "movle" + | Opcode.MOVGE -> "movge" + | Opcode.MOVL -> "movl" + | Opcode.MOVGU -> "movgu" + | Opcode.MOVLEU -> "movleu" + | Opcode.MOVCC -> "movcc" + | Opcode.MOVCS -> "movcs" + | Opcode.MOVPOS -> "movpos" + | Opcode.MOVNEG -> "movneg" + | Opcode.MOVVC -> "movvc" + | Opcode.MOVVS -> "movvs" + | Opcode.MOVFA -> "mova" + | Opcode.MOVFN -> "movn" + | Opcode.MOVFU -> "movu" + | Opcode.MOVFG -> "movg" + | Opcode.MOVFUG -> "movug" + | Opcode.MOVFL -> "movl" + | Opcode.MOVFUL -> "movul" + | Opcode.MOVFLG -> "movlg" + | Opcode.MOVFNE -> "movne" + | Opcode.MOVFE -> "move" + | Opcode.MOVFUE -> "movue" + | Opcode.MOVFGE -> "movge" + | Opcode.MOVFUGE -> "movuge" + | Opcode.MOVFLE -> "movle" + | Opcode.MOVFULE -> "movule" + | Opcode.MOVFO -> "movo" + | Opcode.MOVRZ -> "movrz" + | Opcode.MOVRLEZ -> "movrlez" + | Opcode.MOVRLZ -> "movrlz" + | Opcode.MOVRNZ -> "movrnz" + | Opcode.MOVRGZ -> "movrgz" + | Opcode.MOVRGEZ -> "movrgez" + | Opcode.MULScc -> "mulscc" + | Opcode.MULX -> "mulx" + | Opcode.NOP -> "nop" + | Opcode.OR -> "or" + | Opcode.ORcc -> "orcc" + | Opcode.ORN -> "opn" + | Opcode.ORNcc -> "orncc" + | Opcode.POPC -> "popc" + | Opcode.PREFETCH -> "prefetch" + | Opcode.PREFETCHA -> "prefetcha" + | Opcode.RDASI -> "rd" + | Opcode.RDASR -> "rd" + | Opcode.RDCCR -> "rd" + | Opcode.RDFPRS -> "rd" + | Opcode.RDPC -> "rd" + | Opcode.RDPR -> "rdpr" + | Opcode.RDTICK -> "rd" + | Opcode.RDY -> "rd" + | Opcode.RESTORE -> "restore" + | Opcode.RESTORED -> "restored" + | Opcode.RETRY -> "retry" + | Opcode.RETURN -> "return" + | Opcode.SAVE -> "save" + | Opcode.SAVED -> "saved" + | Opcode.SDIV -> "sdiv" + | Opcode.SDIVcc -> "sdivcc" + | Opcode.SDIVX -> "sdivx" + | Opcode.SETHI -> "sethi" + | Opcode.SIR -> "sir" + | Opcode.SLL -> "sll" + | Opcode.SLLX -> "sllx" + | Opcode.SMUL -> "smul" + | Opcode.SMULcc -> "smulcc" + | Opcode.SRA -> "sra" + | Opcode.SRAX -> "srax" + | Opcode.SRL -> "srl" + | Opcode.SRLX -> "srlx" + | Opcode.STB -> "stb" + | Opcode.STBA -> "stba" + | Opcode.STBAR -> "stbar" + | Opcode.STD -> "std" + | Opcode.STDA -> "stda" + | Opcode.STDF -> "std" + | Opcode.STDFA -> "stda" + | Opcode.STF -> "st" + | Opcode.STFA -> "sta" + | Opcode.STFSR -> "st" + | Opcode.STH -> "sth" + | Opcode.STHA -> "stha" + | Opcode.STQF -> "stqf" + | Opcode.STQFA -> "stqa" + | Opcode.STW -> "stw" + | Opcode.STWA -> "stwa" + | Opcode.STX -> "stx" + | Opcode.STXA -> "stxa" + | Opcode.STXFSR -> "stx" + | Opcode.SUB -> "sub" + | Opcode.SUBcc -> "subcc" + | Opcode.SWAP -> "swap" + | Opcode.SWAPA -> "swapa" + | Opcode.TADDcc -> "taddcc" + | Opcode.TADDccTV ->" taddcctv" + | Opcode.Tcc -> "tcc" + | Opcode.TA -> "ta" + | Opcode.TN -> "tn" + | Opcode.TNE -> "tne" + | Opcode.TE -> "te" + | Opcode.TG -> "tg" + | Opcode.TLE -> "tle" + | Opcode.TGE -> "tge" + | Opcode.TL -> "tl" + | Opcode.TGU -> "tgu" + | Opcode.TLEU -> "tleu" + | Opcode.TCC -> "tcc" + | Opcode.TCS -> "tcs" + | Opcode.TPOS -> "tpos" + | Opcode.TNEG -> "tneg" + | Opcode.TVC -> "tvc" + | Opcode.TVS -> "tvs" + | Opcode.TSUBcc -> "tsubcc" + | Opcode.TSUBccTV -> " tsubcctv" + | Opcode.UDIV -> "udiv" + | Opcode.UDIVcc -> "udivcc" + | Opcode.UDIVX -> "udivx" + | Opcode.UMUL -> "umul" + | Opcode.UMULcc -> "umulcc" + | Opcode.WRASI -> "wr" + | Opcode.WRASR -> "wr" + | Opcode.WRCCR -> "wr" + | Opcode.WRFPRS -> "wr" + | Opcode.WRPR -> "wrpr" + | Opcode.WRY -> "wr" + | Opcode.WNOR -> "wnor" + | Opcode.WNORcc -> "wnorcc" + | Opcode.XOR -> "xor" + | Opcode.XORcc -> "xorcc" + | Opcode.XNOR -> "xnor" + | Opcode.XNORcc -> "xnorcc" + | Opcode.InvalidOp -> "(invalid)" + | _ -> Utils.impossible () + +let prependDelimiter delimiter (builder: DisasmBuilder) = + match delimiter with + | None -> () + | Some delim -> builder.Accumulate AsmWordKind.String delim + +let immToString imm (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 imm) + +let immToStringNoPrefix imm (builder: DisasmBuilder) = + builder.Accumulate AsmWordKind.Value $"{imm:x}" + +let ccToString cc (builder: DisasmBuilder) = + let cc = ConditionCode.toString cc + builder.Accumulate AsmWordKind.Variable cc + +let buildReg ins reg (builder: DisasmBuilder) = + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + +let memToString addrMode (builder: DisasmBuilder) = + match addrMode with + | DispMode (reg,c) -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + builder.Accumulate AsmWordKind.String "+" + builder.Accumulate AsmWordKind.Value (string c) + | PreIdxMode reg -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.String "-" + builder.Accumulate AsmWordKind.Variable reg + | PostIdxMode reg -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + builder.Accumulate AsmWordKind.String "+" + | UnchMode reg -> + let reg = Register.toString reg + builder.Accumulate AsmWordKind.Variable reg + +let oprToString ins addr operand delim builder = + match operand with + | OprReg reg -> + prependDelimiter delim builder + buildReg ins reg builder + | OprImm k -> + prependDelimiter delim builder + immToString k builder + | OprCC cc -> + prependDelimiter delim builder + ccToString cc builder + | OprPriReg prireg -> + prependDelimiter delim builder + buildReg ins prireg builder + | OprAddr k -> + prependDelimiter delim builder + immToString k builder + | OprMemory addrMode -> + prependDelimiter delim builder + memToString addrMode builder + +let buildComment2 opr1 opr2 (builder: DisasmBuilder) = + match opr1, opr2 with + | OprImm imm, _ | _, OprImm imm -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (string imm) + | OprMemory addrMode, _ | _, OprMemory addrMode -> + match addrMode with + | DispMode (reg, c) -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 c) + | _ -> () + | _ -> () + +let buildComment3 opr1 opr2 opr3 (builder: DisasmBuilder) = + match opr1, opr2, opr3 with + | OprImm imm, _, _ | _, OprImm imm, _ | _, _, OprImm imm -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (string imm) + | OprMemory addrMode, _, _ | _, OprMemory addrMode, _ + | _, _, OprMemory addrMode -> + match addrMode with + | DispMode (reg, c) -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 c) + | _ -> () + | _ -> () + +let buildComment3Bracket opr1 opr2 opr3 (builder: DisasmBuilder) = + match opr1, opr2, opr3 with + | OprImm imm, _, _ | _, OprImm imm, _ | _, _, OprImm imm -> + builder.Accumulate AsmWordKind.String "] ! " + builder.Accumulate AsmWordKind.Value (string imm) + | OprMemory addrMode, _, _ | _, OprMemory addrMode, _ + | _, _, OprMemory addrMode -> + match addrMode with + | DispMode (reg, c) -> + builder.Accumulate AsmWordKind.String "] ! " + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 c) + | _ -> () + | OprReg _, OprReg _, OprReg _ -> + builder.Accumulate AsmWordKind.String "]" + | _ -> () + +let buildComment4 opr1 opr2 opr3 opr4 (builder: DisasmBuilder) = + match opr1, opr2, opr3, opr4 with + | OprImm imm, _, _, _ | _, OprImm imm, _, _ | _, _, OprImm imm, _ + | _, _, _, OprImm imm -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (string imm) + | _ -> () + +let buildComment5 opr1 opr2 opr3 opr4 opr5 (builder: DisasmBuilder) = + match opr1, opr2, opr3, opr4, opr5 with + | OprImm imm, _, _, _ ,_ | _, OprImm imm, _, _, _ | _, _, OprImm imm, _, _ + | _, _, _, OprImm imm, _ | _, _, _, _, OprImm imm -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (string imm) + | OprMemory addrMode, _, _, _, _ | _, OprMemory addrMode, _, _, _ + | _, _, OprMemory addrMode, _, _ | _, _, _, OprMemory addrMode, _ + | _, _, _, _, OprMemory addrMode -> + match addrMode with + | DispMode (reg, c) -> + builder.Accumulate AsmWordKind.String " ! " + builder.Accumulate AsmWordKind.Value (HexString.ofInt32 c) + | _ -> () + | _ -> () + +let buildOprs ins pc builder = + let pcValue = int32 pc + match ins.Operands with + | NoOperand -> () + | OneOperand opr -> + match ins.Opcode with + | Opcode.CALL -> + match opr with + | OprAddr k -> + prependDelimiter (Some " 0x") builder + immToStringNoPrefix (k) builder + | _ -> Utils.impossible () + | _ -> + oprToString ins pc opr (Some " ") builder + | TwoOperands (opr1, opr2) -> + match ins.Opcode with + | Opcode.FBA | Opcode.FBN | Opcode.FBU + | Opcode.FBG | Opcode.FBUG | Opcode.FBL + | Opcode.FBUL | Opcode.FBLG | Opcode.FBNE + | Opcode.FBE | Opcode.FBUE | Opcode.FBGE | Opcode.FBUGE + | Opcode.FBLE | Opcode.FBULE | Opcode.FBO -> + match opr1, opr2 with + | OprImm 0b0, OprAddr k -> + prependDelimiter (Some " 0x") builder + immToStringNoPrefix (k) builder + | OprImm 0b1, OprAddr k -> + prependDelimiter (Some ",a 0x") builder + immToStringNoPrefix (k) builder + | _ -> Utils.impossible () + | Opcode.BA | Opcode.BN + | Opcode.BNE | Opcode.BE | Opcode.BG | Opcode.BLE | Opcode.BGE + | Opcode.BL | Opcode.BGU | Opcode.BLEU | Opcode.BCC | Opcode.BCS + | Opcode.BPOS | Opcode.BNEG | Opcode.BVC | Opcode.BVS -> + match opr1, opr2 with + | OprImm 0b0, OprAddr k -> + prependDelimiter (Some " 0x") builder + immToStringNoPrefix (k) builder + | OprImm 0b1, OprAddr k -> + prependDelimiter (Some ",a 0x") builder + immToStringNoPrefix (k) builder + | _ -> Utils.impossible () + | Opcode.FdTOx | Opcode.FNEGs | Opcode.FNEGd | Opcode.FNEGq | Opcode.FABSs + | Opcode.FABSd | Opcode.FABSq | Opcode.FSQRTs | Opcode.FSQRTd + | Opcode.FSQRTq | Opcode.FCMPs | Opcode.FCMPd | Opcode.FCMPq + | Opcode.FMOVs | Opcode.FMOVd | Opcode.FMOVq -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + | _ -> + match (opr1, opr2) with + | (OprReg reg, OprReg reg1) -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + | (OprReg reg, OprImm imm) -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + | _ -> + match ins.Opcode with + | Opcode.SETHI -> + oprToString ins pc opr1 (Some " %hi(") builder + oprToString ins pc opr2 (Some "), ") builder + | _ -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + buildComment2 opr1 opr2 builder + | ThreeOperands (opr1, opr2, opr3) -> + match ins.Opcode with + | Opcode.LDF | Opcode.LDDF | Opcode.LDQF | Opcode.LDFSR | Opcode.LDXFSR + | Opcode.LDSB | Opcode.LDSH | Opcode.LDSW | Opcode.LDUB | Opcode.LDUH + | Opcode.LDUW | Opcode.LDX | Opcode.LDD | Opcode.LDSTUB | Opcode.PREFETCH + | Opcode.SWAP -> + oprToString ins pc opr1 (Some " [") builder + oprToString ins pc opr2 (Some " + ") builder + oprToString ins pc opr3 (Some "], ") builder + buildComment3 opr1 opr2 opr3 builder + | Opcode.STF | Opcode.STDF | Opcode.STQF | Opcode.STFSR | Opcode.STXFSR + | Opcode.STB | Opcode.STH | Opcode.STW | Opcode.STX | Opcode.STD -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", [") builder + oprToString ins pc opr3 (Some " + ") builder + buildComment3Bracket opr1 opr2 opr3 builder + | Opcode.JMPL -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some " + ") builder + oprToString ins pc opr3 (Some ", ") builder + buildComment3 opr1 opr2 opr3 builder + | _ -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + oprToString ins pc opr3 (Some ", ") builder + buildComment3 opr1 opr2 opr3 builder + | FourOperands (opr1, opr2, opr3, opr4) -> + match ins.Opcode with + | Opcode.BPA | Opcode.BPN | Opcode.BPNE | Opcode.BPE | Opcode.BPG + | Opcode.BPLE | Opcode.BPGE | Opcode.BPL | Opcode.BPGU | Opcode.BPLEU + | Opcode.BPCC | Opcode.BPCS | Opcode.BPPOS | Opcode.BPNEG | Opcode.BPVC + | Opcode.BPVS -> + match opr1, opr2, opr3, opr4 with + | OprCC c, OprAddr k, OprImm 0b0, OprImm 0b0 -> + prependDelimiter (Some ",pn ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprCC c, OprAddr k, OprImm 0b1, OprImm 0b0 -> + prependDelimiter (Some ",a,pn ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprCC c, OprAddr k, OprImm 0b0, OprImm 0b1 -> + prependDelimiter (Some ",pt ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprCC c, OprAddr k, OprImm 0b1, OprImm 0b1 -> + prependDelimiter (Some ",a,pt ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | _ -> Utils.impossible () + | Opcode.FBPA | Opcode.FBPN | Opcode.FBPU | Opcode.FBPG | Opcode.FBPUG + | Opcode.FBPL | Opcode.FBPUL | Opcode.FBPLG | Opcode.FBPNE | Opcode.FBPE + | Opcode.FBPUE | Opcode.FBPGE | Opcode.FBPUGE | Opcode.FBPLE + | Opcode.FBPULE | Opcode.FBPO-> + match opr1, opr2, opr3, opr4 with + | OprCC c, OprAddr k, OprImm 0b0, OprImm 0b0 -> + prependDelimiter (Some ",pn ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprCC c, OprAddr k, OprImm 0b1, OprImm 0b0 -> + prependDelimiter (Some ",a,pn ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprCC c, OprAddr k, OprImm 0b0, OprImm 0b1 -> + prependDelimiter (Some ",pt ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprCC c, OprAddr k, OprImm 0b1, OprImm 0b1 -> + prependDelimiter (Some ",a,pt ") builder + ccToString c builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | _ -> Utils.impossible () + | Opcode.LDFA | Opcode.LDDFA | Opcode.LDQFA | Opcode.LDSTUBA + | Opcode.LDSBA | Opcode.LDSHA | Opcode.LDSWA | Opcode.LDUBA + | Opcode.LDUHA | Opcode.LDUWA | Opcode.LDXA | Opcode.LDDA -> + oprToString ins pc opr1 (Some " [") builder + oprToString ins pc opr2 (Some " + ") builder + oprToString ins pc opr3 (Some "] ") builder + oprToString ins pc opr4 (Some ", ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | Opcode.BRZ | Opcode.BRLEZ | Opcode.BRLZ | Opcode.BRNZ + | Opcode.BRGZ | Opcode.BRGEZ -> + match opr1, opr2, opr3, opr4 with + | OprReg reg, OprAddr k, OprImm 0b0, OprImm 0b0 -> + prependDelimiter (Some ",pn ") builder + buildReg ins reg builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprReg reg, OprAddr k, OprImm 0b0, OprImm 0b1 -> + prependDelimiter (Some ",pt ") builder + buildReg ins reg builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprReg reg, OprAddr k, OprImm 0b1, OprImm 0b0 -> + prependDelimiter (Some ",a,pn ") builder + buildReg ins reg builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | OprReg reg, OprAddr k, OprImm 0b1, OprImm 0b1 -> + prependDelimiter (Some ",a,pt ") builder + buildReg ins reg builder + prependDelimiter (Some ", 0x") builder + immToStringNoPrefix (k) builder + | _ -> Utils.impossible () + | Opcode.PREFETCHA -> + oprToString ins pc opr1 (Some " [") builder + oprToString ins pc opr2 (Some " + ") builder + oprToString ins pc opr3 (Some "], ") builder + oprToString ins pc opr4 (Some ", ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | Opcode.STBA | Opcode.STHA | Opcode.STWA | Opcode.STXA | Opcode.STDA -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", [") builder + oprToString ins pc opr3 (Some " + ") builder + oprToString ins pc opr4 (Some "] ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | Opcode.STFA | Opcode.STDFA | Opcode.STQFA -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", [") builder + oprToString ins pc opr3 (Some " + ") builder + oprToString ins pc opr4 (Some "] ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | Opcode.SWAPA -> + oprToString ins pc opr1 (Some " [") builder + oprToString ins pc opr2 (Some " + ") builder + oprToString ins pc opr3 (Some "] ") builder + oprToString ins pc opr4 (Some ", ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | Opcode.CASA | Opcode.CASXA -> + oprToString ins pc opr1 (Some " [") builder + oprToString ins pc opr2 (Some "] ") builder + oprToString ins pc opr3 (Some ", ") builder + oprToString ins pc opr4 (Some ", ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | _ -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + oprToString ins pc opr3 (Some ", ") builder + oprToString ins pc opr4 (Some ", ") builder + buildComment4 opr1 opr2 opr3 opr4 builder + | FiveOperands (opr1, opr2, opr3, opr4, opr5) -> + oprToString ins pc opr1 (Some " ") builder + oprToString ins pc opr2 (Some ", ") builder + oprToString ins pc opr3 (Some ", ") builder + oprToString ins pc opr4 (Some ", ") builder + oprToString ins pc opr5 (Some ", ") builder + buildComment5 opr1 opr2 opr3 opr4 opr5 builder + +let inline buildOpcode ins (builder: DisasmBuilder) = + let str = opCodeToString ins.Opcode + builder.Accumulate AsmWordKind.Mnemonic str + +let disasm insInfo (builder: DisasmBuilder) = + let pc = insInfo.Address + if builder.ShowAddr then builder.AccumulateAddr () else () + buildOpcode insInfo builder + buildOprs insInfo pc builder diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCGeneralLifter.fs b/src/FrontEnd/BinLifter/SPARC/SPARCGeneralLifter.fs new file mode 100644 index 00000000..998e98f8 --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCGeneralLifter.fs @@ -0,0 +1,4044 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.SPARC.GeneralLifter + +open B2R2 +open B2R2.BinIR +open B2R2.BinIR.LowUIR +open B2R2.BinIR.LowUIR.AST.InfixOp +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.LiftingOperators +open B2R2.FrontEnd.BinLifter.SPARC + +let inline getRegVar (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let inline numI32 n t = BitVector.OfInt32 n t |> AST.num + +let inline numI32PC n = BitVector.OfInt32 n 64 |> AST.num + +let inline numU32 n t = BitVector.OfUInt32 n t |> AST.num + +let inline numU64 n t = BitVector.OfUInt64 n t |> AST.num + +let inline numI64 n t = BitVector.OfInt64 n t |> AST.num + +let inline tmpVars2 ir t = + struct (!+ir t, !+ir t) + +let inline ( !. ) (ctxt: TranslationContext) name = + Register.toRegID name |> ctxt.GetRegVar + +let inline getCCVar (ctxt: TranslationContext) name = + ConditionCode.toRegID name |> ctxt.GetRegVar + +let dstAssign oprSize dst src = + match oprSize with + | 8 | 16 -> dst := src (* No extension for 8- and 16-bit operands *) + | _ -> let dst = AST.unwrap dst + let dstOrigSz = dst |> TypeCheck.typeOf + let oprBitSize = RegType.toBitWidth oprSize + let dstBitSize = RegType.toBitWidth dstOrigSz + if dstBitSize > oprBitSize then dst := AST.zext dstOrigSz src + elif dstBitSize = oprBitSize then dst := src + else raise InvalidOperandSizeException + +let private cfOnAdd e1 r = AST.lt r e1 + +let private ofOnAdd e1 e2 r = + let e1High = AST.xthi 1 e1 + let e2High = AST.xthi 1 e2 + let rHigh = AST.xthi 1 r + (e1High .& e2High .& (AST.neg rHigh)) + .| ((AST.neg e1High) .& (AST.neg e2High) .& rHigh) + +let transOprToExpr ins insLen ctxt = function + | OprReg reg -> !.ctxt reg + | OprImm imm -> numI32 imm 64 + | OprAddr addr -> numI32PC addr + | OprCC cc -> getCCVar ctxt cc + | OprPriReg prireg -> !.ctxt prireg + | _ -> Utils.impossible () + +let isRegOpr ins insLen ctxt = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> + match o2 with + | OprReg reg -> true + | _ -> false + | _ -> raise InvalidOperandException + +let getOneOpr insInfo = + match insInfo.Operands with + | OneOperand opr -> opr + | _ -> raise InvalidOperandException + +let getTwoOprs insInfo = + match insInfo.Operands with + | TwoOperands (o1, o2) -> o1, o2 + | _ -> raise InvalidOperandException + +let getThreeOprs insInfo = + match insInfo.Operands with + | ThreeOperands (o1, o2, o3) -> o1, o2, o3 + | _ -> raise InvalidOperandException + +let transOneOpr (ins: InsInfo) insLen ctxt = + match ins.Operands with + | OneOperand o1 -> transOprToExpr ins insLen ctxt o1 + | _ -> raise InvalidOperandException + +let transTwoOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | TwoOperands (o1, o2) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2) + | _ -> raise InvalidOperandException + +let transThreeOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2, + transOprToExpr ins insLen ctxt o3) + | _ -> raise InvalidOperandException + +let transFourOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | FourOperands (o1, o2, o3, o4) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2, + transOprToExpr ins insLen ctxt o3, + transOprToExpr ins insLen ctxt o4) + | _ -> raise InvalidOperandException + +let transAddrThreeOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> + struct (transOprToExpr ins insLen ctxt o1 .+ + transOprToExpr ins insLen ctxt o2, + transOprToExpr ins insLen ctxt o3) + | _ -> raise InvalidOperandException + +let transAddrFourOprs (ins: InsInfo) insLen ctxt = + match ins.Operands with + | FourOperands (o1, o2, o3, o4) -> + struct (transOprToExpr ins insLen ctxt o1 .+ + transOprToExpr ins insLen ctxt o2, + transOprToExpr ins insLen ctxt o3, + transOprToExpr ins insLen ctxt o4) + | _ -> raise InvalidOperandException + +let transTwooprsAddr (ins: InsInfo) insLen ctxt = + match ins.Operands with + | ThreeOperands (o1, o2, o3) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2 .+ + transOprToExpr ins insLen ctxt o3) + | _ -> raise InvalidOperandException + +let transThroprsAddr (ins: InsInfo) insLen ctxt = + match ins.Operands with + | FourOperands (o1, o2, o3, o4) -> + struct (transOprToExpr ins insLen ctxt o1, + transOprToExpr ins insLen ctxt o2 .+ + transOprToExpr ins insLen ctxt o3, + transOprToExpr ins insLen ctxt o4) + | _ -> raise InvalidOperandException + +let inline tmpVars3 ir t = + struct (!+ir t, !+ir t, !+ir t) + +let inline tmpVars4 ir t = + struct (!+ir t, !+ir t, !+ir t, !+ir t) + +let getConditionCodeAdd res src src1 = + let sign = AST.extract src 1 63 + let sign1 = AST.extract src1 1 63 + let ressign = AST.extract res 1 63 + let res32 = AST.extract res 32 0 + let sign32 = AST.extract src 1 31 + let sign321 = AST.extract src1 1 31 + let ressign32 = AST.extract res 1 31 + let xccn = ressign + let xccz = res == AST.num0 64 + let xccv = ((sign .& sign1 .& AST.not ressign) .| + (AST.not sign .& AST.not sign1 .& ressign)) + let xccc = (sign .& sign1) .| ((AST.not ressign) .& (sign .| sign1)) + let iccn = (ressign32) + let iccz = ((res32) == AST.num0 32) + let iccv = ((sign32 .& sign321 .& AST.not ressign32) .| + (AST.not sign32 .& AST.not sign321 .& ressign32)) + let iccc = (sign32 .& sign321) .| ((AST.not ressign32) .& (sign32 .| sign321)) + // AST.concat xccn (AST. concat xccz (AST.concat xccv (AST.concat xccc + // (AST.concat iccn (AST.concat iccz (AST.concat iccv iccc)))))) + AST.concatArr [| iccc; iccv; iccz; iccn; xccc; xccv; xccz; iccn |] + +let getConditionCodeSub res src src1 = + let sign = AST.extract src 1 63 + let sign1 = AST.extract src1 1 63 + let ressign = AST.extract res 1 63 + let res32 = AST.extract res 32 0 + let sign32 = AST.extract src 1 31 + let sign321 = AST.extract src1 1 31 + let ressign32 = AST.extract res 1 31 + let xccn = ressign + let xccz = res == AST.num0 64 + let xccv = ((sign .& AST.not sign1 .& AST.not ressign) .| + (AST.not sign .& sign1 .& ressign)) + let xccc = (((AST.not sign) .& sign1) .| + (ressign .& ((AST.not sign) .| sign1))) + let iccn = (ressign32) + let iccz = ((res32) == AST.num0 32) + let iccv = ((sign32 .& AST.not sign321 .& AST.not ressign32) .| + (AST.not sign32 .& sign321 .& ressign32)) + let iccc = (((AST.not sign32) .& sign321) .| + (ressign32 .& ((AST.not sign32) .| sign321))) + // AST.concat xccn (AST. concat xccz (AST.concat xccv (AST.concat xccc + // (AST.concat iccn (AST.concat iccz (AST.concat iccv iccc)))))) + AST.concatArr [| iccc; iccv; iccz; iccn; xccc; xccv; xccz; iccn |] + +let getConditionCodeLog res src src1 = + let sign = AST.extract src 1 63 + let sign1 = AST.extract src1 1 63 + let ressign = AST.extract res 1 63 + let res32 = AST.extract res 32 0 + let sign32 = AST.extract src 1 31 + let sign321 = AST.extract src1 1 31 + let ressign32 = AST.extract res 1 31 + let xccn = ressign + let xccz = res == AST.num0 64 + let xccv = AST.num0 1 + let xccc = AST.num0 1 + let iccn = (ressign32) + let iccz = ((res32) == AST.num0 32) + let iccv = AST.num0 1 + let iccc = AST.num0 1 + // AST.concat xccn (AST. concat xccz (AST.concat xccv (AST.concat xccc + // (AST.concat iccn (AST.concat iccz (AST.concat iccv iccc)))))) + AST.concatArr [| iccc; iccv; iccz; iccn; xccc; xccv; xccz; iccn |] + +let getConditionCodeMul res src src1 = + let sign = AST.extract src 1 63 + let sign1 = AST.extract src1 1 63 + let ressign = AST.extract res 1 63 + let res32 = AST.extract res 32 0 + let sign32 = AST.extract src 1 31 + let sign321 = AST.extract src1 1 31 + let ressign32 = AST.extract res 1 31 + let xccn = ressign + let xccz = res == AST.num0 64 + let xccv = AST.num0 1 + let xccc = AST.num0 1 + let iccn = (ressign32) + let iccz = ((res32) == AST.num0 32) + let iccv = AST.num0 1 + let iccc = AST.num0 1 + // AST.concat xccn (AST. concat xccz (AST.concat xccv (AST.concat xccc + // (AST.concat iccn (AST.concat iccz (AST.concat iccv iccc)))))) + AST.concatArr [| iccc; iccv; iccz; iccn; xccc; xccv; xccz; iccn |] + +let getConditionCodeMulscc res src src1 = + let res32 = AST.extract res 32 0 + let sign32 = AST.extract src 1 31 + let sign321 = AST.extract src1 1 31 + let ressign32 = AST.extract res 1 31 + let iccn = (ressign32) + let iccz = ((res32) == AST.num0 32) + let iccv = ((sign32 .& sign321 .& AST.not ressign32) .| + (AST.not sign32 .& AST.not sign321 .& ressign32)) + let iccc = (sign32 .& sign321) .| ((AST.not ressign32) + .& (sign32 .| sign321)) + AST.concatArr [| iccc; iccv; iccz; iccn |] + +let getNextReg ctxt reg = + if (reg = getRegVar ctxt R.G0) then R.G1 + elif (reg = getRegVar ctxt R.G2) then R.G3 + elif (reg = getRegVar ctxt R.G4) then R.G5 + elif (reg = getRegVar ctxt R.G6) then R.G7 + elif (reg = getRegVar ctxt R.O0) then R.O1 + elif (reg = getRegVar ctxt R.O2) then R.O3 + elif (reg = getRegVar ctxt R.O4) then R.O5 + elif (reg = getRegVar ctxt R.O6) then R.O7 + elif (reg = getRegVar ctxt R.L0) then R.L1 + elif (reg = getRegVar ctxt R.L2) then R.L3 + elif (reg = getRegVar ctxt R.L4) then R.L5 + elif (reg = getRegVar ctxt R.L6) then R.L7 + elif (reg = getRegVar ctxt R.I0) then R.I1 + elif (reg = getRegVar ctxt R.I2) then R.I3 + elif (reg = getRegVar ctxt R.I4) then R.I5 + elif (reg = getRegVar ctxt R.I6) then R.I7 + else raise InvalidRegisterException + +let getFloatClass ctxt freg = + if (freg = getRegVar ctxt R.F0 || freg = getRegVar ctxt R.F2 + || freg = getRegVar ctxt R.F4 || freg = getRegVar ctxt R.F6 + || freg = getRegVar ctxt R.F8|| freg = getRegVar ctxt R.F10 + || freg = getRegVar ctxt R.F12 || freg = getRegVar ctxt R.F14 + || freg = getRegVar ctxt R.F16 || freg = getRegVar ctxt R.F18 + || freg = getRegVar ctxt R.F20 || freg = getRegVar ctxt R.F22 + || freg = getRegVar ctxt R.F24 || freg = getRegVar ctxt R.F26 + || freg = getRegVar ctxt R.F28 || freg = getRegVar ctxt R.F30) then 0 + elif (freg = getRegVar ctxt R.F32 || freg = getRegVar ctxt R.F34 + || freg = getRegVar ctxt R.F36 || freg = getRegVar ctxt R.F38 + || freg = getRegVar ctxt R.F40 || freg = getRegVar ctxt R.F42 + || freg = getRegVar ctxt R.F44 || freg = getRegVar ctxt R.F46 + || freg = getRegVar ctxt R.F48 || freg = getRegVar ctxt R.F50 + || freg = getRegVar ctxt R.F52 || freg = getRegVar ctxt R.F54 + || freg = getRegVar ctxt R.F56 || freg = getRegVar ctxt R.F58 + || freg = getRegVar ctxt R.F60 || freg = getRegVar ctxt R.F62) then 1 + else raise InvalidRegisterException + +let getDFloatNext ctxt freg = + if (freg = getRegVar ctxt R.F0) then R.F1 + elif (freg = getRegVar ctxt R.F2) then R.F3 + elif (freg = getRegVar ctxt R.F4) then R.F5 + elif (freg = getRegVar ctxt R.F6) then R.F7 + elif (freg = getRegVar ctxt R.F8) then R.F9 + elif (freg = getRegVar ctxt R.F10) then R.F11 + elif (freg = getRegVar ctxt R.F12) then R.F13 + elif (freg = getRegVar ctxt R.F14) then R.F15 + elif (freg = getRegVar ctxt R.F16) then R.F17 + elif (freg = getRegVar ctxt R.F18) then R.F19 + elif (freg = getRegVar ctxt R.F20) then R.F21 + elif (freg = getRegVar ctxt R.F22) then R.F23 + elif (freg = getRegVar ctxt R.F24) then R.F25 + elif (freg = getRegVar ctxt R.F26) then R.F27 + elif (freg = getRegVar ctxt R.F28) then R.F29 + elif (freg = getRegVar ctxt R.F30) then R.F31 + else raise InvalidRegisterException + +let movFregD ctxt ir src dst = + let sClass = getFloatClass ctxt src + let dClass = getFloatClass ctxt dst + match sClass, dClass with + | 0, 0 -> + let nextsrc = getRegVar ctxt (getDFloatNext ctxt src) + let nextdst = getRegVar ctxt (getDFloatNext ctxt dst) + !!ir (dst := src) + !!ir (nextdst := nextsrc) + | 0, 1 -> + let nextsrc = getRegVar ctxt (getDFloatNext ctxt src) + !!ir (AST.extract dst 32 0 := nextsrc) + !!ir (AST.extract dst 32 32 := src) + | 1, 0 -> + let nextdst = getRegVar ctxt (getDFloatNext ctxt dst) + !!ir (dst := AST.extract src 32 32) + !!ir (nextdst := AST.extract src 32 0) + | 1, 1 -> + !!ir (dst := src) + | _ -> raise InvalidRegisterException + +let getQFloatNext0 ctxt freg = + if (freg = getRegVar ctxt R.F0) then struct (R.F1, R.F2, R.F3) + elif (freg = getRegVar ctxt R.F4) then struct (R.F5, R.F6, R.F7) + elif (freg = getRegVar ctxt R.F8) then struct (R.F9, R.F10, R.F11) + elif (freg = getRegVar ctxt R.F12) then struct (R.F13, R.F14, R.F15) + elif (freg = getRegVar ctxt R.F16) then struct (R.F17, R.F18, R.F19) + elif (freg = getRegVar ctxt R.F20) then struct (R.F21, R.F22, R.F23) + elif (freg = getRegVar ctxt R.F24) then struct (R.F25, R.F26, R.F27) + elif (freg = getRegVar ctxt R.F28) then struct (R.F29, R.F30, R.F31) + else raise InvalidRegisterException + +let getQFloatNext1 ctxt freg = + if (freg = getRegVar ctxt R.F32) then R.F34 + elif (freg = getRegVar ctxt R.F36) then R.F38 + elif (freg = getRegVar ctxt R.F40) then R.F42 + elif (freg = getRegVar ctxt R.F44) then R.F46 + elif (freg = getRegVar ctxt R.F48) then R.F50 + elif (freg = getRegVar ctxt R.F52) then R.F54 + elif (freg = getRegVar ctxt R.F56) then R.F58 + elif (freg = getRegVar ctxt R.F60) then R.F62 + else raise InvalidRegisterException + +let movFregQ ctxt ir src dst = + let sClass = getFloatClass ctxt src + let dClass = getFloatClass ctxt dst + match sClass, dClass with + | 0, 0 -> + let struct (s1, s2, s3) = getQFloatNext0 ctxt src + let src1 = getRegVar ctxt s1 + let src2 = getRegVar ctxt s2 + let src3 = getRegVar ctxt s3 + let struct (d1, d2, d3) = getQFloatNext0 ctxt dst + let dst1 = getRegVar ctxt d1 + let dst2 = getRegVar ctxt d2 + let dst3 = getRegVar ctxt d3 + !!ir (dst := src) + !!ir (dst1 := src1) + !!ir (dst2 := src2) + !!ir (dst3 := src3) + | 0, 1 -> + let struct (s1, s2, s3) = getQFloatNext0 ctxt src + let src1 = getRegVar ctxt s1 + let src2 = getRegVar ctxt s2 + let src3 = getRegVar ctxt s3 + let nextdst = getRegVar ctxt (getQFloatNext1 ctxt dst) + !!ir (AST.extract nextdst 32 0 := src3) + !!ir (AST.extract nextdst 32 32 := src2) + !!ir (AST.extract dst 32 0 := src1) + !!ir (AST.extract dst 32 32 := src) + | 1, 0 -> + let nextsrc = getRegVar ctxt (getQFloatNext1 ctxt src) + let struct (d1, d2, d3) = getQFloatNext0 ctxt dst + let dst1 = getRegVar ctxt d1 + let dst2 = getRegVar ctxt d2 + let dst3 = getRegVar ctxt d3 + !!ir (dst := AST.extract src 32 32) + !!ir (dst1 := AST.extract src 32 0) + !!ir (dst2 := AST.extract nextsrc 32 32) + !!ir (dst3 := AST.extract nextsrc 32 0) + | 1, 1 -> + let nextsrc = getRegVar ctxt (getQFloatNext1 ctxt src) + let nextdst = getRegVar ctxt (getQFloatNext1 ctxt dst) + !!ir (nextdst := nextsrc) + !!ir (dst := src) + | _ -> raise InvalidRegisterException + +let getDFloatOp ctxt ir src op = + let regclass = getFloatClass ctxt src + match regclass with + | 0 -> + let nextreg = getRegVar ctxt (getDFloatNext ctxt src) + !!ir ((AST.extract op 32 32) := src) + !!ir ((AST.extract op 32 0) := nextreg) + | 1 -> + !!ir (op := src) + | _ -> raise InvalidRegisterException + +let getQFloatOp ctxt ir src op1 op2 = + let regclass = getFloatClass ctxt src + match regclass with + | 0 -> + let struct (r1, r2, r3) = getQFloatNext0 ctxt src + let src1 = getRegVar ctxt r1 + let src2 = getRegVar ctxt r2 + let src3 = getRegVar ctxt r3 + !!ir ((AST.extract op1 32 32) := src) + !!ir ((AST.extract op1 32 0) := src1) + !!ir ((AST.extract op2 32 32) := src2) + !!ir ((AST.extract op2 32 0) := src3) + | 1 -> + let r1 = getQFloatNext1 ctxt src + let src1 = getRegVar ctxt r1 + !!ir ((AST.extract op1 64 0) := src) + !!ir ((AST.extract op2 64 0) := src1) + | _ -> raise InvalidRegisterException + +let setDFloatOp ctxt ir dst res = + let regclass = getFloatClass ctxt dst + match regclass with + | 0 -> + let nextreg = getRegVar ctxt (getDFloatNext ctxt dst) + !!ir (dst := (AST.extract res 32 32)) + !!ir (nextreg := (AST.extract res 32 0)) + | 1 -> + !!ir (dst := res) + | _ -> raise InvalidRegisterException + +let setQFloatOp ctxt ir dst res1 res2 = + let regclass = getFloatClass ctxt dst + match regclass with + | 0 -> + let struct (r1, r2, r3) = getQFloatNext0 ctxt dst + let dst1 = getRegVar ctxt r1 + let dst2 = getRegVar ctxt r2 + let dst3 = getRegVar ctxt r3 + !!ir (dst := (AST.extract res1 32 32)) + !!ir (dst1 := (AST.extract res1 32 0)) + !!ir (dst2 := (AST.extract res2 32 32)) + !!ir (dst3 := (AST.extract res2 32 0)) + | 1 -> + let r1 = getQFloatNext1 ctxt dst + let dst1 = getRegVar ctxt r1 + !!ir (dst := (AST.extract res1 64 0)) + !!ir (dst1 := (AST.extract res2 64 0) ) + | _ -> raise InvalidRegisterException + +let cast64To128 ctxt ir src dst1 dst2 = + let oprSize = 64 + let zero = AST.num0 64 + let tmpSrc = !+ir oprSize + let n63 = numI32 63 64 + let n15 = numI32 15 16 + let n52 = numI32 52 64 + let one = numI32 1 64 + let n60 = numI32 60 64 + let final = !+ir 52 + let biasDiff = numI32 0x3c00 16 + let sign = (AST.xtlo 16 (((src >> n63) .& one))) << n15 + let exponent = + (AST.xtlo 16 (((src>> n52) .& (numI32 0x7ff 64)))) .+ biasDiff + let integerpart = numI64 0x0010000000000000L 64 + let significand = src .& numI64 0xFFFFFFFFFFFFFL 64 .| integerpart + !!ir (AST.extract dst1 16 48 := AST.ite (AST.eq src zero) + (AST.num0 16) (sign .| exponent)) + !!ir (final := AST.ite (AST.eq tmpSrc zero) + (AST.num0 52) (AST.extract significand 52 0)) + !!ir (AST.extract dst1 48 0 := (AST.extract final 48 4)) + !!ir (AST.extract dst2 4 60 := (AST.extract final 4 0)) + !!ir (AST.extract dst2 60 4 := AST.num0 60) + +let cast128to64 ctxt ir src1 src2 dst = + let n48 = numI32 48 64 + let n63 = numI32 63 64 + let top16b = AST.extract src1 16 48 + let sign = (AST.zext 64 top16b .& (numI32 0x8000 64)) << n48 + let biasDiff = numI32 0x3c00 64 + let tmpExp = !+ir 64 + let significand = !+ir 64 + let computedExp = + (AST.zext 64 (top16b .& (numI32 0x7fff 16)) .- biasDiff) + let maxExp = numI32 0x7fe 64 + let exponent = + AST.ite (AST.eq top16b (AST.num0 16)) + (AST.num0 64) + (AST.ite (AST.gt tmpExp maxExp) maxExp tmpExp) + let exponent = exponent << numI32 52 64 + let n11 = numI32 11 64 + !!ir (AST.extract significand 16 48 := AST.extract src1 16 32) + !!ir (AST.extract significand 32 0 := AST.extract src2 32 32) + !!ir (tmpExp := computedExp) + !!ir (dst := (sign .| exponent .| significand)) + +let add ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + !) + else + !!ir (dst := res) + !>ir insLen + +let addcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + !) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeAdd res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let addC ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + ! (AST.extract ccr 1 0)) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !>ir insLen + +let addCcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + ! (AST.extract ccr 1 0)) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeAdd res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let ``and`` ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + !) + else + !!ir (dst := res) + !>ir insLen + +let andcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let ccr = !.ctxt R.CCR + let res = !+ir oprSize + let byte = !+ir 8 + !) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeLog res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let andn ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + !) + else + !!ir (dst := res) + !>ir insLen + +let andncc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let ccr = !.ctxt R.CCR + let res = !+ir oprSize + let byte = !+ir 8 + !) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeLog res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let branchpr ins insLen ctxt = + let ir = IRBuilder (16) + let oprSize = 64 + let struct (src, label, an, pr) = transFourOprs ins insLen ctxt + let pc = !.ctxt R.PC + ! (src == AST.num0 oprSize) + | Opcode.BRLEZ ->(src ?<= AST.num0 oprSize) + | Opcode.BRLZ -> (src ?< AST.num0 oprSize) + | Opcode.BRNZ -> (src != AST.num0 oprSize) + | Opcode.BRGZ -> (src ?> AST.num0 oprSize) + | Opcode.BRGEZ -> (src ?>= AST.num0 oprSize) + | _ -> raise InvalidOpcodeException + let annoffset = + if (AST.extract an 1 0 = AST.b1) then numI32PC 4 + else numI32PC 0 + let fallThrough = pc .+ numI32PC 4 .+ annoffset + let jumpTarget = pc .+ AST.zext 64 label + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir insLen + +let branchicc ins insLen ctxt = + let ir = IRBuilder (16) + let oprSize = 64 + let struct (an, label) = transTwoOprs ins insLen ctxt + let pc = !.ctxt R.PC + let ccr = !.ctxt R.CCR + ! (AST.b1) + | Opcode.BN -> (AST.b0) + | Opcode.BNE -> (AST.extract ccr 1 2 == AST.b0) + | Opcode.BE -> (AST.extract ccr 1 2 == AST.b1) + | Opcode.BG -> + (((AST.extract ccr 1 2) .| ((AST.extract ccr 1 1) <+> + (AST.extract ccr 1 3))) == AST.b0) + | Opcode.BLE -> + (((AST.extract ccr 1 2) .| ((AST.extract ccr 1 1) <+> + (AST.extract ccr 1 3))) == AST.b1) + | Opcode.BGE -> + ((AST.extract ccr 1 1) <+> (AST.extract ccr 1 3) == AST.b1) + | Opcode.BL -> + ((AST.extract ccr 1 1) <+> (AST.extract ccr 1 3) == AST.b1) + | Opcode.BGU -> + ((AST.extract ccr 1 0) .| (AST.extract ccr 1 2) == AST.b0) + | Opcode.BLEU -> + ((AST.extract ccr 1 0) .| (AST.extract ccr 1 2) == AST.b1) + | Opcode.BCC -> (AST.extract ccr 1 0 == AST.b0) + | Opcode.BCS -> (AST.extract ccr 1 0 == AST.b1) + | Opcode.BPOS -> (AST.extract ccr 1 3 == AST.b0) + | Opcode.BNEG -> (AST.extract ccr 1 3 == AST.b1) + | Opcode.BVC -> (AST.extract ccr 1 1 == AST.b0) + | Opcode.BVS -> (AST.extract ccr 1 1 == AST.b1) + | _ -> raise InvalidOpcodeException + let annoffset = + if (AST.extract an 1 0 = AST.b1) then numI32PC 4 + else numI32PC 0 + let fallThrough = pc .+ numI32PC 4 .+ annoffset + let jumpTarget = pc .+ AST.zext 64 label + if (ins.Opcode = Opcode.BA) then + !!ir (AST.interjmp jumpTarget InterJmpKind.Base) + !>ir insLen + elif (ins.Opcode = Opcode.BN) then + !>ir insLen + else + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir insLen + +let branchpcc ins insLen ctxt = + let ir = IRBuilder (16) + let oprSize = 64 + let struct (cc, label, an, pr) = transFourOprs ins insLen ctxt + let pc = !.ctxt R.PC + let ccr = !.ctxt R.CCR + ! (AST.b1) + | Opcode.BPN -> (AST.b0) + | Opcode.BPNE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 2 == AST.b0) + else + (AST.extract ccr 1 4 == AST.b0) + | Opcode.BPE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 2 == AST.b1) + else + (AST.extract ccr 1 6 == AST.b1) + | Opcode.BPG -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (((AST.extract ccr 1 2) .| ((AST.extract ccr 1 1) <+> + (AST.extract ccr 1 3))) == AST.b0) + else + (((AST.extract ccr 1 6) .| ((AST.extract ccr 1 5) <+> + (AST.extract ccr 1 7))) == AST.b0) + | Opcode.BPLE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (((AST.extract ccr 1 2) .| ((AST.extract ccr 1 1) <+> + (AST.extract ccr 1 3))) == AST.b1) + else + (((AST.extract ccr 1 6) .| ((AST.extract ccr 1 5) <+> + (AST.extract ccr 1 7))) == AST.b1) + | Opcode.BPGE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + ((AST.extract ccr 1 1) <+> (AST.extract ccr 1 3) == AST.b1) + else + ((AST.extract ccr 1 5) <+> (AST.extract ccr 1 7) == AST.b1) + | Opcode.BPL -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + ((AST.extract ccr 1 1) <+> (AST.extract ccr 1 3) == AST.b1) + else + ((AST.extract ccr 1 5) <+> (AST.extract ccr 1 7) == AST.b1) + | Opcode.BPGU -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + ((AST.extract ccr 1 0) .| (AST.extract ccr 1 2) == AST.b0) + else + ((AST.extract ccr 1 4) .| (AST.extract ccr 1 6) == AST.b0) + | Opcode.BPLEU -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + ((AST.extract ccr 1 0) .| (AST.extract ccr 1 2) == AST.b1) + else + ((AST.extract ccr 1 4) .| (AST.extract ccr 1 6) == AST.b1) + | Opcode.BPCC -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 0 == AST.b0) + else + (AST.extract ccr 1 4 == AST.b0) + | Opcode.BPCS -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 0 == AST.b1) + else + (AST.extract ccr 1 4 == AST.b1) + | Opcode.BPPOS -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 3 == AST.b0) + else + (AST.extract ccr 1 7 == AST.b0) + | Opcode.BPNEG -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 3 == AST.b1) + else + (AST.extract ccr 1 7 == AST.b1) + | Opcode.BPVC -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 1 == AST.b0) + else + (AST.extract ccr 1 5 == AST.b0) + | Opcode.BPVS -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + (AST.extract ccr 1 1 == AST.b1) + else + (AST.extract ccr 1 5 == AST.b1) + | _ -> raise InvalidOpcodeException + let annoffset = + if (AST.extract an 1 0 = AST.b1) then numI32PC 4 + else numI32PC 0 + let fallThrough = pc .+ numI32PC 4 .+ annoffset + let jumpTarget = pc .+ AST.zext 64 label + if (ins.Opcode = Opcode.BPA) then + !!ir (AST.interjmp jumpTarget InterJmpKind.Base) + !>ir insLen + elif (ins.Opcode = Opcode.BPN) then + !>ir insLen + else + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir insLen + +let call ins insLen ctxt = + let ir = IRBuilder (16) + let dst = transOneOpr ins insLen ctxt + let sp = !.ctxt R.O7 + let pc = !.ctxt R.PC + !ir insLen + +let casa ins insLen ctxt = + let struct (src, asi, src1, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! 0) == (AST.loadBE 32 (src .+ asi))) + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.loadBE 32 (src .+ asi) := AST.extract src1 32 0) + !!ir (AST.lmark lblEnd) + !!ir (AST.extract dst 32 0 := AST.extract src1 32 0) + !!ir (AST.extract dst 32 32 := AST.num0 32) + !>ir insLen + +let casxa ins insLen ctxt = + let struct (src, asi, src1, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! (src .+ asi)) + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.loadBE 64 (src .+ asi) := dst) + !!ir (AST.lmark lblEnd) + !!ir (dst := src1) + !>ir insLen + +let ``done`` ins insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let fabss ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 32 + let ir = IRBuilder (16) + ! 31 := AST.b0) + !!ir (AST.extract dst 31 0 := AST.extract src 31 0) + !>ir insLen + +let fabsd ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let op = !+ir oprSize + let res = !+ir oprSize + ! 63 := AST.b0) + !!ir (AST.extract res 63 0 := AST.extract op 63 0) + setDFloatOp ctxt ir dst res + !>ir insLen + +let fabsq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let op1 = !+ir oprSize + let op2 = !+ir oprSize + let res1 = !+ir oprSize + let res2 = !+ir oprSize + ! 63 := AST.b0) + !!ir (AST.extract res1 63 0 := AST.extract op1 63 0) + !!ir (AST.extract res2 64 0 := AST.extract op2 64 0) + setQFloatOp ctxt ir dst res1 res2 + !>ir insLen + +let fmovs ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + !ir insLen + +let fmovd ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + !ir insLen + +let fmovq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + !ir insLen + +let fnegs ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 32 + let ir = IRBuilder (16) + let sign = ((AST.extract src 1 31) <+> (AST.b1)) + ! 31 := sign) + !!ir (AST.extract dst 31 0 := AST.extract src 31 0) + !>ir insLen + +let fnegd ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let op = !+ir oprSize + let res = !+ir oprSize + ! 63) <+> (AST.b1)) + !!ir (AST.extract res 1 63 := sign) + !!ir (AST.extract res 63 0 := AST.extract op 63 0) + setDFloatOp ctxt ir dst res + !>ir insLen + +let fnegq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let op1 = !+ir oprSize + let op2 = !+ir oprSize + let res1 = !+ir oprSize + let res2 = !+ir oprSize + ! 63) <+> (AST.b1)) + !!ir (AST.extract res1 1 63 := sign) + !!ir (AST.extract res1 63 0 := AST.extract op1 63 0) + !!ir (AST.extract res2 64 0 := AST.extract op2 64 0) + setQFloatOp ctxt ir dst res1 res2 + !>ir insLen + +let fadds ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 32 + let res = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let faddd ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let op = !+ir regSize + let op1 = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let faddq ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res1 = !+ir regSize + let res2 = !+ir regSize + let op01 = !+ir regSize + let op02 = !+ir regSize + let op11 = !+ir regSize + let op12 = !+ir regSize + let op64 = !+ir 64 + let op164 = !+ir 64 + let res64 = !+ir 64 + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fbranchfcc ins insLen ctxt = + let ir = IRBuilder (16) + let struct (an, label) = transTwoOprs ins insLen ctxt + let pc = !.ctxt R.PC + let fsr = getRegVar ctxt R.FSR + let u = ((AST.extract fsr 2 10) == (numI32 3 2)) + let g = ((AST.extract fsr 2 10) == (numI32 2 2)) + let l = ((AST.extract fsr 2 10) == (numI32 1 2)) + let e = ((AST.extract fsr 2 10) == (numI32 0 2)) + let branchCond = + match ins.Opcode with + | Opcode.FBA -> AST.b1 + | Opcode.FBN -> AST.b0 + | Opcode.FBU -> u + | Opcode.FBG -> g + | Opcode.FBUG -> (u .| g) + | Opcode.FBL -> l + | Opcode.FBUL -> (u .| l) + | Opcode.FBLG -> (l .| g) + | Opcode.FBNE -> (l .| g .| u) + | Opcode.FBE -> e + | Opcode.FBUE -> (e .| u) + | Opcode.FBGE -> (g .| e) + | Opcode.FBUGE -> (u .| g .| e) + | Opcode.FBLE -> (l .| e) + | Opcode.FBULE -> (u .| l .| e) + | Opcode.FBO -> (l .| e .| g) + | _ -> raise InvalidOpcodeException + ! label + !!ir (AST.interjmp jumpTarget InterJmpKind.Base) + !>ir insLen + elif (ins.Opcode = Opcode.FBN) then + !>ir insLen + else + let annoffset = + if (AST.extract an 1 0 = AST.b1) then numI32PC 4 + else numI32PC 0 + let fallThrough = pc .+ numI32PC 4 .+ annoffset + let jumpTarget = pc .+ AST.zext 64 label + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir insLen + +let fbranchpfcc ins insLen ctxt = + let ir = IRBuilder (16) + let struct (cc, label, an, pr) = transFourOprs ins insLen ctxt + let pc = !.ctxt R.PC + let fsr = getRegVar ctxt R.FSR + let fcc0 = getCCVar ctxt ConditionCode.Fcc0 + let fcc1 = getCCVar ctxt ConditionCode.Fcc1 + let fcc2 = getCCVar ctxt ConditionCode.Fcc2 + let fcc3 = getCCVar ctxt ConditionCode.Fcc3 + let pos = + if (cc = fcc0) then 10 + elif (cc = fcc1) then 32 + elif (cc = fcc2) then 34 + elif (cc = fcc3) then 36 + else raise InvalidOperandException + let u = ((AST.extract fsr 2 pos) == (numI32 3 2)) + let g = ((AST.extract fsr 2 pos) == (numI32 2 2)) + let l = ((AST.extract fsr 2 pos) == (numI32 1 2)) + let e = ((AST.extract fsr 2 pos) == (numI32 0 2)) + let branchCond = + match ins.Opcode with + | Opcode.FBPA -> AST.b1 + | Opcode.FBPN -> AST.b0 + | Opcode.FBPU -> u + | Opcode.FBPG -> g + | Opcode.FBPUG -> (u .| g) + | Opcode.FBPL -> l + | Opcode.FBPUL -> (u .| l) + | Opcode.FBPLG -> (l .| g) + | Opcode.FBPNE -> (l .| g .| u) + | Opcode.FBPE -> e + | Opcode.FBPUE -> (e .| u) + | Opcode.FBPGE -> (g .| e) + | Opcode.FBPUGE -> (u .| g .| e) + | Opcode.FBPLE -> (l .| e) + | Opcode.FBPULE -> (u .| l .| e) + | Opcode.FBPO -> (l .| e .| g) + | _ -> raise InvalidOpcodeException + ! 0 = AST.b1) then numI32PC 4 + else numI32PC 0 + let fallThrough = pc .+ numI32PC 4 .+ annoffset + let jumpTarget = pc .+ AST.zext 64 label + !!ir (AST.intercjmp branchCond jumpTarget fallThrough) + !>ir insLen + +let fcmps ins insLen ctxt = + let struct (cc, src, src1) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let pc = !.ctxt R.PC + let fsr = getRegVar ctxt R.FSR + let fcc0 = getCCVar ctxt ConditionCode.Fcc0 + let fcc1 = getCCVar ctxt ConditionCode.Fcc1 + let fcc2 = getCCVar ctxt ConditionCode.Fcc2 + let fcc3 = getCCVar ctxt ConditionCode.Fcc3 + let pos = + if (cc = fcc0) then 10 + elif (cc = fcc1) then 32 + elif (cc = fcc2) then 34 + elif (cc = fcc3) then 36 + else raise InvalidOperandException + let op = AST.extract src 32 0 + let op1 = AST.extract src1 32 0 + ! pos) := (numI32 0 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp cond1 (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir ((AST.extract fsr 2 pos) := (numI32 1 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (AST.cjmp cond2 (AST.name lblL4) (AST.name lblL5)) + !!ir (AST.lmark lblL4) + !!ir ((AST.extract fsr 2 pos) := (numI32 2 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL5) + !!ir ((AST.extract fsr 2 pos) := (numI32 3 2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fcmpd ins insLen ctxt = + let struct (cc, src, src1) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let regSize = 64 + let pc = !.ctxt R.PC + let fsr = getRegVar ctxt R.FSR + let fcc0 = getCCVar ctxt ConditionCode.Fcc0 + let fcc1 = getCCVar ctxt ConditionCode.Fcc1 + let fcc2 = getCCVar ctxt ConditionCode.Fcc2 + let fcc3 = getCCVar ctxt ConditionCode.Fcc3 + let pos = + if (cc = fcc0) then 10 + elif (cc = fcc1) then 32 + elif (cc = fcc2) then 34 + elif (cc = fcc3) then 36 + else raise InvalidOperandException + let op = !+ir regSize + let op1 = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + ! pos) := (numI32 0 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp cond1 (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir ((AST.extract fsr 2 pos) := (numI32 1 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (AST.cjmp cond2 (AST.name lblL4) (AST.name lblL5)) + !!ir (AST.lmark lblL4) + !!ir ((AST.extract fsr 2 pos) := (numI32 2 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL5) + !!ir ((AST.extract fsr 2 pos) := (numI32 3 2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fcmpq ins insLen ctxt = + let struct (cc, src, src1) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let regSize = 64 + let pc = !.ctxt R.PC + let fsr = getRegVar ctxt R.FSR + let fcc0 = getCCVar ctxt ConditionCode.Fcc0 + let fcc1 = getCCVar ctxt ConditionCode.Fcc1 + let fcc2 = getCCVar ctxt ConditionCode.Fcc2 + let fcc3 = getCCVar ctxt ConditionCode.Fcc3 + let pos = + if (cc = fcc0) then 10 + elif (cc = fcc1) then 32 + elif (cc = fcc2) then 34 + elif (cc = fcc3) then 36 + else raise InvalidOperandException + let op01 = !+ir regSize + let op02 = !+ir regSize + let op11 = !+ir regSize + let op12 = !+ir regSize + let op64 = !+ir regSize + let op164 = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + ! pos) := (numI32 0 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp cond1 (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir ((AST.extract fsr 2 pos) := (numI32 1 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (AST.cjmp cond2 (AST.name lblL4) (AST.name lblL5)) + !!ir (AST.lmark lblL4) + !!ir ((AST.extract fsr 2 pos) := (numI32 2 2)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL5) + !!ir ((AST.extract fsr 2 pos) := (numI32 3 2)) + !!ir (AST.lmark lblEnd) + !>ir insLen + + +let fdivs ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 32 + let res = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fdivd ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let op = !+ir regSize + let op1 = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fdivq ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res1 = !+ir regSize + let res2 = !+ir regSize + let op01 = !+ir regSize + let op02 = !+ir regSize + let op11 = !+ir regSize + let op12 = !+ir regSize + let op64 = !+ir 64 + let op164 = !+ir 64 + let res64 = !+ir 64 + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fmovscc ins insLen ctxt = + let struct (cc, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let ccr = getRegVar ctxt R.CCR + let offset = + if (cc = getCCVar ctxt ConditionCode.Icc) then 0 + else 4 + let n = AST.extract ccr 1 (3 + offset) + let z = AST.extract ccr 1 (2 + offset) + let v = AST.extract ccr 1 (1 + offset) + let c = AST.extract ccr 1 (offset) + let cond = + match ins.Opcode with + | Opcode.FMOVsA -> AST.b1 + | Opcode.FMOVsN -> AST.b0 + | Opcode.FMOVsNE -> (z == AST.b0) + | Opcode.FMOVsE -> (z == AST.b1) + | Opcode.FMOVsG -> ((z .| (n <+> v)) == AST.b0) + | Opcode.FMOVsLE -> ((z .| (n <+> v)) == AST.b1) + | Opcode.FMOVsGE -> ((n <+> v) == AST.b0) + | Opcode.FMOVsL -> ((n <+> v) == AST.b1) + | Opcode.FMOVsGU -> ((c .| z) == AST.b0) + | Opcode.FMOVsLEU -> ((c .| z) == AST.b1) + | Opcode.FMOVsCC -> (c == AST.b0) + | Opcode.FMOVsCS -> (c == AST.b1) + | Opcode.FMOVsPOS -> (n == AST.b0) + | Opcode.FMOVsNEG -> (n == AST.b1) + | Opcode.FMOVsVC -> (v == AST.b0) + | Opcode.FMOVsVS -> (n == AST.b1) + | _ -> raise InvalidOpcodeException + !ir insLen + elif (ins.Opcode = Opcode.FMOVsA) then + !>ir insLen + else + !!ir (fdst := AST.ite (cond) (fsrc) (fdst)) + !>ir insLen + +let fmovdcc ins insLen ctxt = + let struct (cc, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let ccr = getRegVar ctxt R.CCR + let offset = + if (cc = getCCVar ctxt ConditionCode.Icc) then 0 + else 4 + let n = AST.extract ccr 1 (3 + offset) + let z = AST.extract ccr 1 (2 + offset) + let v = AST.extract ccr 1 (1 + offset) + let c = AST.extract ccr 1 (offset) + let cond = + match ins.Opcode with + | Opcode.FMOVdA -> AST.b1 + | Opcode.FMOVdN -> AST.b0 + | Opcode.FMOVdNE -> (z == AST.b0) + | Opcode.FMOVdE -> (z == AST.b1) + | Opcode.FMOVdG -> ((z .| (n <+> v)) == AST.b0) + | Opcode.FMOVdLE -> ((z .| (n <+> v)) == AST.b1) + | Opcode.FMOVdGE -> ((n <+> v) == AST.b0) + | Opcode.FMOVdL -> ((n <+> v) == AST.b1) + | Opcode.FMOVdGU -> ((c .| z) == AST.b0) + | Opcode.FMOVdLEU -> ((c .| z) == AST.b1) + | Opcode.FMOVdCC -> (c == AST.b0) + | Opcode.FMOVdCS -> (c == AST.b1) + | Opcode.FMOVdPOS -> (n == AST.b0) + | Opcode.FMOVdNEG -> (n == AST.b1) + | Opcode.FMOVdVC -> (v == AST.b0) + | Opcode.FMOVdVS -> (n == AST.b1) + | _ -> raise InvalidOpcodeException + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + !ir insLen + elif (ins.Opcode = Opcode.FMOVdN) then + !>ir insLen + else + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + movFregD ctxt ir fsrc fdst + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fmovqcc ins insLen ctxt = + let struct (cc, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let ccr = getRegVar ctxt R.CCR + let offset = + if (cc = getCCVar ctxt ConditionCode.Icc) then 0 + else 4 + let n = AST.extract ccr 1 (3 + offset) + let z = AST.extract ccr 1 (2 + offset) + let v = AST.extract ccr 1 (1 + offset) + let c = AST.extract ccr 1 (offset) + let cond = + match ins.Opcode with + | Opcode.FMOVqA -> AST.b1 + | Opcode.FMOVqN -> AST.b0 + | Opcode.FMOVqNE -> (z == AST.b0) + | Opcode.FMOVqE -> (z == AST.b1) + | Opcode.FMOVqG -> ((z .| (n <+> v)) == AST.b0) + | Opcode.FMOVqLE -> ((z .| (n <+> v)) == AST.b1) + | Opcode.FMOVqGE -> ((n <+> v) == AST.b0) + | Opcode.FMOVqL -> ((n <+> v) == AST.b1) + | Opcode.FMOVqGU -> ((c .| z) == AST.b0) + | Opcode.FMOVqLEU -> ((c .| z) == AST.b1) + | Opcode.FMOVqCC -> (c == AST.b0) + | Opcode.FMOVqCS -> (c == AST.b1) + | Opcode.FMOVqPOS -> (n == AST.b0) + | Opcode.FMOVqNEG -> (n == AST.b1) + | Opcode.FMOVqVC -> (v == AST.b0) + | Opcode.FMOVqVS -> (n == AST.b1) + | _ -> raise InvalidOpcodeException + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + !ir insLen + elif (ins.Opcode = Opcode.FMOVqN) then + !>ir insLen + else + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + movFregQ ctxt ir fsrc fdst + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fmovfscc ins insLen ctxt = + let struct (cc, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let pos = + if (cc = getCCVar ctxt ConditionCode.Fcc0) then 10 + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then 32 + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then 34 + elif (cc = getCCVar ctxt ConditionCode.Fcc3) then 36 + else raise InvalidRegisterException + let fsr0 = AST.extract fsr 1 pos + let fsr1 = AST.extract fsr 1 (pos+1) + let e = (fsr1 == AST.b0 .& fsr0 == AST.b0) + let l = (fsr1 == AST.b0 .& fsr0 == AST.b1) + let g = (fsr1 == AST.b1 .& fsr0 == AST.b0) + let u = (fsr1 == AST.b1 .& fsr0 == AST.b1) + let cond = + match ins.Opcode with + | Opcode.FMOVFsA -> AST.b1 + | Opcode.FMOVFsN -> AST.b0 + | Opcode.FMOVFsU -> u + | Opcode.FMOVFsG -> g + | Opcode.FMOVFsUG -> (g .| u) + | Opcode.FMOVFsL -> l + | Opcode.FMOVFsUL -> (u .| l) + | Opcode.FMOVFsLG -> (l .| g) + | Opcode.FMOVFsNE -> (l .| g .| u) + | Opcode.FMOVFsE -> e + | Opcode.FMOVFsUE -> (u .| e) + | Opcode.FMOVFsGE -> (g .| e) + | Opcode.FMOVFsUGE -> (u .| g .| e) + | Opcode.FMOVFsLE -> (l .| e) + | Opcode.FMOVFsULE -> (u .| l .| e) + | Opcode.FMOVFsO -> (e .|l .| g) + | _ -> raise InvalidOpcodeException + !ir insLen + elif (ins.Opcode = Opcode.FMOVFsN) then + !>ir insLen + else + !!ir (fdst := AST.ite (cond) (fsrc) (fdst)) + !>ir insLen + +let fmovfdcc ins insLen ctxt = + let struct (cc, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let pos = + if (cc = getCCVar ctxt ConditionCode.Fcc0) then 10 + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then 32 + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then 34 + elif (cc = getCCVar ctxt ConditionCode.Fcc3) then 36 + else raise InvalidRegisterException + let fsr0 = AST.extract fsr 1 pos + let fsr1 = AST.extract fsr 1 (pos+1) + let e = (fsr1 == AST.b0 .& fsr0 == AST.b0) + let l = (fsr1 == AST.b0 .& fsr0 == AST.b1) + let g = (fsr1 == AST.b1 .& fsr0 == AST.b0) + let u = (fsr1 == AST.b1 .& fsr0 == AST.b1) + let cond = + match ins.Opcode with + | Opcode.FMOVFdA -> AST.b1 + | Opcode.FMOVFdN -> AST.b0 + | Opcode.FMOVFdU -> u + | Opcode.FMOVFdG -> g + | Opcode.FMOVFdUG -> (g .| u) + | Opcode.FMOVFdL -> l + | Opcode.FMOVFdUL -> (u .| l) + | Opcode.FMOVFdLG -> (l .| g) + | Opcode.FMOVFdNE -> (l .| g .| u) + | Opcode.FMOVFdE -> e + | Opcode.FMOVFdUE -> (u .| e) + | Opcode.FMOVFdGE -> (g .| e) + | Opcode.FMOVFdUGE -> (u .| g .| e) + | Opcode.FMOVFdLE -> (l .| e) + | Opcode.FMOVFdULE -> (u .| l .| e) + | Opcode.FMOVFdO -> (e .|l .| g) + | _ -> raise InvalidOpcodeException + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + !ir insLen + elif (ins.Opcode = Opcode.FMOVFdN) then + !>ir insLen + else + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + movFregD ctxt ir fsrc fdst + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fmovfqcc ins insLen ctxt = + let struct (cc, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let pos = + if (cc = getCCVar ctxt ConditionCode.Fcc0) then 10 + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then 32 + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then 34 + elif (cc = getCCVar ctxt ConditionCode.Fcc3) then 36 + else raise InvalidRegisterException + let fsr0 = AST.extract fsr 1 pos + let fsr1 = AST.extract fsr 1 (pos+1) + let e = (fsr1 == AST.b0 .& fsr0 == AST.b0) + let l = (fsr1 == AST.b0 .& fsr0 == AST.b1) + let g = (fsr1 == AST.b1 .& fsr0 == AST.b0) + let u = (fsr1 == AST.b1 .& fsr0 == AST.b1) + let cond = + match ins.Opcode with + | Opcode.FMOVFqA -> AST.b1 + | Opcode.FMOVFqN -> AST.b0 + | Opcode.FMOVFqU -> u + | Opcode.FMOVFqG -> g + | Opcode.FMOVFqUG -> (g .| u) + | Opcode.FMOVFqL -> l + | Opcode.FMOVFqUL -> (u .| l) + | Opcode.FMOVFqLG -> (l .| g) + | Opcode.FMOVFqNE -> (l .| g .| u) + | Opcode.FMOVFqE -> e + | Opcode.FMOVFqUE -> (u .| e) + | Opcode.FMOVFqGE -> (g .| e) + | Opcode.FMOVFqUGE -> (u .| g .| e) + | Opcode.FMOVFqLE -> (l .| e) + | Opcode.FMOVFqULE -> (u .| l .| e) + | Opcode.FMOVFqO -> (e .|l .| g) + | _ -> raise InvalidOpcodeException + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + !ir insLen + elif (ins.Opcode = Opcode.FMOVFqN) then + !>ir insLen + else + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + movFregQ ctxt ir fsrc fdst + !!ir (AST.lmark lblEnd) + !>ir insLen + +let fmovrs ins insLen ctxt = + let struct (src, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! + !!ir (fdst := AST.ite (src == AST.num0 oprSize) (fsrc) (fdst)) + | Opcode.FMOVRsLEZ -> + !!ir (fdst := AST.ite (src ?<= AST.num0 oprSize) (fsrc) (fdst)) + | Opcode.FMOVRsLZ -> + !!ir (fdst := AST.ite (src ?< AST.num0 oprSize) (fsrc) (fdst)) + | Opcode.FMOVRsNZ -> + !!ir (fdst := AST.ite (src != AST.num0 oprSize) (fsrc) (fdst)) + | Opcode.FMOVRsGZ -> + !!ir (fdst := AST.ite (src ?> AST.num0 oprSize) (fsrc) (fdst)) + | Opcode.FMOVRsGEZ -> + !!ir (fdst := AST.ite (src ?>= AST.num0 oprSize) (fsrc) (fdst)) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let fmovrd ins insLen ctxt = + let struct (src, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let cond = + match ins.Opcode with + | Opcode.FMOVRdZ -> + src == AST.num0 oprSize + | Opcode.FMOVRdLEZ -> + src ?<= AST.num0 oprSize + | Opcode.FMOVRdLZ -> + src ?< AST.num0 oprSize + | Opcode.FMOVRdNZ -> + src != AST.num0 oprSize + | Opcode.FMOVRdGZ -> + src ?> AST.num0 oprSize + | Opcode.FMOVRdGEZ -> + src ?>= AST.num0 oprSize + | _ -> raise InvalidOpcodeException + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + !ir insLen + +let fmovrq ins insLen ctxt = + let struct (src, fsrc, fdst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let cond = + match ins.Opcode with + | Opcode.FMOVRqZ -> + src == AST.num0 oprSize + | Opcode.FMOVRqLEZ -> + src ?<= AST.num0 oprSize + | Opcode.FMOVRqLZ -> + src ?< AST.num0 oprSize + | Opcode.FMOVRqNZ -> + src != AST.num0 oprSize + | Opcode.FMOVRqGZ -> + src ?> AST.num0 oprSize + | Opcode.FMOVRqGEZ -> + src ?>= AST.num0 oprSize + | _ -> raise InvalidOpcodeException + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + !ir insLen + +let fmuls ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 32 + let res = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fmuld ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let op = !+ir regSize + let op1 = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fmulq ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res1 = !+ir regSize + let res2 = !+ir regSize + let op01 = !+ir regSize + let op02 = !+ir regSize + let op11 = !+ir regSize + let op12 = !+ir regSize + let op64 = !+ir 64 + let op164 = !+ir 64 + let res64 = !+ir 64 + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fsmuld ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + ! src + let op2 = AST.cast CastKind.FloatCast 64 src1 + !!ir (res := (AST.fmul op1 op2)) + !!ir (AST.cjmp cond0 (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL0) + !!ir (rounded := AST.cast CastKind.FtoFRound regSize (res)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL1) + !!ir (AST.cjmp cond1 (AST.name lblL2) (AST.name lblL3)) + !!ir (AST.lmark lblL2) + !!ir (rounded := AST.cast CastKind.FtoFTrunc regSize (res)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL3) + !!ir (AST.cjmp cond2 (AST.name lblL4) (AST.name lblL5)) + !!ir (AST.lmark lblL4) + !!ir (rounded := AST.cast CastKind.FtoFCeil regSize (res)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL5) + !!ir (rounded := AST.cast CastKind.FtoFFloor regSize (res)) + !!ir (AST.lmark lblEnd) + setDFloatOp ctxt ir dst rounded + !>ir insLen + +let fdmulq ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let res1 = !+ir regSize + let res2 = !+ir regSize + let op = !+ir regSize + let op1 = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fsqrts ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 32 + let res = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fsqrtd ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let op = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fsqrtq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res1 = !+ir regSize + let res2 = !+ir regSize + let op01 = !+ir regSize + let op02 = !+ir regSize + let op64 = !+ir 64 + let res64 = !+ir 64 + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fstox ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let cst = !+ir oprSize + !ir insLen + +let fdtox ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let op = !+ir oprSize + let cst = !+ir oprSize + !ir insLen + +let fqtox ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let regSize = 64 + let ir = IRBuilder (16) + let op1 = !+ir regSize + let op2 = !+ir regSize + let op64 = !+ir regSize + let cst = !+ir oprSize + !ir insLen + +let fstoi ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 32 + let ir = IRBuilder (16) + let cst = !+ir oprSize + !ir insLen + +let fdtoi ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let regSize = 32 + let ir = IRBuilder (16) + let op = !+ir oprSize + let cst = !+ir regSize + !ir insLen + +let fqtoi ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 32 + let regSize = 64 + let ir = IRBuilder (16) + let op1 = !+ir regSize + let op2 = !+ir regSize + let op64 = !+ir regSize + let cst = !+ir oprSize + !ir insLen + +let fstod ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let res = !+ir oprSize + let rounded = !+ir oprSize + let regSize = 64 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fstoq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let res1 = !+ir oprSize + let res2 = !+ir oprSize + let res64 = !+ir oprSize + let rounded = !+ir oprSize + let regSize = 64 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fdtos ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let fdtoq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let fqtos ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let fqtod ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let fsubs ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 32 + let res = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fsubd ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res = !+ir regSize + let op = !+ir regSize + let op1 = !+ir regSize + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fsubq ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let regSize = 64 + let res1 = !+ir regSize + let res2 = !+ir regSize + let op01 = !+ir regSize + let op02 = !+ir regSize + let op11 = !+ir regSize + let op12 = !+ir regSize + let op64 = !+ir 64 + let op164 = !+ir 64 + let res64 = !+ir 64 + let rounded = !+ir regSize + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fxtos ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 32 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let res = !+ir oprSize + let op = !+ir 64 + let regSize = !+ir 32 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fitos ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 32 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let res = !+ir oprSize + let regSize = 32 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fxtod ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let fsr = getRegVar ctxt R.FSR + let fsr30 = AST.extract fsr 1 30 + let fsr31 = AST.extract fsr 1 31 + let res = !+ir oprSize + let rounded = !+ir oprSize + let regSize = 64 + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblL2 = !%ir "L2" + let lblL3 = !%ir "L3" + let lblL4 = !%ir "L4" + let lblL5 = !%ir "L5" + let lblEnd = !%ir "End" + let cond0 = (fsr31 == AST.b0) .& (fsr30 == AST.b0) + let cond1 = (fsr31 == AST.b0) .& (fsr30 == AST.b1) + let cond2 = (fsr31 == AST.b1) .& (fsr30 == AST.b0) + !ir insLen + +let fitod ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let rounded = !+ir oprSize + ! src) + setDFloatOp ctxt ir dst rounded + !>ir insLen + +let fxtoq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let op = !+ir oprSize + let op64 = !+ir oprSize + let rounded = !+ir 64 + let res1 = !+ir oprSize + let res2 = !+ir oprSize + ! op) + cast64To128 ctxt ir rounded res1 res2 + setQFloatOp ctxt ir dst res1 res2 + !>ir insLen + +let fitoq ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let rounded = !+ir 64 + let res1 = !+ir oprSize + let res2 = !+ir oprSize + !ir insLen + +let jmpl ins insLen ctxt = + let struct (addr, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let t1 = !+ir oprSize + !ir insLen + +let ldf ins insLen ctxt = + let struct (addr, dst) = transAddrThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir (dst := (AST.loadBE 32 addr)) + | Opcode.LDDF -> + let op = !+ir oprSize + !!ir (op := (AST.loadBE oprSize addr)) + setDFloatOp ctxt ir dst op + | Opcode.LDQF -> + let op0 = !+ir oprSize + let op1 = !+ir oprSize + !!ir (op0 := (AST.loadBE oprSize addr)) + !!ir (op1 := (AST.loadBE oprSize (addr .+ numI64 8 64))) + setQFloatOp ctxt ir dst op0 op1 + | Opcode.LDFSR -> !!ir ((AST.extract dst 32 0) := + (AST.loadBE 32 addr)) + | Opcode.LDXFSR -> !!ir (dst := (AST.loadBE oprSize addr)) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let ldfa ins insLen ctxt = + let struct (addr, asi, dst) = transAddrFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir (dst := (AST.loadBE 32 (addr .+ asi))) + | Opcode.LDDFA -> + let op = !+ir oprSize + !!ir (op := (AST.loadBE oprSize (addr .+ asi))) + setDFloatOp ctxt ir dst op + | Opcode.LDQFA -> + let op0 = !+ir oprSize + let op1 = !+ir oprSize + !!ir (op0 := (AST.loadBE oprSize (addr .+ asi))) + !!ir (op1 := (AST.loadBE oprSize ((addr .+ asi) .+ numI64 8 64))) + setQFloatOp ctxt ir dst op0 op1 + | _ -> raise InvalidOpcodeException + !>ir insLen + +let ld ins insLen ctxt = + let struct (addr, dst) = transAddrThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir (dst := (AST.sext oprSize (AST.loadBE 8 addr))) + | Opcode.LDSH -> !!ir (dst := (AST.sext oprSize (AST.loadBE 16 addr))) + | Opcode.LDSW -> !!ir (dst := (AST.sext oprSize (AST.loadBE 32 addr))) + | Opcode.LDUB -> !!ir (dst := (AST.zext oprSize (AST.loadBE 8 addr))) + | Opcode.LDUH -> !!ir (dst := (AST.zext oprSize (AST.loadBE 16 addr))) + | Opcode.LDUW -> !!ir (dst := (AST.zext oprSize (AST.loadBE 32 addr))) + | Opcode.LDX -> !!ir (dst := AST.loadBE oprSize addr) + | Opcode.LDD -> + if (dst = getRegVar ctxt R.G0) then + let nxt = getRegVar ctxt R.G1 + !!ir (nxt := (AST.zext oprSize (AST.extract + (AST.loadBE oprSize addr) 32 32))) + else + let nxt = getRegVar ctxt (getNextReg ctxt dst) + !!ir (dst := (AST.zext oprSize (AST.extract + (AST.loadBE oprSize addr) 32 0))) + !!ir (nxt := (AST.zext oprSize (AST.extract + (AST.loadBE oprSize addr) 32 32))) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let lda ins insLen ctxt = + let struct (src, src1, asi, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir (dst := (AST.sext oprSize + (AST.loadBE 8 (addr .+ asi)))) + | Opcode.LDSHA -> !!ir (dst := (AST.sext oprSize + (AST.loadBE 16 (addr .+ asi)))) + | Opcode.LDSWA -> !!ir (dst := (AST.sext oprSize + (AST.loadBE 32 (addr .+ asi)))) + | Opcode.LDUBA -> !!ir (dst := (AST.zext oprSize + (AST.loadBE 8 (addr .+ asi)))) + | Opcode.LDUHA -> !!ir (dst := (AST.zext oprSize + (AST.loadBE 16 (addr .+ asi)))) + | Opcode.LDUWA -> !!ir (dst := (AST.zext oprSize + (AST.loadBE 32 (addr .+ asi)))) + | Opcode.LDXA -> !!ir (dst := AST.loadBE oprSize (addr .+ asi)) + | Opcode.LDDA -> + if (dst = getRegVar ctxt R.G0) then + let nxt = getRegVar ctxt R.G1 + !!ir (nxt := (AST.zext oprSize (AST.extract + (AST.loadBE oprSize (addr .+ asi)) 32 32))) + else + let nxt = getRegVar ctxt (getNextReg ctxt dst) + !!ir (dst := (AST.zext oprSize (AST.extract + (AST.loadBE oprSize (addr .+ asi)) 32 0))) + !!ir (nxt := (AST.zext oprSize (AST.extract + (AST.loadBE oprSize (addr .+ asi)) 32 32))) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let ldstub ins insLen ctxt = + let struct (addr, dst) = transAddrThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! addr))) + !!ir ((AST.loadBE 8 addr) := (numI32 0xff 8)) + !>ir insLen + +let ldstuba ins insLen ctxt = + let struct (src, src1, asi, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! (addr .+ asi)))) + !!ir ((AST.loadBE 8 (addr .+ asi)) := (numI32 0xff 8)) + !>ir insLen + +let membar ins insLen ctxt = (* FIXME *) + let mask = transOneOpr ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let t1 = !+ir oprSize + !ir insLen + +let movcc ins insLen ctxt = + let struct (cc, src, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let ccr = getRegVar ctxt R.CCR + let fsr = getRegVar ctxt R.FSR + ! getRegVar ctxt R.G0) then + match ins.Opcode with + | Opcode.MOVA | Opcode.MOVFA -> + !!ir (dst := src) + | Opcode.MOVN | Opcode.MOVFN -> + () + | Opcode.MOVNE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let cond = (AST.extract ccr 1 2 == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let cond = (AST.extract ccr 1 6 == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let cond = (AST.extract ccr 1 2 == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let cond = (AST.extract ccr 1 6 == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVG -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let n = AST.extract ccr 1 3 + let z = AST.extract ccr 1 2 + let v = AST.extract ccr 1 1 + let cond = ((z .| (n <+> v)) == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let n = AST.extract ccr 1 7 + let z = AST.extract ccr 1 6 + let v = AST.extract ccr 1 5 + let cond = ((z .| (n <+> v)) == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVLE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let n = AST.extract ccr 1 3 + let z = AST.extract ccr 1 2 + let v = AST.extract ccr 1 1 + let cond = ((z .| (n <+> v)) == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let n = AST.extract ccr 1 7 + let z = AST.extract ccr 1 6 + let v = AST.extract ccr 1 5 + let cond = ((z .| (n <+> v)) == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVGE -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let n = AST.extract ccr 1 3 + let v = AST.extract ccr 1 1 + let cond = ((n <+> v) == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let n = AST.extract ccr 1 7 + let v = AST.extract ccr 1 5 + let cond = ((n <+> v) == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVL -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let n = AST.extract ccr 1 3 + let v = AST.extract ccr 1 1 + let cond = ((n <+> v) == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let n = AST.extract ccr 1 7 + let v = AST.extract ccr 1 5 + let cond = ((n <+> v) == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVGU -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let z = AST.extract ccr 1 2 + let c = AST.extract ccr 1 0 + let cond = ((c .| z) == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let z = AST.extract ccr 1 6 + let c = AST.extract ccr 1 4 + let cond = ((c .| z) == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVLEU -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let z = AST.extract ccr 1 2 + let c = AST.extract ccr 1 0 + let cond = ((c .| z) == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let z = AST.extract ccr 1 6 + let c = AST.extract ccr 1 4 + let cond = ((c .| z) == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVCC -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let c = AST.extract ccr 1 0 + let cond = (c == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let c = AST.extract ccr 1 4 + let cond = (c == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVCS -> + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let ccr = getRegVar ctxt R.CCR + if (cc = getCCVar ctxt ConditionCode.Icc) then + let c = AST.extract ccr 1 0 + let cond = (c == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let c = AST.extract ccr 1 4 + let cond = (c == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVPOS -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let n = AST.extract ccr 1 3 + let cond = (n == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let n = AST.extract ccr 1 7 + let cond = (n == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVNEG -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let n = AST.extract ccr 1 3 + let cond = (n == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let n = AST.extract ccr 1 7 + let cond = (n == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVVC -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let v = AST.extract ccr 1 1 + let cond = (v == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let v = AST.extract ccr 1 5 + let cond = (v == AST.b0) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVVS -> + if (cc = getCCVar ctxt ConditionCode.Icc) then + let v = AST.extract ccr 1 1 + let cond = (v == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let v = AST.extract ccr 1 5 + let cond = (v == AST.b1) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVFU -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = ((AST.extract fsr 2 10) == (numI32 3 2)) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVFG -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = ((AST.extract fsr 2 10) == (numI32 2 2)) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 2 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 2 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 2 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVFUG -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 3 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + let cond2 = (AST.extract fsr 2 32 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + let cond2 = (AST.extract fsr 2 34 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + let cond2 = (AST.extract fsr 2 36 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + | Opcode.MOVFL -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = ((AST.extract fsr 2 10) == (numI32 1 2)) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 1 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 1 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 1 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVFUL -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 3 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + let cond2 = (AST.extract fsr 2 32 == numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + let cond2 = (AST.extract fsr 2 34 == numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + let cond2 = (AST.extract fsr 2 36 == numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + | Opcode.MOVFLG -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 1 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 1 2) + let cond2 = (AST.extract fsr 2 32 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 1 2) + let cond2 = (AST.extract fsr 2 34 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 1 2) + let cond2 = (AST.extract fsr 2 36 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + | Opcode.MOVFNE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 3 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 2 2) + let cond3 = (AST.extract fsr 2 10) == (numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + let cond2 = (AST.extract fsr 2 32 == numI32 2 2) + let cond3 = (AST.extract fsr 2 32 == numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + let cond2 = (AST.extract fsr 2 34 == numI32 2 2) + let cond3 = (AST.extract fsr 2 34 == numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + let cond2 = (AST.extract fsr 2 36 == numI32 2 2) + let cond3 = (AST.extract fsr 2 36 == numI32 1 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + | Opcode.MOVFE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = ((AST.extract fsr 2 10) == (numI32 0 2)) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 0 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 0 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 0 2) + !!ir (dst := AST.ite (cond) (src) (dst)) + | Opcode.MOVFUE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 3 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + let cond2 = (AST.extract fsr 2 32 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + let cond2 = (AST.extract fsr 2 34 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + let cond2 = (AST.extract fsr 2 36 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + | Opcode.MOVFGE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 0 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 0 2) + let cond2 = (AST.extract fsr 2 32 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 0 2) + let cond2 = (AST.extract fsr 2 34 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 0 2) + let cond2 = (AST.extract fsr 2 36 == numI32 2 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + | Opcode.MOVFUGE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 3 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 2 2) + let cond3 = (AST.extract fsr 2 10) == (numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + let cond2 = (AST.extract fsr 2 32 == numI32 2 2) + let cond3 = (AST.extract fsr 2 32 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + let cond2 = (AST.extract fsr 2 34 == numI32 2 2) + let cond3 = (AST.extract fsr 2 34 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + let cond2 = (AST.extract fsr 2 36 == numI32 2 2) + let cond3 = (AST.extract fsr 2 36 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + | Opcode.MOVFLE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 1 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 1 2) + let cond2 = (AST.extract fsr 2 32 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 1 2) + let cond2 = (AST.extract fsr 2 34 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 1 2) + let cond2 = (AST.extract fsr 2 36 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2) (src) (dst)) + | Opcode.MOVFULE -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 3 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 1 2) + let cond3 = (AST.extract fsr 2 10) == (numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 3 2) + let cond2 = (AST.extract fsr 2 32 == numI32 1 2) + let cond3 = (AST.extract fsr 2 32 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 3 2) + let cond2 = (AST.extract fsr 2 34 == numI32 1 2) + let cond3 = (AST.extract fsr 2 34 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 3 2) + let cond2 = (AST.extract fsr 2 36 == numI32 1 2) + let cond3 = (AST.extract fsr 2 36 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + | Opcode.MOVFO -> + if (cc = getCCVar ctxt ConditionCode.Fcc0) then + let cond = (AST.extract fsr 2 10) == (numI32 1 2) + let cond2 = (AST.extract fsr 2 10) == (numI32 2 2) + let cond3 = (AST.extract fsr 2 10) == (numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc1) then + let cond = (AST.extract fsr 2 32 == numI32 1 2) + let cond2 = (AST.extract fsr 2 32 == numI32 2 2) + let cond3 = (AST.extract fsr 2 32 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + elif (cc = getCCVar ctxt ConditionCode.Fcc2) then + let cond = (AST.extract fsr 2 34 == numI32 1 2) + let cond2 = (AST.extract fsr 2 34 == numI32 2 2) + let cond3 = (AST.extract fsr 2 34 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + else + let cond = (AST.extract fsr 2 36 == numI32 1 2) + let cond2 = (AST.extract fsr 2 36 == numI32 2 2) + let cond3 = (AST.extract fsr 2 36 == numI32 0 2) + !!ir (dst := AST.ite (cond .| cond2 .| cond3) (src) (dst)) + | _ -> + raise InvalidOpcodeException + !>ir insLen + +let movr ins insLen ctxt = (* TODO : check that destination is not g0*) + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! + !!ir (dst := AST.ite (src == AST.num0 oprSize) (src1) (dst)) + | Opcode.MOVRLEZ -> + !!ir (dst := AST.ite (src ?<= AST.num0 oprSize) (src1) (dst)) + | Opcode.MOVRLZ -> + !!ir (dst := AST.ite (src ?< AST.num0 oprSize) (src1) (dst)) + | Opcode.MOVRNZ -> + !!ir (dst := AST.ite (src != AST.num0 oprSize) (src1) (dst)) + | Opcode.MOVRGZ -> + !!ir (dst := AST.ite (src ?> AST.num0 oprSize) (src1) (dst)) + | Opcode.MOVRGEZ -> + !!ir (dst := AST.ite (src ?>= AST.num0 oprSize) (src1) (dst)) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let mulscc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let src32 = !+ir 32 + let y = !.ctxt R.Y + let ccr = !.ctxt R.CCR + let src2 = !+ir 32 + let hbyte = !+ir 4 + ! 3) <+> + (AST.extract ccr 1 1)) (AST.extract src 31 1)) + !!ir (src2 := AST.ite ((AST.extract y 1 0) == AST.b0) + (AST.num0 32) (AST.extract src1 32 0)) + !!ir (res := AST.zext 64 (src32 .+ src2)) + if (dst <> getRegVar ctxt R.G0) then + !!ir (dst := res) + !!ir ((AST.extract y 32 0) := AST.concat (AST.extract src 1 0) + (AST.extract y 31 1)) + !!ir (hbyte := getConditionCodeMulscc res src src1) + !!ir (AST.extract ccr 4 0 := hbyte) + !>ir insLen + +let mulx ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !) + else + !!ir (dst := src .* src1) + !>ir insLen + +let nop insLen = + let ir = IRBuilder (16) + !ir insLen + +let ``or`` ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + !) + else + !!ir (dst := res) + !>ir insLen + + +let orcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + !) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeLog res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let orn ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + !) + else + !!ir (dst := res) + !>ir insLen + +let orncc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + !) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeLog res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let popc ins insLen ctxt = + let struct (src, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let max = numI32 (RegType.toBitWidth oprSize) 64 + let ir = IRBuilder (16) + let lblLoop = ir.NewSymbol "Loop" + let lblExit = ir.NewSymbol "Exit" + let lblLoopCond = ir.NewSymbol "LoopCond" + let struct (i, count) = tmpVars2 ir oprSize + ! (src >> i)) == AST.b1 + !!ir (count := AST.ite cond (count .+ AST.num1 oprSize) count) + !!ir (i := i .+ AST.num1 oprSize) + !!ir (AST.jmp (AST.name lblLoopCond)) + !!ir (AST.lmark lblExit) + !!ir (dst := count) + !>ir insLen + +let rd ins insLen ctxt = + let struct (reg, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let restore ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let restored ins insLen ctxt = + let ir = IRBuilder (16) + let cs = getRegVar ctxt R.CANSAVE + let cr = getRegVar ctxt R.CANRESTORE + let ow = getRegVar ctxt R.OTHERWIN + !)) + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + let cond = (ow == AST.num0 64) + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (cr := (cs .- AST.num1 64)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (ow := (ow .- AST.num1 64)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let ret ins insLen ctxt = + let struct (src, src1) = transTwoOprs ins insLen ctxt + let ir = IRBuilder (16) + !ir insLen + +let retry ins insLen ctxt = + let ir = IRBuilder (16) + !ir insLen + +let save ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !ir insLen + +let saved ins insLen ctxt = + let ir = IRBuilder (16) + let cs = getRegVar ctxt R.CANSAVE + let cr = getRegVar ctxt R.CANRESTORE + let ow = getRegVar ctxt R.OTHERWIN + !)) + let lblL0 = !%ir "L0" + let lblEnd = !%ir "End" + let cond = (ow == AST.num0 64) + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (cr := (cr .- AST.num1 64)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (ow := (ow .- AST.num1 64)) + !!ir (AST.lmark lblEnd) + !>ir insLen + +let sdiv ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let divisor = !+ir 32 + let dividend = !+ir 64 + let quotient = !+ir 64 + let y = getRegVar ctxt R.Y + let ccr = getRegVar ctxt R.CCR + ! 0) + !!ir (dividend := AST.concat (AST.extract y 32 0) + (AST.extract src 32 0)) + let cond = (divisor == AST.num0 32) + if (divisor = AST.num0 32 || src1 = getRegVar ctxt R.G0) then + !!ir (AST.sideEffect (Exception "Division by zero exception")) + elif (isRegOpr ins insLen ctxt) then + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL1) + if (dst <> getRegVar ctxt R.G0) then + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.extract ccr 1 1 := AST.ite + ((AST.extract quotient 32 32) == AST.num0 32) (AST.b0) (AST.b1)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "Division by zero exception")) + !!ir (AST.lmark lblEnd) + else + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.extract ccr 1 1 := AST.ite + ((AST.extract quotient 32 32) == AST.num0 32) (AST.b0) (AST.b1)) + !!ir (AST.extract ccr 4 4 := AST.num0 4) + !!ir (AST.extract ccr 1 3 := AST.ite + ((AST.extract quotient 1 31) == AST.b1) (AST.b1) (AST.b0)) + !!ir (AST.extract ccr 1 2 := AST.ite + ((AST.extract quotient 32 0) == AST.num0 32) (AST.b1) (AST.b0)) + !!ir (AST.extract ccr 1 0 := AST.b0) + !>ir insLen + +let sdivcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let divisor = !+ir 32 + let dividend = !+ir 64 + let quotient = !+ir 64 + let y = getRegVar ctxt R.Y + let ccr = getRegVar ctxt R.CCR + ! 0) + !!ir (dividend := AST.concat (AST.extract y 32 0) + (AST.extract src 32 0)) + let cond = (divisor == AST.num0 32) + if (divisor = AST.num0 32 || src1 = getRegVar ctxt R.G0) then + !!ir (AST.sideEffect (Exception "Division by zero exception")) + elif (isRegOpr ins insLen ctxt) then + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL1) + if (dst <> getRegVar ctxt R.G0) then + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.extract ccr 1 1 := AST.ite + ((AST.extract quotient 32 32) == AST.num0 32) (AST.b0) (AST.b1)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "Division by zero exception")) + !!ir (AST.lmark lblEnd) + else + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.extract ccr 1 1 := AST.ite + ((AST.extract quotient 32 32) == AST.num0 32) (AST.b0) (AST.b1)) + !!ir (AST.extract ccr 4 4 := AST.num0 4) + !!ir (AST.extract ccr 1 3 := AST.ite + ((AST.extract quotient 1 31) == AST.b1) (AST.b1) (AST.b0)) + !!ir (AST.extract ccr 1 2 := AST.ite + ((AST.extract quotient 32 0) == AST.num0 32) (AST.b1) (AST.b0)) + !!ir (AST.extract ccr 1 0 := AST.b0) + !>ir insLen + +let sdivx ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let cond = (src1 == AST.num0 64) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + ! || src1 = getRegVar ctxt R.G0) then + !!ir (AST.sideEffect (Exception "Division by zero exception")) + elif (isRegOpr ins insLen ctxt) then + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL1) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := src ?/ src1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "Division by zero exception")) + !!ir (AST.lmark lblEnd) + else + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := src ?/ src1) + !>ir insLen + +let sethi ins insLen ctxt = + let struct (imm, dst) = transTwoOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! getRegVar ctxt R.G0) then + !!ir (dst := AST.concat (AST.zext 32 AST.b0) + (AST.extract imm 32 0)) + !>ir insLen + +let sll ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !) + else + !!ir (dst := src << src1) + !>ir insLen + +let smul ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let yreg = getRegVar ctxt R.Y + let oprSize = 64 + let ir = IRBuilder (16) + !) + else + !!ir (dst := AST.sext 64 ((AST.extract src 32 0) + .* (AST.extract src1 32 0))) + !!ir (AST.extract yreg 64 0 := AST.zext 64 + (AST.extract dst 32 32)) + !>ir insLen + +let smulcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let yreg = getRegVar ctxt R.Y + let ccr = getRegVar ctxt R.CCR + let oprSize = 64 + let byte = !+ir 8 + !) + else + !!ir (dst := AST.sext 64 ((AST.extract src 32 0) + .* (AST.extract src1 32 0))) + !!ir (AST.extract yreg 64 0 := AST.zext 64 + (AST.extract dst 32 32)) + !!ir (byte := (getConditionCodeMul dst src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let sra ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !) + else + !!ir (dst := src ?>> src1) + !>ir insLen + +let srl ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + !) + else + !!ir (dst := src >> src1) + !>ir insLen + +let st ins insLen ctxt = + let struct (src, addr) = transTwooprsAddr ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir ((AST.loadBE 8 addr) := (AST.extract src 8 0)) + | Opcode.STH -> !!ir ((AST.loadBE 16 addr) := (AST.extract src 16 0)) + | Opcode.STW -> !!ir ((AST.loadBE 32 addr) := (AST.extract src 32 0)) + | Opcode.STX -> !!ir ((AST.loadBE 64 addr) := (AST.extract src 64 0)) + | Opcode.STD -> + if (src = getRegVar ctxt R.G0) then + let nxt = getRegVar ctxt R.G1 + !!ir ((AST.loadBE 32 addr) := (AST.extract src 32 0)) + else + let nxt = getRegVar ctxt (getNextReg ctxt src) + !!ir ((AST.loadBE 32 addr) := (AST.extract src 32 0)) + !!ir ((AST.loadBE 32 (addr .+ numI64 4 64)) := + (AST.extract nxt 32 0)) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let sta ins insLen ctxt = + let struct (src, src1, asi, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir ((AST.loadBE 8 (addr .+ asi)) + := (AST.extract src 8 0)) + | Opcode.STHA -> !!ir ((AST.loadBE 16 (addr .+ asi)) + := (AST.extract src 16 0)) + | Opcode.STWA -> !!ir ((AST.loadBE 32 (addr .+ asi)) + := (AST.extract src 32 0)) + | Opcode.STXA -> !!ir ((AST.loadBE 64 (addr .+ asi)) + := (AST.extract src 64 0)) + | Opcode.STDA -> + if (src = getRegVar ctxt R.G0) then + let nxt = getRegVar ctxt R.G1 + !!ir ((AST.loadBE 32 (addr .+ asi)) := (AST.extract src 32 0)) + else + let nxt = getRegVar ctxt (getNextReg ctxt src) + !!ir ((AST.loadBE 32 (addr .+ asi)) := (AST.extract src 32 0)) + !!ir ((AST.loadBE 32 ((addr .+ asi) .+ numI64 4 64)) := + (AST.extract nxt 32 0)) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let stf ins insLen ctxt = + let struct (src, addr) = transTwooprsAddr ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir ((AST.loadBE 32 addr) := (AST.extract src 32 0)) + | Opcode.STDF -> + let op = !+ir oprSize + getDFloatOp ctxt ir src op + !!ir ((AST.loadBE 64 addr) := (AST.extract op 64 0)) + | Opcode.STQF -> + let op0 = !+ir oprSize + let op1 = !+ir oprSize + getQFloatOp ctxt ir src op0 op1 + !!ir ((AST.loadBE 64 addr) := (AST.extract op0 64 0)) + !!ir ((AST.loadBE 64 (addr .+ numI64 8 64)) := + (AST.extract op1 64 0)) + | Opcode.STFSR -> + !!ir ((AST.loadBE 32 addr) := (AST.extract src 32 0)) + | Opcode.STXFSR -> + !!ir ((AST.loadBE 64 addr) := src) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let stfa ins insLen ctxt = + let struct (src, src1, asi, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! !!ir ((AST.loadBE 32 (addr)) := + (AST.extract src 32 0)) + | Opcode.STDFA -> + let op = !+ir oprSize + getDFloatOp ctxt ir src op + !!ir ((AST.loadBE 64 (addr)) := + (AST.extract op 64 0)) + | Opcode.STQFA -> + let op0 = !+ir oprSize + let op1 = !+ir oprSize + getQFloatOp ctxt ir src op0 op1 + !!ir ((AST.loadBE 64 (addr)) := (AST.extract op0 64 0)) + !!ir ((AST.loadBE 64 ((addr) .+ numI64 8 64)) := + (AST.extract op1 64 0)) + | _ -> raise InvalidOpcodeException + !>ir insLen + +let sub ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + !) + else + !!ir (dst := res) + !>ir insLen + +let subcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + !) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeSub res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + + +let subC ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let byte = !+ir 8 + let ccr = !.ctxt R.CCR + ! (AST.extract ccr 1 0)) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !>ir insLen + +let subCcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + ! (AST.extract ccr 1 0)) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeSub res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let swap ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let addr = !+ir oprSize + ! addr))) + !>ir insLen + +let swapa ins insLen ctxt = + let struct (src, src1, asi, dst) = transFourOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let struct (t1, t2) = tmpVars2 ir oprSize + ! (src .+ src1 .+ asi)))) + !>ir insLen + +let udiv ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let divisor = !+ir 32 + let dividend = !+ir 64 + let quotient = !+ir 64 + let y = getRegVar ctxt R.Y + ! 0) + !!ir (dividend := AST.concat (AST.extract y 32 0) + (AST.extract src 32 0)) + let cond = (divisor == AST.num0 32) + if (divisor = AST.num0 32 || src1 = getRegVar ctxt R.G0) then + !!ir (AST.sideEffect (Exception "Division by zero exception")) + elif (isRegOpr ins insLen ctxt) then + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL1) + if (dst <> getRegVar ctxt R.G0) then + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "Division by zero exception")) + !!ir (AST.lmark lblEnd) + else + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !>ir insLen + +let udivcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + let divisor = !+ir 32 + let dividend = !+ir 64 + let quotient = !+ir 64 + let y = getRegVar ctxt R.Y + let ccr = getRegVar ctxt R.CCR + ! 0) + !!ir (dividend := AST.concat (AST.extract y 32 0) + (AST.extract src 32 0)) + let cond = (divisor == AST.num0 32) + if (divisor = AST.num0 32 || src1 = getRegVar ctxt R.G0) then + !!ir (AST.sideEffect (Exception "Division by zero exception")) + elif (isRegOpr ins insLen ctxt) then + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL1) + if (dst <> getRegVar ctxt R.G0) then + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.extract ccr 1 1 := AST.ite + ((AST.extract quotient 32 32) == AST.num0 32) (AST.b0) (AST.b1)) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "Division by zero exception")) + !!ir (AST.lmark lblEnd) + else + !!ir (quotient := dividend ./ (AST.zext 64 divisor)) + !!ir (dst := AST.ite ((AST.extract quotient 32 32) == AST.num0 32) + (AST.zext 64 (AST.extract quotient 32 0)) + (numU64 0x0000FFFFUL 64)) + !!ir (AST.extract ccr 1 1 := AST.ite + ((AST.extract quotient 32 32) == AST.num0 32) (AST.b0) (AST.b1)) + !!ir (AST.extract ccr 4 4 := AST.num0 4) + !!ir (AST.extract ccr 1 3 := AST.ite + ((AST.extract quotient 1 31) == AST.b1) (AST.b1) (AST.b0)) + !!ir (AST.extract ccr 1 2 := AST.ite + ((AST.extract quotient 32 0) == AST.num0 32) (AST.b1) (AST.b0)) + !!ir (AST.extract ccr 1 0 := AST.b0) + !>ir insLen + +let udivx ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let cond = (src1 == AST.num0 64) + let lblL0 = !%ir "L0" + let lblL1 = !%ir "L1" + let lblEnd = !%ir "End" + ! || src1 = getRegVar ctxt R.G0) then + !!ir (AST.sideEffect (Exception "Division by zero exception")) + elif (isRegOpr ins insLen ctxt) then + !!ir (AST.cjmp (cond) (AST.name lblL0) (AST.name lblL1)) + !!ir (AST.lmark lblL1) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := src ./ src1) + !!ir (AST.jmp (AST.name lblEnd)) + !!ir (AST.lmark lblL0) + !!ir (AST.sideEffect (Exception "Division by zero exception")) + !!ir (AST.lmark lblEnd) + else + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := src ./ src1) + !>ir insLen + +let umul ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let yreg = getRegVar ctxt R.Y + let oprSize = 64 + let ir = IRBuilder (16) + !) + else + !!ir (dst := AST.zext 64 ((AST.extract src 32 0) + .* (AST.extract src1 32 0))) + !!ir (AST.extract yreg 64 0 := + AST.zext 64 (AST.extract dst 32 32)) + !>ir insLen + +let umulcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let ir = IRBuilder (16) + let yreg = getRegVar ctxt R.Y + let ccr = getRegVar ctxt R.CCR + let oprSize = 64 + let byte = !+ir 8 + !) + else + !!ir (dst := AST.zext 64 ((AST.extract src 32 0) + .* (AST.extract src1 32 0))) + !!ir (AST.extract yreg 64 0 := + AST.zext 64 (AST.extract dst 32 32)) + !!ir (byte := (getConditionCodeMul dst src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let wr ins insLen ctxt = + let struct (src, src1, reg) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + ! src1) + !>ir insLen + +let xor ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + ! src1) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !>ir insLen + +let xorcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + ! src1) + !!ir (byte := (getConditionCodeLog res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen + +let xnor ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + ! AST.not (src1)) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !>ir insLen + +let xnorcc ins insLen ctxt = + let struct (src, src1, dst) = transThreeOprs ins insLen ctxt + let oprSize = 64 + let ir = IRBuilder (16) + let res = !+ir oprSize + let ccr = !.ctxt R.CCR + let byte = !+ir 8 + ! AST.not (src1)) + if (dst = getRegVar ctxt R.G0) then + !!ir (dst := AST.num0 64) + else + !!ir (dst := res) + !!ir (byte := (getConditionCodeLog res src src1)) + !!ir (AST.extract ccr 8 0 := byte) + !>ir insLen \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCInstruction.fs b/src/FrontEnd/BinLifter/SPARC/SPARCInstruction.fs new file mode 100644 index 00000000..48acdbc7 --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCInstruction.fs @@ -0,0 +1,107 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SPARC + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// The internal representation for a SPARC instruction used by our +/// disassembler and lifter. +type SPARCInstruction (addr, numBytes, insInfo) = + inherit Instruction (addr, numBytes, WordSize.Bit32) + + /// Basic instruction information. + member val Info: InsInfo = insInfo + + override __.IsBranch () = Utils.futureFeature () + + override __.IsModeChanging () = false + + member __.HasConcJmpTarget () = Utils.futureFeature () + + override __.IsDirectBranch () = + __.IsBranch () && __.HasConcJmpTarget () + + override __.IsIndirectBranch () = + __.IsBranch () && (not <| __.HasConcJmpTarget ()) + + override __.IsCondBranch () = Utils.futureFeature () + + override __.IsCJmpOnTrue () = Utils.futureFeature () + + override __.IsCall () = Utils.futureFeature () + + override __.IsRET () = Utils.futureFeature () + + override __.IsInterrupt () = Utils.futureFeature () + + override __.IsExit () = Utils.futureFeature () + + override __.IsBBLEnd () = + __.IsDirectBranch () || + __.IsIndirectBranch () + + override __.DirectBranchTarget (_addr: byref) = Utils.futureFeature () + + override __.IndirectTrampolineAddr (_addr: byref) = + Utils.futureFeature () + + override __.Immediate (_v: byref) = Utils.futureFeature () + + override __.GetNextInstrAddrs () = Utils.futureFeature () + + override __.InterruptNum (_num: byref) = Utils.futureFeature () + + override __.IsNop () = Utils.futureFeature () + + override __.Translate ctxt = + Lifter.translate __.Info numBytes ctxt + + override __.TranslateToList _ctxt = Utils.futureFeature () + + override __.Disasm (showAddr, _) = + let builder = + DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm __.Info builder + builder.ToString () + + override __.Disasm () = + let builder = + DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) + Disasm.disasm __.Info builder + builder.ToString () + + override __.Decompose (showAddr) = + let builder = + DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) + Disasm.disasm __.Info builder + builder.ToArray () + + override __.IsInlinedAssembly () = false + + override __.Equals (_) = Utils.futureFeature () + override __.GetHashCode () = Utils.futureFeature () + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCLifter.fs b/src/FrontEnd/BinLifter/SPARC/SPARCLifter.fs new file mode 100644 index 00000000..1551fedb --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCLifter.fs @@ -0,0 +1,238 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.FrontEnd.BinLifter.SPARC.Lifter + +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.SPARC +open B2R2.FrontEnd.BinLifter.SPARC.GeneralLifter + +/// Translate IR. +let translate (ins: InsInfo) insLen (ctxt: TranslationContext) = + match ins.Opcode with + | Opcode.ADD -> add ins insLen ctxt + | Opcode.ADDcc -> addcc ins insLen ctxt + | Opcode.ADDC -> addC ins insLen ctxt + | Opcode.ADDCcc -> addCcc ins insLen ctxt + | Opcode.AND -> ``and`` ins insLen ctxt + | Opcode.ANDcc -> andcc ins insLen ctxt + | Opcode.ANDN -> andn ins insLen ctxt + | Opcode.ANDNcc -> andncc ins insLen ctxt + | Opcode.BPA | Opcode.BPN | Opcode.BPNE | Opcode.BPE | Opcode.BPG + | Opcode.BPLE | Opcode.BPGE | Opcode.BPL | Opcode.BPGU | Opcode.BPLEU + | Opcode.BPCC | Opcode.BPCS | Opcode.BPPOS | Opcode.BPNEG | Opcode.BPVC + | Opcode.BPVS -> branchpcc ins insLen ctxt + | Opcode.BA | Opcode.BN | Opcode.BNE | Opcode.BE | Opcode.BG + | Opcode.BLE | Opcode.BGE | Opcode.BL | Opcode.BGU | Opcode.BLEU + | Opcode.BCC | Opcode.BCS | Opcode.BPOS | Opcode.BNEG | Opcode.BVC + | Opcode.BVS -> branchicc ins insLen ctxt + | Opcode.BRZ | Opcode.BRLEZ | Opcode.BRLZ | Opcode.BRNZ | Opcode.BRGZ + | Opcode.BRGEZ -> branchpr ins insLen ctxt + | Opcode.CALL -> call ins insLen ctxt + | Opcode.CASA -> casa ins insLen ctxt + | Opcode.CASXA -> casxa ins insLen ctxt + | Opcode.DONE -> ``done`` ins insLen ctxt + | Opcode.FABSs -> fabss ins insLen ctxt + | Opcode.FABSd -> fabsd ins insLen ctxt + | Opcode.FABSq -> fabsq ins insLen ctxt + | Opcode.FADDs -> fadds ins insLen ctxt + | Opcode.FADDd -> faddd ins insLen ctxt + | Opcode.FADDq-> faddq ins insLen ctxt + | Opcode.FBA | Opcode.FBN | Opcode.FBU | Opcode.FBG | Opcode.FBUG + | Opcode.FBL | Opcode.FBUL | Opcode.FBLG | Opcode.FBNE | Opcode.FBE + | Opcode.FBUE | Opcode.FBGE | Opcode.FBUGE | Opcode.FBLE | Opcode.FBULE + | Opcode.FBO -> fbranchfcc ins insLen ctxt + | Opcode.FBPA | Opcode.FBPN | Opcode.FBPU | Opcode.FBPG | Opcode.FBPUG + | Opcode.FBPL | Opcode.FBPUL | Opcode.FBPLG | Opcode.FBPNE | Opcode.FBPE + | Opcode.FBPUE | Opcode.FBPGE | Opcode.FBPUGE | Opcode.FBPLE | Opcode.FBPULE + | Opcode.FBPO -> fbranchpfcc ins insLen ctxt + | Opcode.FCMPs | Opcode.FCMPEs -> fcmps ins insLen ctxt + | Opcode.FCMPd | Opcode.FCMPEd -> fcmpd ins insLen ctxt + | Opcode.FCMPq | Opcode.FCMPEq -> fcmpq ins insLen ctxt + | Opcode.FDIVs -> fdivs ins insLen ctxt + | Opcode.FDIVd -> fdivd ins insLen ctxt + | Opcode.FDIVq -> fdivq ins insLen ctxt + | Opcode.FiTOs -> fitos ins insLen ctxt + | Opcode.FiTOd -> fitod ins insLen ctxt + | Opcode.FiTOq -> fitoq ins insLen ctxt + | Opcode.FMOVs -> fmovs ins insLen ctxt + | Opcode.FMOVd -> fmovd ins insLen ctxt + | Opcode.FMOVq -> fmovq ins insLen ctxt + (* Fix Me *) + | Opcode.FMOVsA | Opcode.FMOVsN | Opcode.FMOVsNE | Opcode.FMOVsE + | Opcode.FMOVsG | Opcode.FMOVsLE | Opcode.FMOVsGE | Opcode.FMOVsL + | Opcode.FMOVsGU | Opcode.FMOVsLEU | Opcode.FMOVsCC | Opcode.FMOVsCS + | Opcode.FMOVsPOS | Opcode.FMOVsNEG | Opcode.FMOVsVC | Opcode.FMOVsVS + -> fmovscc ins insLen ctxt + | Opcode.FMOVdA | Opcode.FMOVdN | Opcode.FMOVdNE | Opcode.FMOVdE + | Opcode.FMOVdG | Opcode.FMOVdLE | Opcode.FMOVdGE | Opcode.FMOVdL + | Opcode.FMOVdGU | Opcode.FMOVdLEU | Opcode.FMOVdCC | Opcode.FMOVdCS + | Opcode.FMOVdPOS | Opcode.FMOVdNEG | Opcode.FMOVdVC | Opcode.FMOVdVS + -> fmovdcc ins insLen ctxt + | Opcode.FMOVqA | Opcode.FMOVqN | Opcode.FMOVqNE | Opcode.FMOVqE + | Opcode.FMOVqG | Opcode.FMOVqLE | Opcode.FMOVqGE | Opcode.FMOVqL + | Opcode.FMOVqGU | Opcode.FMOVqLEU | Opcode.FMOVqCC | Opcode.FMOVqCS + | Opcode.FMOVqPOS | Opcode.FMOVqNEG | Opcode.FMOVqVC | Opcode.FMOVqVS + -> fmovqcc ins insLen ctxt + | Opcode.FMOVFsA | Opcode.FMOVFsN | Opcode.FMOVFsU | Opcode.FMOVFsG + | Opcode.FMOVFsUG | Opcode.FMOVFsL | Opcode.FMOVFsUL | Opcode.FMOVFsLG + | Opcode.FMOVFsNE | Opcode.FMOVFsE | Opcode.FMOVFsUE | Opcode.FMOVFsGE + | Opcode.FMOVFsUGE | Opcode.FMOVFsLE | Opcode.FMOVFsULE | Opcode.FMOVFsO + -> fmovfscc ins insLen ctxt + | Opcode.FMOVFdA | Opcode.FMOVFdN | Opcode.FMOVFdU | Opcode.FMOVFdG + | Opcode.FMOVFdUG | Opcode.FMOVFdL | Opcode.FMOVFdUL | Opcode.FMOVFdLG + | Opcode.FMOVFdNE | Opcode.FMOVFdE | Opcode.FMOVFdUE | Opcode.FMOVFdGE + | Opcode.FMOVFdUGE | Opcode.FMOVFdLE | Opcode.FMOVFdULE | Opcode.FMOVFdO + -> fmovfdcc ins insLen ctxt + | Opcode.FMOVFqA | Opcode.FMOVFqN | Opcode.FMOVFqU | Opcode.FMOVFqG + | Opcode.FMOVFqUG | Opcode.FMOVFqL | Opcode.FMOVFqUL | Opcode.FMOVFqLG + | Opcode.FMOVFqNE | Opcode.FMOVFqE | Opcode.FMOVFqUE | Opcode.FMOVFqGE + | Opcode.FMOVFqUGE | Opcode.FMOVFqLE | Opcode.FMOVFqULE | Opcode.FMOVFqO + -> fmovfqcc ins insLen ctxt + | Opcode.FMOVRsZ | Opcode.FMOVRsLEZ | Opcode.FMOVRsLZ | Opcode.FMOVRsNZ + | Opcode.FMOVRsGZ | Opcode.FMOVRsGEZ -> fmovrs ins insLen ctxt + | Opcode.FMOVRdZ | Opcode.FMOVRdLEZ | Opcode.FMOVRdLZ | Opcode.FMOVRdNZ + | Opcode.FMOVRdGZ | Opcode.FMOVRdGEZ -> fmovrd ins insLen ctxt + | Opcode.FMOVRqZ | Opcode.FMOVRqLEZ | Opcode.FMOVRqLZ | Opcode.FMOVRqNZ + | Opcode.FMOVRqGZ | Opcode.FMOVRqGEZ -> fmovrq ins insLen ctxt + | Opcode.FMULs -> fmuls ins insLen ctxt + | Opcode.FMULd -> fmuld ins insLen ctxt + | Opcode.FMULq -> fmulq ins insLen ctxt + | Opcode.FNEGs -> fnegs ins insLen ctxt + | Opcode.FNEGd -> fnegd ins insLen ctxt + | Opcode.FNEGq -> fnegq ins insLen ctxt + | Opcode.FsMULd -> fsmuld ins insLen ctxt + | Opcode.FdMULq -> fdmulq ins insLen ctxt + | Opcode.FSQRTs -> fsqrts ins insLen ctxt + | Opcode.FSQRTd -> fsqrtd ins insLen ctxt + | Opcode.FSQRTq -> fsqrtq ins insLen ctxt + | Opcode.FsTOx -> fstox ins insLen ctxt + | Opcode.FdTOx -> fdtox ins insLen ctxt + | Opcode.FqTOx -> fqtox ins insLen ctxt + | Opcode.FsTOi -> fstoi ins insLen ctxt + | Opcode.FdTOi -> fdtoi ins insLen ctxt + | Opcode.FqTOi -> fqtoi ins insLen ctxt + | Opcode.FsTOd -> fstod ins insLen ctxt + | Opcode.FsTOq -> fstoq ins insLen ctxt + | Opcode.FdTOs -> fdtos ins insLen ctxt + | Opcode.FdTOq -> fdtoq ins insLen ctxt + | Opcode.FqTOs -> fqtos ins insLen ctxt + | Opcode.FqTOd -> fqtod ins insLen ctxt + | Opcode.FSUBs -> fsubs ins insLen ctxt + | Opcode.FSUBd -> fsubd ins insLen ctxt + | Opcode.FSUBq -> fsubq ins insLen ctxt + | Opcode.FxTOs -> fxtos ins insLen ctxt + | Opcode.FxTOd -> fxtod ins insLen ctxt + | Opcode.FxTOq -> fxtoq ins insLen ctxt + | Opcode.JMPL -> jmpl ins insLen ctxt + | Opcode.LDF | Opcode.LDDF | Opcode.LDQF | Opcode.LDFSR + | Opcode.LDXFSR -> ldf ins insLen ctxt + | Opcode.LDFA | Opcode.LDDFA | Opcode.LDQFA -> ldfa ins insLen ctxt + | Opcode.LDSB | Opcode.LDSH | Opcode.LDSW | Opcode.LDUB | Opcode.LDUH + | Opcode.LDUW | Opcode.LDX | Opcode.LDD -> ld ins insLen ctxt + | Opcode.LDSBA | Opcode.LDSHA | Opcode.LDSWA | Opcode.LDUBA | Opcode.LDUHA + | Opcode.LDUWA | Opcode.LDXA | Opcode.LDDA -> lda ins insLen ctxt + | Opcode.LDSTUB -> ldstub ins insLen ctxt + | Opcode.LDSTUBA -> ldstuba ins insLen ctxt + | Opcode.MEMBAR -> membar ins insLen ctxt + | Opcode.MOVA | Opcode.MOVN | Opcode.MOVNE | Opcode.MOVE | Opcode.MOVG + | Opcode.MOVLE | Opcode.MOVGE | Opcode.MOVL | Opcode.MOVGU | Opcode.MOVLEU + | Opcode.MOVCC | Opcode.MOVCS | Opcode.MOVPOS | Opcode.MOVNEG | Opcode.MOVVC + | Opcode.MOVVS -> movcc ins insLen ctxt + | Opcode.MOVFA | Opcode.MOVFN | Opcode.MOVFU | Opcode.MOVFG | Opcode.MOVFUG + | Opcode.MOVFL | Opcode.MOVFUL | Opcode.MOVFLG | Opcode.MOVFNE + | Opcode.MOVFE | Opcode.MOVFUE | Opcode.MOVFGE | Opcode.MOVFUGE + | Opcode.MOVFLE | Opcode.MOVFULE | Opcode.MOVFO -> movcc ins insLen ctxt + | Opcode.MOVRZ | Opcode.MOVRLEZ | Opcode.MOVRLZ | Opcode.MOVRNZ + | Opcode.MOVRGZ | Opcode.MOVRGEZ -> movr ins insLen ctxt + | Opcode.MULScc -> mulscc ins insLen ctxt + | Opcode.MULX -> mulx ins insLen ctxt + | Opcode.NOP -> nop insLen + | Opcode.OR -> ``or`` ins insLen ctxt + | Opcode.ORcc -> orcc ins insLen ctxt + | Opcode.ORN -> orn ins insLen ctxt + | Opcode.ORNcc -> orncc ins insLen ctxt + | Opcode.POPC -> popc ins insLen ctxt + | Opcode.PREFETCH | Opcode.PREFETCHA -> nop insLen + | Opcode.RDASI | Opcode.RDASR | Opcode.RDCCR | Opcode.RDFPRS | Opcode.RDPC + | Opcode.RDTICK | Opcode.RDY | Opcode.RDPR -> rd ins insLen ctxt + | Opcode.RESTORE -> restore ins insLen ctxt + | Opcode.RESTORED -> restored ins insLen ctxt + | Opcode.RETRY -> retry ins insLen ctxt + | Opcode.RETURN -> ret ins insLen ctxt + | Opcode.SAVE -> save ins insLen ctxt + | Opcode.SAVED -> saved ins insLen ctxt + | Opcode.SDIVX -> sdivx ins insLen ctxt + | Opcode.SETHI -> sethi ins insLen ctxt + | Opcode.SIR -> nop insLen + | Opcode.SLL + | Opcode.SLLX -> sll ins insLen ctxt + | Opcode.SMUL -> smul ins insLen ctxt + | Opcode.SMULcc -> smulcc ins insLen ctxt + | Opcode.SRA + | Opcode.SRAX -> sra ins insLen ctxt + | Opcode.SRL + | Opcode.SRLX -> srl ins insLen ctxt + | Opcode.STB | Opcode.STH | Opcode.STW | Opcode.STX | Opcode.STD -> + st ins insLen ctxt + | Opcode.STBA | Opcode.STHA | Opcode.STWA | Opcode.STXA | Opcode.STDA -> + sta ins insLen ctxt + | Opcode.STBAR -> nop insLen + | Opcode.STF | Opcode.STDF | Opcode.STQF | Opcode.STFSR | Opcode.STXFSR -> + stf ins insLen ctxt + | Opcode.STFA | Opcode.STDFA | Opcode.STQFA -> stfa ins insLen ctxt + | Opcode.SUB -> sub ins insLen ctxt + | Opcode.SUBcc -> subcc ins insLen ctxt + | Opcode.SUBC -> subC ins insLen ctxt + | Opcode.SUBCcc -> subCcc ins insLen ctxt + | Opcode.SWAP -> swap ins insLen ctxt + | Opcode.SWAPA -> swapa ins insLen ctxt + | Opcode.TADDcc -> addcc ins insLen ctxt + | Opcode.TADDccTV -> addcc ins insLen ctxt + | Opcode.TA | Opcode.TN | Opcode.TNE | Opcode.TE | Opcode.TG | Opcode.TLE + | Opcode.TGE | Opcode.TL | Opcode.TGU | Opcode.TLEU | Opcode.TCC | Opcode.TCS + | Opcode.TPOS | Opcode.TNEG | Opcode.TVC | Opcode.TVS -> nop insLen + | Opcode.TSUBcc -> subcc ins insLen ctxt + | Opcode.TSUBccTV -> subcc ins insLen ctxt + | Opcode.UDIVX -> udivx ins insLen ctxt + | Opcode.UMUL -> umul ins insLen ctxt + | Opcode.UMULcc -> umulcc ins insLen ctxt + | Opcode.WRASI | Opcode.WRASR | Opcode.WRCCR | Opcode.WRFPRS | Opcode.WRPR + | Opcode.WRY -> wr ins insLen ctxt + | Opcode.XOR -> xor ins insLen ctxt + | Opcode.XORcc -> xorcc ins insLen ctxt + | Opcode.XNOR -> xnor ins insLen ctxt + | Opcode.XNORcc -> xnorcc ins insLen ctxt + | Opcode.SDIV -> sdiv ins insLen ctxt + | Opcode.SDIVcc -> sdivcc ins insLen ctxt + | Opcode.UDIV -> udiv ins insLen ctxt + | Opcode.UDIVcc -> udivcc ins insLen ctxt + | Opcode.FLUSH | Opcode.FLUSHW | Opcode.ILLTRAP -> nop insLen + | Opcode.InvalidOp -> raise InvalidOpcodeException + | o -> + #if DEBUG + eprintfn "%A" o + #endif + raise <| NotImplementedIRException (Disasm.opCodeToString o) + |> fun ir -> ir.ToStmts () diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCParser.fs b/src/FrontEnd/BinLifter/SPARC/SPARCParser.fs new file mode 100644 index 00000000..8f66e08f --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCParser.fs @@ -0,0 +1,46 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SPARC + +open System +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Parser for SPARC instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type SPARCParser (isa: ISA) = + let reader = BinReader.Init isa.Endian + + interface IInstructionParsable with + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader addr :> Instruction + + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader addr :> Instruction + + member __.MaxInstructionSize = 4 + + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCParsingMain.fs b/src/FrontEnd/BinLifter/SPARC/SPARCParsingMain.fs new file mode 100644 index 00000000..562273cf --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCParsingMain.fs @@ -0,0 +1,3700 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.SPARC.ParsingMain + +open B2R2.FrontEnd.BinLifter.SPARC + +open B2R2 +open B2R2.FrontEnd.BinLifter + +let getRegister = function + | 0x0uy -> R.G0 + | 0x1uy -> R.G1 + | 0x2uy -> R.G2 + | 0x3uy -> R.G3 + | 0x4uy -> R.G4 + | 0x5uy -> R.G5 + | 0x6uy -> R.G6 + | 0x7uy -> R.G7 + | 0x8uy -> R.O0 + | 0x9uy -> R.O1 + | 0xAuy -> R.O2 + | 0xBuy -> R.O3 + | 0xCuy -> R.O4 + | 0xDuy -> R.O5 + | 0xEuy -> R.O6 + | 0xFuy -> R.O7 + | 0x10uy -> R.L0 + | 0x11uy -> R.L1 + | 0x12uy -> R.L2 + | 0x13uy -> R.L3 + | 0x14uy -> R.L4 + | 0x15uy -> R.L5 + | 0x16uy -> R.L6 + | 0x17uy -> R.L7 + | 0x18uy -> R.I0 + | 0x19uy -> R.I1 + | 0x1Auy -> R.I2 + | 0x1Buy -> R.I3 + | 0x1Cuy -> R.I4 + | 0x1Duy -> R.I5 + | 0x1Euy -> R.I6 + | 0x1Fuy -> R.I7 + | _ -> raise InvalidRegisterException + +let getFloatRegister = function + | 0x0uy -> R.F0 + | 0x1uy -> R.F1 + | 0x2uy -> R.F2 + | 0x3uy -> R.F3 + | 0x4uy -> R.F4 + | 0x5uy -> R.F5 + | 0x6uy -> R.F6 + | 0x7uy -> R.F7 + | 0x8uy -> R.F8 + | 0x9uy -> R.F9 + | 0xauy -> R.F10 + | 0xbuy -> R.F11 + | 0xcuy -> R.F12 + | 0xduy -> R.F13 + | 0xeuy -> R.F14 + | 0xfuy -> R.F15 + | 0x10uy -> R.F16 + | 0x11uy -> R.F17 + | 0x12uy -> R.F18 + | 0x13uy -> R.F19 + | 0x14uy -> R.F20 + | 0x15uy -> R.F21 + | 0x16uy -> R.F22 + | 0x17uy -> R.F23 + | 0x18uy -> R.F24 + | 0x19uy -> R.F25 + | 0x1auy -> R.F26 + | 0x1buy -> R.F27 + | 0x1cuy -> R.F28 + | 0x1duy -> R.F29 + | 0x1euy -> R.F30 + | 0x1fuy -> R.F31 + | _ -> raise InvalidRegisterException + +let getDPFloatRegister = function + | 0x0uy -> R.F0 + | 0x1uy -> R.F32 + | 0x2uy -> R.F2 + | 0x3uy -> R.F34 + | 0x4uy -> R.F4 + | 0x5uy -> R.F36 + | 0x6uy -> R.F6 + | 0x7uy -> R.F38 + | 0x8uy -> R.F8 + | 0x9uy -> R.F40 + | 0xauy -> R.F10 + | 0xbuy -> R.F42 + | 0xcuy -> R.F12 + | 0xduy -> R.F44 + | 0xeuy -> R.F14 + | 0xfuy -> R.F46 + | 0x10uy -> R.F16 + | 0x11uy -> R.F48 + | 0x12uy -> R.F18 + | 0x13uy -> R.F50 + | 0x14uy -> R.F20 + | 0x15uy -> R.F52 + | 0x16uy -> R.F22 + | 0x17uy -> R.F54 + | 0x18uy -> R.F24 + | 0x19uy -> R.F56 + | 0x1auy -> R.F26 + | 0x1buy -> R.F58 + | 0x1cuy -> R.F28 + | 0x1duy -> R.F60 + | 0x1euy -> R.F30 + | 0x1fuy -> R.F62 + | _ -> raise InvalidRegisterException + +let getQPFloatRegister = function + | 0x0uy -> R.F0 + | 0x01uy -> R.F32 + | 0x4uy -> R.F4 + | 0x05uy -> R.F36 + | 0x8uy -> R.F8 + | 0x9uy -> R.F40 + | 0xcuy -> R.F12 + | 0xduy -> R.F44 + | 0x10uy -> R.F16 + | 0x11uy -> R.F48 + | 0x14uy -> R.F20 + | 0x15uy -> R.F52 + | 0x18uy -> R.F24 + | 0x19uy -> R.F56 + | 0x1cuy -> R.F28 + | 0x1duy -> R.F60 + | _ -> raise InvalidRegisterException + +let pickBit binary (pos: uint32) = binary >>> int pos &&& 0b1u + +let concat (n1: uint32) (n2: uint32) shift = (n1 <<< shift) + n2 + +let parseOneOpr b op1 = OneOperand (op1 b) + +let parseTwoOpr b op1 op2 = TwoOperands (op1 b, op2 b) + +let parseThrOpr b op1 op2 op3 = ThreeOperands (op1 b, op2 b, op3 b) + +let parseFourOpr b op1 op2 op3 op4 = + FourOperands (op1 b, op2 b, op3 b, op4 b) + +let parseOneCC cc1 = OneOperand (cc1) + +let parseOneCCOneOpr b cc1 op1 = TwoOperands (cc1, op1 b) + +let parseOneCCTwoOpr b cc1 op1 op2 = ThreeOperands (cc1, op1 b, op2 b) + +let parseOneCCThrOpr b cc1 op1 op2 op3 = FourOperands (cc1, op1 b, op2 b, op3 b) + +let parseOneOprOneCC b op1 cc1 = TwoOperands (op1 b, cc1) + +let parseOneRegOneOpr b reg op1 = TwoOperands (reg, op1 b) + +let parseTwoOprOneReg b op1 op2 reg = ThreeOperands (op1 b, op2 b, reg) + +let parseOneRegTwoOpr b reg op1 op2 = ThreeOperands (reg, op1 b, op2 b) + +let parseThrOprOneReg b op1 op2 reg op3 = + FourOperands (op1 b, op2 b, reg, op3 b) + +let parseSTXA b op1 op2 op3 reg = + FourOperands (op1 b, op2 b, op3 b, reg) + +let extract binary n1 n2 = + let m, n = if max n1 n2 = n1 then n1, n2 else n2, n1 + let range = m - n + 1u + if range > 31u then failwith "invalid range" else () + let mask = pown 2 (int range) - 1 |> uint32 + binary >>> int n &&& mask + +let getReg b s e = getRegister (extract b s e |> byte) + +let getRegRd b = getReg b 29u 25u |> OprReg + +let getRegRs1 b = getReg b 18u 14u |> OprReg + +let getRegRs2 b = getReg b 4u 0u |> OprReg + +let getFloatReg b s e = getFloatRegister (extract b s e |> byte) + +let getFloatRegRd b = getFloatReg b 29u 25u |> OprReg + +let getFloatRegRs1 b = getFloatReg b 18u 14u |> OprReg + +let getFloatRegRs2 b = getFloatReg b 4u 0u |> OprReg + +let getDPFloatReg b s e = getDPFloatRegister (extract b s e |> byte) + +let getDPFloatRegRd b = getDPFloatReg b 29u 25u |> OprReg + +let getDPFloatRegRs1 b = getDPFloatReg b 18u 14u |> OprReg + +let getDPFloatRegRs2 b = getDPFloatReg b 4u 0u |> OprReg + +let getQPFloatReg b s e = getQPFloatRegister (extract b s e |> byte) + +let getQPFloatRegRd b = getQPFloatReg b 29u 25u |> OprReg + +let getQPFloatRegRs1 b = getQPFloatReg b 18u 14u |> OprReg + +let getQPFloatRegRs2 b = getQPFloatReg b 4u 0u |> OprReg + +let getRegAsi b = R.ASI |> OprReg + +let getRegFsr b = R.FSR |> OprReg + +let getConst22 b = extract b 21u 0u |> int32 |> OprImm + +let getimm22 b = + extract b 21u 0u <<< 10 |> int32 |> OprImm + +let getSimm13 b = + (extract b 12u 0u) <<< 19 |> int32 >>> 19 |> OprImm + +let getSimm13Zero b = + let checkSimm13 = (extract b 12u 0u) <<< 19 |> int32 >>> 19 + if checkSimm13 = 0 then getReg b 12u 0u |> OprReg + else checkSimm13 |> OprImm + +let getSimm11 b = + (extract b 10u 0u) <<< 21 |> int32 >>> 21 |> OprImm + +let getSimm10 b = + (extract b 9u 0u) <<< 22 |> int32 >>> 22 |> OprImm + + +let getAbit b = pickBit b 29u |> int32 |> OprImm + +let getPbit b = pickBit b 19u |> int32 |> OprImm + +let getd16hi b = extract b 21u 20u |> uint32 + +let getd16lo b = extract b 13u 0u |> uint32 + +let getdisp30 b = + let disp30 = extract b 29u 0u <<< 2 |> int32 >>> 2 + 4 * disp30 |> int32 |> OprAddr + +let getdisp22 b = + let disp22 = extract b 21u 0u <<< 10 |> int32 >>> 10 + 4 * disp22 |> OprAddr + +let getdisp19 b = + let disp19 = extract b 18u 0u <<< 13 |> int32 >>> 13 + 4 * disp19 |> OprAddr + +let get26cc1 b = pickBit b 26u + +let get25cc0 b = pickBit b 25u + +let get21cc1 b = pickBit b 21u + +let get20cc0 b = pickBit b 20u + +let get18cc2 b = pickBit b 18u + +let get13cc2 b = pickBit b 13u + +let get12cc1 b = pickBit b 12u + +let get11cc0 b = pickBit b 11u + +let getImmAsi b = extract b 12u 5u |> int32 |> OprImm + +let getImplDep b = + concat (extract b 29u 25u) (extract b 18u 0u) 19 |> int32 |> OprImm + +let getcmask b = extract b 6u 4u |> int32 |> OprImm + +let getmmask b = extract b 3u 0u |> int32 |> OprImm + +let getMembarMask b = + let cmask = extract b 6u 4u + let mmask = extract b 3u 0u + cmask ||| mmask |> int32 |> OprImm + +let getOpFCC b = extract b 13u 11u |> int32 |> OprImm + +let getshcnt32 b = extract b 4u 0u |> int32 |> OprImm + +let getshcnt64 b = extract b 5u 0u |> int32 |> OprImm + +let getfcn b = extract b 29u 25u |> int32 |> OprImm + +let getAddrRs1 b = getReg b 18u 14u |> OprReg + +let getAddrRs2 b = getReg b 4u 0u |> OprReg + +let getAddrSimm13 b = + (extract b 12u 0u) <<< 19 |> int32 >>> 19 |> OprImm + +let setPriReg r = r |> OprReg + +let getThrCC (cc2: uint32) (cc1: uint32) (cc0: uint32) = + match cc2, cc1, cc0 with + | 0b0u, 0b0u, 0b0u -> ConditionCode.Fcc0 |> OprCC + | 0b0u, 0b0u, 0b1u -> ConditionCode.Fcc1 |> OprCC + | 0b0u, 0b1u, 0b0u -> ConditionCode.Fcc2 |> OprCC + | 0b0u, 0b1u, 0b1u -> ConditionCode.Fcc3 |> OprCC + | 0b1u, 0b0u, 0b0u -> ConditionCode.Icc |> OprCC + | 0b1u, 0b1u, 0b0u -> ConditionCode.Xcc |> OprCC + | _ -> raise InvalidOperandException + +let getTwoCCix (cc1: uint32) (cc0: uint32) = + match cc1, cc0 with + | 0b0u, 0b0u -> ConditionCode.Icc |> OprCC + | 0b1u, 0b0u -> ConditionCode.Xcc |> OprCC + | _ -> raise InvalidOperandException + +let getTwoCCFcc (cc1: uint32) (cc0: uint32) = + match cc1, cc0 with + | 0b0u, 0b0u -> ConditionCode.Fcc0 |> OprCC + | 0b0u, 0b1u -> ConditionCode.Fcc1 |> OprCC + | 0b1u, 0b0u -> ConditionCode.Fcc2 |> OprCC + | 0b1u, 0b1u -> ConditionCode.Fcc3 |> OprCC + | _ -> raise InvalidOperandException + +let getTwod16 (hi: uint32) (lo: uint32) = + (hi <<< 14 ||| lo) * 4u |> int32 |> OprImm + +let getd16 b = + let hi = extract b 21u 20u + let lo = extract b 13u 0u + (hi <<< 14 ||| lo) * 4u |> int32 |> OprAddr + +let getPriReg b32 s e = + match (extract b32 s e) |> byte with + | 0uy -> Register.TPC |> OprPriReg + | 1uy -> Register.TNPC |> OprPriReg + | 2uy -> Register.TSTATE |> OprPriReg + | 3uy -> Register.TT |> OprPriReg + | 4uy -> Register.TICK |> OprPriReg + | 5uy -> Register.TBA |> OprPriReg + | 6uy -> Register.PSTATE |> OprPriReg + | 7uy -> Register.TL |> OprPriReg + | 8uy -> Register.PIL |> OprPriReg + | 9uy -> Register.CWP |> OprPriReg + | 10uy -> Register.CANSAVE |> OprPriReg + | 11uy -> Register.CANRESTORE |> OprPriReg + | 12uy -> Register.CLEANWIN |> OprPriReg + | 13uy -> Register.OTHERWIN |> OprPriReg + | 14uy -> Register.WSTATE |> OprPriReg + | 15uy -> Register.FQ |> OprPriReg + | 31uy -> Register.VER |> OprPriReg + | _ -> raise InvalidRegisterException + +let priregRDPR b32 = getPriReg b32 18u 14u + +let priregWRPR b32 = getPriReg b32 29u 25u + +(* + 00r_ __d1 1010 0--- + --o_ __p_ __f- ---- +*) +let parseFP b32 = + match extract b32 13u 5u with + | 0b001000001u -> + struct ( + Opcode.FADDs, + parseThrOpr b32 getFloatRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b001000010u -> + struct ( + Opcode.FADDd, + parseThrOpr b32 getDPFloatRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b001000011u -> + struct ( + Opcode.FADDq, + parseThrOpr b32 getQPFloatRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b001000101u -> + struct ( + Opcode.FSUBs, + parseThrOpr b32 getFloatRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b001000110u -> + struct ( + Opcode.FSUBd, + parseThrOpr b32 getDPFloatRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b001000111u -> + struct ( + Opcode.FSUBq, + parseThrOpr b32 getQPFloatRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b010000001u -> + struct ( + Opcode.FsTOx, + parseTwoOpr b32 getFloatRegRs2 getDPFloatRegRd + ) + | 0b010000010u -> + struct ( + Opcode.FdTOx, + parseTwoOpr b32 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b010000011u -> + struct ( + Opcode.FqTOx, + parseTwoOpr b32 getQPFloatRegRs2 getDPFloatRegRd + ) + | 0b011010001u -> + struct ( + Opcode.FsTOi, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b011010010u -> + struct ( + Opcode.FdTOi, + parseTwoOpr b32 getDPFloatRegRs2 getFloatRegRd + ) + | 0b011010011u -> + struct ( + Opcode.FqTOi, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b011001001u -> + struct ( + Opcode.FsTOd, + parseTwoOpr b32 getFloatRegRs2 getDPFloatRegRd + ) + | 0b011001101u -> + struct ( + Opcode.FsTOq, + parseTwoOpr b32 getFloatRegRs2 getQPFloatRegRd + ) + | 0b011000110u -> + struct ( + Opcode.FdTOs, + parseTwoOpr b32 getDPFloatRegRs2 getFloatRegRd + ) + | 0b011001110u -> + struct ( + Opcode.FdTOq, + parseTwoOpr b32 getDPFloatRegRs2 getQPFloatRegRd + ) + | 0b011000111u -> + struct ( + Opcode.FqTOs, + parseTwoOpr b32 getQPFloatRegRs2 getFloatRegRd + ) + | 0b011001011u -> + struct ( + Opcode.FqTOd, + parseTwoOpr b32 getQPFloatRegRs2 getDPFloatRegRd + ) + | 0b010000100u -> + struct ( + Opcode.FxTOs, + parseTwoOpr b32 getDPFloatRegRs2 getFloatRegRd + ) + | 0b010001000u -> + struct ( + Opcode.FxTOd, + parseTwoOpr b32 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b010001100u -> + struct ( + Opcode.FxTOq, + parseTwoOpr b32 getDPFloatRegRs2 getQPFloatRegRd + ) + | 0b011000100u -> + struct ( + Opcode.FiTOs, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b011001000u -> + struct ( + Opcode.FiTOd, + parseTwoOpr b32 getFloatRegRs2 getDPFloatRegRd + ) + | 0b011001100u -> + struct ( + Opcode.FiTOq, + parseTwoOpr b32 getFloatRegRs2 getQPFloatRegRd + ) + | 0b000000001u -> + struct ( + Opcode.FMOVs, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b000000010u -> + struct ( + Opcode.FMOVd, + parseTwoOpr b32 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000000011u -> + struct ( + Opcode.FMOVq, + parseTwoOpr b32 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b000000101u -> + struct ( + Opcode.FNEGs, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b000000110u -> + struct ( + Opcode.FNEGd, + parseTwoOpr b32 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000000111u -> + struct ( + Opcode.FNEGq, + parseTwoOpr b32 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b000001001u -> + struct ( + Opcode.FABSs, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b000001010u -> + struct ( + Opcode.FABSd, + parseTwoOpr b32 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000001011u -> + struct ( + Opcode.FABSq, + parseTwoOpr b32 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b001001001u -> + struct ( + Opcode.FMULs, + parseThrOpr b32 getFloatRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b001001010u -> + struct ( + Opcode.FMULd, + parseThrOpr b32 getDPFloatRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b001001011u -> + struct ( + Opcode.FMULq, + parseThrOpr b32 getQPFloatRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b001101001u -> + struct ( + Opcode.FsMULd, + parseThrOpr b32 getFloatRegRs1 getFloatRegRs2 getDPFloatRegRd + ) + | 0b001101110u -> + struct ( + Opcode.FdMULq, + parseThrOpr b32 getDPFloatRegRs1 getDPFloatRegRs2 getQPFloatRegRd + ) + | 0b001001101u -> + struct ( + Opcode.FDIVs, + parseThrOpr b32 getFloatRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b001001110u -> + struct ( + Opcode.FDIVd, + parseThrOpr b32 getDPFloatRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b001001111u -> + struct ( + Opcode.FDIVq, + parseThrOpr b32 getQPFloatRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | 0b000101001u -> + struct ( + Opcode.FSQRTs, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b000101010u -> + struct ( + Opcode.FSQRTd, + parseTwoOpr b32 getFloatRegRs2 getFloatRegRd + ) + | 0b000101011u -> + struct ( + Opcode.FSQRTq, + parseTwoOpr b32 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + + +let parse110101fmovr b32 = + match extract b32 12u 10u with + | 0b001u -> + match extract b32 9u 5u with + | 0b00101u -> + struct ( + Opcode.FMOVRsZ, + parseThrOpr b32 getRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b00110u -> + struct ( + Opcode.FMOVRdZ, + parseThrOpr b32 getRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b00111u -> + struct ( + Opcode.FMOVRqZ, + parseThrOpr b32 getRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b010u -> + match extract b32 9u 5u with + | 0b00101u -> + struct ( + Opcode.FMOVRsLEZ, + parseThrOpr b32 getRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b00110u -> + struct (Opcode.FMOVRdLEZ, + parseThrOpr b32 getRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b00111u -> + struct ( + Opcode.FMOVRqLEZ, + parseThrOpr b32 getRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b011u -> + match extract b32 9u 5u with + | 0b00101u -> + struct ( + Opcode.FMOVRsLZ, + parseThrOpr b32 getRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b00110u -> + struct ( + Opcode.FMOVRdLZ, + parseThrOpr b32 getRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b00111u -> + struct ( + Opcode.FMOVRqLZ, + parseThrOpr b32 getRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b101u -> + match extract b32 9u 5u with + | 0b00101u -> + struct ( + Opcode.FMOVRsNZ, + parseThrOpr b32 getRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b00110u -> + struct ( + Opcode.FMOVRdNZ, + parseThrOpr b32 getRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b00111u -> + struct ( + Opcode.FMOVRqNZ, + parseThrOpr b32 getRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b110u -> + match extract b32 9u 5u with + | 0b00101u -> + struct ( + Opcode.FMOVRsGZ, + parseThrOpr b32 getRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b00110u -> + struct ( + Opcode.FMOVRdGZ, + parseThrOpr b32 getRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b00111u -> + struct ( + Opcode.FMOVRqGZ, + parseThrOpr b32 getRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b111u -> + match extract b32 9u 5u with + | 0b00101u -> + struct ( + Opcode.FMOVRsGEZ, + parseThrOpr b32 getRegRs1 getFloatRegRs2 getFloatRegRd + ) + | 0b00110u -> + struct ( + Opcode.FMOVRdGEZ, + parseThrOpr b32 getRegRs1 getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b00111u -> + struct ( + Opcode.FMOVRqGEZ, + parseThrOpr b32 getRegRs1 getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 10r_ __d1 1010 10-- + ---- ---- ---- ---- +*) +let parse110101 b32 = + match extract b32 13u 11u with + | 0b100u | 0b110u -> + match extract b32 17u 14u with + | 0b1000u -> + // struct (Opcode.FMOVA, parseThrOpr b32 getOpFCC getFloatRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsA, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdA, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqA, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0000u -> + // struct (Opcode.FMOVN, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsN, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdN, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqN, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1001u -> + // struct (Opcode.FMOVNE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsNE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdNE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqNE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0001u -> + // struct (Opcode.FMOVE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1010u -> + // struct (Opcode.FMOVG, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0010u -> + // struct (Opcode.FMOVLE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsLE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdLE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqLE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1011u -> + // struct (Opcode.FMOVGE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0011u -> + // struct (Opcode.FMOVL, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1100u -> + // struct (Opcode.FMOVGU, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsGU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdGU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqGU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0100u -> + // struct (Opcode.FMOVLEU, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsLEU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdLEU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqLEU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1101u -> + // struct (Opcode.FMOVCC, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsCC, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdCC, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqCC, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0101u -> + // struct (Opcode.FMOVCS, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsCS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdCS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqCS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1110u -> + // struct (Opcode.FMOVPOS, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsPOS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdPOS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqPOS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0110u -> + // struct (Opcode.FMOVNEG, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsNEG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdNEG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqNEG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1111u -> + // struct (Opcode.FMOVVC, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsVC, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdVC, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqVC, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0111u -> + // struct (Opcode.FMOVVS, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVsVS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVdVS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVqVS, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | _ -> parse110101fmovr b32 + + | 0b000u | 0b001u | 0b010u | 0b011u -> + match extract b32 17u 14u with + | 0b1000u -> + // struct (Opcode.FMOVA, parseThrOpr b32 getOpFCC getFloatRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsA, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdA, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqA, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0000u -> + // struct (Opcode.FMOVN, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsN, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdN, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqN, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0111u -> + // struct (Opcode.FMOVNE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqU, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b110u -> + // struct (Opcode.FMOVE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0101u -> + // struct (Opcode.FMOVG, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsUG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdUG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqUG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0100u -> + // struct (Opcode.FMOVLE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0011u -> + // struct (Opcode.FMOVGE, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsUL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdUL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqUL, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0010u -> + // struct (Opcode.FMOVL, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsLG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdLG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqLG, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b0001u -> + // struct (Opcode.FMOVGU, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsNE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdNE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqNE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1001u -> + // struct (Opcode.FMOVLEU, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1010u -> + // struct (Opcode.FMOVCC, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsUE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdUE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqUE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1011u -> + // struct (Opcode.FMOVCS, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1100u -> + // struct (Opcode.FMOVPOS, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsUGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdUGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqUGE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1101u -> + // struct (Opcode.FMOVNEG, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsLE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdLE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqLE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1110u -> + // struct (Opcode.FMOVVC, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsULE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdULE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqULE, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | 0b1111u -> + // struct (Opcode.FMOVVS, parseThrOpr b32 getOpFCC getRegRs2 getRegRd) + match extract b32 10u 5u with + | 0b000001u -> + struct ( + Opcode.FMOVFsO, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getFloatRegRs2 getFloatRegRd + ) + | 0b000010u -> + struct ( + Opcode.FMOVFdO, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getDPFloatRegRs2 getDPFloatRegRd + ) + | 0b000011u -> + struct ( + Opcode.FMOVFqO, + parseOneCCTwoOpr b32 + (getThrCC (get13cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getQPFloatRegRs2 getQPFloatRegRd + ) + | _ -> parse110101fmovr b32 + | _ -> struct (Opcode.InvalidOp, NoOperand) + + | _ -> parse110101fmovr b32 + + +(* + 10r_ __d1 0100 0--- + ---- ---- ---- ---- +*) +let parse101000 b32 = + match extract b32 18u 14u with + | 0u -> struct (Opcode.RDY, parseOneRegOneOpr b32 (setPriReg R.Y) getRegRd) + | 2u -> + struct (Opcode.RDCCR, parseOneRegOneOpr b32 (setPriReg R.CCR) getRegRd) + | 3u -> + struct (Opcode.RDASI, parseOneRegOneOpr b32 (setPriReg R.ASI) getRegRd) + | 4u -> + struct (Opcode.RDTICK, parseOneRegOneOpr b32 (setPriReg R.TICK) getRegRd) + | 5u -> struct (Opcode.RDPC, parseOneRegOneOpr b32 (setPriReg R.PC) getRegRd) + | 6u -> + struct (Opcode.RDFPRS, parseOneRegOneOpr b32 (setPriReg R.FPRS) getRegRd) + | 7u + | 8u + | 9u + | 10u + | 12u + | 13u + | 14u -> struct (Opcode.RDASR, parseTwoOpr b32 getRegRs1 getRegRd) + | 15u -> + match pickBit b32 13u with + | 0b0u -> struct (Opcode.STBAR, NoOperand) + | _ -> struct (Opcode.MEMBAR, parseOneOpr b32 getMembarMask) + | 16u + | 17u + | 18u + | 19u + | 20u + | 21u + | 22u + | 23u + | 24u + | 25u + | 26u + | 27u + | 28u + | 29u + | 30u + | 31u -> struct (Opcode.RDASR, parseTwoOpr b32 getRegRs1 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 10r_ __d1 1000 0--- + ---- ---- ---- ---- +*) +let parse110000 b32 = + match pickBit b32 13u with + | 0b0u -> + match extract b32 29u 25u with + | 0u -> struct (Opcode.WRY, + parseTwoOprOneReg b32 getRegRs1 getRegRs2 (setPriReg R.Y)) + | 2u -> struct (Opcode.WRCCR, + parseTwoOprOneReg b32 getRegRs1 getRegRs2 (setPriReg R.CCR)) + | 3u -> struct (Opcode.WRASI, + parseTwoOprOneReg b32 getRegRs1 getRegRs2 (setPriReg R.ASI)) + | 4u + | 5u + | 7u + | 8u + | 9u + | 10u + | 12u + | 13u + | 14u -> struct (Opcode.WRASR, parseTwoOpr b32 getRegRs1 getRegRs2) + | 6u -> struct (Opcode.WRFPRS, + parseTwoOprOneReg b32 getRegRs1 getRegRs2 (setPriReg R.FPRS)) + | 15u -> struct (Opcode.SIR, NoOperand) + | 16u + | 17u + | 18u + | 19u + | 20u + | 21u + | 22u + | 23u + | 24u + | 25u + | 26u + | 27u + | 28u + | 29u + | 30u + | 31u -> struct (Opcode.WRASR, parseTwoOpr b32 getRegRs1 getRegRs2) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u -> + match extract b32 29u 25u with + | 0u -> + struct (Opcode.WRY, + parseTwoOprOneReg b32 getRegRs1 getSimm13 (setPriReg R.Y)) + | 2u -> + struct (Opcode.WRCCR, + parseTwoOprOneReg b32 getRegRs1 getSimm13 (setPriReg R.CCR)) + | 3u -> + struct (Opcode.WRASI, + parseTwoOprOneReg b32 getRegRs1 getSimm13 (setPriReg R.ASI)) + | 4u + | 5u + | 7u + | 8u + | 9u + | 10u + | 12u + | 13u + | 14u -> struct (Opcode.WRASR, parseTwoOpr b32 getRegRs1 getSimm13) + | 6u -> + struct ( + Opcode.WRFPRS, + parseTwoOprOneReg b32 getRegRs1 getSimm13 (setPriReg R.FPRS) + ) + | 15u -> struct (Opcode.SIR, parseOneOpr b32 getSimm13) + | 16u + | 17u + | 18u + | 19u + | 20u + | 21u + | 22u + | 23u + | 24u + | 25u + | 26u + | 27u + | 28u + | 29u + | 30u + | 31u -> + struct (Opcode.WRASR, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 10r_ __d1 0110 0--- + ---- ---- ---- ---- +*) +let parse101100 b32 = + match (get18cc2 b32), (get12cc1 b32), (get11cc0 b32) with + | 0b0u, 0b0u, 0b0u + | 0b0u, 0b0u, 0b1u + | 0b0u, 0b1u, 0b0u + | 0b0u, 0b1u, 0b1u -> + match pickBit b32 13u with + | 0b0u -> + match extract b32 17u 14u with + | 0b1000u -> + struct ( + Opcode.MOVFA, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0000u -> + struct ( + Opcode.MOVFN, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0111u -> + struct ( + Opcode.MOVFU, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0110u -> + struct ( + Opcode.MOVFG, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0101u -> + struct ( + Opcode.MOVFUG, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0100u -> + struct ( + Opcode.MOVFL, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0011u -> + struct ( + Opcode.MOVFUL, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0010u -> + struct ( + Opcode.MOVFLG, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0001u -> + struct ( + Opcode.MOVFNE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1001u -> + struct ( + Opcode.MOVFE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1010u -> + struct ( + Opcode.MOVFUE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1011u -> + struct ( + Opcode.MOVFGE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1100u -> + struct ( + Opcode.MOVFUGE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1101u -> + struct ( + Opcode.MOVFLE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1110u -> + struct ( + Opcode.MOVFULE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd) + | 0b1111u -> + struct ( + Opcode.MOVFO, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u -> + match extract b32 17u 14u with + | 0b1000u -> + struct ( + Opcode.MOVFA, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 getRegRd + ) + | 0b0000u -> + struct ( + Opcode.MOVFN, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 getRegRd + ) + | 0b0111u -> + struct ( + Opcode.MOVFU, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0110u -> + struct ( + Opcode.MOVFG, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0101u -> + struct ( + Opcode.MOVFUG, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0100u -> + struct ( + Opcode.MOVFL, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 getRegRd + ) + | 0b0011u -> + struct ( + Opcode.MOVFUL, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 getRegRd + ) + | 0b0010u -> + struct ( + Opcode.MOVFLG, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 getRegRd + ) + | 0b0001u -> + struct ( + Opcode.MOVFNE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1001u -> + struct ( + Opcode.MOVFE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1010u -> + struct ( + Opcode.MOVFUE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1011u -> + struct ( + Opcode.MOVFGE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1100u -> + struct ( + Opcode.MOVFUGE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1101u -> + struct ( + Opcode.MOVFLE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1110u -> + struct ( + Opcode.MOVFULE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd) + | 0b1111u -> + struct ( + Opcode.MOVFO, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u, 0b0u, 0b0u + | 0b1u, 0b1u, 0b0u -> + match pickBit b32 13u with + | 0b0u -> + match extract b32 17u 14u with + | 0b1000u -> + struct ( + Opcode.MOVA, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0000u -> + struct ( + Opcode.MOVN, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b1001u -> + struct ( + Opcode.MOVNE, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0001u -> + struct ( + Opcode.MOVE, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1010u -> + struct ( + Opcode.MOVG, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0010u -> + struct ( + Opcode.MOVLE, + parseOneCCTwoOpr + b32 (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b1011u -> + struct ( + Opcode.MOVGE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b0011u -> + struct ( + Opcode.MOVL, + parseOneCCTwoOpr b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 getRegRd + ) + | 0b1100u -> + struct ( + Opcode.MOVGU, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0100u -> + struct ( + Opcode.MOVLEU, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1101u -> + struct ( + Opcode.MOVCC, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0101u -> + struct ( + Opcode.MOVCS, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1110u -> + struct ( + Opcode.MOVPOS, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b0110u -> + struct ( + Opcode.MOVNEG, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | 0b1111u -> + struct ( + Opcode.MOVVC, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd) + | 0b0111u -> + struct ( + Opcode.MOVVS, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getRegRs2 + getRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u -> + match extract b32 17u 14u with + | 0b1000u -> + struct ( + Opcode.MOVA, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0000u -> + struct ( + Opcode.MOVN, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1001u -> + struct ( + Opcode.MOVNE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0001u -> + struct ( + Opcode.MOVE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1010u -> + struct ( + Opcode.MOVG, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0010u -> + struct ( + Opcode.MOVLE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1011u -> + struct ( + Opcode.MOVGE, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0011u -> + struct ( + Opcode.MOVL, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1100u -> + struct ( + Opcode.MOVGU, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0100u -> + struct ( + Opcode.MOVLEU, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1101u -> + struct ( + Opcode.MOVCC, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0101u -> + struct ( + Opcode.MOVCS, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1110u -> + struct ( + Opcode.MOVPOS, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0110u -> + struct ( + Opcode.MOVNEG, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b1111u -> + struct ( + Opcode.MOVVC, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | 0b0111u -> + struct ( + Opcode.MOVVS, + parseOneCCTwoOpr + b32 + (getThrCC (get18cc2 b32) (get12cc1 b32) (get11cc0 b32)) + getSimm11 + getRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 10r_ __d1 0111 1--- + ---- ---- ---- ---- +*) +let parse101111 b32 = + match pickBit b32 13u with + | 0b0u -> + match extract b32 12u 10u with + | 0b001u -> + struct (Opcode.MOVRZ, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010u -> + struct (Opcode.MOVRLEZ, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011u -> + struct (Opcode.MOVRLZ, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b101u -> + struct (Opcode.MOVRNZ, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b110u -> + struct (Opcode.MOVRGZ, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b111u -> + struct (Opcode.MOVRGEZ, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u -> + match extract b32 12u 10u with + | 0b001u -> + struct (Opcode.MOVRZ, parseThrOpr b32 getRegRs1 getSimm10 getRegRd) + | 0b010u -> + struct (Opcode.MOVRLEZ, parseThrOpr b32 getRegRs1 getSimm10 getRegRd) + | 0b011u -> + struct (Opcode.MOVRLZ, parseThrOpr b32 getRegRs1 getSimm10 getRegRd) + | 0b101u -> + struct (Opcode.MOVRNZ, parseThrOpr b32 getRegRs1 getSimm10 getRegRd) + | 0b110u -> + struct (Opcode.MOVRGZ, parseThrOpr b32 getRegRs1 getSimm10 getRegRd) + | 0b111u -> + struct (Opcode.MOVRGEZ, parseThrOpr b32 getRegRs1 getSimm10 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 10r_ __do ___p 3--- + ---- ---- ---- ---- +*) +let parse10rd b32 = + match pickBit b32 13u with + | 0b0u -> + match extract b32 24u 19u with + (* ADD *) + | 0b000000u -> + struct (Opcode.ADD, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010000u -> + struct (Opcode.ADDcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b001000u -> + struct (Opcode.ADDC, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011000u -> + struct (Opcode.ADDCcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Divide *) + | 0b001110u -> + struct (Opcode.UDIV, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b001111u -> + struct (Opcode.SDIV, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011110u -> + struct (Opcode.UDIVcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011111u -> + struct (Opcode.SDIVcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Jump and Link *) + | 0b111000u -> + struct (Opcode.JMPL, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Logical Operations *) + | 0b000001u -> + struct (Opcode.AND, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010001u -> + struct (Opcode.ANDcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b000101u -> + struct (Opcode.ANDN, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010101u -> + struct (Opcode.ANDNcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b000010u -> + struct (Opcode.OR, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010010u -> + struct (Opcode.ORcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b000110u -> + struct (Opcode.ORN, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010110u -> + struct (Opcode.ORNcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b000011u -> + struct (Opcode.XOR, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010011u -> + struct (Opcode.XORcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b000111u -> + struct (Opcode.XNOR, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010111u -> + struct (Opcode.XNORcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Multiply and Divide (64-bit) *) + | 0b001001u -> + struct (Opcode.MULX, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b101101u -> + struct (Opcode.SDIVX, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b001101u -> + struct (Opcode.UDIVX, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Multiply (32-bit) *) + | 0b001010u -> + struct (Opcode.UMUL, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b001011u -> + struct (Opcode.SMUL, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011010u -> + struct (Opcode.UMULcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011011u -> + struct (Opcode.SMULcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Multiply Step *) + | 0b100100u -> + struct (Opcode.MULScc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Population Count*) + | 0b101110u -> struct (Opcode.POPC, parseTwoOpr b32 getRegRs2 getRegRd) + (* SAVE and RESTORE *) + | 0b111100u -> + struct (Opcode.SAVE, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b111101u -> + struct (Opcode.RESTORE, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Shift *) + | 0b100101u -> + struct (Opcode.SLL, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b100110u -> + struct (Opcode.SRL, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b100111u -> + struct (Opcode.SRA, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Subtract *) + | 0b000100u -> + struct (Opcode.SUB, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b010100u -> + struct (Opcode.SUBcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b001100u -> + struct (Opcode.SUBC, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b011100u -> + struct (Opcode.SUBCcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Tagged Add *) + | 0b100000u -> + struct (Opcode.TADDcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b100010u -> + struct (Opcode.TADDccTV, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Tagged Subtract *) + | 0b100001u -> + struct (Opcode.TSUBcc, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b100011u -> + struct (Opcode.TSUBccTV, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + (* Write Privileged Register *) + | 0b110010u -> + struct (Opcode.WRPR, parseThrOpr b32 getRegRs1 getRegRs2 priregWRPR) + (* Move Floating-Point Register on Condition (FMOVcc) *) + | 0b110101u -> parse110101 b32 + (* Floating-Point *) + | 0b110100u -> parseFP b32 + (* Read State Register *) + | 0b101000u -> parse101000 b32 + (* Read Privileged State Register *) + | 0b101010u -> struct (Opcode.RDPR, parseTwoOpr b32 priregRDPR getRegRd) + (* Write State Register *) + | 0b110000u -> parse110000 b32 + (* Move Integer Register on Condition *) + | 0b101100u -> parse101100 b32 + (* Move Integer Register on Register Condition *) + | 0b101111u -> parse101111 b32 + | _ -> Opcode.InvalidOp, NoOperand + | 0b1u -> + match extract b32 24u 19u with + (* ADD *) + | 0b000000u -> + struct (Opcode.ADD, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b010000u -> + struct (Opcode.ADDcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b001000u -> + struct (Opcode.ADDC, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b011000u -> + struct (Opcode.ADDCcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Divide *) + | 0b001110u -> + struct (Opcode.UDIV, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b001111u -> + struct (Opcode.SDIV, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b011110u -> + struct (Opcode.UDIVcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b011111u -> + struct (Opcode.SDIVcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Jump and Link *) + | 0b111000u -> + struct (Opcode.JMPL, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Logical Operations *) + | 0b000001u -> + struct (Opcode.AND, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b010001u -> + struct (Opcode.ANDcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b000101u -> + struct (Opcode.ANDN, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b010101u -> + struct (Opcode.ANDNcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b000010u -> + struct (Opcode.OR, parseThrOpr b32 getRegRs1 getSimm13Zero getRegRd) + | 0b010010u -> + struct (Opcode.ORcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b000110u -> + struct (Opcode.ORN, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b010110u -> + struct (Opcode.ORNcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b000011u -> + struct (Opcode.XOR, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b010011u -> + struct (Opcode.XORcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b000111u -> + struct (Opcode.XNOR, parseThrOpr b32 getRegRs1 getSimm13Zero getRegRd) + | 0b010111u -> + struct (Opcode.XNORcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Multiply and Divide (64-bit) *) + | 0b001001u -> + struct (Opcode.MULX, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b101101u -> + struct (Opcode.SDIVX, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b001101u -> + struct (Opcode.UDIVX, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Multiply (32-bit) *) + | 0b001010u -> + struct (Opcode.UMUL, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b001011u -> + struct (Opcode.SMUL, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b011010u -> + struct (Opcode.UMULcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b011011u -> + struct (Opcode.SMULcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Multiply Step *) + | 0b100100u -> + struct (Opcode.MULScc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Population Count *) + | 0b101110u -> struct (Opcode.POPC, parseTwoOpr b32 getSimm13 getRegRd) + (* SAVE and RESTORE *) + | 0b111100u -> + struct (Opcode.SAVE, parseThrOpr b32 getRegRs1 getSimm13Zero getRegRd) + | 0b111101u -> + struct (Opcode.RESTORE, parseThrOpr b32 getRegRs1 getSimm13Zero getRegRd) + (* Shift *) + | 0b100101u -> + match pickBit b32 12u with + | 0b0u -> + struct (Opcode.SLL, parseThrOpr b32 getRegRs1 getshcnt32 getRegRd) + | 0b1u -> + struct (Opcode.SLLX, parseThrOpr b32 getRegRs1 getshcnt64 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b100110u -> + match pickBit b32 12u with + | 0b0u -> + struct (Opcode.SRL, parseThrOpr b32 getRegRs1 getshcnt32 getRegRd) + | 0b1u -> + struct (Opcode.SRLX, parseThrOpr b32 getRegRs1 getshcnt64 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b100111u -> + match pickBit b32 12u with + | 0b0u -> + struct (Opcode.SRA, parseThrOpr b32 getRegRs1 getshcnt32 getRegRd) + | 0b1u -> + struct (Opcode.SRAX, parseThrOpr b32 getRegRs1 getshcnt64 getRegRd) + | _ -> struct (Opcode.InvalidOp, NoOperand) + (* Subtract *) + | 0b000100u -> + struct (Opcode.SUB, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b010100u -> + struct (Opcode.SUBcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b001100u -> + struct (Opcode.SUBC, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b011100u -> + struct (Opcode.SUBCcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Tagged Add *) + | 0b100000u -> + struct (Opcode.TADDcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b100010u -> + struct (Opcode.TADDccTV, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Tagged Subtract *) + | 0b100001u -> + struct (Opcode.TSUBcc, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b100011u -> + struct (Opcode.TSUBccTV, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + (* Write Privileged Register *) + | 0b110010u -> + struct (Opcode.WRPR, parseThrOpr b32 getRegRs1 getSimm13 priregWRPR) + (* Read Privileged Register *) + | 0b101010u -> struct (Opcode.RDPR, parseTwoOpr b32 priregRDPR getRegRd) + (* Write State Register *) + | 0b110000u -> parse110000 b32 + (* Move Integer Register on Condition *) + | 0b101100u -> parse101100 b32 + (* Move Integer Register on Register Condition *) + | 0b101111u -> parse101111 b32 + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 11r_ __d- ---- ---- + ---- ---- ---- ---- +*) +let parse11rd b32 = + match pickBit b32 13u with + | 0b0u -> + match extract b32 24u 19u with + | 0b011111u -> struct (Opcode.SWAPA, parseFourOpr b32 getAddrRs1 + getAddrRs2 getImmAsi getRegRd) + | 0b001111u -> struct ( + Opcode.SWAP, + parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd + ) + | 0b010101u -> + struct ( + Opcode.STBA, + parseFourOpr b32 getRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b010110u -> + struct ( + Opcode.STHA, + parseFourOpr b32 getRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b010100u -> + struct ( + Opcode.STWA, + parseFourOpr b32 getRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b011110u -> + struct ( + Opcode.STXA, + parseFourOpr b32 getRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b010111u -> + struct ( + Opcode.STDA, + parseFourOpr b32 getRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b000101u -> + struct (Opcode.STB, parseThrOpr b32 getRegRd getAddrRs1 getAddrRs2) + | 0b000110u -> + struct (Opcode.STH, parseThrOpr b32 getRegRd getAddrRs1 getAddrRs2) + | 0b000100u -> + struct (Opcode.STW, parseThrOpr b32 getRegRd getAddrRs1 getAddrRs2) + | 0b001110u -> + struct (Opcode.STX, parseThrOpr b32 getRegRd getAddrRs1 getAddrRs2) + | 0b000111u -> + struct (Opcode.STD, parseThrOpr b32 getRegRd getAddrRs1 getAddrRs2) + | 0b110100u -> + struct ( + Opcode.STFA, + parseFourOpr b32 getFloatRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b110111u -> + struct ( + Opcode.STDFA, + parseFourOpr b32 getDPFloatRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b110110u -> + struct ( + Opcode.STQFA, + parseFourOpr b32 getQPFloatRegRd getAddrRs1 getAddrRs2 getImmAsi + ) + | 0b100100u -> + struct ( + Opcode.STF, + parseThrOpr b32 getFloatRegRd getAddrRs1 getAddrRs2 + ) + | 0b100111u -> + struct ( + Opcode.STDF, + parseThrOpr b32 getDPFloatRegRd getAddrRs1 getAddrRs2 + ) + | 0b100110u -> + struct ( + Opcode.STQF, + parseThrOpr b32 getQPFloatRegRd getAddrRs1 getAddrRs2 + ) + | 0b100101u -> + match extract b32 29u 25u with + | 0b00000u -> + struct ( + Opcode.STFSR, + parseOneRegTwoOpr b32 (setPriReg R.FSR) getAddrRs1 getAddrRs2 + ) + | 0b00001u -> + struct ( + Opcode.STXFSR, + parseOneRegTwoOpr b32 (setPriReg R.FSR) getAddrRs1 getAddrRs2 + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b111100u -> + struct ( + Opcode.CASA, + parseFourOpr b32 getRegRs1 getImmAsi getRegRs2 getRegRd + ) + | 0b111110u -> + struct ( + Opcode.CASXA, + parseFourOpr b32 getRegRs1 getImmAsi getRegRs2 getRegRd + ) + | 0b100000u -> + struct ( + Opcode.LDF, + parseThrOpr b32 getAddrRs1 getAddrRs2 getFloatRegRd + ) + | 0b100011u -> + struct ( + Opcode.LDDF, + parseThrOpr b32 getAddrRs1 getAddrRs2 getDPFloatRegRd + ) + | 0b100010u -> + struct ( + Opcode.LDQF, + parseThrOpr b32 getAddrRs1 getAddrRs2 getQPFloatRegRd + ) + | 0b100001u -> + match extract b32 29u 25u with + | 0b00000u -> + struct ( + Opcode.LDFSR, + parseTwoOprOneReg b32 getAddrRs1 getAddrRs2 (setPriReg R.FSR) + ) + | 0b00001u -> + struct ( + Opcode.LDXFSR, + parseTwoOprOneReg b32 getAddrRs1 getAddrRs2 (setPriReg R.FSR) + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b110000u -> + struct ( + Opcode.LDFA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getFloatRegRd + ) + | 0b110011u -> + struct ( + Opcode.LDDFA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getDPFloatRegRd + ) + | 0b110010u -> + struct ( + Opcode.LDQFA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getQPFloatRegRd + ) + | 0b001001u -> + struct (Opcode.LDSB, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b001010u -> + struct (Opcode.LDSH, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b001000u -> + struct (Opcode.LDSW, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b000001u -> + struct (Opcode.LDUB, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b000010u -> + struct (Opcode.LDUH, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b000000u -> + struct (Opcode.LDUW, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b001011u -> + struct (Opcode.LDX, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b000011u -> + struct (Opcode.LDD, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b011001u -> + struct ( + Opcode.LDSBA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b011010u -> + struct ( + Opcode.LDSHA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b011000u -> + struct ( + Opcode.LDSWA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b010001u -> + struct ( + Opcode.LDUBA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b010010u -> + struct ( + Opcode.LDUHA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b010000u -> + struct ( + Opcode.LDUWA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b011011u -> + struct ( + Opcode.LDXA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b010011u -> + struct ( + Opcode.LDDA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | 0b001101u -> + struct (Opcode.LDSTUB, parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd) + | 0b011101u -> + struct ( + Opcode.LDSTUBA, + parseFourOpr b32 getAddrRs1 getAddrRs2 getImmAsi getRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u -> + match extract b32 24u 19u with + | 0b011111u -> struct (Opcode.SWAPA, parseFourOpr b32 getRegRs1 + getSimm13 getRegAsi getRegRd) + | 0b001111u -> struct ( + Opcode.SWAP, + parseThrOpr b32 getAddrRs1 getAddrRs2 getRegRd + ) + | 0b010101u -> + struct ( + Opcode.STBA, + parseFourOpr b32 getRegRd getAddrRs1 + getAddrSimm13 getRegAsi + ) + | 0b010110u -> + struct ( + Opcode.STHA, + parseFourOpr b32 getRegRd getAddrRs1 + getAddrSimm13 getRegAsi + ) + | 0b010100u -> + struct ( + Opcode.STWA, + parseFourOpr b32 getRegRd getAddrRs1 + getAddrSimm13 getRegAsi + ) + | 0b011110u -> + struct ( + Opcode.STXA, + parseFourOpr b32 getRegRd getAddrRs1 + getAddrSimm13 getRegAsi + ) + | 0b010111u -> + struct ( + Opcode.STDA, + parseFourOpr b32 getRegRd getAddrRs1 + getAddrSimm13 getRegAsi + ) + | 0b000101u -> + struct (Opcode.STB, parseThrOpr b32 getRegRd getAddrRs1 getAddrSimm13) + | 0b000110u -> + struct (Opcode.STH, parseThrOpr b32 getRegRd getAddrRs1 getAddrSimm13) + | 0b000100u -> + struct (Opcode.STW, parseThrOpr b32 getRegRd getAddrRs1 getAddrSimm13) + | 0b001110u -> + struct (Opcode.STX, parseThrOpr b32 getRegRd getAddrRs1 getAddrSimm13) + | 0b000111u -> + struct (Opcode.STD, parseThrOpr b32 getRegRd getAddrRs1 getAddrSimm13) + | 0b110100u -> + struct ( + Opcode.STFA, + parseSTXA b32 getFloatRegRd getAddrRs1 getAddrSimm13 (setPriReg R.ASI) + ) + | 0b110111u -> + struct ( + Opcode.STDFA, + parseSTXA b32 getDPFloatRegRd getAddrRs1 getAddrSimm13 (setPriReg R.ASI) + ) + | 0b110110u -> + struct ( + Opcode.STQFA, + parseSTXA b32 getQPFloatRegRd getAddrRs1 getAddrSimm13 (setPriReg R.ASI) + ) + | 0b100100u -> + struct ( + Opcode.STF, + parseThrOpr b32 getFloatRegRd getAddrRs1 getAddrSimm13 + ) + | 0b100111u -> + struct ( + Opcode.STDF, + parseThrOpr b32 getDPFloatRegRd getAddrRs1 getAddrSimm13 + ) + | 0b100110u -> + struct ( + Opcode.STQF, + parseThrOpr b32 getQPFloatRegRd getAddrRs1 getAddrSimm13 + ) + | 0b100101u -> + match extract b32 29u 25u with + | 0b00000u -> + struct ( + Opcode.STFSR, + parseOneRegTwoOpr b32 (setPriReg R.FSR) getAddrRs1 getAddrSimm13 + ) + | 0b00001u -> + struct ( + Opcode.STXFSR, + parseOneRegTwoOpr b32 (setPriReg R.FSR) getAddrRs1 getAddrSimm13 + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b111100u -> + struct ( + Opcode.CASA, + parseFourOpr b32 getRegRs1 getRegAsi getRegRs2 getRegRd + ) + | 0b111110u -> + struct ( + Opcode.CASXA, + parseFourOpr b32 getRegRs1 getRegAsi getRegRs2 getRegRd + ) + | 0b100000u -> + struct ( + Opcode.LDF, + parseThrOpr b32 getAddrRs1 getAddrSimm13 getFloatRegRd + ) + | 0b100011u -> + struct ( + Opcode.LDDF, + parseThrOpr b32 getAddrRs1 getAddrSimm13 getDPFloatRegRd + ) + | 0b100010u -> + struct ( + Opcode.LDQF, + parseThrOpr b32 getAddrRs1 getAddrSimm13 getQPFloatRegRd + ) + | 0b100001u -> + match extract b32 29u 25u with + | 0b00000u -> + struct ( + Opcode.LDFSR, + parseTwoOprOneReg b32 getAddrRs1 getAddrSimm13 + (setPriReg R.FSR) + ) + | 0b00001u -> + struct ( + Opcode.LDXFSR, + parseTwoOprOneReg b32 getAddrRs1 getAddrSimm13 + (setPriReg R.FSR) + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b110000u -> + struct ( + Opcode.LDFA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getFloatRegRd + ) + | 0b110011u -> + struct ( + Opcode.LDDFA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getDPFloatRegRd) + | 0b110010u -> + struct ( + Opcode.LDQFA, + parseThrOprOneReg b32 getAddrRs1 getAddrSimm13 + (setPriReg R.ASI) getQPFloatRegRd + ) + + | 0b001001u -> + struct (Opcode.LDSB, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b001010u -> + struct (Opcode.LDSH, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b001000u -> + struct (Opcode.LDSW, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b000001u -> + struct (Opcode.LDUB, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b000010u -> + struct (Opcode.LDUH, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b000000u -> + struct (Opcode.LDUW, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b001011u -> + struct (Opcode.LDX, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b000011u -> + struct (Opcode.LDD, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b011001u -> + struct ( + Opcode.LDSBA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b011010u -> + struct ( + Opcode.LDSHA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b011000u -> + struct ( + Opcode.LDSWA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b010001u -> + struct ( + Opcode.LDUBA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b010010u -> + struct ( + Opcode.LDUHA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b010000u -> + struct ( + Opcode.LDUWA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b011011u -> + struct ( + Opcode.LDXA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b010011u -> + struct ( + Opcode.LDDA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | 0b001101u -> + struct (Opcode.LDSTUB, parseThrOpr b32 getAddrRs1 getAddrSimm13 getRegRd) + | 0b011101u -> + struct ( + Opcode.LDSTUBA, + parseFourOpr b32 getAddrRs1 getAddrSimm13 + getRegAsi getRegRd + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 00-- ---- ---- ---- + ---- ---- ---- ---- +*) +let parse00 b32 = + match extract b32 24u 22u with + | 0b000u -> struct (Opcode.ILLTRAP, parseOneOpr b32 getConst22) + | 0b100u -> + match extract b32 29u 25u with + | 0b00000u -> struct (Opcode.NOP, NoOperand) + | _ -> struct (Opcode.SETHI, parseTwoOpr b32 getimm22 getRegRd) + | 0b110u -> + match extract b32 28u 25u with + | 0b1000u -> struct (Opcode.FBA, parseTwoOpr b32 getAbit getdisp22) + | 0b0000u -> struct (Opcode.FBN, parseTwoOpr b32 getAbit getdisp22) + | 0b0111u -> struct (Opcode.FBU, parseTwoOpr b32 getAbit getdisp22) + | 0b0110u -> struct (Opcode.FBG, parseTwoOpr b32 getAbit getdisp22) + | 0b0101u -> struct (Opcode.FBUG, parseTwoOpr b32 getAbit getdisp22) + | 0b0100u -> struct (Opcode.FBL, parseTwoOpr b32 getAbit getdisp22) + | 0b0011u -> struct (Opcode.FBUL, parseTwoOpr b32 getAbit getdisp22) + | 0b0010u -> struct (Opcode.FBLG, parseTwoOpr b32 getAbit getdisp22) + | 0b0001u -> struct (Opcode.FBNE, parseTwoOpr b32 getAbit getdisp22) + | 0b1001u -> struct (Opcode.FBE, parseTwoOpr b32 getAbit getdisp22) + | 0b1010u -> struct (Opcode.FBUE, parseTwoOpr b32 getAbit getdisp22) + | 0b1011u -> struct (Opcode.FBGE, parseTwoOpr b32 getAbit getdisp22) + | 0b1100u -> struct (Opcode.FBUGE, parseTwoOpr b32 getAbit getdisp22) + | 0b1101u -> struct (Opcode.FBLE, parseTwoOpr b32 getAbit getdisp22) + | 0b1110u -> struct (Opcode.FBULE, parseTwoOpr b32 getAbit getdisp22) + | 0b1111u -> struct (Opcode.FBO, parseTwoOpr b32 getAbit getdisp22) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b101u -> + match extract b32 28u 25u with + | 0b1000u -> + struct ( + Opcode.FBPA, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0000u -> + struct ( + Opcode.FBPN, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0111u -> + struct ( + Opcode.FBPU, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0110u -> + struct ( + Opcode.FBPG, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0101u -> + struct ( + Opcode.FBPUG, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0100u -> + struct ( + Opcode.FBPL, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0011u -> + struct ( + Opcode.FBPUL, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0010u -> + struct ( + Opcode.FBPLG, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0001u -> + struct ( + Opcode.FBPNE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1001u -> + struct ( + Opcode.FBPE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1010u -> + struct ( + Opcode.FBPUE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1011u -> + struct ( + Opcode.FBPGE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1100u -> + struct ( + Opcode.FBPUGE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1101u -> + struct ( + Opcode.FBPLE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1110u -> + struct ( + Opcode.FBPULE, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1111u -> + struct ( + Opcode.FBPO, + parseOneCCThrOpr + b32 + (getTwoCCFcc (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b010u -> + match extract b32 28u 25u with + | 0b1000u -> struct (Opcode.BA, parseTwoOpr b32 getAbit getdisp22) + | 0b0000u -> struct (Opcode.BN, parseTwoOpr b32 getAbit getdisp22) + | 0b1001u -> struct (Opcode.BNE, parseTwoOpr b32 getAbit getdisp22) + | 0b0001u -> struct (Opcode.BE, parseTwoOpr b32 getAbit getdisp22) + | 0b1010u -> struct (Opcode.BG, parseTwoOpr b32 getAbit getdisp22) + | 0b0010u -> struct (Opcode.BLE, parseTwoOpr b32 getAbit getdisp22) + | 0b1011u -> struct (Opcode.BGE, parseTwoOpr b32 getAbit getdisp22) + | 0b0011u -> struct (Opcode.BL, parseTwoOpr b32 getAbit getdisp22) + | 0b1100u -> struct (Opcode.BGU, parseTwoOpr b32 getAbit getdisp22) + | 0b0100u -> struct (Opcode.BLEU, parseTwoOpr b32 getAbit getdisp22) + | 0b1101u -> struct (Opcode.BCC, parseTwoOpr b32 getAbit getdisp22) + | 0b0101u -> struct (Opcode.BCS, parseTwoOpr b32 getAbit getdisp22) + | 0b1110u -> struct (Opcode.BPOS, parseTwoOpr b32 getAbit getdisp22) + | 0b0110u -> struct (Opcode.BNEG, parseTwoOpr b32 getAbit getdisp22) + | 0b1111u -> struct (Opcode.BVC, parseTwoOpr b32 getAbit getdisp22) + | 0b0111u -> struct (Opcode.BVS, parseTwoOpr b32 getAbit getdisp22) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b001u -> + match extract b32 28u 25u with + | 0b1000u -> + struct ( + Opcode.BPA, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0000u -> + struct ( + Opcode.BPN, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1001u -> + struct ( + Opcode.BPNE, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0001u -> + struct ( + Opcode.BPE, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1010u -> + struct ( + Opcode.BPG, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0010u -> + struct ( + Opcode.BPLE, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1011u -> + struct ( + Opcode.BPGE, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0011u -> + struct ( + Opcode.BPL, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1100u -> + struct ( + Opcode.BPGU, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0100u -> + struct ( + Opcode.BPLEU, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1101u -> + struct ( + Opcode.BPCC, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0101u -> + struct ( + Opcode.BPCS, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1110u -> + struct ( + Opcode.BPPOS, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0110u -> + struct ( + Opcode.BPNEG, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b1111u -> + struct ( + Opcode.BPVC, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | 0b0111u -> + struct ( + Opcode.BPVS, + parseOneCCThrOpr + b32 + (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + getdisp19 + getAbit + getPbit + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b011u -> + match extract b32 27u 25u with + | 0b001u -> + struct ( + Opcode.BRZ, + parseFourOpr + b32 + getRegRs1 + getd16 + getAbit + getPbit + ) + | 0b010u -> + struct ( + Opcode.BRLEZ, + parseFourOpr + b32 + getRegRs1 + getd16 + getAbit + getPbit + ) + | 0b011u -> + struct ( + Opcode.BRLZ, + parseFourOpr + b32 + getRegRs1 + getd16 + getAbit + getPbit + ) + | 0b101u -> + struct ( + Opcode.BRNZ, + parseFourOpr + b32 + getRegRs1 + getd16 + getAbit + getPbit + ) + | 0b110u -> + struct ( + Opcode.BRGZ, + parseFourOpr + b32 + getRegRs1 + getd16 + getAbit + getPbit + ) + | 0b111u -> + struct ( + Opcode.BRGEZ, + parseFourOpr + b32 + getRegRs1 + getd16 + getAbit + getPbit + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + +(* + 10-- ---- ---- ---- + ---- ---- ---- ---- +*) +let parse10 b32 = + match extract b32 24u 19u with + | 0b111010u -> + match pickBit b32 13u with + | 0b0u -> + match extract b32 28u 25u with + | 0b1000u -> + struct ( + Opcode.TA, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0000u -> + struct ( + Opcode.TN, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1001u -> + struct ( + Opcode.TNE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0001u -> + struct ( + Opcode.TE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1010u -> + struct ( + Opcode.TG, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0010u -> + struct ( + Opcode.TLE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1011u -> + struct ( + Opcode.TGE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0011u -> + struct ( + Opcode.TL, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1100u -> + struct ( + Opcode.TGU, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0100u -> + struct ( + Opcode.TLEU, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1101u -> + struct ( + Opcode.TCC, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0101u -> + struct ( + Opcode.TCS, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1110u -> + struct ( + Opcode.TPOS, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0110u -> + struct ( + Opcode.TNEG, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32))) + | 0b1111u -> + struct ( + Opcode.TVC, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0111u -> + struct ( + Opcode.TVS, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b1u -> + match extract b32 28u 25u with + | 0b1000u -> + struct ( + Opcode.TA, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0000u -> + struct ( + Opcode.TN, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1001u -> + struct ( + Opcode.TNE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0001u -> + struct ( + Opcode.TE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1010u -> + struct ( + Opcode.TG, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0010u -> + struct ( + Opcode.TLE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1011u -> + struct ( + Opcode.TGE, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0011u -> + struct ( + Opcode.TL, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1100u -> + struct ( + Opcode.TGU, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0100u -> + struct ( + Opcode.TLEU, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1101u -> + struct ( + Opcode.TCC, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0101u -> + struct ( + Opcode.TCS, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1110u -> + struct (Opcode.TPOS, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32))) + | 0b0110u -> + struct ( + Opcode.TNEG, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b1111u -> + struct ( + Opcode.TVC, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | 0b0111u -> + struct ( + Opcode.TVS, + parseOneCC (getTwoCCix (get21cc1 b32) (get20cc0 b32)) + ) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b101000u -> + match pickBit b32 13u with + | 0b0u -> parse101000 b32 + | _ -> + match pickBit b32 25u with + | 0u -> + match pickBit b32 13u with + | 0b0u -> struct (Opcode.STBAR, NoOperand) + | 0b1u -> struct (Opcode.MEMBAR, parseOneOpr b32 getMembarMask) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b110000u -> parse110000 b32 + | 0b110001u -> + match pickBit b32 25u with + | 0u -> struct (Opcode.SAVED, NoOperand) + | 1u -> struct (Opcode.RESTORED, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b111001u -> + match pickBit b32 13u with + | 0b0u -> struct (Opcode.RETURN, parseTwoOpr b32 getRegRs1 getRegRs2) + | 0b1u -> struct (Opcode.RETURN, parseTwoOpr b32 getRegRs1 getSimm13) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b111110u -> + match pickBit b32 25u with + | 0u -> struct (Opcode.DONE, NoOperand) + | 1u -> struct (Opcode.RETRY, NoOperand) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b110101u -> + match extract b32 13u 5u with + | 0b001010001u -> + struct ( + Opcode.FCMPs, + parseOneCCTwoOpr b32 (getTwoCCFcc (get26cc1 b32) (get25cc0 b32)) + getFloatRegRs1 + getFloatRegRs2 + ) + | 0b001010010u -> + struct (Opcode.FCMPd, + parseOneCCTwoOpr + b32 + (getTwoCCFcc (get26cc1 b32) (get25cc0 b32)) + getDPFloatRegRs1 + getDPFloatRegRs2) + | 0b001010011u -> + struct ( + Opcode.FCMPq, + parseOneCCTwoOpr b32 (getTwoCCFcc (get26cc1 b32) (get25cc0 b32)) + getQPFloatRegRs1 + getQPFloatRegRs2 + ) + | 0b001010101u -> + struct ( + Opcode.FCMPEs, + parseOneCCTwoOpr b32 (getTwoCCFcc (get26cc1 b32) (get25cc0 b32)) + getFloatRegRs1 + getFloatRegRs2 + ) + | 0b001010110u -> + struct ( + Opcode.FCMPEd, + parseOneCCTwoOpr b32 (getTwoCCFcc (get26cc1 b32) (get25cc0 b32)) + getDPFloatRegRs1 getDPFloatRegRs2 + ) + | 0b001010111u -> + struct ( + Opcode.FCMPEq, + parseOneCCTwoOpr b32 (getTwoCCFcc (get26cc1 b32) (get25cc0 b32)) + getQPFloatRegRs1 + getQPFloatRegRs2 + ) + | _ -> parse110101 b32 + | 0b111011u -> + match pickBit b32 13u with + | 0b0u -> struct (Opcode.FLUSH, parseTwoOpr b32 getRegRs1 getRegRs2) + | 0b1u -> struct (Opcode.FLUSH, parseTwoOpr b32 getRegRs1 getSimm13) + | _ -> struct (Opcode.InvalidOp, NoOperand) + | 0b101011u -> struct (Opcode.FLUSHW, NoOperand) + | 0b110110u -> struct (Opcode.IMPDEP1, parseOneOpr b32 getImplDep) + | 0b110111u -> struct (Opcode.IMPDEP2, parseOneOpr b32 getImplDep) + | _ -> parse10rd b32 + +(* + 11-- ---- ---- ---- + ---- ---- ---- ---- +*) +let parse11 b32 = + match pickBit b32 13u with + | 0b0u -> + match extract b32 24u 19u with + | 0b101101u -> + struct (Opcode.PREFETCH, parseThrOpr b32 getRegRs1 getRegRs2 getRegRd) + | 0b111101u -> + struct ( + Opcode.PREFETCHA, + parseFourOpr b32 getRegRs1 getRegRs2 getImmAsi getRegRd + ) + | _ -> parse11rd b32 + | 0b1u -> + match extract b32 24u 19u with + | 0b101101u -> + struct (Opcode.PREFETCH, parseThrOpr b32 getRegRs1 getSimm13 getRegRd) + | 0b111101u -> + struct ( + Opcode.PREFETCHA, + parseThrOprOneReg b32 getRegRs1 getSimm13 (setPriReg R.ASI) + getRegRd + ) + | _ -> parse11rd b32 + | _ -> parse11rd b32 + +let parseTwoBits bin = + match extract bin 31u 30u with + | 0b00u -> parse00 bin + | 0b01u -> struct (Opcode.CALL, parseOneOpr bin getdisp30) + | 0b10u -> parse10 bin + | 0b11u -> parse11 bin + | _ -> struct (Opcode.InvalidOp, NoOperand) + +let parse (span: ByteSpan) (reader: IBinReader) addr = + let bin = reader.ReadInt32 (span, 0) + let struct (op, operands) = uint32 bin |> parseTwoBits + let insInfo = + { Address = addr + NumBytes = 4u + Opcode = op + Operands = operands } + SPARCInstruction (addr, 4u, insInfo) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCRegExprs.fs b/src/FrontEnd/BinLifter/SPARC/SPARCRegExprs.fs new file mode 100644 index 00000000..de298bee --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCRegExprs.fs @@ -0,0 +1,257 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SPARC + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.BinIR.LowUIR + +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name + + (* Registers *) + let regType = WordSize.toRegType wordSize + let fRegType = WordSize.toRegType WordSize.Bit32 + + member val G0 = var regType (Register.toRegID Register.G0) "g0" with get + member val G1 = var regType (Register.toRegID Register.G1) "g1" with get + member val G2 = var regType (Register.toRegID Register.G2) "g2" with get + member val G3 = var regType (Register.toRegID Register.G3) "g3" with get + member val G4 = var regType (Register.toRegID Register.G4) "g4" with get + member val G5 = var regType (Register.toRegID Register.G1) "g5" with get + member val G6 = var regType (Register.toRegID Register.G6) "g6" with get + member val G7 = var regType (Register.toRegID Register.G1) "g7" with get + member val O0 = var regType (Register.toRegID Register.O0) "o0" with get + member val O1 = var regType (Register.toRegID Register.O1) "o1" with get + member val O2 = var regType (Register.toRegID Register.O2) "o2" with get + member val O3 = var regType (Register.toRegID Register.O3) "o3" with get + member val O4 = var regType (Register.toRegID Register.O4) "o4" with get + member val O5 = var regType (Register.toRegID Register.O5) "o5" with get + member val O6 = var regType (Register.toRegID Register.O6) "o6" with get + member val O7 = var regType (Register.toRegID Register.O7) "o7" with get + member val L0 = var regType (Register.toRegID Register.L0) "l0" with get + member val L1 = var regType (Register.toRegID Register.L1) "l1" with get + member val L2 = var regType (Register.toRegID Register.L2) "l2" with get + member val L3 = var regType (Register.toRegID Register.L3) "l3" with get + member val L4 = var regType (Register.toRegID Register.L4) "l4" with get + member val L5 = var regType (Register.toRegID Register.L5) "l5" with get + member val L6 = var regType (Register.toRegID Register.L6) "l6" with get + member val L7 = var regType (Register.toRegID Register.L7) "l7" with get + member val I0 = var regType (Register.toRegID Register.I0) "i0" with get + member val I1 = var regType (Register.toRegID Register.I1) "i1" with get + member val I2 = var regType (Register.toRegID Register.I2) "i2" with get + member val I3 = var regType (Register.toRegID Register.I3) "i3" with get + member val I4 = var regType (Register.toRegID Register.I4) "i4" with get + member val I5 = var regType (Register.toRegID Register.I5) "i5" with get + member val I6 = var regType (Register.toRegID Register.I6) "i6" with get + member val I7 = var regType (Register.toRegID Register.I7) "i7" with get + member val F0 = var fRegType (Register.toRegID Register.F0) "f0" with get + member val F1 = var fRegType (Register.toRegID Register.F1) "f1" with get + member val F2 = var fRegType (Register.toRegID Register.F2) "f2" with get + member val F3 = var fRegType (Register.toRegID Register.F3) "f3" with get + member val F4 = var fRegType (Register.toRegID Register.F4) "f4" with get + member val F5 = var fRegType (Register.toRegID Register.F5) "f5" with get + member val F6 = var fRegType (Register.toRegID Register.F6) "f6" with get + member val F7 = var fRegType (Register.toRegID Register.F7) "f7" with get + member val F8 = var fRegType (Register.toRegID Register.F8) "f8" with get + member val F9 = var fRegType (Register.toRegID Register.F9) "f9" with get + member val F10 = var fRegType (Register.toRegID Register.F10) "f10" with get + member val F11 = var fRegType (Register.toRegID Register.F11) "f11" with get + member val F12 = var fRegType (Register.toRegID Register.F12) "f12" with get + member val F13 = var fRegType (Register.toRegID Register.F13) "f13" with get + member val F14 = var fRegType (Register.toRegID Register.F14) "f14" with get + member val F15 = var fRegType (Register.toRegID Register.F15) "f15" with get + member val F16 = var fRegType (Register.toRegID Register.F16) "f16" with get + member val F17 = var fRegType (Register.toRegID Register.F17) "f17" with get + member val F18 = var fRegType (Register.toRegID Register.F18) "f18" with get + member val F19 = var fRegType (Register.toRegID Register.F19) "f19" with get + member val F20 = var fRegType (Register.toRegID Register.F20) "f20" with get + member val F21 = var fRegType (Register.toRegID Register.F21) "f21" with get + member val F22 = var fRegType (Register.toRegID Register.F22) "f22" with get + member val F23 = var fRegType (Register.toRegID Register.F23) "f23" with get + member val F24 = var fRegType (Register.toRegID Register.F24) "f24" with get + member val F25 = var fRegType (Register.toRegID Register.F25) "f25" with get + member val F26 = var fRegType (Register.toRegID Register.F26) "f26" with get + member val F27 = var fRegType (Register.toRegID Register.F27) "f27" with get + member val F28 = var fRegType (Register.toRegID Register.F28) "f28" with get + member val F29 = var fRegType (Register.toRegID Register.F29) "f29" with get + member val F30 = var fRegType (Register.toRegID Register.F30) "f30" with get + member val F31 = var fRegType (Register.toRegID Register.F31) "f31" with get + member val F32 = var regType (Register.toRegID Register.F32) "f32" with get + member val F34 = var regType (Register.toRegID Register.F34) "f34" with get + member val F36 = var regType (Register.toRegID Register.F36) "f36" with get + member val F38 = var regType (Register.toRegID Register.F38) "f38" with get + member val F40 = var regType (Register.toRegID Register.F40) "f40" with get + member val F42 = var regType (Register.toRegID Register.F42) "f42" with get + member val F44 = var regType (Register.toRegID Register.F44) "f44" with get + member val F46 = var regType (Register.toRegID Register.F46) "f46" with get + member val F48 = var regType (Register.toRegID Register.F48) "f48" with get + member val F50 = var regType (Register.toRegID Register.F50) "f50" with get + member val F52 = var regType (Register.toRegID Register.F52) "f52" with get + member val F54 = var regType (Register.toRegID Register.F54) "f54" with get + member val F56 = var regType (Register.toRegID Register.F56) "f56" with get + member val F58 = var regType (Register.toRegID Register.F58) "f58" with get + member val F60 = var regType (Register.toRegID Register.F60) "f60" with get + member val F62 = var regType (Register.toRegID Register.F62) "f62" with get + member val PC = var regType (Register.toRegID Register.PC) "PC" with get + member val NPC = var regType (Register.toRegID Register.NPC) "nPC" with get + member val Y = var regType (Register.toRegID Register.Y) "Y" with get + member val CCR = var regType (Register.toRegID Register.CCR) "CCR" with get + member val FSR = var regType (Register.toRegID Register.FSR) "FSR" with get + member val ASI = var regType (Register.toRegID Register.ASI) "ASI" with get + member val ASRs = var regType (Register.toRegID Register.ASRs) "ASRs" with get + member val FPRS = var regType (Register.toRegID Register.FPRS) "FPRS" with get + member val TICK = var regType (Register.toRegID Register.TICK) "TICK" with get + member val PSTATE = + var regType (Register.toRegID Register.PSTATE) "PSTATE" with get + member val TL = var regType (Register.toRegID Register.TL) "TL" with get + member val PIL = var regType (Register.toRegID Register.PIL) "PIL" with get + member val TPC = var regType (Register.toRegID Register.TPC) "TPC" with get + member val TNPC = var regType (Register.toRegID Register.TNPC) "TNPC" with get + member val TSTATE = + var regType (Register.toRegID Register.TSTATE) "TSTATE" with get + member val TT = var regType (Register.toRegID Register.TT) "TT" with get + member val TBA = var regType (Register.toRegID Register.TBA) "TBA" with get + member val VER = var regType (Register.toRegID Register.VER) "VER" with get + member val CWP = var regType (Register.toRegID Register.CWP) "CWP" with get + member val CANSAVE = + var regType (Register.toRegID Register.CANSAVE) "CANSAVE" with get + member val CANRESTORE = + var regType (Register.toRegID Register.CANRESTORE) "CANRESTORE" with get + member val OTHERWIN = + var regType (Register.toRegID Register.OTHERWIN) "OTHERWIN" with get + member val WSTATE = + var regType (Register.toRegID Register.WSTATE) "WSTATE" with get + member val FQ = var regType (Register.toRegID Register.FQ) "FQ" with get + member val CLEANWIN = + var regType (Register.toRegID Register.CLEANWIN) "CLEANWIN" with get + + member __.GetRegVar (name) = + match name with + | R.G0 -> __.G0 + | R.G1 -> __.G1 + | R.G2 -> __.G2 + | R.G3 -> __.G3 + | R.G4 -> __.G4 + | R.G5 -> __.G5 + | R.G6 -> __.G6 + | R.G7 -> __.G7 + | R.O0 -> __.O0 + | R.O1 -> __.O1 + | R.O2 -> __.O2 + | R.O3 -> __.O3 + | R.O4 -> __.O4 + | R.O5 -> __.O5 + | R.O6 -> __.O6 + | R.O7 -> __.O7 + | R.L0 -> __.L0 + | R.L1 -> __.L1 + | R.L2 -> __.L2 + | R.L3 -> __.L3 + | R.L4 -> __.L4 + | R.L5 -> __.L5 + | R.L6 -> __.L6 + | R.L7 -> __.L7 + | R.I0 -> __.I0 + | R.I1 -> __.I1 + | R.I2 -> __.I2 + | R.I3 -> __.I3 + | R.I4 -> __.I4 + | R.I5 -> __.I5 + | R.I6 -> __.I6 + | R.I7 -> __.I7 + | R.PC -> __.PC + | R.CCR -> __.CCR + | R.FSR -> __.FSR + | R.Y -> __.Y + | R.F0 -> __.F0 + | R.F1 -> __.F1 + | R.F2 -> __.F2 + | R.F3 -> __.F3 + | R.F4 -> __.F4 + | R.F5 -> __.F5 + | R.F6 -> __.F6 + | R.F7 -> __.F7 + | R.F8 -> __.F8 + | R.F9 -> __.F9 + | R.F10 -> __.F10 + | R.F11 -> __.F11 + | R.F12 -> __.F12 + | R.F13 -> __.F13 + | R.F14 -> __.F14 + | R.F15 -> __.F15 + | R.F16 -> __.F16 + | R.F17 -> __.F17 + | R.F18 -> __.F18 + | R.F19 -> __.F19 + | R.F20 -> __.F20 + | R.F21 -> __.F21 + | R.F22 -> __.F22 + | R.F23 -> __.F23 + | R.F24 -> __.F24 + | R.F25 -> __.F25 + | R.F26 -> __.F26 + | R.F27 -> __.F27 + | R.F28 -> __.F28 + | R.F29 -> __.F29 + | R.F30 -> __.F30 + | R.F31 -> __.F31 + | R.F32 -> __.F32 + | R.F34 -> __.F34 + | R.F36 -> __.F36 + | R.F38 -> __.F38 + | R.F40 -> __.F40 + | R.F42 -> __.F42 + | R.F44 -> __.F44 + | R.F46 -> __.F46 + | R.F48 -> __.F48 + | R.F50 -> __.F50 + | R.F52 -> __.F52 + | R.F54 -> __.F54 + | R.F56 -> __.F56 + | R.F58 -> __.F58 + | R.F60 -> __.F60 + | R.F62 -> __.F62 + | R.ASI -> __.ASI + | R.ASRs -> __.ASRs + | R.FPRS -> __.FPRS + | R.TICK -> __.TICK + | R.PSTATE -> __.PSTATE + | R.TL -> __.TL + | R.PIL -> __.PIL + | R.TPC -> __.TPC + | R.TNPC -> __.TNPC + | R.TSTATE -> __.TSTATE + | R.TT -> __.TT + | R.TBA -> __.TBA + | R.VER -> __.VER + | R.CWP -> __.CWP + | R.CANSAVE -> __.CANSAVE + | R.CANRESTORE -> __.CANRESTORE + | R.OTHERWIN -> __.OTHERWIN + | R.WSTATE -> __.WSTATE + | R.FQ -> __.FQ + | R.CLEANWIN -> __.CLEANWIN + | _ -> raise UnhandledRegExprException diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCRegister.fs b/src/FrontEnd/BinLifter/SPARC/SPARCRegister.fs new file mode 100644 index 00000000..d8c36ce3 --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCRegister.fs @@ -0,0 +1,364 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SPARC + +open B2R2 + +type Register = + | G0 = 0x0 + | G1 = 0x1 + | G2 = 0x2 + | G3 = 0x3 + | G4 = 0x4 + | G5 = 0x5 + | G6 = 0x6 + | G7 = 0x7 + | O0 = 0x8 + | O1 = 0x9 + | O2 = 0xA + | O3 = 0xB + | O4 = 0xC + | O5 = 0xD + | O6 = 0xE + | O7 = 0xF + | L0 = 0x10 + | L1 = 0x11 + | L2 = 0x12 + | L3 = 0x13 + | L4 = 0x14 + | L5 = 0x15 + | L6 = 0x16 + | L7 = 0x17 + | I0 = 0x18 + | I1 = 0x19 + | I2 = 0x1A + | I3 = 0x1B + | I4 = 0x1C + | I5 = 0x1D + | I6 = 0x1E + | I7 = 0x1F + | PC = 0x20 + | NPC = 0x21 + | Y = 0x22 + | ASRs = 0x23 + | CCR = 0x24 + | FPRS = 0x25 + | FSR = 0x26 + | ASI = 0x27 + | TICK = 0x28 + | PSTATE = 0x29 + | TL = 0x2A + | PIL = 0x2B + | TPC = 0x2C + | TNPC = 0x2D + | TSTATE = 0x2E + | TT = 0x2F + | TBA = 0x30 + | VER = 0x31 + | CWP = 0x32 + | CANSAVE = 0x33 + | CANRESTORE = 0x34 + | OTHERWIN = 0x35 + | WSTATE = 0x36 + | FQ = 0x37 + | CLEANWIN = 0x38 + | F0 = 0x39 + | F1 = 0x3a + | F2 = 0x3b + | F3 = 0x3c + | F4 = 0x3d + | F5 = 0x3e + | F6 = 0x3f + | F7 = 0x40 + | F8 = 0x41 + | F9 = 0x42 + | F10 = 0x43 + | F11 = 0x44 + | F12 = 0x45 + | F13 = 0x46 + | F14 = 0x47 + | F15 = 0x48 + | F16 = 0x49 + | F17 = 0x4a + | F18 = 0x4b + | F19 = 0x4c + | F20 = 0x4d + | F21 = 0x4e + | F22 = 0x4f + | F23 = 0x50 + | F24 = 0x51 + | F25 = 0x52 + | F26 = 0x53 + | F27 = 0x54 + | F28 = 0x55 + | F29 = 0x56 + | F30 = 0x57 + | F31 = 0x58 + | F32 = 0x59 + | F34 = 0x5a + | F36 = 0x5b + | F38 = 0x5c + | F40 = 0x5d + | F42 = 0x5e + | F44 = 0x5f + | F46 = 0x60 + | F48 = 0x61 + | F50 = 0x62 + | F52 = 0x63 + | F54 = 0x64 + | F56 = 0x65 + | F58 = 0x66 + | F60 = 0x67 + | F62 = 0x68 + +/// Shortcut for Register type. +type internal R = Register + +/// This module exposes several useful functions to handle SPARC +/// registers. +[] +module Register = + let inline ofRegID (n: RegisterID): Register = + int n |> LanguagePrimitives.EnumOfValue + + let inline toRegID (reg: Register) = + LanguagePrimitives.EnumToValue (reg) |> RegisterID.create + + let ofString (str: string) = + match str.ToLowerInvariant () with + | "g0" -> R.G0 + | "g1" -> R.G1 + | "g2" -> R.G2 + | "g3" -> R.G3 + | "g4" -> R.G4 + | "g5" -> R.G5 + | "g6" -> R.G6 + | "g7" -> R.G7 + | "o0" -> R.O0 + | "o1" -> R.O1 + | "o2" -> R.O2 + | "o3" -> R.O3 + | "o4" -> R.O4 + | "o5" -> R.O5 + | "o6" -> R.O6 + | "o7" -> R.O7 + | "l0" -> R.L0 + | "l1" -> R.L1 + | "l2" -> R.L2 + | "l3" -> R.L3 + | "l4" -> R.L4 + | "l5" -> R.L5 + | "l6" -> R.L6 + | "l7" -> R.L7 + | "i0" -> R.I0 + | "i1" -> R.I1 + | "i2" -> R.I2 + | "i3" -> R.I3 + | "i4" -> R.I4 + | "i5" -> R.I5 + | "i6" -> R.I6 + | "i7" -> R.I7 + | "pc" -> R.PC + | "npc" -> R.NPC + | "y" -> R.Y + | "asrs" -> R.ASRs + | "ccr" -> R.CCR + | "fprs" -> R.FPRS + | "fsr" -> R.FSR + | "asi" -> R.ASI + | "tick" -> R.TICK + | "pstate" -> R.PSTATE + | "tl" -> R.TL + | "pil" -> R.PIL + | "tpc" -> R.TPC + | "tnpc" -> R.TNPC + | "tstate" -> R.TSTATE + | "tt" -> R.TT + | "tba" -> R.TBA + | "ver" -> R.VER + | "cwp" -> R.CWP + | "cansave" -> R.CANSAVE + | "canrestore" -> R.CANRESTORE + | "otherwin" -> R.OTHERWIN + | "wstate" -> R.WSTATE + | "fq" -> R.FQ + | "cleanwin" -> R.CLEANWIN + | "f0" -> R.F0 + | "f1" -> R.F1 + | "f2" -> R.F2 + | "f3" -> R.F3 + | "f4" -> R.F4 + | "f5" -> R.F5 + | "f6" -> R.F6 + | "f7" -> R.F7 + | "f8" -> R.F8 + | "f9" -> R.F9 + | "f10" -> R.F10 + | "f11" -> R.F11 + | "f12" -> R.F12 + | "f13" -> R.F13 + | "f14" -> R.F14 + | "f15" -> R.F15 + | "f16" -> R.F16 + | "f17" -> R.F17 + | "f18" -> R.F18 + | "f19" -> R.F19 + | "f20" -> R.F20 + | "f21" -> R.F21 + | "f22" -> R.F22 + | "f23" -> R.F23 + | "f24" -> R.F24 + | "f25" -> R.F25 + | "f26" -> R.F26 + | "f27" -> R.F27 + | "f28" -> R.F28 + | "f29" -> R.F29 + | "f30" -> R.F30 + | "f31" -> R.F31 + | "f32" -> R.F32 + | "f34" -> R.F34 + | "f36" -> R.F36 + | "f38" -> R.F38 + | "f40" -> R.F40 + | "f42" -> R.F42 + | "f44" -> R.F44 + | "f46" -> R.F46 + | "f48" -> R.F48 + | "f50" -> R.F50 + | "f52" -> R.F52 + | "f54" -> R.F54 + | "f56" -> R.F56 + | "f58" -> R.F58 + | "f60" -> R.F60 + | "f62" -> R.F62 + | _ -> Utils.impossible () + + let toString = function + | R.G0 -> "%g0" + | R.G1 -> "%g1" + | R.G2 -> "%g2" + | R.G3 -> "%g3" + | R.G4 -> "%g4" + | R.G5 -> "%g5" + | R.G6 -> "%g6" + | R.G7 -> "%g7" + | R.O0 -> "%o0" + | R.O1 -> "%o1" + | R.O2 -> "%o2" + | R.O3 -> "%o3" + | R.O4 -> "%o4" + | R.O5 -> "%o5" + | R.O6 -> "%o6" + | R.O7 -> "%o7" + | R.L0 -> "%l0" + | R.L1 -> "%l1" + | R.L2 -> "%l2" + | R.L3 -> "%l3" + | R.L4 -> "%l4" + | R.L5 -> "%l5" + | R.L6 -> "%l6" + | R.L7 -> "%l7" + | R.I0 -> "%i0" + | R.I1 -> "%i1" + | R.I2 -> "%i2" + | R.I3 -> "%i3" + | R.I4 -> "%i4" + | R.I5 -> "%i5" + | R.I6 -> "%i6" + | R.I7 -> "%i7" + | R.PC -> "pc" + | R.NPC -> "npc" + | R.Y -> "y" + | R.ASRs -> "asrs" + | R.CCR -> "ccr" + | R.FPRS -> "fprs" + | R.FSR -> "%fsr" + | R.ASI -> "%asi" + | R.TICK -> "%tick" + | R.PSTATE -> "%pstate" + | R.TL -> "%tl" + | R.PIL -> "%pil" + | R.TPC -> "%tpc" + | R.TNPC -> "%tnpc" + | R.TSTATE -> "%tstate" + | R.TT -> "%tt" + | R.TBA -> "%tba" + | R.VER -> "%ver" + | R.CWP -> "%cwp" + | R.CANSAVE -> "%cansave" + | R.CANRESTORE -> "%canrestore" + | R.OTHERWIN -> "%otherwin" + | R.WSTATE -> "%wstate" + | R.FQ -> "%fq" + | R.CLEANWIN -> "%cleanwin" + | R.F0 -> "%f0" + | R.F1 -> "%f1" + | R.F2 -> "%f2" + | R.F3 -> "%f3" + | R.F4 -> "%f4" + | R.F5 -> "%f5" + | R.F6 -> "%f6" + | R.F7 -> "%f7" + | R.F8 -> "%f8" + | R.F9 -> "%f9" + | R.F10 -> "%f10" + | R.F11 -> "%f11" + | R.F12 -> "%f12" + | R.F13 -> "%f13" + | R.F14 -> "%f14" + | R.F15 -> "%f15" + | R.F16 -> "%f16" + | R.F17 -> "%f17" + | R.F18 -> "%f18" + | R.F19 -> "%f19" + | R.F20 -> "%f20" + | R.F21 -> "%f21" + | R.F22 -> "%f22" + | R.F23 -> "%f23" + | R.F24 -> "%f24" + | R.F25 -> "%f25" + | R.F26 -> "%f26" + | R.F27 -> "%f27" + | R.F28 -> "%f28" + | R.F29 -> "%f29" + | R.F30 -> "%f30" + | R.F31 -> "%f31" + | R.F32 -> "%f32" + | R.F34 -> "%f34" + | R.F36 -> "%f36" + | R.F38 -> "%f38" + | R.F40 -> "%f40" + | R.F42 -> "%f42" + | R.F44 -> "%f44" + | R.F46 -> "%f46" + | R.F48 -> "%f48" + | R.F50 -> "%f50" + | R.F52 -> "%f52" + | R.F54 -> "%f54" + | R.F56 -> "%f56" + | R.F58 -> "%f58" + | R.F60 -> "%f60" + | R.F62 -> "%f62" + | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterBay.fs b/src/FrontEnd/BinLifter/SPARC/SPARCRegisterFactory.fs similarity index 79% rename from src/FrontEnd/BinLifter/RISCV/RISCV64RegisterBay.fs rename to src/FrontEnd/BinLifter/SPARC/SPARCRegisterFactory.fs index f738236a..d7516683 100644 --- a/src/FrontEnd/BinLifter/RISCV/RISCV64RegisterBay.fs +++ b/src/FrontEnd/BinLifter/SPARC/SPARCRegisterFactory.fs @@ -22,15 +22,14 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.RISCV +namespace B2R2.FrontEnd.BinLifter.SPARC open B2R2 open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type RISCV64RegisterBay () = - - inherit RegisterBay () +type SPARCRegisterFactory () = + inherit RegisterFactory () override __.GetAllRegExprs () = Utils.futureFeature () @@ -40,9 +39,9 @@ type RISCV64RegisterBay () = override __.RegIDFromRegExpr (e) = match e.E with - | Var (_, id, _ ,_) -> id - | PCVar (_, _) -> Register.toRegID Register.R0 (* FIXME *) - | _ -> failwith "not a register expression" + | Var (_, id, _) -> id + | PCVar _ -> Register.toRegID Register.PC + | _ -> raise InvalidRegisterException override __.RegIDToRegExpr (id) = Utils.futureFeature () override __.StrToRegExpr _s = Utils.futureFeature () @@ -50,9 +49,9 @@ type RISCV64RegisterBay () = override __.RegIDToString _ = Utils.futureFeature () override __.RegIDToRegType _ = Utils.futureFeature () override __.GetRegisterAliases _ = Utils.futureFeature () - override __.ProgramCounter = Utils.futureFeature () - override __.StackPointer = Utils.futureFeature () - override __.FramePointer = Utils.futureFeature () - override __.IsProgramCounter _ = Utils.futureFeature () + override __.ProgramCounter = Register.PC |> Register.toRegID + override __.StackPointer = Register.O6 |> Register.toRegID |> Some + override __.FramePointer = Register.I6 |> Register.toRegID |> Some + override __.IsProgramCounter regid = __.ProgramCounter = regid override __.IsStackPointer _ = Utils.futureFeature () override __.IsFramePointer _ = Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCTranslationContext.fs b/src/FrontEnd/BinLifter/SPARC/SPARCTranslationContext.fs new file mode 100644 index 00000000..86a29f50 --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCTranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SPARC + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for SPARC instructions. +type SPARCTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/SPARC/SPARCTypes.fs b/src/FrontEnd/BinLifter/SPARC/SPARCTypes.fs new file mode 100644 index 00000000..943885c4 --- /dev/null +++ b/src/FrontEnd/BinLifter/SPARC/SPARCTypes.fs @@ -0,0 +1,853 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.SPARC + + +open B2R2 +open System.Runtime.CompilerServices +open B2R2.FrontEnd.BinLifter.SPARC + +[] +do () + +type Opcode = + /// Add + | ADD = 0 + /// Add and modify cc's + | ADDcc = 1 + /// Add with carry + | ADDC = 2 + /// Add with Carry and modify cc's + | ADDCcc = 3 + /// And + | AND = 4 + /// And and modify cc's + | ANDcc = 5 + /// And Not + | ANDN = 6 + /// And Not and modify cc's + | ANDNcc = 7 + /// Branch on Integer Condition Codes with Prediction (BPcc) + /// Branch Always + | BPA = 8 + /// Branch Never + | BPN = 9 + /// Branch on Not Equal + | BPNE = 10 + /// Branch on Equal + | BPE = 11 + /// Branch on Greater + | BPG = 12 + /// Branch on Less or Equal + | BPLE = 13 + /// Branch on Greater or Equal + | BPGE = 14 + /// Branch on Less + | BPL = 15 + /// Branch on Greater Unsigned + | BPGU = 16 + /// Branch on Less or Equal Unsigned + | BPLEU = 17 + /// Branch on Carry Clear (Greater Than or Equal, Unsigned) + | BPCC = 18 + /// Branch on Carry Set (Less than, Unsigned) + | BPCS = 19 + /// Branch on Positive + | BPPOS = 20 + /// Branch on Negative + | BPNEG = 21 + /// Branch on Overflow Clear + | BPVC = 22 + /// Branch on Overflow Set + | BPVS = 23 + /// Branch on Integer Condition Codes (Bicc) + /// Branch Always + | BA = 24 + /// Branch Never + | BN = 25 + /// Branch on Not Equal + | BNE = 26 + /// Branch on Equal + | BE = 27 + /// Branch on Greater + | BG = 28 + /// Branch on Less or Equal + | BLE = 29 + /// Branch on Greater or Equal + | BGE = 30 + /// Branch on Less + | BL = 31 + /// Branch on Greater Unsigned + | BGU = 32 + /// Branch on Less or Equal Unsigned + | BLEU = 33 + /// Branch on Carry Clear (Greater Than or Equal, Unsigned) + | BCC = 34 + /// Branch on Carry Set (Less than, Unsigned) + | BCS = 35 + /// Branch on Positive + | BPOS = 36 + /// Branch on Negative + | BNEG = 37 + /// Branch on Overflow Clear + | BVC = 38 + /// Branch on Overflow Set + | BVS = 39 + /// Branch on Integer Register with Prediction (BPr) + /// Branch on Register Zero + | BRZ = 40 + /// Branch on Register Less Than or Equal to Zero + | BRLEZ = 41 + /// Branch on Register Less Than Zero + | BRLZ = 42 + /// Branch on Register Not Zero + | BRNZ = 43 + /// Branch on Register Greater Than Zero + | BRGZ = 44 + /// Branch on Register Grater Than Equal to Zero + | BRGEZ = 45 + /// Call and link + | CALL = 46 + /// Compare and sawp word in alternate space + | CASA = 47 + /// Compare and swap doubleword in alternate space + | CASXA = 48 + /// Return from Trap (skip trapped instruction) + | DONE = 49 + /// Floating-point absolute value + /// Absolute Value Single + | FABSs = 50 + /// Absolute Value Double + | FABSd = 51 + /// Absolute Value Quad + | FABSq = 52 + /// Floating-Point Add and Subtract + /// Add Single + | FADDs = 53 + /// Add Double + | FADDd = 54 + /// Add Quad + | FADDq = 55 + /// Branch on Floating-Point Condition Codes (FBFcc) + /// Branch Always + | FBA = 56 + /// Branch Never + | FBN = 57 + /// Branch on Unordered + | FBU = 58 + /// Branch on Greater + | FBG = 59 + /// Branch on Unordered or Greater + | FBUG = 60 + /// Branch on Less + | FBL = 61 + /// Branch on Unordered or LEss + | FBUL = 62 + /// Branch on Less or Greater + | FBLG = 63 + /// Branch on Not Equal + | FBNE = 64 + /// Branch on Equal + | FBE = 65 + /// Branch on Unordered or Equal + | FBUE = 66 + /// Branch on Greater or Euqal + | FBGE = 67 + /// Branch on Unordered or Greater or Equal + | FBUGE = 68 + /// Branch on Less or Equal + | FBLE = 69 + /// Branch on Unordered or Less or Equal + | FBULE = 70 + /// Branch on Ordered + | FBO = 71 + /// Branch on Floating-Point Condition Codes with Prediction (FBPFcc) + /// Branch Always + | FBPA = 72 + /// Branch Never + | FBPN = 73 + /// Branch on Unordered + | FBPU = 74 + /// Branch on Greater + | FBPG = 75 + /// Branch on Unordered or Greater + | FBPUG = 76 + /// Branch on Less + | FBPL = 77 + /// Branch on Unordered or LEss + | FBPUL = 78 + /// Branch on Less or Greater + | FBPLG = 79 + /// Branch on Not Equal + | FBPNE = 80 + /// Branch on Equal + | FBPE = 81 + /// Branch on Unordered or Equal + | FBPUE = 82 + /// Branch on Greater or Euqal + | FBPGE = 83 + /// Branch on Unordered or Greater or Equal + | FBPUGE = 84 + /// Branch on Less or Equal + | FBPLE = 85 + /// Branch on Unordered or Less or Equal + | FBPULE = 86 + /// Branch on Ordered + | FBPO = 87 + /// Floating-Point Compare + /// Compare Single + | FCMPs = 88 + /// Compare Double + | FCMPd = 89 + /// Compare Quad + | FCMPq = 90 + /// Compare Single and Exception if Unordered + | FCMPEs = 91 + /// Compare Double and Exception if Unordered + | FCMPEd = 92 + /// COmapre Quad and Exception if Unordered + | FCMPEq = 93 + /// Floating-Point Multiply and Divide + /// Divide Single + | FDIVs = 94 + /// Divide Double + | FDIVd = 95 + /// Divide Quad + | FDIVq = 96 + /// Convert Integer to Floating-Point + /// Convert 32-bit Integer to Single + | FiTOs = 97 + /// Convert 32-bit Integer to Double + | FiTOd = 98 + /// Convert 32-bit Integer to Quad + | FiTOq = 99 + /// Flush Instruction Memory + | FLUSH = 100 + /// Flush Register Windows + | FLUSHW = 101 + /// Floating-Point Move + /// Move Single + | FMOVs = 102 + /// Move Double + | FMOVd = 103 + /// Move Quad + | FMOVq = 104 + /// Move Floating-Point Register on Condition (FMOVcc) + /// Integer Condition Codes + /// Move Always + | FMOVA = 105 + /// Move Never + | FMOVN = 106 + /// Move if Not Equal + | FMOVNE = 107 + /// Move if Equal + | FMOVE = 108 + /// Move if Greater + | FMOVG = 109 + /// Move if Less or Equal + | FMOVLE = 110 + /// Move if Greater or Equal + | FMOVGE = 111 + /// Move if Less + | FMOVL = 112 + /// Move if Greater Unsigned + | FMOVGU = 113 + /// Move if Less or Equal Unsigned + | FMOVLEU = 114 + /// Move if Carry Clear (Greater or Equal, Unsigned) + | FMOVCC = 115 + /// Move if Carry Set (Less than, Unsigned) + | FMOVCS = 116 + /// Move if Positive + | FMOVPOS = 117 + /// Move if Negative + | FMOVNEG = 118 + /// Move if Overflow Clear + | FMOVVC = 119 + /// Move if Overflow Set + | FMOVVS = 120 + /// Floating-Point Condition Codes + /// More Always + | FMOVFA = 121 + /// Move Never + | FMOVFN = 122 + /// Move if Unordered + | FMOVFU = 123 + /// Move if Greater + | FMOVFG = 124 + /// Move if Unordered or Greater + | FMOVFUG = 125 + /// Move if Less + | FMOVFL = 126 + /// Move if Unordered or Less + | FMOVFUL = 127 + /// Move if Less or Greater + | FMOVFLG = 128 + /// Move if Not Equal + | FMOVFNE = 129 + /// Move if Equal + | FMOVFE = 130 + /// Move if Unordered or Equal + | FMOVFUE = 131 + /// Move if Greater or Equal + | FMOVFGE = 132 + /// Move if Unordered or Greater or Equal + | FMOVFUGE = 133 + /// Move if Less or Equal + | FMOVFLE = 134 + /// Move if Unordered or Less or Equal + | FMOVFULE = 135 + /// Move if Ordered + | FMOVFO = 136 + /// Move F-P Register on Integer Register Condition (FMOVr) + /// Move if Register Zero + | FMOVRZ = 137 + /// Move if Register Less Than or Equal to Zero + | FMOVRLEZ = 138 + /// Move if Register Less Than Zero + | FMOVRLZ = 139 + /// Move if Register Not Zero + | FMOVRNZ = 140 + /// Move if Register Greater Than Zero + | FMOVRGZ = 141 + /// Move if Register Greater Than or Equal to Zero + | FMOVRGEZ = 142 + /// Floating-Point Multiply + /// Multiply Single + | FMULs = 143 + /// Multiply Double + | FMULd = 144 + /// Multiply Quad + | FMULq = 145 + /// Floating-Point Negate + /// Negate Single + | FNEGs = 146 + /// Negate Double + | FNEGd = 147 + /// Negate Quad + | FNEGq = 148 + /// Floating-Point Multiply Single to Double + /// Multiply Single to Double + | FsMULd = 149 + /// Multiyply Double to Quad + | FdMULq = 150 + /// Floating-Point Square Root + /// Square Root Single + | FSQRTs = 151 + /// Square Root Double + | FSQRTd = 152 + /// Square Root Quad + | FSQRTq = 153 + /// Convert Floating Point to Integer + /// Convert Single to 32-bit Integer + | FsTOi = 154 + /// Convert Double to 32-bit Integer + | FdTOi = 155 + /// Convert Quad to 32-bit Integer + | FqTOi = 156 + /// Convert Between Floating-Point Formats + /// Convert Single to Double + | FsTOd = 157 + /// Convert Single to Quad + | FsTOq = 158 + /// Convert Double to Single + | FdTOs = 159 + /// Convert Double to Quad + | FdTOq = 160 + /// Convert Quad to Single + | FqTOs = 161 + /// Convert Quad To Double + | FqTOd = 162 + /// Convert Floating Point 64-bit to Integer + /// Convert Single to 64-bit to Integer + | FsTOx = 163 + /// Convert Double to 64-bit to Integer + | FdTOx = 164 + /// Convert Quad to 64-bit to integer + | FqTOx = 165 + /// Floating-Point Subtract + /// Subtract Single + | FSUBs = 166 + /// Subtract Double + | FSUBd = 167 + /// Subtract Quad + | FSUBq = 168 + /// Convert 64-bit Integer to Floating-Point + /// Convert 64-bit Integer to Single + | FxTOs = 169 + /// Convert 64-bit Integer to Double + | FxTOd = 170 + /// Convert 64-bit Integer to Quad + | FxTOq = 171 + /// Illegal Instruction Trap + | ILLTRAP = 172 + /// Implementation-Dependent Instructions 1 + | IMPDEP1 = 173 + /// Implementation-Dependent Instructions 2 + | IMPDEP2 = 174 + /// Jump and Link + | JMPL = 175 + /// Load Doubleword + | LDD = 176 + /// Load Doubleword from Alternate space + | LDDA = 177 + /// Load Double Floating-Point Register + | LDDF = 178 + /// Load Double Floating-Point Register from Alternate space + | LDDFA = 179 + /// Load Floating-Point Register + | LDF = 180 + /// Load Floating-Point Register from Alternate space + | LDFA = 181 + /// Load Floating-Point State Register Lower + | LDFSR = 182 + | LDQF = 183 + | LDQFA = 184 + | LDSB = 185 + | LDSBA = 186 + | LDSH = 187 + | LDSHA = 188 + | LDSTUB = 189 + | LDSTUBA = 190 + | LDSW = 191 + | LDSWA = 192 + | LDUB = 193 + | LDUBA = 194 + | LDUH = 195 + | LDUHA = 196 + | LDUW = 197 + | LDUWA = 198 + | LDX = 199 + | LDXA = 200 + | LDXFSR = 201 + | MEMBAR = 202 + /// Move Integer Register on Condition (MOVcc) + /// Move Integer Register if Condition is Satisfied + /// Move Always + | MOVA = 203 + /// Move Never + | MOVN = 204 + /// Move if Not Equal + | MOVNE = 205 + /// Move if Equal + | MOVE = 206 + /// Move if Greater + | MOVG = 207 + /// Move if Less or Equal + | MOVLE = 208 + /// Move if Greater or Equal + | MOVGE = 209 + /// Move if Less + | MOVL = 210 + /// Move if Greater Unsigned + | MOVGU = 211 + /// Move if Less or Equal Unsigned + | MOVLEU = 212 + /// Move if Carry Clear (Greater or Equal, Unsigned) + | MOVCC = 213 + /// Move if Carry Set (Less than, Unsigned) + | MOVCS = 214 + /// Move if Positive + | MOVPOS = 215 + /// Move if Negative + | MOVNEG = 216 + /// Move if Overflow Clear + | MOVVC = 217 + /// Move if Overflow Set + | MOVVS = 218 + /// Floating-Point Condition Codes + /// More Always + | MOVFA = 219 + /// Move Never + | MOVFN = 220 + /// Move if Unordered + | MOVFU = 221 + /// Move if Greater + | MOVFG = 222 + /// Move if Unordered or Greater + | MOVFUG = 223 + /// Move if Less + | MOVFL = 224 + /// Move if Unordered or Less + | MOVFUL = 225 + /// Move if Less or Greater + | MOVFLG = 226 + /// Move if Not Equal + | MOVFNE = 227 + /// Move if Equal + | MOVFE = 228 + /// Move if Unordered or Equal + | MOVFUE = 229 + /// Move if Greater or Equal + | MOVFGE = 230 + /// Move if Unordered or Greater or Equal + | MOVFUGE = 231 + /// Move if Less or Equal + | MOVFLE = 232 + /// Move if Unordered or Less or Equal + | MOVFULE = 233 + /// Move if Ordered + | MOVFO = 234 + /// Move Integer Register on Register Condition (MOVR) + /// Move if Register Zero + | MOVRZ = 235 + /// Move if Register Less Than or Equal to Zero + | MOVRLEZ = 236 + /// Move if Register Less Than Zero + | MOVRLZ = 237 + /// Move if Register Not Zero + | MOVRNZ = 238 + /// Move if Register Greater Than Zero + | MOVRGZ = 239 + /// Move if Register Greater Than or Equal to Zero + | MOVRGEZ = 240 + /// Multiply Step and modify cc's + | MULScc = 241 + /// Multiply (signed or unsigned) + | MULX = 242 + /// No Operation + | NOP = 243 + /// Inclusive Or + | OR = 244 + /// Inclusive Or and modify cc's + | ORcc = 245 + /// Inclusive Or Not + | ORN = 246 + /// Inclusive Or Not and modify cc's + | ORNcc = 247 + /// Population Count + | POPC = 248 + /// Prefetch Data + | PREFETCH = 249 + /// Prefetch Data from Alternate Space + | PREFETCHA = 250 + /// Read ASI Register + | RDASI = 251 + /// Read Ancillary State Register + | RDASR = 252 + /// Read Condition Codes Register + | RDCCR = 253 + /// Read Floating-Point Register State Register + | RDFPRS = 254 + /// Read Program Counter + | RDPC = 255 + /// Read Privileged Register + | RDPR = 256 + /// Read TICK Register + | RDTICK = 257 + /// Read Y Register + | RDY = 258 + | RESTORE = 259 + | RESTORED = 260 + | RETRY = 261 + | RETURN = 262 + | SAVE = 263 + | SAVED = 264 + /// Signed Integer Divide + | SDIV = 265 + /// Signed Integer Divide and modify cc's + | SDIVcc = 266 + /// Signed Divide + | SDIVX = 267 + | SETHI = 268 + | SIR = 269 + | SLL = 270 + | SLLX = 271 + | SMUL = 272 + | SMULcc = 273 + | SRA = 274 + | SRAX = 275 + | SRL = 276 + | SRLX = 277 + | STB = 278 + | STBA = 279 + | STBAR = 280 + | STD = 281 + | STDA = 282 + | STDF = 283 + | STDFA = 284 + | STF = 285 + | STFA = 286 + | STFSR = 287 + | STH = 288 + | STHA = 289 + | STQF = 290 + | STQFA = 291 + | STW = 292 + | STWA = 293 + | STX = 294 + | STXA = 295 + | STXFSR = 296 + | SUB = 297 + | SUBcc = 298 + | SUBC = 299 + | SUBCcc = 300 + | SWAP = 301 + | SWAPA = 302 + | TADDcc = 303 + | TADDccTV = 304 + | Tcc = 305 + | TA = 306 + | TN = 307 + | TNE = 308 + | TE = 309 + | TG = 310 + | TLE = 311 + | TGE = 312 + | TL = 313 + | TGU = 314 + | TLEU = 315 + | TCC = 316 + | TCS = 317 + | TPOS = 318 + | TNEG = 319 + | TVC = 320 + | TVS = 321 + | TSUBcc = 322 + | TSUBccTV = 323 + | UDIV = 324 + | UDIVcc = 325 + | UDIVX = 326 + | UMUL = 327 + | UMULcc = 328 + | WRASI = 329 + | WRASR = 330 + | WRCCR = 331 + | WRFPRS = 332 + | WRPR = 333 + | WRY = 334 + | WNOR = 335 + | WNORcc = 336 + | XOR = 337 + | XORcc = 338 + | XNOR = 339 + | XNORcc = 340 + | FMOVsA = 341 + | FMOVdA = 342 + | FMOVqA = 343 + | FMOVsN = 344 + | FMOVdN = 345 + | FMOVqN = 346 + | FMOVsNE = 347 + | FMOVdNE = 348 + | FMOVqNE = 349 + | FMOVsE = 350 + | FMOVdE = 351 + | FMOVqE = 352 + | FMOVsG = 353 + | FMOVdG = 354 + | FMOVqG = 355 + | FMOVsLE = 357 + | FMOVdLE = 358 + | FMOVqLE = 359 + | FMOVsGE = 361 + | FMOVdGE = 362 + | FMOVqGE = 363 + | FMOVsL = 365 + | FMOVdL = 366 + | FMOVqL = 367 + | FMOVsGU = 369 + | FMOVdGU = 370 + | FMOVqGU = 371 + | FMOVsLEU = 373 + | FMOVdLEU = 374 + | FMOVqLEU = 375 + | FMOVsCC = 377 + | FMOVdCC = 378 + | FMOVqCC = 379 + | FMOVsCS = 382 + | FMOVdCS = 383 + | FMOVqCS = 384 + | FMOVsPOS = 386 + | FMOVdPOS = 387 + | FMOVqPOS = 388 + | FMOVsNEG = 390 + | FMOVdNEG = 391 + | FMOVqNEG = 392 + | FMOVsVC = 394 + | FMOVdVC = 395 + | FMOVqVC = 396 + | FMOVsVS = 398 + | FMOVdVS = 399 + | FMOVqVS = 400 + | FMOVFsA = 401 + | FMOVFdA = 402 + | FMOVFqA = 403 + | FMOVFsN = 404 + | FMOVFdN = 405 + | FMOVFqN = 406 + | FMOVFsU = 407 + | FMOVFdU = 408 + | FMOVFqU = 409 + | FMOVFsG = 410 + | FMOVFdG = 411 + | FMOVFqG = 412 + | FMOVFsUG = 413 + | FMOVFdUG = 414 + | FMOVFqUG = 415 + | FMOVFsL = 416 + | FMOVFdL = 417 + | FMOVFqL = 418 + | FMOVFsUL = 419 + | FMOVFdUL = 420 + | FMOVFqUL = 421 + | FMOVFsLG = 422 + | FMOVFdLG = 423 + | FMOVFqLG = 424 + | FMOVFsNE = 425 + | FMOVFdNE = 426 + | FMOVFqNE = 427 + | FMOVFsE = 428 + | FMOVFdE = 429 + | FMOVFqE = 430 + | FMOVFsUE = 431 + | FMOVFdUE = 432 + | FMOVFqUE = 433 + | FMOVFsGE = 434 + | FMOVFdGE = 435 + | FMOVFqGE = 436 + | FMOVFsUGE = 437 + | FMOVFdUGE = 438 + | FMOVFqUGE = 439 + | FMOVFsLE = 440 + | FMOVFdLE = 441 + | FMOVFqLE = 442 + | FMOVFsULE = 443 + | FMOVFdULE = 444 + | FMOVFqULE = 445 + | FMOVFsO = 446 + | FMOVFdO = 447 + | FMOVFqO = 448 + | FMOVRsZ = 449 + | FMOVRsLEZ = 450 + | FMOVRsLZ = 451 + | FMOVRsNZ = 452 + | FMOVRsGZ = 453 + | FMOVRsGEZ = 454 + | FMOVRdZ = 455 + | FMOVRdLEZ = 456 + | FMOVRdLZ = 457 + | FMOVRdNZ = 458 + | FMOVRdGZ = 459 + | FMOVRdGEZ = 460 + | FMOVRqZ = 461 + | FMOVRqLEZ = 462 + | FMOVRqLZ = 463 + | FMOVRqNZ = 464 + | FMOVRqGZ = 465 + | FMOVRqGEZ = 466 + | InvalidOp = 467 + +type ConditionCode = + /// floating-point condition code + | Fcc0 = 0 + | Fcc1 = 1 + | Fcc2 = 2 + | Fcc3 = 3 + /// integer condition codes + /// based on either the 32-bit result of an operation + | Icc = 4 + /// based on either the 64-bit result of an operation + | Xcc = 5 + /// Invalid Condition Code + | InvalidCC = 6 + +module ConditionCode = + let inline ofRegID (n: RegisterID): ConditionCode = + int n |> LanguagePrimitives.EnumOfValue + + let inline toRegID (reg: ConditionCode) = + LanguagePrimitives.EnumToValue (reg) |> RegisterID.create + + let ofString (str: string) = + match str.ToLowerInvariant () with + | "fcc0" -> ConditionCode.Fcc0 + | "fcc1" -> ConditionCode.Fcc1 + | "fcc2" -> ConditionCode.Fcc2 + | "fcc3" -> ConditionCode.Fcc3 + | "icc" -> ConditionCode.Icc + | "xcc" -> ConditionCode.Xcc + | _ -> Utils.impossible () + + let toString = function + | ConditionCode.Fcc0 -> "%fcc0" + | ConditionCode.Fcc1 -> "%fcc1" + | ConditionCode.Fcc2 -> "%fcc2" + | ConditionCode.Fcc3 -> "%fcc3" + | ConditionCode.Icc -> "%icc" + | ConditionCode.Xcc -> "%xcc" + | _ -> Utils.impossible () + +type Const = int32 + +type AddressingMode = + | DispMode of Register * Const + | PreIdxMode of Register + | PostIdxMode of Register + | UnchMode of Register + +type Operand = + | OprReg of Register + | OprImm of Const + | OprAddr of Const + | OprMemory of AddressingMode + | OprCC of ConditionCode + | OprPriReg of Register + +type Operands = + | NoOperand + | OneOperand of Operand + | TwoOperands of Operand * Operand + | ThreeOperands of Operand * Operand * Operand + | FourOperands of Operand * Operand * Operand * Operand + | FiveOperands of Operand * Operand * Operand * Operand * Operand + +/// Basic information obtained by parsing a SPARC instruction. +[] +type InsInfo = { + /// Address. + Address: Addr + /// Instruction length. + NumBytes: uint32 + /// Opcode. + Opcode: Opcode + /// Operands + Operands: Operands +} +with + override __.GetHashCode () = + hash (__.Address, + __.NumBytes, + __.Opcode, + __.Operands) + + override __.Equals (i) = + match i with + | :? InsInfo as i -> + i.Address = __.Address + && i.NumBytes = __.NumBytes + && i.Opcode = __.Opcode + && i.Operands = __.Operands + | _ -> false diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64.fs b/src/FrontEnd/BinLifter/Sparc64/Sparc64.fs deleted file mode 100644 index c4e5d739..00000000 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64.fs +++ /dev/null @@ -1,65 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.Sparc64 - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for Sparc64 instructions. -type Sparc64TranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for Sparc64 instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type Sparc64Parser (isa: ISA) = - inherit Parser () - - let reader = - if isa.Endian = Endian.Little then BinReader.binReaderLE - else BinReader.binReaderBE - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader addr :> Instruction - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader addr :> Instruction - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - Sparc64TranslationContext (isa, regexprs) :> TranslationContext, - Sparc64RegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64RegisterBay.fs b/src/FrontEnd/BinLifter/Sparc64/Sparc64RegisterBay.fs deleted file mode 100644 index 37c414e2..00000000 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64RegisterBay.fs +++ /dev/null @@ -1,54 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.Sparc64 - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR.LowUIR - -type Sparc64RegisterBay () = - - inherit RegisterBay () - - override __.GetAllRegExprs () = Utils.futureFeature () - - override __.GetAllRegNames () = Utils.futureFeature () - - override __.GetGeneralRegExprs () = Utils.futureFeature () - - override __.RegIDFromRegExpr (e) = Utils.futureFeature () - - override __.RegIDToRegExpr (id) = Utils.futureFeature () - override __.StrToRegExpr _s = Utils.futureFeature () - override __.RegIDFromString _s = Utils.futureFeature () - override __.RegIDToString _ = Utils.futureFeature () - override __.RegIDToRegType _ = Utils.futureFeature () - override __.GetRegisterAliases _ = Utils.futureFeature () - override __.ProgramCounter = Utils.futureFeature () - override __.StackPointer = Utils.futureFeature () - override __.FramePointer = Utils.futureFeature () - override __.IsProgramCounter _ = Utils.futureFeature () - override __.IsStackPointer _ = Utils.futureFeature () - override __.IsFramePointer _ = Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/Sparc64/Sparc64RegisterSet.fs b/src/FrontEnd/BinLifter/Sparc64/Sparc64RegisterSet.fs deleted file mode 100644 index c5ba26ba..00000000 --- a/src/FrontEnd/BinLifter/Sparc64/Sparc64RegisterSet.fs +++ /dev/null @@ -1,59 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.Sparc64 - -open B2R2 - -module private RegisterSetLiteral = - let [] arrLen = 2 - -open RegisterSetLiteral - -type Sparc64RegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = - Sparc64RegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) - - override __.Tag = RegisterSetTag.Sparc64 - - override __.ArrSize = arrLen - - override __.New arr s = new Sparc64RegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | _ -> Utils.futureFeature () - - override __.IndexToRegID _index: RegisterID = - Utils.futureFeature () - - override __.ToString () = - sprintf "Sparc64RegisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] - -[] -module Sparc64RegisterSet = - let singleton rid = Sparc64RegisterSet().Add(rid) - let empty = Sparc64RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj b/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj index 696cb705..0c8d2eda 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj +++ b/src/FrontEnd/BinLifter/TMS320C6000/B2R2.FrontEnd.BinLifter.TMS320C6000.fsproj @@ -9,15 +9,15 @@ - - + + - + diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000.fs deleted file mode 100644 index 034f5bf4..00000000 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000.fs +++ /dev/null @@ -1,63 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.TMS320C6000 - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for TMS320C6000 instructions. -type TMS320C6000TranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for TMS320C6000 instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type TMS320C6000Parser () = - inherit Parser () - let mutable inParallel = false - let reader = BinReader.binReaderLE - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader &inParallel addr :> Instruction - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader &inParallel addr :> Instruction - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs (isa.WordSize) - struct ( - TMS320C6000TranslationContext (isa, regexprs) :> TranslationContext, - TMS320C6000RegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs index e2c3ead7..9aec16f8 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Disasm.fs @@ -277,14 +277,14 @@ let inline appendUnit insInfo opcode = | D2XUnit -> opcode + ".D2X" | NoUnit -> opcode -let buildParallelPipe ins (builder: DisasmBuilder<_>) = +let buildParallelPipe ins (builder: DisasmBuilder) = if ins.IsParallel then builder.Accumulate AsmWordKind.String "|| " else () -let inline buildOpcode ins (builder: DisasmBuilder<_>) = +let inline buildOpcode ins (builder: DisasmBuilder) = let str = opCodeToString ins.Opcode |> appendUnit ins builder.Accumulate AsmWordKind.Mnemonic str -let buildMemBase (builder: DisasmBuilder<_>) baseR = function +let buildMemBase (builder: DisasmBuilder) baseR = function | NegativeOffset -> builder.Accumulate AsmWordKind.String "-" builder.Accumulate AsmWordKind.Variable (Register.toString baseR) @@ -304,13 +304,13 @@ let buildMemBase (builder: DisasmBuilder<_>) baseR = function builder.Accumulate AsmWordKind.Variable (Register.toString baseR) builder.Accumulate AsmWordKind.String "++" -let private offsetToString (builder: DisasmBuilder<_>) offset = +let private offsetToString (builder: DisasmBuilder) offset = match offset with | UCst5 i -> builder.Accumulate AsmWordKind.Value (i.ToString()) | UCst15 i -> builder.Accumulate AsmWordKind.Value (i.ToString()) | OffsetR r -> builder.Accumulate AsmWordKind.Variable (Register.toString r) -let private buildMemOffset (builder: DisasmBuilder<_>) offset = +let private buildMemOffset (builder: DisasmBuilder) offset = match offset with | UCst5 0UL -> () | offset -> @@ -322,7 +322,7 @@ let memToString builder baseR modification offset = buildMemBase builder baseR modification buildMemOffset builder offset -let oprToString opr delim (builder: DisasmBuilder<_>) = +let oprToString opr delim (builder: DisasmBuilder) = match opr with | OpReg reg -> builder.Accumulate AsmWordKind.String delim @@ -338,7 +338,7 @@ let oprToString opr delim (builder: DisasmBuilder<_>) = memToString builder baseR modification offset | Immediate imm -> builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (String.u64ToHex imm) + builder.Accumulate AsmWordKind.Value (HexString.ofUInt64 imm) let buildOprs insInfo builder = match insInfo.Operands with @@ -358,7 +358,7 @@ let buildOprs insInfo builder = oprToString opr3 ", " builder oprToString opr4 ", " builder -let disasm insInfo (builder: DisasmBuilder<_>) = +let disasm insInfo (builder: DisasmBuilder) = if builder.ShowAddr then builder.AccumulateAddr () else () buildParallelPipe insInfo builder buildOpcode insInfo builder diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs index 55376d10..05fb2a9e 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Instruction.fs @@ -82,23 +82,23 @@ type TMS320C6000Instruction (addr, numBytes, insInfo) = override __.TranslateToList _ctxt = Utils.futureFeature () - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs index 191fbf5f..89ba45bd 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Parser.fs @@ -22,1969 +22,26 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinLifter.TMS320C6000.Parser +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 +open System open B2R2 open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinLifter.BitData -/// Table 3-1. Instruction Operation and Execution Notations. -type OperandType = - /// Register B14 or B15. - | B14B15 - /// Bit vector of two flags for s2 or u2 data type. - | BVec2 - /// Bit vector of four flags for s4 or u4 data type. - | BVec4 - /// n-bit constant field (for example, cst5). - | Const - /// 64-bit integer value (two registers). - | DInt - /// Double-precision floating-point register value. - | DP - /// Two packed signed 16-bit integers in a single 64-bit register pair. - | DS2 - /// Unsigned 64-bit integer value (two registers). - | DUInt - /// Four packed signed 16-bit integers in a 64-bit register pair. - | DWS4 - /// Four packed unsigned 16-bit integers in a 64-bit register pair. - | DWU4 - /// Two packed 16-bit integers in a single 32-bit register. - | I2 - /// Four packed 8-bit integers in a single 32-bit register. - | I4 - /// 32-bit integer value. - | Int - /// Two packed signed 16-bit integers in a single 32-bit register. - | S2 - /// Four packed signed 8-bit integers in a single 32-bit register. - | S4 - /// n-bit signed constant field. - | SConst - /// Signed 64-bit integer value (two registers). - | SDInt - /// Signed 32-bit integer value. - | SInt - /// Signed 64-bit integer value. - | SLLong - /// Signed 40-bit integer value. - | SLong - /// Signed 16-bit integer value in lower half of 32-bit register. - | SLsb16 - /// Signed 16-bit integer value in upper half of 32-bit register. - | SMsb16 - /// Single-precision floating-point register value that can optionally use - /// cross path. - | SP - /// Two packed unsigned 16-bit integers in a single 32-bit register. - | U2 - /// Four packed unsigned 8-bit integers in a single 32-bit register. - | U4 - /// n-bit unsigned constant field (for example, ucst5). - | UConst - /// Unsigned 32-bit integer value. - | UInt - /// Unsigned 64-bit integer value. - | ULLong - /// Unsigned 40-bit integer value. - | ULong - /// Unsigned 16-bit integer value in lower half of 32-bit register. - | ULsb16 - /// Unsigned 16-bit integer value in upper half of 32-bit register. - | UMsb16 - /// Double-precision floating-point register value that can optionally use - /// cross path. - | XDP - /// Two packed 16-bit integers in a single 32-bit register that can optionally - /// use cross path. - | XI2 - /// Four packed 8-bit integers in a single 32-bit register that can optionally - /// use cross path. - | XI4 - /// 32-bit integer value that can optionally use cross path. - | XInt - /// Two packed signed 16-bit integers in a single 32-bit register that can - /// optionally use cross path. - | XS2 - /// Four packed signed 8-bit integers in a single 32-bit register that can - /// optionally use cross path. - | XS4 - /// Signed 32-bit integer value that can optionally use cross path. - | XSInt - /// Signed 16 LSB of register that can optionally use cross path. - | XSLsb16 - /// Signed 16 MSB of register that can optionally use cross path. - | XSMsb16 - /// Single-precision floating-point register value that can optionally use - /// cross path. - | XSP - /// Two packed unsigned 16-bit integers in a single 32-bit register that can - /// optionally use cross path. - | XU2 - /// Four packed unsigned 8-bit integers in a single 32-bit register that can - /// optionally use cross path. - | XU4 - /// Unsigned 32-bit integer value that can optionally use cross path. - | XUInt - /// Unsigned 16 LSB of register that can optionally use cross path. - | XULsb16 - /// Unsigned 16 MSB of register that can optionally use cross path. - | XUMsb16 +/// Parser for TMS320C6000 instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type TMS320C6000Parser () = + let mutable inParallel = false + let reader = BinReader.Init Endian.Little -type MemoryOpOrder = - | RegMem - | MemReg + interface IInstructionParsable with + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader &inParallel addr :> Instruction -let buildMemOperand reg mem = function - | RegMem -> TwoOperands (reg, mem) - | MemReg -> TwoOperands (mem, reg) + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader &inParallel addr :> Instruction -[] -type OperandInfo = - struct - val OperandValue: uint32 - val OperandType: OperandType - new (v, t) = { OperandValue = v; OperandType = t } - end + member __.MaxInstructionSize = 4 -let private getRegisterA = function - | 0b00000u -> R.A0 - | 0b00001u -> R.A1 - | 0b00010u -> R.A2 - | 0b00011u -> R.A3 - | 0b00100u -> R.A4 - | 0b00101u -> R.A5 - | 0b00110u -> R.A6 - | 0b00111u -> R.A7 - | 0b01000u -> R.A8 - | 0b01001u -> R.A9 - | 0b01010u -> R.A10 - | 0b01011u -> R.A11 - | 0b01100u -> R.A12 - | 0b01101u -> R.A13 - | 0b01110u -> R.A14 - | 0b01111u -> R.A15 - | 0b10000u -> R.A16 - | 0b10001u -> R.A17 - | 0b10010u -> R.A18 - | 0b10011u -> R.A19 - | 0b10100u -> R.A20 - | 0b10101u -> R.A21 - | 0b10110u -> R.A22 - | 0b10111u -> R.A23 - | 0b11000u -> R.A24 - | 0b11001u -> R.A25 - | 0b11010u -> R.A26 - | 0b11011u -> R.A27 - | 0b11100u -> R.A28 - | 0b11101u -> R.A29 - | 0b11110u -> R.A30 - | 0b11111u -> R.A31 - | _ -> Utils.impossible () - -let private getRegisterB = function - | 0b00000u -> R.B0 - | 0b00001u -> R.B1 - | 0b00010u -> R.B2 - | 0b00011u -> R.B3 - | 0b00100u -> R.B4 - | 0b00101u -> R.B5 - | 0b00110u -> R.B6 - | 0b00111u -> R.B7 - | 0b01000u -> R.B8 - | 0b01001u -> R.B9 - | 0b01010u -> R.B10 - | 0b01011u -> R.B11 - | 0b01100u -> R.B12 - | 0b01101u -> R.B13 - | 0b01110u -> R.B14 - | 0b01111u -> R.B15 - | 0b10000u -> R.B16 - | 0b10001u -> R.B17 - | 0b10010u -> R.B18 - | 0b10011u -> R.B19 - | 0b10100u -> R.B20 - | 0b10101u -> R.B21 - | 0b10110u -> R.B22 - | 0b10111u -> R.B23 - | 0b11000u -> R.B24 - | 0b11001u -> R.B25 - | 0b11010u -> R.B26 - | 0b11011u -> R.B27 - | 0b11100u -> R.B28 - | 0b11101u -> R.B29 - | 0b11110u -> R.B30 - | 0b11111u -> R.B31 - | _ -> Utils.impossible () - -let private parseReg bin isCrossPath = function - | L1Unit | S1Unit | M1Unit | D1Unit -> getRegisterA bin - | L2Unit | S2Unit | M2Unit | D2Unit -> getRegisterB bin - | L1XUnit | S1XUnit | M1XUnit | D1XUnit -> - if isCrossPath then getRegisterB bin else getRegisterA bin - | L2XUnit | S2XUnit | M2XUnit | D2XUnit -> - if isCrossPath then getRegisterA bin else getRegisterB bin - | _ -> Utils.impossible () - -let private parseRegBySide bin = function - | SideA -> getRegisterA bin - | SideB -> getRegisterB bin - -let private parseAddrMode unit offset mode baseR = - match mode with - | 0b0000u -> baseR, NegativeOffset, uint64 offset |> UCst5 - | 0b0001u -> baseR, PositiveOffset, uint64 offset |> UCst5 - | 0b0100u -> baseR, NegativeOffset, parseReg offset false unit |> OffsetR - | 0b0101u -> baseR, PositiveOffset, parseReg offset false unit |> OffsetR - | 0b1000u -> baseR, PreDecrement, uint64 offset |> UCst5 - | 0b1001u -> baseR, PreIncrement, uint64 offset |> UCst5 - | 0b1010u -> baseR, PostDecrement, uint64 offset |> UCst5 - | 0b1011u -> baseR, PostIncrement, uint64 offset |> UCst5 - | 0b1100u -> baseR, PreDecrement, parseReg offset false unit |> OffsetR - | 0b1101u -> baseR, PreIncrement, parseReg offset false unit |> OffsetR - | 0b1110u -> baseR, PostDecrement, parseReg offset false unit |> OffsetR - | 0b1111u -> baseR, PostIncrement, parseReg offset false unit |> OffsetR - | _ -> Utils.impossible () - -let private parseMem oprVal unit = - parseReg (extract oprVal 13u 9u) false unit (* Base register *) - |> parseAddrMode unit (extract oprVal 8u 4u) (extract oprVal 3u 0u) - |> OprMem - -let private assertEvenNumber v = -#if DEBUG - if v &&& 1u <> 0u then raise InvalidOperandException else () -#endif - () - -let getSide sBit = if sBit = 0b0u then SideA else SideB - -let private xBit bin = pickBit bin 12u -let private yBit bin = pickBit bin 7u -let private sBit bin = pickBit bin 1u -let private pBit bin = pickBit bin 0u - -let private isSrc1Zero bin = extract bin 17u 13u = 0u -let private isSrc111111 bin = extract bin 17u 13u = 0b11111u -let private isSrc100010 bin = extract bin 17u 13u = 0b000010u -let private isEqualSrc1Src2 bin = - xBit bin = 0u && extract bin 22u 18u = extract bin 17u 13u - -let private parseRegPair v unit isCPath = - let high, low = if v &&& 0b1u = 0b0u then v + 1u, v else v, v - 1u - (parseReg high isCPath unit, parseReg low isCPath unit) |> RegisterPair - -let getB14orB15 value = if value = 0b0u then R.B14 else R.B15 - -let private translateOperand unit (oprInfo: OperandInfo) = - let v = oprInfo.OperandValue - match oprInfo.OperandType with - | B14B15 -> getB14orB15 v |> OpReg - | BVec2 | BVec4 | I2 | I4 | Int | S2 | S4 | SInt | SLsb16 | SMsb16 | SP | U2 - | U4 | UInt | ULsb16 | UMsb16 -> parseReg v false unit |> OpReg - | Const | SConst | UConst -> uint64 v |> Immediate - | DInt | DP | DS2 | DUInt | DWS4 | DWU4 | SDInt | SLLong | SLong | ULLong - | ULong -> parseRegPair v unit false - | XDP -> parseRegPair v unit true - | XI2 | XI4 | XInt | XS2 | XS4 | XSInt | XSLsb16 | XSMsb16 | XSP | XU2 | XU4 - | XUInt | XULsb16 | XUMsb16 -> parseReg v true unit |> OpReg - -let private parseOneOpr unit o = OneOperand (translateOperand unit o) - -let private parseTwoOprs unit o1 o2 = - TwoOperands (translateOperand unit o1, translateOperand unit o2) - -let private parseThreeOprs unit o1 o2 o3 = - ThreeOperands (translateOperand unit o1, - translateOperand unit o2, - translateOperand unit o3) - -let private parseFourOprs unit o1 o2 o3 o4 = - FourOperands (translateOperand unit o1, - translateOperand unit o2, - translateOperand unit o3, - translateOperand unit o4) - -/// scst21 -let private parseSc21 bin opcode unit = - let o = OperandInfo (extract bin 27u 7u, SConst) - struct (opcode, unit, parseOneOpr unit o) - -/// xuint -let private parseXUi bin opcode unit = - let o = OperandInfo (extract bin 22u 18u, XUInt) - struct (opcode, unit, parseOneOpr unit o) - -/// ucst4 (NOP) -let private parseUc4 bin opcode unit = - let o = OperandInfo (extract bin 16u 13u + 1u, UConst) - struct (opcode, unit, parseOneOpr unit o) - -/// slong -let private parseSl bin opcode unit = - let o = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseOneOpr unit o) - -/// sint -let private parseSi bin opcode unit = - let o = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseOneOpr unit o) - -/// xsint, sint -let private parseXSiSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// slong, slong -let private parseSlSl bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SLong) - let o2 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// dp, dp -let private parseXDpDp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XDP) - let o2 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xsp, sp -let private parseXSpSp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSP) - let o2 = OperandInfo (extract bin 27u 23u, SP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// scst16, uint -let private parseSc16Ui bin opcode unit = - let o1 = OperandInfo (extract bin 22u 7u, SConst) - let o2 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// dp, sint -let private parseDpSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, DP) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// dp, sp -let private parseDpSp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, DP) - let o2 = OperandInfo (extract bin 27u 23u, SP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xsint, dp -let private parseXSiDp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xuint, dp -let private parseXUiDp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xsint, sp -let private parseXSiSp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 27u 23u, SP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xuint, sp -let private parseXUiSp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 27u 23u, SP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xs2, s2 -let private parseXs2S2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XS2) - let o2 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// scst10, int -let private parseSc10Int bin opcode unit = - let o1 = OperandInfo (extract bin 22u 13u, SConst) - let o2 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xu4, u4 -let private parseXU4U4 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XU4) - let o2 = OperandInfo (extract bin 27u 23u, U4) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xuint, uint -let private parseXUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// scst12, ucst3 -let private parseSc12Uc3 bin opcode unit = - let o1 = OperandInfo (extract bin 27u 16u, SConst) - let o2 = OperandInfo (extract bin 15u 13u, UConst) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xuint, ucst3 -let private parseXUiUc3 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 15u 13u, UConst) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// sint, sint -let private parseSiSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SInt) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xint, int -let private parseXiInt bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XInt) - let o2 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// scst16, sint -let private parseSc16Si bin opcode unit = - let o1 = OperandInfo (extract bin 22u 7u, SConst) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// scst5 (22-18), sint -let private parseSc5Si1 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SConst) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// scst5 (17-13), sint -let private parseSc5Si2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xsint, uint -let private parseXSiUi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// slong, uint -let private parseSlUi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SLong) - let o2 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// dp, dp -let private parseDpDp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, DP) - let o2 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// slong, sint -let private parseSlSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SLong) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xsp, dp -let private parseXSpDp bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSP) - let o2 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xsp, sint -let private parseXSpSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSP) - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// xu4, u2 -let private parseXU4U2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XU4) - let o2 = OperandInfo (extract bin 27u 23u, U2) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// s2, s2 -let private parseS2S2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, S2) - let o2 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// uscst16, sint -let private parseUSc16Si bin opcode unit = - let o1 = OperandInfo (extract bin 22u 7u, UConst) // FIXME - let o2 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseTwoOprs unit o1 o2) - -/// sint, xsint, sint -let private parseSiXSiSi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SInt) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, xsint, slong -let private parseSiXSiSl bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SInt) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, slong, slong -let private parseXSiSlSl bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XSInt) - let o2 = OperandInfo (extract bin 22u 18u, SLong) - let o3 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, xsint, sint -let private parseSc5XSiSi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, slong, slong -let private parseSc5SlSl bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, SLong) - let o3 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, sint, sint -let private parseSiSiSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SInt) - let o2 = OperandInfo (extract bin 17u 13u, SInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, ucst5, sint -let private parseSiUc5Si bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SInt) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sp, xsp, sp -let parseSpXSpSp bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SP) - let o2 = OperandInfo (extract bin 22u 18u, XSP) - let o3 = OperandInfo (extract bin 27u 23u, SP) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// dp, xdp, dp -let parseDpXDpDp bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, DP) - let o2 = OperandInfo (extract bin 22u 18u, XDP) - let o3 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// uint, xuint, ulong -let parseUiXUiUl bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UInt) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, ulong, ulong -let parseXUiUlUl bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XUInt) - let o2 = OperandInfo (extract bin 22u 18u, ULong) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// uint, xuint, uint -let parseUiXUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UInt) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, xuint, uint -let parseSc5XUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, uint, uint -let parseXUiUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, xsint, uint -let parseSiXSiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SInt) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, xsint, uint -let parseSc5XSiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, slong, uint -let parseXSiSlUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XSInt) - let o2 = OperandInfo (extract bin 22u 18u, SLong) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, slong, uint -let parseSc5SlUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, SLong) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// dp, xdp, sint -let parseDpXDpSi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, DP) - let o2 = OperandInfo (extract bin 22u 18u, XDP) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sp, xsp, sint -let parseSpXSpSi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SP) - let o2 = OperandInfo (extract bin 22u 18u, XSP) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ucst4, xuint, uint -let parseUc4XUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UConst) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, ulong, uint -let parseXUiUlUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XUInt) - let o2 = OperandInfo (extract bin 22u 18u, ULong) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ucst4, ulong, uint -let parseUc4UlUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UConst) - let o2 = OperandInfo (extract bin 22u 18u, ULong) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, uint, sint -let parseXSiUiSi bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// cst5, xuint, uint -let parseC5XUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Const) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// slsb16, xslsb16, sint -let parseSlsb16XSlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SLsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, xslsb16, sint -let parseSc5XSlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst7, ucst3, uint -let parseSc7Uc3Ui bin opcode unit = - let o1 = OperandInfo (extract bin 22u 16u, SConst) - let o2 = OperandInfo (extract bin 15u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, xsint, dint -let parseSiXSiDi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SInt) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// i4, xi4, i4 -let parseI4Xi4I4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, I4) - let o2 = OperandInfo (extract bin 22u 18u, XI4) - let o3 = OperandInfo (extract bin 27u 23u, I4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// B14/B15, ucst15, sint -let parseB14B15Uc15Si bin opcode unit = - let o1 = OperandInfo (pickBit bin 7u, B14B15) - let o2 = OperandInfo (extract bin 22u 8u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// i2, xi2, i2 -let parseI2Xi2I2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, I2) - let o2 = OperandInfo (extract bin 22u 18u, XI2) - let o3 = OperandInfo (extract bin 27u 23u, I2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, s2 -let parseS2XS2S2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// u4, xu4, u4 -let parseU4XU4U4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, U4) - let o2 = OperandInfo (extract bin 22u 18u, XU4) - let o3 = OperandInfo (extract bin 27u 23u, U4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, bv2 -let parseS2XS2Bv2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, BVec2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s4, xs4, bv4 -let parseS4XS4Bv4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S4) - let o2 = OperandInfo (extract bin 22u 18u, XS4) - let o3 = OperandInfo (extract bin 27u 23u, BVec4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// u4, xu4, bv4 -let parseU4XU4Bv4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, U4) - let o2 = OperandInfo (extract bin 22u 18u, XU4) - let o3 = OperandInfo (extract bin 27u 23u, BVec4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, dint -let parseS2XS2Di bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs4, dint -let parseS2XS4Di bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS4) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ds2, xs2, dint -let parseDS2XS2Di bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, DS2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ds2, xs2, s2 -let parseDS2XS2S2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, DS2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, int -let parseS2XS2Int bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, sllong -let parseS2XS2Sll bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, SLLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xu2, int -let parseS2XU2Int bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XU2) - let o3 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s4, xu4, int -let parseS4XU4Int bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S4) - let o2 = OperandInfo (extract bin 22u 18u, XU4) - let o3 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// u4, xu4, uint -let parseU4XU4Ui bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, U4) - let o2 = OperandInfo (extract bin 22u 18u, XU4) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// uint, uint, uint -let parseUiUiUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UInt) - let o2 = OperandInfo (extract bin 22u 18u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// smsb16, xsmsb16, sint -let parseSmsb16XSmsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// int, xint, sllong -let parseIntXiSll bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Int) - let o2 = OperandInfo (extract bin 22u 18u, XInt) - let o3 = OperandInfo (extract bin 27u 23u, SLLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// int, xint, int -let parseIntXiInt bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Int) - let o2 = OperandInfo (extract bin 22u 18u, XInt) - let o3 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// smsb16, xslsb16, sint -let parseSmsb16XSlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// umsb16, xulsb16, uint -let parseUmsb16XUlsb16Ui bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XULsb16) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// smsb16, xulsb16, sint -let parseSmsb16XUlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XULsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// smsb16, xumsb16, sint -let parseSmsb16XUmsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// umsb16, xumsb16, uint -let parseUmsb16XUmsb16Ui bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// umsb16, xslsb16, sint -let parseUmsb16XSlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// umsb16, xsmsb16, sint -let parseUmsb16XSmsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UMsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// cst5, xsint, sint -let parseC5XSiSi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Const) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, xsint, sdint -let parseSiXSiSDi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SInt) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, SDInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// cst5, xsint, sdint -let parseC5XSiSDi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Const) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, SDInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// slsb16, xsmsb16, sint -let parseSlsb16XSmsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SLsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ulsb16, xumsb16, uint -let parseUlsb16XUmsb16Ui bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, ULsb16) - let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// slsb16, xumsb16, sint -let parseSlsb16XUmsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SLsb16) - let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ulsb16, xsmsb16, sint -let parseUlsb16XSmsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, ULsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sp, xdp, dp -let parseSpXDpDp bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SP) - let o2 = OperandInfo (extract bin 22u 18u, XDP) - let o3 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sp, xsp, dp -let parseSpXSpDp bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SP) - let o2 = OperandInfo (extract bin 22u 18u, XSP) - let o3 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// slsb16, xulsb16, sint -let parseSlsb16XUlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SLsb16) - let o2 = OperandInfo (extract bin 22u 18u, XULsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// scst5, xulsb16, sint -let parseSc5XUlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SConst) - let o2 = OperandInfo (extract bin 22u 18u, XULsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s4, xu4, dws4 -let parseS4XU4DWS4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S4) - let o2 = OperandInfo (extract bin 22u 18u, XU4) - let o3 = OperandInfo (extract bin 27u 23u, DWS4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ulsb16, xulsb16, uint -let parseUlsb16XUlsb16Ui bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, ULsb16) - let o2 = OperandInfo (extract bin 22u 18u, XULsb16) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// u4, xu4, dwu4 -let parseU4XU4DWU4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, U4) - let o2 = OperandInfo (extract bin 22u 18u, XU4) - let o3 = OperandInfo (extract bin 27u 23u, DWU4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ulsb16, xslsb16, sint -let parseUlsb16XSlsb16Si bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, ULsb16) - let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, ullong -let parseS2XS2Ull bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, ULLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// int, xint, dint -let parseIntXiDi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Int) - let o2 = OperandInfo (extract bin 22u 18u, XInt) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// int, xuint, dint -let parseIntXUiDi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Int) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// uint, xuint, duint -let parseUiXUiDUi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UInt) - let o2 = OperandInfo (extract bin 22u 18u, XUInt) - let o3 = OperandInfo (extract bin 27u 23u, DUInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// uint, xint, dint -let parseUiXiDi bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, UInt) - let o2 = OperandInfo (extract bin 22u 18u, XInt) - let o3 = OperandInfo (extract bin 27u 23u, DInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, ucst5, uint -let parseXUiUc5Ui bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// sint, xsint, s2 -let parseSiXSiS2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, SInt) - let o2 = OperandInfo (extract bin 22u 18u, XSInt) - let o3 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// u2, xs2, u2 -let parseU2XS2U2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, U2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, U2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// slong, uint, slong -let parseSlUiSl bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SLong) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, uint, ulong -let parseXUiUiUl1 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XUInt) - let o2 = OperandInfo (extract bin 22u 18u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, uint, ulong -let parseXUiUiUl2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, ucst5, sint -let parseXSiUc5Si bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// slong, ucst5, slong -let parseSlUc5Sl bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SLong) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xuint, ucst5, ulong -let parseXUiUc5Ul bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XUInt) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xs2, uint, s2 -let parseXS2UiS2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XS2) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xs2, ucst5, s2 -let parseXS2Uc5S2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XS2) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ulong, uint, ulong -let parseUlUiUl bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, ULong) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// ulong, ucst5, ulong -let parseUlUc5Ul bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, ULong) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, ULong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xu2, uint, u2 -let parseXU2UiU2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XU2) - let o2 = OperandInfo (extract bin 17u 13u, UInt) - let o3 = OperandInfo (extract bin 27u 23u, U2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xu2, ucst5, u2 -let parseXU2Uc5U2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XU2) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 27u 23u, U2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// int, xint, s2 -let parseIntXiS2 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, Int) - let o2 = OperandInfo (extract bin 22u 18u, XInt) - let o3 = OperandInfo (extract bin 27u 23u, S2) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// s2, xs2, u4 -let parseS2XS2U4 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, S2) - let o2 = OperandInfo (extract bin 22u 18u, XS2) - let o3 = OperandInfo (extract bin 27u 23u, U4) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, sint, sint -let parseXSiSiSi1 bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XSInt) - let o2 = OperandInfo (extract bin 22u 18u, SInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, sint, sint -let parseXSiSiSi2 bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XSInt) - let o2 = OperandInfo (extract bin 17u 13u, SInt) - let o3 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xint, int, int -let parseXiIntInt bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, XInt) - let o2 = OperandInfo (extract bin 17u 13u, Int) - let o3 = OperandInfo (extract bin 27u 23u, Int) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsint, sint, slong -let parseXSiSiSl bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XSInt) - let o2 = OperandInfo (extract bin 22u 18u, SInt) - let o3 = OperandInfo (extract bin 27u 23u, SLong) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xdp, dp, dp -let parseXDpDpDp bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XDP) - let o2 = OperandInfo (extract bin 22u 18u, DP) - let o3 = OperandInfo (extract bin 27u 23u, DP) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// xsp, sp, sp -let parseXSpSpSp bin opcode unit = - let o1 = OperandInfo (extract bin 17u 13u, XSP) - let o2 = OperandInfo (extract bin 22u 18u, SP) - let o3 = OperandInfo (extract bin 27u 23u, SP) - struct (opcode, unit, parseThreeOprs unit o1 o2 o3) - -/// unit, ucst5, ucst5, uint -let parseUiUc5Uc5Ui bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, UInt) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 12u 8u, UConst) - let o4 = OperandInfo (extract bin 27u 23u, UInt) - struct (opcode, unit, parseFourOprs unit o1 o2 o3 o4) - -/// snit, ucst5, ucst5, sint -let parseSiUc5Uc5Si bin opcode unit = - let o1 = OperandInfo (extract bin 22u 18u, SInt) - let o2 = OperandInfo (extract bin 17u 13u, UConst) - let o3 = OperandInfo (extract bin 12u 8u, UConst) - let o4 = OperandInfo (extract bin 27u 23u, SInt) - struct (opcode, unit, parseFourOprs unit o1 o2 o3 o4) - -/// mem [offsetR/ucst5] -let parseDUnitLSBasicOperands bin opcode unit order = - let mem = parseMem (extract bin 22u 9u) unit - let reg = - parseRegBySide (extract bin 27u 23u) (getSide (sBit bin)) |> OpReg - struct (opcode, unit, buildMemOperand reg mem order) - -/// mem [ucst15] -let parseDUnitLSLongImmOperands bin opcode unit order = - let baseReg = getB14orB15 (yBit bin) - let mem = - OprMem (baseReg, PositiveOffset, UCst15 (uint64 (extract bin 22u 8u))) - let reg = - parseRegBySide (extract bin 27u 23u) (getSide (sBit bin)) |> OpReg - struct (opcode, unit, buildMemOperand reg mem order) - -/// mem, regPair -let parseDUnitDWordOperands bin opcode unit order = - let mem = parseMem (extract bin 22u 9u) unit - let v = extract bin 27u 23u - let regPair = - let high, low = if v &&& 0b1u = 0b0u then v + 1u, v else v, v - 1u - let side = getSide (sBit bin) - (parseRegBySide high side, parseRegBySide low side) |> RegisterPair - struct (opcode, unit, buildMemOperand regPair mem order) - -let is0xxxx address = address &&& 0b10000u = 0b00000u - -let getCtrlReg crHi crLo = - match crHi, crLo with - | _, 0b00000u when is0xxxx crHi -> R.AMR - | _, 0b00001u when is0xxxx crHi -> R.CSR - | 0b00000u, 0b11001u -> R.DIER - | 0b00000u, 0b10001u -> R.DNUM - | 0b00000u, 0b11101u -> R.ECR - (* | 0b00000u, 0b11101u -> R.EFR *) // XXX: depending on the MVC - | 0b00000u, 0b10010u -> R.FADCR - | 0b00000u, 0b10011u -> R.FAUCR - | 0b00000u, 0b10100u -> R.FMCR - | 0b00000u, 0b11000u -> R.GFPGFR - | 0b00000u, 0b10110u -> R.GPLYA - | 0b00000u, 0b10111u -> R.GPLYB - | _, 0b00011u when is0xxxx crHi -> R.ICR - | _, 0b00100u when is0xxxx crHi -> R.IER - | 0b00000u, 0b11111u -> R.IERR - | 0b00000u, 0b00010u -> R.IFR - | 0b00010u, 0b00010u -> R.IFR - | 0b00000u, 0b01101u -> R.ILC - | _, 0b00110u when is0xxxx crHi -> R.IRP - | _, 0b00010u when is0xxxx crHi -> R.ISR - | _, 0b00101u when is0xxxx crHi -> R.ISTP - | 0b00000u, 0b11011u -> R.ITSR - | _, 0b00111u when is0xxxx crHi -> R.NRP - | 0b00000u, 0b11100u -> R.NTSR - | 0b00000u, 0b10000u -> R.PCE1 - | 0b10000u, 0b10000u -> R.PCE1 - | 0b00000u, 0b01111u -> R.REP - | 0b00000u, 0b01110u -> R.RILC - | 0b00000u, 0b10101u -> R.SSR - | 0b00000u, 0b01011u -> R.TSCH - | 0b00000u, 0b01010u -> R.TSCL - | 0b00000u, 0b11010u -> R.TSR - | _ -> Utils.impossible () - -/// Control Register to Register -let parseCtrlRegToReg bin opcode unit = - let o1 = getCtrlReg (extract bin 17u 13u) (extract bin 22u 18u) |> OpReg - let o2 = translateOperand unit (OperandInfo (extract bin 27u 23u, UInt)) - struct (opcode, unit, TwoOperands (o1, o2)) - -/// Register to Control Register -let parseRegToCtrlReg bin opcode unit = - let o1 = translateOperand unit (OperandInfo (extract bin 22u 18u, XUInt)) - let o2 = getCtrlReg (extract bin 17u 13u) (extract bin 27u 23u) |> OpReg - struct (opcode, unit, TwoOperands (o1, o2)) - -let private getDUnit s x = - match s, x with - | 0b0u, 0b0u -> D1Unit - | 0b0u, 0b1u -> D1XUnit - | 0b1u, 0b0u -> D2Unit - | _ (* 0b1u, 0b1u *) -> D2XUnit - -/// Appendix C. page 724. Fig. C-1 -let private parseDUnitSrcs bin = - let unit = getDUnit (sBit bin) 0u - match extract bin 12u 7u with - | 0b000000u -> parseSc5Si2 bin Op.MVK unit - | 0b010000u -> parseSiSiSi bin Op.ADD unit - | 0b010001u -> parseSiSiSi bin Op.SUB unit - | 0b010010u when isSrc1Zero bin -> parseSiSi bin Op.MV unit - | 0b010010u -> parseSiUc5Si bin Op.ADD unit - | 0b010011u -> parseSiUc5Si bin Op.SUB unit - | 0b110000u -> parseSiSiSi bin Op.ADDAB unit - | 0b110001u -> parseSiSiSi bin Op.SUBAB unit - | 0b110010u -> parseSiUc5Si bin Op.ADDAB unit - | 0b110011u -> parseSiUc5Si bin Op.SUBAB unit - | 0b110100u -> parseSiSiSi bin Op.ADDAH unit - | 0b110101u -> parseSiSiSi bin Op.SUBAH unit - | 0b110110u -> parseSiUc5Si bin Op.ADDAH unit - | 0b110111u -> parseSiUc5Si bin Op.SUBAH unit - | 0b111000u -> parseSiSiSi bin Op.ADDAW unit - | 0b111001u -> parseSiSiSi bin Op.SUBAW unit - | 0b111010u -> parseSiUc5Si bin Op.ADDAW unit - | 0b111011u -> parseSiUc5Si bin Op.SUBAW unit - | 0b111100u -> parseSiSiSi bin Op.ADDAD unit - | 0b111101u -> parseSiUc5Si bin Op.ADDAD unit - | _ -> Utils.impossible () - -/// Appendix C. page 724. Fig. C-2 -let private parseDUnitSrcsExt bin = - let unit = getDUnit (sBit bin) (xBit bin) - match extract bin 9u 6u with - | 0b0000u -> parseUiXUiUi bin Op.ANDN unit - | 0b0010u -> parseUiXUiUi bin Op.OR unit - | 0b0011u when isSrc1Zero bin -> parseXUiUi bin Op.MV unit - | 0b0011u -> parseSc5XUiUi bin Op.OR unit - | 0b0100u -> parseI2Xi2I2 bin Op.ADD2 unit - | 0b0101u -> parseI2Xi2I2 bin Op.SUB2 unit - | 0b0110u -> parseUiXUiUi bin Op.AND unit - | 0b0111u -> parseSc5XUiUi bin Op.AND unit - | 0b1010u -> parseSiXSiSi bin Op.ADD unit - | 0b1011u -> parseSc5XSiSi bin Op.ADD unit - | 0b1100u -> parseSiXSiSi bin Op.SUB unit - | 0b1110u -> parseUiXUiUi bin Op.XOR unit - | 0b1111u when isSrc111111 bin -> parseXUiUi bin Op.NOT unit - | 0b1111u -> parseSc5XUiUi bin Op.XOR unit - | _ -> Utils.impossible () - -/// Appendix C. page 724. Fig. C-3 -let private parseDUnitADDLongImm bin = - let unit = getDUnit (sBit bin) 0u - match extract bin 6u 4u with - | 0b011u -> parseB14B15Uc15Si bin Op.ADDAB unit - | 0b101u -> parseB14B15Uc15Si bin Op.ADDAH unit - | 0b111u -> parseB14B15Uc15Si bin Op.ADDAW unit - | _ -> Utils.impossible () - -/// Appendix C. page 724. Fig. C-4 -let private parseDUnitLSBasic bin = - let unit = getDUnit (yBit bin) 0u - match extract bin 6u 4u with - | 0b000u -> parseDUnitLSBasicOperands bin Op.LDHU unit MemReg - | 0b001u -> parseDUnitLSBasicOperands bin Op.LDBU unit MemReg - | 0b010u -> parseDUnitLSBasicOperands bin Op.LDB unit MemReg - | 0b011u -> parseDUnitLSBasicOperands bin Op.STB unit RegMem - | 0b100u -> parseDUnitLSBasicOperands bin Op.LDH unit MemReg - | 0b101u -> parseDUnitLSBasicOperands bin Op.STH unit RegMem - | 0b110u -> parseDUnitLSBasicOperands bin Op.LDW unit MemReg - | 0b111u -> parseDUnitLSBasicOperands bin Op.STW unit RegMem - | _ -> Utils.impossible () - -/// Appendix C. page 724. Fig. C-5 -let private parseDUnitLSLongImm bin = - match extract bin 6u 4u with - | 0b000u -> parseDUnitLSLongImmOperands bin Op.LDHU D2Unit MemReg - | 0b001u -> parseDUnitLSLongImmOperands bin Op.LDBU D2Unit MemReg - | 0b010u -> parseDUnitLSLongImmOperands bin Op.LDB D2Unit MemReg - | 0b011u -> parseDUnitLSLongImmOperands bin Op.STB D2Unit RegMem - | 0b100u -> parseDUnitLSLongImmOperands bin Op.LDH D2Unit MemReg - | 0b101u -> parseDUnitLSLongImmOperands bin Op.STH D2Unit RegMem - | 0b110u -> parseDUnitLSLongImmOperands bin Op.LDW D2Unit MemReg - | 0b111u -> parseDUnitLSLongImmOperands bin Op.STW D2Unit RegMem - | _ -> Utils.impossible () - -/// Appendix C. page 724. Fig. C-6 -let private parseDUnitLSDWord bin = struct (Op.InvalOP, NoUnit, NoOperand) - -/// Appendix C. page 724. Fig. C-7 -let private parseDUnitLSNonalignDWord bin = - struct (Op.InvalOP, NoUnit, NoOperand) - -let private getLUnit s x = - match s, x with - | 0b0u, 0b0u -> L1Unit - | 0b0u, 0b1u -> L1XUnit - | 0b1u, 0b0u -> L2Unit - | _ (* 0b1u, 0b1u *) -> L2XUnit - -let private getSUnit s x = - match s, x with - | 0b0u, 0b0u -> S1Unit - | 0b0u, 0b1u -> S1XUnit - | 0b1u, 0b0u -> S2Unit - | _ (* 0b1u, 0b1u *) -> S2XUnit - -/// Appendix D. page 735. Fig. D-1 -let private parseLUnitSrcs bin = struct (Op.InvalOP, NoUnit, NoOperand) - -/// Appendix D. page 735. Fig. D-2 -let private parseLUnitUnary bin = - let unit = getLUnit (sBit bin) (xBit bin) - match extract bin 17u 13u with - | 0b00000u -> parseXSiSi bin Op.ABS unit - | 0b00001u -> parseXU4U4 bin Op.SWAP4 unit - | 0b00010u -> parseXU4U2 bin Op.UNPKLU4 unit - | 0b00011u -> parseXU4U2 bin Op.UNPKHU4 unit - | 0b00100u -> parseXs2S2 bin Op.ABS2 unit - | 0b00101u -> parseSc5Si1 bin Op.MVK unit - | _ -> Utils.impossible () - -/// Appendix D. page 735. Fig. D-3 -let private parseLUnitNonCond bin = struct (Op.InvalOP, NoUnit, NoOperand) - -let private getMUnit s x = - match s, x with - | 0b0u, 0b0u -> M1Unit - | 0b0u, 0b1u -> M1XUnit - | 0b1u, 0b0u -> M2Unit - | _ (* 0b1u, 0b1u *) -> M2XUnit - -/// Appendix E. page 743. Fig. E-1 -let private parseMUnitCompound bin = - let unit = getMUnit (sBit bin) (xBit bin) - match extract bin 10u 6u with - | 0b00000u -> parseS2XS2Ull bin Op.MPY2 unit - | 0b00001u -> parseS2XS2Sll bin Op.SMPY2 unit - | 0b00010u -> parseS4XU4Int bin Op.DOTPSU4 unit (* DOTPUS4 *) - | 0b00100u -> parseU4XU4DWU4 bin Op.MPYU4 unit - | 0b00101u -> parseS4XU4DWS4 bin Op.MPYSU4 unit (* MPYUS4 *) - | 0b00110u -> parseU4XU4Ui bin Op.DOTPU4 unit - | 0b00111u -> parseS2XU2Int bin Op.DOTPNRSU2 unit (* DOTPNRUS2 *) - | 0b01001u -> parseS2XS2Int bin Op.DOTPN2 unit - | 0b01101u -> parseS2XU2Int bin Op.DOTPRSU2 unit (* DOTPRUS2 *) - | 0b01011u -> parseS2XS2Sll bin Op.DOTP2 unit - | 0b01100u -> parseS2XS2Int bin Op.DOTP2 unit - | 0b01110u -> parseIntXiInt bin Op.MPYLIR unit (* MPYILR *) - | 0b10000u -> parseIntXiInt bin Op.MPYHIR unit (* MPYIHR *) - | 0b10001u -> parseU4XU4U4 bin Op.GMPY4 unit - | 0b10010u -> parseU4XU4U4 bin Op.AVGU4 unit - | 0b10011u -> parseS2XS2S2 bin Op.AVG2 unit - | 0b10100u -> parseIntXiSll bin Op.MPYHI unit (* MPYIH *) - | 0b10101u -> parseIntXiSll bin Op.MPYLI unit (* MPYIL *) - | 0b10110u -> parseSpXDpDp bin Op.MPYSPDP unit - | 0b10111u -> parseSpXSpDp bin Op.MPYSP2DP unit - | 0b11000u -> parseUiXUiDUi bin Op.MPY32U unit - | 0b11001u -> parseUiXiDi bin Op.MPY32US unit - | 0b11010u -> parseXiIntInt bin Op.SSHVR unit - | 0b11100u -> parseXiIntInt bin Op.SSHVL unit - | 0b11101u -> parseXUiUiUi bin Op.ROTL unit - | 0b11110u -> parseXUiUc5Ui bin Op.ROTL unit - | _ -> Utils.impossible () - -/// Appendix E. page 743. Fig. E-2 -let private parseMUnitUnaryExt bin = - let unit = getMUnit (sBit bin) (xBit bin) - match extract bin 17u 13u with - | 0b11010u -> parseXiInt bin Op.MVD unit - | 0b11000u -> parseXUiUi bin Op.XPND4 unit - | 0b11001u -> parseXUiUi bin Op.XPND2 unit - | 0b11101u -> parseXUiUi bin Op.DEAL unit - | 0b11100u -> parseXUiUi bin Op.SHFL unit - | 0b11110u -> parseXU4U4 bin Op.BITC4 unit - | 0b11111u -> parseXUiUi bin Op.BITR unit - | _ -> Utils.impossible () - -/// Appendix E. page 743. Fig. E-3 -let private parseMUnitNonCond bin = - let unit = getMUnit (sBit bin) (xBit bin) - match extract bin 10u 6u with - | 0b01010u -> parseS2XS2Di bin Op.CMPY unit - | 0b01011u -> parseS2XS2S2 bin Op.CMPYR unit - | 0b01100u -> parseS2XS2S2 bin Op.CMPYR1 unit - | 0b01111u -> parseIntXiDi bin Op.MPY2IR unit (* E-1, Exceptional case. *) - | 0b10100u -> parseDS2XS2S2 bin Op.DDOTPL2R unit - | 0b10101u -> parseDS2XS2S2 bin Op.DDOTPH2R unit - | 0b10110u -> parseDS2XS2Di bin Op.DDOTPL2 unit - | 0b10111u -> parseDS2XS2Di bin Op.DDOTPH2 unit - | 0b11000u -> parseS2XS4Di bin Op.DDOTP4 unit - | 0b11001u -> parseIntXiInt bin Op.SMPY32 unit - | 0b11011u -> parseUiXUiUi bin Op.XORMPY unit - | 0b11111u -> parseUiUiUi bin Op.GMPY unit - | _ -> Utils.impossible () - -/// Appendix E. page 743. Fig. E-4 -let private parseMUnitMPY bin = - let unit = getMUnit (sBit bin) (xBit bin) - match extract bin 11u 7u with - | 0b00001u -> parseSmsb16XSmsb16Si bin Op.MPYH unit - | 0b00010u -> parseSmsb16XSmsb16Si bin Op.SMPYH unit - | 0b00011u -> parseSmsb16XUmsb16Si bin Op.MPYHSU unit - | 0b00100u -> parseSiXSiSi bin Op.MPYI unit - | 0b00101u -> parseUmsb16XSmsb16Si bin Op.MPYHUS unit - | 0b00110u -> parseC5XSiSi bin Op.MPYI unit - | 0b00111u -> parseUmsb16XUmsb16Ui bin Op.MPYHU unit - | 0b01000u -> parseSiXSiSDi bin Op.MPYID unit - | 0b01001u -> parseSmsb16XSlsb16Si bin Op.MPYHL unit - | 0b01010u -> parseSmsb16XSlsb16Si bin Op.SMPYHL unit - | 0b01011u -> parseSmsb16XUlsb16Si bin Op.MPYHSLU unit - | 0b01100u -> parseC5XSiSDi bin Op.MPYID unit - | 0b01101u -> parseUmsb16XSlsb16Si bin Op.MPYHULS unit - | 0b01110u -> parseDpXDpDp bin Op.MPYDP unit - | 0b01111u -> parseUmsb16XUlsb16Ui bin Op.MPYHLU unit - | 0b10000u -> parseIntXiInt bin Op.MPY32 unit - | 0b10001u -> parseSlsb16XSmsb16Si bin Op.MPYLH unit - | 0b10010u -> parseSlsb16XSmsb16Si bin Op.SMPYLH unit - | 0b10011u -> parseSlsb16XUmsb16Si bin Op.MPYLSHU unit - | 0b10100u -> parseIntXiDi bin Op.MPY32 unit - | 0b10101u -> parseUlsb16XSmsb16Si bin Op.MPYLUHS unit - | 0b10110u -> parseIntXUiDi bin Op.MPY32SU unit - | 0b10111u -> parseUlsb16XUmsb16Ui bin Op.MPYLHU unit - | 0b11000u -> parseSc5XSlsb16Si bin Op.MPY unit - | 0b11001u -> parseSlsb16XSlsb16Si bin Op.MPY unit - | 0b11010u -> parseSlsb16XSlsb16Si bin Op.SMPY unit - | 0b11011u -> parseSlsb16XUlsb16Si bin Op.MPYSU unit - | 0b11100u -> parseSpXSpSp bin Op.MPYSP unit - | 0b11101u -> parseUlsb16XSlsb16Si bin Op.MPYUS unit - | 0b11110u -> parseSc5XUlsb16Si bin Op.MPYSU unit - | 0b11111u -> parseUlsb16XUlsb16Ui bin Op.MPYU unit - | _ -> Utils.impossible () - -/// Appendix F. page 747. Fig. F-1 -let private parseSUnitSrcs bin = - let unit = getSUnit (sBit bin) (xBit bin) - match extract bin 11u 6u with - | 0b000001u -> parseI2Xi2I2 bin Op.ADD2 unit - | 0b000010u -> parseXSpDp bin Op.SPDP unit - | 0b000110u when isSrc1Zero bin -> parseXSiSi bin Op.MV unit - | 0b000110u -> parseSc5XSiSi bin Op.ADD unit - | 0b000111u -> parseSiXSiSi bin Op.ADD unit - | 0b001000u -> parseI2Xi2I2 bin Op.PACKHL2 unit - | 0b001001u -> parseI2Xi2I2 bin Op.PACKH2 unit - | 0b001010u when isSrc111111 bin -> parseXUiUi bin Op.NOT unit - | 0b001010u -> parseSc5XUiUi bin Op.XOR unit - | 0b001011u -> parseUiXUiUi bin Op.XOR unit - | 0b001110u -> parseRegToCtrlReg bin Op.MVC unit - | 0b001111u -> parseCtrlRegToReg bin Op.MVC unit - | 0b010000u when isSrc100010 bin -> parseS2S2 bin Op.SWAP2 unit // FIXME - | 0b010000u -> parseI2Xi2I2 bin Op.PACKLH2 unit - | 0b010001u -> parseI2Xi2I2 bin Op.SUB2 unit - | 0b010010u -> parseXUiUc5Ul bin Op.SHL unit - | 0b010011u -> parseXUiUiUl2 bin Op.SHL unit - | 0b010100u -> parseS2XS2Bv2 bin Op.CMPGT2 unit (* CMPLT2 src2, src1, dst *) - | 0b010101u -> parseU4XU4Bv4 bin Op.CMPGTU4 unit (* CMPLTU4 src2, src1, dst *) - | 0b010110u when isSrc1Zero bin -> parseXSiSi bin Op.NEG unit - | 0b010110u -> parseSc5XSiSi bin Op.SUB unit - | 0b010111u -> parseSiXSiSi bin Op.SUB unit - | 0b011000u -> parseXS2Uc5S2 bin Op.SHR2 unit - | 0b011001u -> parseXU2Uc5U2 bin Op.SHRU2 unit - | 0b011010u -> parseSc5XUiUi bin Op.OR unit - | 0b011011u -> parseUiXUiUi bin Op.OR unit - | 0b011100u -> parseS4XS4Bv4 bin Op.CMPEQ4 unit - | 0b011101u -> parseS2XS2Bv2 bin Op.CMPEQ2 unit - | 0b011110u -> parseSc5XUiUi bin Op.AND unit - | 0b011111u -> parseUiXUiUi bin Op.AND unit - | 0b100000u -> parseSiXSiSi bin Op.SADD unit - | 0b100010u -> parseXSiUc5Si bin Op.SSHL unit - | 0b100011u -> parseXSiUiSi bin Op.SSHL unit - | 0b100100u -> parseUlUc5Ul bin Op.SHRU unit - | 0b100101u -> parseUlUiUl bin Op.SHRU unit - | 0b100110u -> parseXUiUc5Ui bin Op.SHRU unit - | 0b100111u -> parseXUiUiUi bin Op.SHRU unit - | 0b101000u -> parseDpXDpSi bin Op.CMPEQDP unit - | 0b101001u -> parseDpXDpSi bin Op.CMPGTDP unit - | 0b101010u -> parseDpXDpSi bin Op.CMPLTDP unit - | 0b101011u -> parseXUiUiUi bin Op.EXTU unit - | 0b101100u -> parseXDpDp bin Op.ABSDP unit - | 0b101101u -> parseDpDp bin Op.RCPDP unit - | 0b101110u -> parseDpDp bin Op.RSQRDP unit - | 0b101111u -> parseXSiUiSi bin Op.EXT unit - | 0b110000u -> parseSlUc5Sl bin Op.SHL unit - | 0b110001u -> parseSlUiSl bin Op.SHL unit - | 0b110010u -> parseXSiUc5Si bin Op.SHL unit - | 0b110011u -> parseXSiUiSi bin Op.SHL unit - | 0b110100u -> parseSlUc5Sl bin Op.SHR unit - | 0b110101u -> parseSlUiSl bin Op.SHR unit - | 0b110110u -> parseXSiUc5Si bin Op.SHR unit - | 0b110111u -> parseXSiUiSi bin Op.SHR unit - | 0b111000u -> parseSpXSpSi bin Op.CMPEQSP unit - | 0b111001u -> parseSpXSpSi bin Op.CMPGTSP unit - | 0b111010u -> parseSpXSpSi bin Op.CMPLTSP unit - | 0b111011u -> parseXUiUiUi bin Op.SET unit - | 0b111110u -> parseXSpSp bin Op.RSQRSP unit - | 0b111111u -> parseXUiUiUi bin Op.CLR unit - | _ -> Utils.impossible () - -/// Appendix F. page 747. Fig. F-2 -let private parseSUnitAddSubFloat bin = struct (Op.InvalOP, NoUnit, NoOperand) - -/// Appendix F. page 747. Fig. F-3 -let private parseSUnitADDK bin = - parseSc16Ui bin Op.ADDK (getSUnit (sBit bin) 0u) - -/// Appendix F. page 748. Fig. F-4 -let private parseSUnitADDKPC bin = - parseSc7Uc3Ui bin Op.ADDKPC (getSUnit (sBit bin) 0u) - -/// Appendix F. page 748. Fig. F-5 -let private parseSUnitSrcsExt bin = - let unit = getSUnit (sBit bin) (xBit bin) - match extract bin 9u 6u with - | 0b0000u -> parseS2XS2S2 bin Op.SADD2 unit - | 0b0001u -> parseU2XS2U2 bin Op.SADDUS2 unit (* SADDSU2 *) - | 0b0010u -> parseIntXiS2 bin Op.SPACK2 unit - | 0b0011u -> parseU4XU4U4 bin Op.SADDU4 unit - | 0b0100u -> parseS2XS2U4 bin Op.SPACKU4 unit - | 0b0101u -> parseXSiSiSi2 bin Op.SUB unit - | 0b0110u -> parseUiXUiUi bin Op.ANDN unit - | 0b0111u -> parseXS2UiS2 bin Op.SHR2 unit - | 0b1000u -> parseXU2UiU2 bin Op.SHRU2 unit - | 0b1001u -> parseU4XU4U4 bin Op.SHLMB unit - | 0b1010u -> parseU4XU4U4 bin Op.SHRMB unit - | 0b1011u -> parseSiXSiDi bin Op.DMV unit - | 0b1100u -> parseS2XS2S2 bin Op.MIN2 unit - | 0b1101u -> parseS2XS2S2 bin Op.MAX2 unit - | 0b1111u -> parseI2Xi2I2 bin Op.PACK2 unit - | _ -> Utils.impossible () - -/// Appendix F. page 748. Fig. F-6 -let private parseSUnitBrDisp bin = - parseSc21 bin Op.B (getSUnit (sBit bin) 0u) // FIXME: label - -/// Appendix F. page 748. Fig. F-7 -let private parseSUnitBrRegWithoutNOP bin = - parseXUi bin Op.B (getSUnit (sBit bin) (xBit bin)) - -/// Appendix F. page 748. Fig. F-8 -let private parseSUnitBrPointer bin = struct (Op.InvalOP, NoUnit, NoOperand) - -/// Appendix F. page 748. Fig. F-9 -let private parseSUnitBdecBpos bin = - let unit = getSUnit (sBit bin) 0u - match pickBit bin 12u with - | 0b1u -> parseSc10Int bin Op.BDEC unit - | _ (* 0b0u *) -> parseSc10Int bin Op.BPOS unit - -/// Appendix F. page 748. Fig. F-10 -let private parseSUnitBrDispNOP bin = - parseSc12Uc3 bin Op.BNOP (getSUnit (sBit bin) 0u) - -/// Appendix F. page 748. Fig. F-11 -let private parseSUnitBrRegNOP bin = - parseXUiUc3 bin Op.BNOP (getSUnit (sBit bin) (xBit bin)) - -/// Appendix F. page 749. Fig. F-12 -let private parseSUnitNonCondImm bin = - parseSc21 bin Op.CALLP (getSUnit (sBit bin) 0u) // FIXME: label - -/// Appendix F. page 749. Fig. F-13 -let private parseSUnitMoveConst bin = - match pickBit bin 6u with - | 0b0u -> parseSc16Si bin Op.MVK (getSUnit (sBit bin) 0u) - | _ (* 0b01 *) -> parseUSc16Si bin Op.MVKH (getSUnit (sBit bin) 0u) // FIXME - -/// Appendix F. page 749. Fig. F-14 -let private parseSUnitNonCond bin = - let unit = getSUnit (sBit bin) (xBit bin) - match extract bin 9u 6u with - | 0b1011u -> parseSiXSiS2 bin Op.RPACK2 unit - | _ -> Utils.impossible () - -/// Appendix F. page 749. Fig. F-15 -let private parseSUnitUnary bin = - let unit = getSUnit (sBit bin) (xBit bin) - match extract bin 17u 13u with - | 0b00000u -> parseXSpSp bin Op.ABSSP unit - | 0b00010u -> parseXU4U2 bin Op.UNPKLU4 unit - | 0b00011u -> parseXU4U2 bin Op.UNPKHU4 unit - | _ -> Utils.impossible () - -/// Appendix F. page 749. Fig. F-16 -let private parseSUnitFieldOps bin = - match extract bin 7u 6u with - | 0b00u -> parseUiUc5Uc5Ui bin Op.EXTU (getSUnit (sBit bin) 0u) - | 0b01u -> parseSiUc5Uc5Si bin Op.EXT (getSUnit (sBit bin) 0u) - | 0b10u -> parseUiUc5Uc5Ui bin Op.SET (getSUnit (sBit bin) 0u) - | 0b11u -> parseUiUc5Uc5Ui bin Op.CLR (getSUnit (sBit bin) 0u) - | _ -> Utils.impossible () - -/// Appendix H. page 765. Fig. H-1 -let private parseNoUnitDINT bin = - match extract bin 16u 13u with - | 0b0000u -> struct (Op.SWE, NoUnit, NoOperand) - | 0b0001u -> struct (Op.SWENR, NoUnit, NoOperand) - | 0b0010u -> struct (Op.DINT, NoUnit, NoOperand) - | 0b0011u -> struct (Op.RINT, NoUnit, NoOperand) - | _ -> Utils.impossible () - -/// Appendix H. page 765. Fig. H-2 -let private parseNoUnitIdleNop bin = - match extract bin 16u 13u with - | 0b1111u -> struct (Op.IDLE, NoUnit, NoOperand) - | _ -> parseUc4 bin Op.NOP NoUnit - -/// Appendix H. page 765. Fig. H-3 -let private parseNoUnitLoopNonCond bin = struct (Op.InvalOP, NoUnit, NoOperand) - -/// Appendix H. page 765. Fig. H-4 -let private parseNoUnitLoop bin = struct (Op.InvalOP, NoUnit, NoOperand) - -let private parseNoUnitCase0 bin = - match extract bin 31u 28u with - | 0b0000u -> parseNoUnitIdleNop bin - | 0b0001u -> parseNoUnitDINT bin - | _ -> Utils.impossible () - -let private parseNoUnitCase1 bin = - match extract bin 31u 28u with - | 0b0000u -> parseNoUnitLoopNonCond bin - | _ -> parseNoUnitLoop bin - -let private parseNoUnit bin = - match pickBit bin 17u with - | 0b0u -> parseNoUnitCase0 bin - | _ (* 0b1u *) -> parseNoUnitCase1 bin - -let private parseCase00000 bin = - match extract bin 12u 7u with - | 0b000000u -> parseNoUnit bin - | _ -> parseMUnitMPY bin - -let private parseCase0000 bin = - match pickBit bin 6u with - | 0b1u -> parseDUnitSrcs bin - | _ (* 0b0u *) -> parseCase00000 bin - -let private parseCase00100 bin = - match extract bin 31u 28u with - | 0b0001u -> parseSUnitNonCondImm bin - | _ -> parseSUnitBrDisp bin - -let private parseCase0100 bin = - match pickBit bin 6u with - | 0b0u -> parseCase00100 bin - | _ (* 0b1u *) -> parseSUnitADDK bin - -let private parseSUnitBrReg bin = - match pickBit bin 23u with - | 0b0u -> parseSUnitBrRegWithoutNOP bin - | _ (* 0b1u *) -> parseSUnitBrRegNOP bin - -let private parseCase1000 bin = - match extract bin 11u 6u with - | 0b000000u -> parseSUnitBdecBpos bin - | 0b000011u -> parseSUnitBrPointer bin - | 0b000100u -> parseSUnitBrDispNOP bin - | 0b000101u -> parseSUnitADDKPC bin - | 0b111100u -> parseSUnitUnary bin - | 0b001101u -> parseSUnitBrReg bin - | _ -> parseSUnitSrcs bin - -let parseMUnitSub bin = - match extract bin 31u 28u with - | 0b0001u -> parseMUnitNonCond bin - | _ -> parseMUnitCompound bin - -let private parseMUnit bin = - match extract bin 10u 6u with - | 0b00011u -> parseMUnitUnaryExt bin - | _ -> parseMUnitSub bin - -let parseCase111100 bin = - match extract bin 31u 28u with - | 0b0001u -> parseSUnitNonCond bin - | _ -> parseSUnitSrcsExt bin - -let private parseCase11100 bin = - match pickBit bin 10u with - | 0b0u -> parseDUnitSrcsExt bin - | _ (* 0b1u *) -> parseCase111100 bin - -let private parseCase1100 bin = - match pickBit bin 11u with - | 0b0u -> parseMUnit bin - | _ (* 0b1u *) -> parseCase11100 bin - -let private parseCase00 bin = - match extract bin 5u 4u with - | 0b00u -> parseCase0000 bin - | 0b01u -> parseCase0100 bin - | 0b10u -> parseCase1000 bin - | _ (* 0b11 *) -> parseCase1100 bin - -let private parseCase010 bin = - match pickBit bin 5u with - | 0b0u -> parseSUnitFieldOps bin - | _ (* 0b1u *) -> parseSUnitMoveConst bin - -let private parseCase110 bin = - let x, s = xBit bin, sBit bin - let creg = extract bin 31u 29u - match extract bin 11u 5u with - | 0b0011010u -> parseLUnitUnary bin - (* parseLUnitNonCond, D-3 *) - | 0b0001110u when creg = 0b0001u -> - parseSiXSiDi bin Op.SADDSUB (getLUnit s x) - | 0b0001111u when creg = 0b0001u -> - parseSiXSiDi bin Op.SADDSUB2 (getLUnit s x) - | 0b0110011u -> parseSiXSiDi bin Op.DPACKX2 (getLUnit s x) - | 0b0110100u -> parseSiXSiDi bin Op.DPACK2 (getLUnit s x) - | 0b0110110u -> parseSiXSiDi bin Op.SHFL3 (getLUnit s x) - (* parseLUnitSrcs, D-1 *) - | 0b0000000u -> parseI2Xi2I2 bin Op.PACK2 (getLUnit s x) - | 0b0000001u -> parseDpSi bin Op.DPTRUNC (getLUnit s x) - | 0b0000011u -> parseSiXSiSi bin Op.ADD (getLUnit s x) - | 0b0000010u when isSrc1Zero bin -> parseXSiSi bin Op.MV (getLUnit s x) - | 0b0000010u -> parseSc5XSiSi bin Op.ADD (getLUnit s x) - | 0b0000100u -> parseI2Xi2I2 bin Op.SUB2 (getLUnit s x) - | 0b0000101u -> parseI2Xi2I2 bin Op.ADD2 (getLUnit s x) - | 0b0000110u when isSrc1Zero bin -> parseXSiSi bin Op.NEG (getLUnit s x) - | 0b0000110u -> parseSc5XSiSi bin Op.SUB (getLUnit s x) - | 0b0000111u when isEqualSrc1Src2 bin -> parseSi bin Op.ZERO (getLUnit s x) - | 0b0000111u -> parseSiXSiSi bin Op.SUB (getLUnit s x) - | 0b0001000u -> parseDpSi bin Op.DPINT (getLUnit s x) - | 0b0001001u -> parseDpSp bin Op.DPSP (getLUnit s x) - | 0b0001010u -> parseXSpSi bin Op.SPINT (getLUnit s x) - | 0b0001011u -> parseXSpSi bin Op.SPTRUNC (getLUnit s x) - | 0b0001100u -> parseSiXSiDi bin Op.ADDSUB (getLUnit s x) - | 0b0001101u -> parseSiXSiDi bin Op.ADDSUB2 (getLUnit s x) - | 0b0001110u -> parseSc5XSiSi bin Op.SSUB (getLUnit s x) - | 0b0001111u -> parseSiXSiSi bin Op.SSUB (getLUnit s x) - | 0b0010000u -> parseSpXSpSp bin Op.ADDSP (getLUnit s x) - | 0b0010001u -> parseSpXSpSp bin Op.SUBSP (getLUnit s x) - | 0b0010010u -> parseSc5XSiSi bin Op.SADD (getLUnit s x) - | 0b0010011u -> parseSiXSiSi bin Op.SADD (getLUnit s x) - | 0b0010101u -> parseXSpSpSp bin Op.SUBSP (getLUnit s x) - | 0b0010111u -> parseXSiSiSi1 bin Op.SUB (getLUnit s x) - | 0b0011000u -> parseDpXDpDp bin Op.ADDDP (getLUnit s x) - | 0b0011001u -> parseDpXDpDp bin Op.SUBDP (getLUnit s x) - | 0b0011011u when isSrc100010 bin -> parseS2S2 bin Op.SWAP2 (getLUnit s x) - | 0b0011011u -> parseI2Xi2I2 bin Op.PACKLH2 (getLUnit s x) - | 0b0011100u -> parseI2Xi2I2 bin Op.PACKHL2 (getLUnit s x) - | 0b0011101u -> parseXDpDpDp bin Op.SUBDP (getLUnit s x) - | 0b0011110u -> parseI2Xi2I2 bin Op.PACKH2 (getLUnit s x) - | 0b0011111u -> parseXSiSiSi1 bin Op.SSUB (getLUnit s x) - | 0b0100000u when isSrc1Zero bin -> parseSlSl bin Op.MV (getLUnit s 0u) - | 0b0100000u -> parseSc5SlSl bin Op.ADD (getLUnit s x) - | 0b0100001u -> parseXSiSlSl bin Op.ADD (getLUnit s x) - | 0b0100011u -> parseSiXSiSl bin Op.ADD (getLUnit s x) - | 0b0100100u when isSrc1Zero bin -> parseSlSl bin Op.NEG (getLUnit s x) - | 0b0100100u -> parseSc5SlSl bin Op.SUB (getLUnit s x) - | 0b0100111u when isEqualSrc1Src2 bin -> parseSl bin Op.ZERO (getLUnit s x) - | 0b0100111u -> parseSiXSiSl bin Op.SUB (getLUnit s x) - | 0b0101001u -> parseXUiUlUl bin Op.ADDU (getLUnit s x) - | 0b0101011u -> parseUiXUiUl bin Op.ADDU (getLUnit s x) - | 0b0101100u -> parseSc5SlSl bin Op.SSUB (getLUnit s x) - | 0b0101111u -> parseUiXUiUl bin Op.SUBU (getLUnit s x) - | 0b0110000u -> parseSc5SlSl bin Op.SADD (getLUnit s x) - | 0b0110001u -> parseXSiSlSl bin Op.SADD (getLUnit s x) - | 0b0110111u when isEqualSrc1Src2 bin -> parseSl bin Op.ZERO (getLUnit s x) - | 0b0110111u -> parseXSiSiSl bin Op.SUB (getLUnit s x) - | 0b0111000u -> parseSlSl bin Op.ABS (getLUnit s x) - | 0b0111001u -> parseXSiDp bin Op.INTDP (getLUnit s x) - | 0b0111011u -> parseXUiDp bin Op.INTDPU (getLUnit s x) - | 0b0111111u -> parseXUiUiUl1 bin Op.SUBU (getLUnit s x) - | 0b1000000u -> parseSlSi bin Op.SAT (getLUnit s x) - | 0b1000001u -> parseS2XS2S2 bin Op.MIN2 (getLUnit s x) - | 0b1000010u -> parseS2XS2S2 bin Op.MAX2 (getLUnit s x) - | 0b1000011u -> parseU4XU4U4 bin Op.MAXU4 (getLUnit s x) - | 0b1000100u -> parseSc5SlUi bin Op.CMPGT (getLUnit s x) - | 0b1000101u -> parseXSiSlUi bin Op.CMPGT (getLUnit s x) - | 0b1000110u -> parseSc5XSiUi bin Op.CMPGT (getLUnit s x) - | 0b1000111u -> parseSiXSiUi bin Op.CMPGT (getLUnit s x) - | 0b1001000u -> parseU4XU4U4 bin Op.MINU4 (getLUnit s x) - | 0b1001001u -> parseXUiSp bin Op.INTSPU (getLUnit s x) - | 0b1001010u -> parseXSiSp bin Op.INTSP (getLUnit s x) - | 0b1001011u -> parseUiXUiUi bin Op.SUBC (getLUnit s x) - | 0b1001100u -> parseUc4UlUi bin Op.CMPGTU (getLUnit s x) - | 0b1001101u -> parseXUiUlUi bin Op.CMPGTU (getLUnit s x) - | 0b1001110u -> parseUc4XUiUi bin Op.CMPGTU (getLUnit s x) - | 0b1001111u -> parseUiXUiUi bin Op.CMPGTU (getLUnit s x) - | 0b1010000u -> parseSc5SlUi bin Op.CMPEQ (getLUnit s x) - | 0b1010001u -> parseXSiSlUi bin Op.CMPEQ (getLUnit s x) - | 0b1010010u -> parseSc5XSiUi bin Op.CMPEQ (getLUnit s x) - | 0b1010011u -> parseSiXSiUi bin Op.CMPEQ (getLUnit s x) - | 0b1010100u -> parseSc5SlUi bin Op.CMPLT (getLUnit s x) - | 0b1010101u -> parseXSiSlUi bin Op.CMPLT (getLUnit s x) - | 0b1010110u -> parseSc5XSiUi bin Op.CMPLT (getLUnit s x) - | 0b1010111u -> parseSiXSiUi bin Op.CMPLT (getLUnit s x) - | 0b1011010u -> parseU4XU4U4 bin Op.SUBABS4 (getLUnit s x) - | 0b1011100u -> parseUc4UlUi bin Op.CMPGTU (getLUnit s x) - | 0b1011101u -> parseXUiUlUi bin Op.CMPGTU (getLUnit s x) - | 0b1011110u -> parseUc4XUiUi bin Op.CMPGTU (getLUnit s x) - | 0b1011111u -> parseUiXUiUi bin Op.CMPGTU (getLUnit s x) - | 0b1100000u -> parseSlUi bin Op.NORM (getLUnit s x) - | 0b1100001u -> parseU4XU4U4 bin Op.SHLMB (getLUnit s x) - | 0b1100010u -> parseU4XU4U4 bin Op.SHRMB (getLUnit s x) - | 0b1100011u -> parseXSiUi bin Op.NORM (getLUnit s x) - | 0b1100100u -> parseS2XS2S2 bin Op.SSUB2 (getLUnit s x) - | 0b1100101u -> parseI4Xi4I4 bin Op.ADD4 (getLUnit s x) - | 0b1100110u -> parseI4Xi4I4 bin Op.SUB4 (getLUnit s x) - | 0b1101000u -> parseI4Xi4I4 bin Op.PACKL4 (getLUnit s x) - | 0b1101001u -> parseI4Xi4I4 bin Op.PACKH4 (getLUnit s x) - | 0b1101010u -> parseC5XUiUi bin Op.LMBD (getLUnit s x) - | 0b1101011u -> parseUiXUiUi bin Op.LMBD (getLUnit s x) - | 0b1101110u when isSrc111111 bin -> parseXUiUi bin Op.NOT (getLUnit s x) - | 0b1101110u -> parseSc5XUiUi bin Op.XOR (getLUnit s x) - | 0b1101111u -> parseUiXUiUi bin Op.XOR (getLUnit s x) - | 0b1111010u -> parseSc5XUiUi bin Op.AND (getLUnit s x) - | 0b1111011u -> parseUiXUiUi bin Op.AND (getLUnit s x) - | 0b1111100u -> parseUiXUiUi bin Op.ANDN (getLUnit s x) - | 0b1111110u when isSrc1Zero bin -> parseXUiUi bin Op.MV (getLUnit s x) - | 0b1111110u -> parseSc5XUiUi bin Op.OR (getLUnit s x) - | 0b1111111u -> parseUiXUiUi bin Op.OR (getLUnit s x) - (* parseSUnitAddSubFloat, F-2 *) - | 0b1110000u -> parseSpXSpSp bin Op.ADDSP (getSUnit s x) - | 0b1110001u -> parseSpXSpSp bin Op.SUBSP (getSUnit s x) - | 0b1110010u -> parseDpXDpDp bin Op.ADDDP (getSUnit s x) - | 0b1110011u -> parseDpXDpDp bin Op.SUBDP (getSUnit s x) - | 0b1110101u -> parseSpXSpSp bin Op.SUBSP (getSUnit s x) (* src2 - src1 *) - | 0b1110111u -> parseDpXDpDp bin Op.SUBDP (getSUnit s x) (* src2 - src1 *) - | _ -> Utils.impossible () - -let private parseCase10 bin = - match pickBit bin 4u with - | 0b0u -> parseCase010 bin - | _ (* 0b1u *) -> parseCase110 bin - -let private parseDUnitDWord bin = - let unit = getDUnit (yBit bin) 0u - match extract bin 6u 4u with - (* parseDUnitLSBasic, C-4. Exceptional case. *) - | 0b011u -> parseDUnitLSBasicOperands bin Op.LDNW unit MemReg - | 0b101u -> parseDUnitLSBasicOperands bin Op.STNW unit RegMem - (* parseDUnitLSDWord, C-6 *) - | 0b100u -> parseDUnitDWordOperands bin Op.STDW unit RegMem - | 0b110u -> parseDUnitDWordOperands bin Op.LDDW unit MemReg - (* parseDUnitLSNonalignDWord C-7 *) - | 0b010u -> parseDUnitDWordOperands bin Op.LDNDW unit MemReg - | 0b111u -> parseDUnitDWordOperands bin Op.STNDW unit RegMem - | _ -> Utils.impossible () - -let private parseDUnitLoadStore bin = - match pickBit bin 8u with - | 0b1u -> parseDUnitDWord bin - | _ (* 0b0u *) -> parseDUnitLSBasic bin - -let private parseDUnitLongImm bin = - match extract bin 31u 28u with - | 0b0001u -> parseDUnitADDLongImm bin - | _ -> parseDUnitLSLongImm bin - -let private parseInstruction bin = - match extract bin 3u 2u with - | 0b00u -> parseCase00 bin - | 0b10u -> parseCase10 bin - | 0b01u -> parseDUnitLoadStore bin - | _ (* 0b11u *) -> parseDUnitLongImm bin - -let parse (span: ByteSpan) reader (inParallel: byref) addr = - let bin = (reader: IBinReader).ReadUInt32 (span, 0) - let struct (opcode, unit, operands) = parseInstruction bin - let insInfo = - { Address = addr - NumBytes = 4u - Opcode = opcode - Operands = operands - FunctionalUnit = unit - OperationSize = 32 // FIXME - IsParallel = inParallel - EffectiveAddress = 0UL } - inParallel <- pBit bin <> 0u - TMS320C6000Instruction (addr, 4u, insInfo) - -// vim: set tw=80 sts=2 sw=2: + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000ParsingMain.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000ParsingMain.fs new file mode 100644 index 00000000..b2a2788b --- /dev/null +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000ParsingMain.fs @@ -0,0 +1,1990 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.TMS320C6000.ParsingMain + +open B2R2 +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.BinLifter.BitData + +/// Table 3-1. Instruction Operation and Execution Notations. +type OperandType = + /// Register B14 or B15. + | B14B15 + /// Bit vector of two flags for s2 or u2 data type. + | BVec2 + /// Bit vector of four flags for s4 or u4 data type. + | BVec4 + /// n-bit constant field (for example, cst5). + | Const + /// 64-bit integer value (two registers). + | DInt + /// Double-precision floating-point register value. + | DP + /// Two packed signed 16-bit integers in a single 64-bit register pair. + | DS2 + /// Unsigned 64-bit integer value (two registers). + | DUInt + /// Four packed signed 16-bit integers in a 64-bit register pair. + | DWS4 + /// Four packed unsigned 16-bit integers in a 64-bit register pair. + | DWU4 + /// Two packed 16-bit integers in a single 32-bit register. + | I2 + /// Four packed 8-bit integers in a single 32-bit register. + | I4 + /// 32-bit integer value. + | Int + /// Two packed signed 16-bit integers in a single 32-bit register. + | S2 + /// Four packed signed 8-bit integers in a single 32-bit register. + | S4 + /// n-bit signed constant field. + | SConst + /// Signed 64-bit integer value (two registers). + | SDInt + /// Signed 32-bit integer value. + | SInt + /// Signed 64-bit integer value. + | SLLong + /// Signed 40-bit integer value. + | SLong + /// Signed 16-bit integer value in lower half of 32-bit register. + | SLsb16 + /// Signed 16-bit integer value in upper half of 32-bit register. + | SMsb16 + /// Single-precision floating-point register value that can optionally use + /// cross path. + | SP + /// Two packed unsigned 16-bit integers in a single 32-bit register. + | U2 + /// Four packed unsigned 8-bit integers in a single 32-bit register. + | U4 + /// n-bit unsigned constant field (for example, ucst5). + | UConst + /// Unsigned 32-bit integer value. + | UInt + /// Unsigned 64-bit integer value. + | ULLong + /// Unsigned 40-bit integer value. + | ULong + /// Unsigned 16-bit integer value in lower half of 32-bit register. + | ULsb16 + /// Unsigned 16-bit integer value in upper half of 32-bit register. + | UMsb16 + /// Double-precision floating-point register value that can optionally use + /// cross path. + | XDP + /// Two packed 16-bit integers in a single 32-bit register that can optionally + /// use cross path. + | XI2 + /// Four packed 8-bit integers in a single 32-bit register that can optionally + /// use cross path. + | XI4 + /// 32-bit integer value that can optionally use cross path. + | XInt + /// Two packed signed 16-bit integers in a single 32-bit register that can + /// optionally use cross path. + | XS2 + /// Four packed signed 8-bit integers in a single 32-bit register that can + /// optionally use cross path. + | XS4 + /// Signed 32-bit integer value that can optionally use cross path. + | XSInt + /// Signed 16 LSB of register that can optionally use cross path. + | XSLsb16 + /// Signed 16 MSB of register that can optionally use cross path. + | XSMsb16 + /// Single-precision floating-point register value that can optionally use + /// cross path. + | XSP + /// Two packed unsigned 16-bit integers in a single 32-bit register that can + /// optionally use cross path. + | XU2 + /// Four packed unsigned 8-bit integers in a single 32-bit register that can + /// optionally use cross path. + | XU4 + /// Unsigned 32-bit integer value that can optionally use cross path. + | XUInt + /// Unsigned 16 LSB of register that can optionally use cross path. + | XULsb16 + /// Unsigned 16 MSB of register that can optionally use cross path. + | XUMsb16 + +type MemoryOpOrder = + | RegMem + | MemReg + +let buildMemOperand reg mem = function + | RegMem -> TwoOperands (reg, mem) + | MemReg -> TwoOperands (mem, reg) + +[] +type OperandInfo = + struct + val OperandValue: uint32 + val OperandType: OperandType + new (v, t) = { OperandValue = v; OperandType = t } + end + +let private getRegisterA = function + | 0b00000u -> R.A0 + | 0b00001u -> R.A1 + | 0b00010u -> R.A2 + | 0b00011u -> R.A3 + | 0b00100u -> R.A4 + | 0b00101u -> R.A5 + | 0b00110u -> R.A6 + | 0b00111u -> R.A7 + | 0b01000u -> R.A8 + | 0b01001u -> R.A9 + | 0b01010u -> R.A10 + | 0b01011u -> R.A11 + | 0b01100u -> R.A12 + | 0b01101u -> R.A13 + | 0b01110u -> R.A14 + | 0b01111u -> R.A15 + | 0b10000u -> R.A16 + | 0b10001u -> R.A17 + | 0b10010u -> R.A18 + | 0b10011u -> R.A19 + | 0b10100u -> R.A20 + | 0b10101u -> R.A21 + | 0b10110u -> R.A22 + | 0b10111u -> R.A23 + | 0b11000u -> R.A24 + | 0b11001u -> R.A25 + | 0b11010u -> R.A26 + | 0b11011u -> R.A27 + | 0b11100u -> R.A28 + | 0b11101u -> R.A29 + | 0b11110u -> R.A30 + | 0b11111u -> R.A31 + | _ -> Utils.impossible () + +let private getRegisterB = function + | 0b00000u -> R.B0 + | 0b00001u -> R.B1 + | 0b00010u -> R.B2 + | 0b00011u -> R.B3 + | 0b00100u -> R.B4 + | 0b00101u -> R.B5 + | 0b00110u -> R.B6 + | 0b00111u -> R.B7 + | 0b01000u -> R.B8 + | 0b01001u -> R.B9 + | 0b01010u -> R.B10 + | 0b01011u -> R.B11 + | 0b01100u -> R.B12 + | 0b01101u -> R.B13 + | 0b01110u -> R.B14 + | 0b01111u -> R.B15 + | 0b10000u -> R.B16 + | 0b10001u -> R.B17 + | 0b10010u -> R.B18 + | 0b10011u -> R.B19 + | 0b10100u -> R.B20 + | 0b10101u -> R.B21 + | 0b10110u -> R.B22 + | 0b10111u -> R.B23 + | 0b11000u -> R.B24 + | 0b11001u -> R.B25 + | 0b11010u -> R.B26 + | 0b11011u -> R.B27 + | 0b11100u -> R.B28 + | 0b11101u -> R.B29 + | 0b11110u -> R.B30 + | 0b11111u -> R.B31 + | _ -> Utils.impossible () + +let private parseReg bin isCrossPath = function + | L1Unit | S1Unit | M1Unit | D1Unit -> getRegisterA bin + | L2Unit | S2Unit | M2Unit | D2Unit -> getRegisterB bin + | L1XUnit | S1XUnit | M1XUnit | D1XUnit -> + if isCrossPath then getRegisterB bin else getRegisterA bin + | L2XUnit | S2XUnit | M2XUnit | D2XUnit -> + if isCrossPath then getRegisterA bin else getRegisterB bin + | _ -> Utils.impossible () + +let private parseRegBySide bin = function + | SideA -> getRegisterA bin + | SideB -> getRegisterB bin + +let private parseAddrMode unit offset mode baseR = + match mode with + | 0b0000u -> baseR, NegativeOffset, uint64 offset |> UCst5 + | 0b0001u -> baseR, PositiveOffset, uint64 offset |> UCst5 + | 0b0100u -> baseR, NegativeOffset, parseReg offset false unit |> OffsetR + | 0b0101u -> baseR, PositiveOffset, parseReg offset false unit |> OffsetR + | 0b1000u -> baseR, PreDecrement, uint64 offset |> UCst5 + | 0b1001u -> baseR, PreIncrement, uint64 offset |> UCst5 + | 0b1010u -> baseR, PostDecrement, uint64 offset |> UCst5 + | 0b1011u -> baseR, PostIncrement, uint64 offset |> UCst5 + | 0b1100u -> baseR, PreDecrement, parseReg offset false unit |> OffsetR + | 0b1101u -> baseR, PreIncrement, parseReg offset false unit |> OffsetR + | 0b1110u -> baseR, PostDecrement, parseReg offset false unit |> OffsetR + | 0b1111u -> baseR, PostIncrement, parseReg offset false unit |> OffsetR + | _ -> Utils.impossible () + +let private parseMem oprVal unit = + parseReg (extract oprVal 13u 9u) false unit (* Base register *) + |> parseAddrMode unit (extract oprVal 8u 4u) (extract oprVal 3u 0u) + |> OprMem + +let private assertEvenNumber v = +#if DEBUG + if v &&& 1u <> 0u then raise InvalidOperandException else () +#endif + () + +let getSide sBit = if sBit = 0b0u then SideA else SideB + +let private xBit bin = pickBit bin 12u +let private yBit bin = pickBit bin 7u +let private sBit bin = pickBit bin 1u +let private pBit bin = pickBit bin 0u + +let private isSrc1Zero bin = extract bin 17u 13u = 0u +let private isSrc111111 bin = extract bin 17u 13u = 0b11111u +let private isSrc100010 bin = extract bin 17u 13u = 0b000010u +let private isEqualSrc1Src2 bin = + xBit bin = 0u && extract bin 22u 18u = extract bin 17u 13u + +let private parseRegPair v unit isCPath = + let high, low = if v &&& 0b1u = 0b0u then v + 1u, v else v, v - 1u + (parseReg high isCPath unit, parseReg low isCPath unit) |> RegisterPair + +let getB14orB15 value = if value = 0b0u then R.B14 else R.B15 + +let private translateOperand unit (oprInfo: OperandInfo) = + let v = oprInfo.OperandValue + match oprInfo.OperandType with + | B14B15 -> getB14orB15 v |> OpReg + | BVec2 | BVec4 | I2 | I4 | Int | S2 | S4 | SInt | SLsb16 | SMsb16 | SP | U2 + | U4 | UInt | ULsb16 | UMsb16 -> parseReg v false unit |> OpReg + | Const | SConst | UConst -> uint64 v |> Immediate + | DInt | DP | DS2 | DUInt | DWS4 | DWU4 | SDInt | SLLong | SLong | ULLong + | ULong -> parseRegPair v unit false + | XDP -> parseRegPair v unit true + | XI2 | XI4 | XInt | XS2 | XS4 | XSInt | XSLsb16 | XSMsb16 | XSP | XU2 | XU4 + | XUInt | XULsb16 | XUMsb16 -> parseReg v true unit |> OpReg + +let private parseOneOpr unit o = OneOperand (translateOperand unit o) + +let private parseTwoOprs unit o1 o2 = + TwoOperands (translateOperand unit o1, translateOperand unit o2) + +let private parseThreeOprs unit o1 o2 o3 = + ThreeOperands (translateOperand unit o1, + translateOperand unit o2, + translateOperand unit o3) + +let private parseFourOprs unit o1 o2 o3 o4 = + FourOperands (translateOperand unit o1, + translateOperand unit o2, + translateOperand unit o3, + translateOperand unit o4) + +/// scst21 +let private parseSc21 bin opcode unit = + let o = OperandInfo (extract bin 27u 7u, SConst) + struct (opcode, unit, parseOneOpr unit o) + +/// xuint +let private parseXUi bin opcode unit = + let o = OperandInfo (extract bin 22u 18u, XUInt) + struct (opcode, unit, parseOneOpr unit o) + +/// ucst4 (NOP) +let private parseUc4 bin opcode unit = + let o = OperandInfo (extract bin 16u 13u + 1u, UConst) + struct (opcode, unit, parseOneOpr unit o) + +/// slong +let private parseSl bin opcode unit = + let o = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseOneOpr unit o) + +/// sint +let private parseSi bin opcode unit = + let o = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseOneOpr unit o) + +/// xsint, sint +let private parseXSiSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// slong, slong +let private parseSlSl bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SLong) + let o2 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// dp, dp +let private parseXDpDp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XDP) + let o2 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xsp, sp +let private parseXSpSp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSP) + let o2 = OperandInfo (extract bin 27u 23u, SP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// scst16, uint +let private parseSc16Ui bin opcode unit = + let o1 = OperandInfo (extract bin 22u 7u, SConst) + let o2 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// dp, sint +let private parseDpSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, DP) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// dp, sp +let private parseDpSp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, DP) + let o2 = OperandInfo (extract bin 27u 23u, SP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xsint, dp +let private parseXSiDp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xuint, dp +let private parseXUiDp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xsint, sp +let private parseXSiSp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 27u 23u, SP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xuint, sp +let private parseXUiSp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 27u 23u, SP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xs2, s2 +let private parseXs2S2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XS2) + let o2 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// scst10, int +let private parseSc10Int bin opcode unit = + let o1 = OperandInfo (extract bin 22u 13u, SConst) + let o2 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xu4, u4 +let private parseXU4U4 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XU4) + let o2 = OperandInfo (extract bin 27u 23u, U4) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xuint, uint +let private parseXUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// scst12, ucst3 +let private parseSc12Uc3 bin opcode unit = + let o1 = OperandInfo (extract bin 27u 16u, SConst) + let o2 = OperandInfo (extract bin 15u 13u, UConst) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xuint, ucst3 +let private parseXUiUc3 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 15u 13u, UConst) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// sint, sint +let private parseSiSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SInt) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xint, int +let private parseXiInt bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XInt) + let o2 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// scst16, sint +let private parseSc16Si bin opcode unit = + let o1 = OperandInfo (extract bin 22u 7u, SConst) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// scst5 (22-18), sint +let private parseSc5Si1 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SConst) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// scst5 (17-13), sint +let private parseSc5Si2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xsint, uint +let private parseXSiUi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// slong, uint +let private parseSlUi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SLong) + let o2 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// dp, dp +let private parseDpDp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, DP) + let o2 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// slong, sint +let private parseSlSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SLong) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xsp, dp +let private parseXSpDp bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSP) + let o2 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xsp, sint +let private parseXSpSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSP) + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// xu4, u2 +let private parseXU4U2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XU4) + let o2 = OperandInfo (extract bin 27u 23u, U2) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// s2, s2 +let private parseS2S2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, S2) + let o2 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// uscst16, sint +let private parseUSc16Si bin opcode unit = + let o1 = OperandInfo (extract bin 22u 7u, UConst) // FIXME + let o2 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseTwoOprs unit o1 o2) + +/// sint, xsint, sint +let private parseSiXSiSi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SInt) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, xsint, slong +let private parseSiXSiSl bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SInt) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, slong, slong +let private parseXSiSlSl bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XSInt) + let o2 = OperandInfo (extract bin 22u 18u, SLong) + let o3 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, xsint, sint +let private parseSc5XSiSi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, slong, slong +let private parseSc5SlSl bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, SLong) + let o3 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, sint, sint +let private parseSiSiSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SInt) + let o2 = OperandInfo (extract bin 17u 13u, SInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, ucst5, sint +let private parseSiUc5Si bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SInt) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sp, xsp, sp +let parseSpXSpSp bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SP) + let o2 = OperandInfo (extract bin 22u 18u, XSP) + let o3 = OperandInfo (extract bin 27u 23u, SP) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// dp, xdp, dp +let parseDpXDpDp bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, DP) + let o2 = OperandInfo (extract bin 22u 18u, XDP) + let o3 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// uint, xuint, ulong +let parseUiXUiUl bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UInt) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, ulong, ulong +let parseXUiUlUl bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XUInt) + let o2 = OperandInfo (extract bin 22u 18u, ULong) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// uint, xuint, uint +let parseUiXUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UInt) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, xuint, uint +let parseSc5XUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, uint, uint +let parseXUiUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, xsint, uint +let parseSiXSiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SInt) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, xsint, uint +let parseSc5XSiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, slong, uint +let parseXSiSlUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XSInt) + let o2 = OperandInfo (extract bin 22u 18u, SLong) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, slong, uint +let parseSc5SlUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, SLong) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// dp, xdp, sint +let parseDpXDpSi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, DP) + let o2 = OperandInfo (extract bin 22u 18u, XDP) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sp, xsp, sint +let parseSpXSpSi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SP) + let o2 = OperandInfo (extract bin 22u 18u, XSP) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ucst4, xuint, uint +let parseUc4XUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UConst) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, ulong, uint +let parseXUiUlUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XUInt) + let o2 = OperandInfo (extract bin 22u 18u, ULong) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ucst4, ulong, uint +let parseUc4UlUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UConst) + let o2 = OperandInfo (extract bin 22u 18u, ULong) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, uint, sint +let parseXSiUiSi bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// cst5, xuint, uint +let parseC5XUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Const) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// slsb16, xslsb16, sint +let parseSlsb16XSlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SLsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, xslsb16, sint +let parseSc5XSlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst7, ucst3, uint +let parseSc7Uc3Ui bin opcode unit = + let o1 = OperandInfo (extract bin 22u 16u, SConst) + let o2 = OperandInfo (extract bin 15u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, xsint, dint +let parseSiXSiDi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SInt) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// i4, xi4, i4 +let parseI4Xi4I4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, I4) + let o2 = OperandInfo (extract bin 22u 18u, XI4) + let o3 = OperandInfo (extract bin 27u 23u, I4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// B14/B15, ucst15, sint +let parseB14B15Uc15Si bin opcode unit = + let o1 = OperandInfo (pickBit bin 7u, B14B15) + let o2 = OperandInfo (extract bin 22u 8u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// i2, xi2, i2 +let parseI2Xi2I2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, I2) + let o2 = OperandInfo (extract bin 22u 18u, XI2) + let o3 = OperandInfo (extract bin 27u 23u, I2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, s2 +let parseS2XS2S2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// u4, xu4, u4 +let parseU4XU4U4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, U4) + let o2 = OperandInfo (extract bin 22u 18u, XU4) + let o3 = OperandInfo (extract bin 27u 23u, U4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, bv2 +let parseS2XS2Bv2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, BVec2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s4, xs4, bv4 +let parseS4XS4Bv4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S4) + let o2 = OperandInfo (extract bin 22u 18u, XS4) + let o3 = OperandInfo (extract bin 27u 23u, BVec4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// u4, xu4, bv4 +let parseU4XU4Bv4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, U4) + let o2 = OperandInfo (extract bin 22u 18u, XU4) + let o3 = OperandInfo (extract bin 27u 23u, BVec4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, dint +let parseS2XS2Di bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs4, dint +let parseS2XS4Di bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS4) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ds2, xs2, dint +let parseDS2XS2Di bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, DS2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ds2, xs2, s2 +let parseDS2XS2S2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, DS2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, int +let parseS2XS2Int bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, sllong +let parseS2XS2Sll bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, SLLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xu2, int +let parseS2XU2Int bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XU2) + let o3 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s4, xu4, int +let parseS4XU4Int bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S4) + let o2 = OperandInfo (extract bin 22u 18u, XU4) + let o3 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// u4, xu4, uint +let parseU4XU4Ui bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, U4) + let o2 = OperandInfo (extract bin 22u 18u, XU4) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// uint, uint, uint +let parseUiUiUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UInt) + let o2 = OperandInfo (extract bin 22u 18u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// smsb16, xsmsb16, sint +let parseSmsb16XSmsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// int, xint, sllong +let parseIntXiSll bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Int) + let o2 = OperandInfo (extract bin 22u 18u, XInt) + let o3 = OperandInfo (extract bin 27u 23u, SLLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// int, xint, int +let parseIntXiInt bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Int) + let o2 = OperandInfo (extract bin 22u 18u, XInt) + let o3 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// smsb16, xslsb16, sint +let parseSmsb16XSlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// umsb16, xulsb16, uint +let parseUmsb16XUlsb16Ui bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XULsb16) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// smsb16, xulsb16, sint +let parseSmsb16XUlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XULsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// smsb16, xumsb16, sint +let parseSmsb16XUmsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// umsb16, xumsb16, uint +let parseUmsb16XUmsb16Ui bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// umsb16, xslsb16, sint +let parseUmsb16XSlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// umsb16, xsmsb16, sint +let parseUmsb16XSmsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UMsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// cst5, xsint, sint +let parseC5XSiSi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Const) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, xsint, sdint +let parseSiXSiSDi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SInt) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, SDInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// cst5, xsint, sdint +let parseC5XSiSDi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Const) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, SDInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// slsb16, xsmsb16, sint +let parseSlsb16XSmsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SLsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ulsb16, xumsb16, uint +let parseUlsb16XUmsb16Ui bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, ULsb16) + let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// slsb16, xumsb16, sint +let parseSlsb16XUmsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SLsb16) + let o2 = OperandInfo (extract bin 22u 18u, XUMsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ulsb16, xsmsb16, sint +let parseUlsb16XSmsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, ULsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSMsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sp, xdp, dp +let parseSpXDpDp bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SP) + let o2 = OperandInfo (extract bin 22u 18u, XDP) + let o3 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sp, xsp, dp +let parseSpXSpDp bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SP) + let o2 = OperandInfo (extract bin 22u 18u, XSP) + let o3 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// slsb16, xulsb16, sint +let parseSlsb16XUlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SLsb16) + let o2 = OperandInfo (extract bin 22u 18u, XULsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// scst5, xulsb16, sint +let parseSc5XUlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SConst) + let o2 = OperandInfo (extract bin 22u 18u, XULsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s4, xu4, dws4 +let parseS4XU4DWS4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S4) + let o2 = OperandInfo (extract bin 22u 18u, XU4) + let o3 = OperandInfo (extract bin 27u 23u, DWS4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ulsb16, xulsb16, uint +let parseUlsb16XUlsb16Ui bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, ULsb16) + let o2 = OperandInfo (extract bin 22u 18u, XULsb16) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// u4, xu4, dwu4 +let parseU4XU4DWU4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, U4) + let o2 = OperandInfo (extract bin 22u 18u, XU4) + let o3 = OperandInfo (extract bin 27u 23u, DWU4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ulsb16, xslsb16, sint +let parseUlsb16XSlsb16Si bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, ULsb16) + let o2 = OperandInfo (extract bin 22u 18u, XSLsb16) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, ullong +let parseS2XS2Ull bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, ULLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// int, xint, dint +let parseIntXiDi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Int) + let o2 = OperandInfo (extract bin 22u 18u, XInt) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// int, xuint, dint +let parseIntXUiDi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Int) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// uint, xuint, duint +let parseUiXUiDUi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UInt) + let o2 = OperandInfo (extract bin 22u 18u, XUInt) + let o3 = OperandInfo (extract bin 27u 23u, DUInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// uint, xint, dint +let parseUiXiDi bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, UInt) + let o2 = OperandInfo (extract bin 22u 18u, XInt) + let o3 = OperandInfo (extract bin 27u 23u, DInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, ucst5, uint +let parseXUiUc5Ui bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// sint, xsint, s2 +let parseSiXSiS2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, SInt) + let o2 = OperandInfo (extract bin 22u 18u, XSInt) + let o3 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// u2, xs2, u2 +let parseU2XS2U2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, U2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, U2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// slong, uint, slong +let parseSlUiSl bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SLong) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, uint, ulong +let parseXUiUiUl1 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XUInt) + let o2 = OperandInfo (extract bin 22u 18u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, uint, ulong +let parseXUiUiUl2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, ucst5, sint +let parseXSiUc5Si bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// slong, ucst5, slong +let parseSlUc5Sl bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SLong) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xuint, ucst5, ulong +let parseXUiUc5Ul bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XUInt) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xs2, uint, s2 +let parseXS2UiS2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XS2) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xs2, ucst5, s2 +let parseXS2Uc5S2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XS2) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ulong, uint, ulong +let parseUlUiUl bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, ULong) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// ulong, ucst5, ulong +let parseUlUc5Ul bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, ULong) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, ULong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xu2, uint, u2 +let parseXU2UiU2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XU2) + let o2 = OperandInfo (extract bin 17u 13u, UInt) + let o3 = OperandInfo (extract bin 27u 23u, U2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xu2, ucst5, u2 +let parseXU2Uc5U2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XU2) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 27u 23u, U2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// int, xint, s2 +let parseIntXiS2 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, Int) + let o2 = OperandInfo (extract bin 22u 18u, XInt) + let o3 = OperandInfo (extract bin 27u 23u, S2) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// s2, xs2, u4 +let parseS2XS2U4 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, S2) + let o2 = OperandInfo (extract bin 22u 18u, XS2) + let o3 = OperandInfo (extract bin 27u 23u, U4) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, sint, sint +let parseXSiSiSi1 bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XSInt) + let o2 = OperandInfo (extract bin 22u 18u, SInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, sint, sint +let parseXSiSiSi2 bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XSInt) + let o2 = OperandInfo (extract bin 17u 13u, SInt) + let o3 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xint, int, int +let parseXiIntInt bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, XInt) + let o2 = OperandInfo (extract bin 17u 13u, Int) + let o3 = OperandInfo (extract bin 27u 23u, Int) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsint, sint, slong +let parseXSiSiSl bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XSInt) + let o2 = OperandInfo (extract bin 22u 18u, SInt) + let o3 = OperandInfo (extract bin 27u 23u, SLong) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xdp, dp, dp +let parseXDpDpDp bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XDP) + let o2 = OperandInfo (extract bin 22u 18u, DP) + let o3 = OperandInfo (extract bin 27u 23u, DP) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// xsp, sp, sp +let parseXSpSpSp bin opcode unit = + let o1 = OperandInfo (extract bin 17u 13u, XSP) + let o2 = OperandInfo (extract bin 22u 18u, SP) + let o3 = OperandInfo (extract bin 27u 23u, SP) + struct (opcode, unit, parseThreeOprs unit o1 o2 o3) + +/// unit, ucst5, ucst5, uint +let parseUiUc5Uc5Ui bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, UInt) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 12u 8u, UConst) + let o4 = OperandInfo (extract bin 27u 23u, UInt) + struct (opcode, unit, parseFourOprs unit o1 o2 o3 o4) + +/// snit, ucst5, ucst5, sint +let parseSiUc5Uc5Si bin opcode unit = + let o1 = OperandInfo (extract bin 22u 18u, SInt) + let o2 = OperandInfo (extract bin 17u 13u, UConst) + let o3 = OperandInfo (extract bin 12u 8u, UConst) + let o4 = OperandInfo (extract bin 27u 23u, SInt) + struct (opcode, unit, parseFourOprs unit o1 o2 o3 o4) + +/// mem [offsetR/ucst5] +let parseDUnitLSBasicOperands bin opcode unit order = + let mem = parseMem (extract bin 22u 9u) unit + let reg = + parseRegBySide (extract bin 27u 23u) (getSide (sBit bin)) |> OpReg + struct (opcode, unit, buildMemOperand reg mem order) + +/// mem [ucst15] +let parseDUnitLSLongImmOperands bin opcode unit order = + let baseReg = getB14orB15 (yBit bin) + let mem = + OprMem (baseReg, PositiveOffset, UCst15 (uint64 (extract bin 22u 8u))) + let reg = + parseRegBySide (extract bin 27u 23u) (getSide (sBit bin)) |> OpReg + struct (opcode, unit, buildMemOperand reg mem order) + +/// mem, regPair +let parseDUnitDWordOperands bin opcode unit order = + let mem = parseMem (extract bin 22u 9u) unit + let v = extract bin 27u 23u + let regPair = + let high, low = if v &&& 0b1u = 0b0u then v + 1u, v else v, v - 1u + let side = getSide (sBit bin) + (parseRegBySide high side, parseRegBySide low side) |> RegisterPair + struct (opcode, unit, buildMemOperand regPair mem order) + +let is0xxxx address = address &&& 0b10000u = 0b00000u + +let getCtrlReg crHi crLo = + match crHi, crLo with + | _, 0b00000u when is0xxxx crHi -> R.AMR + | _, 0b00001u when is0xxxx crHi -> R.CSR + | 0b00000u, 0b11001u -> R.DIER + | 0b00000u, 0b10001u -> R.DNUM + | 0b00000u, 0b11101u -> R.ECR + (* | 0b00000u, 0b11101u -> R.EFR *) // XXX: depending on the MVC + | 0b00000u, 0b10010u -> R.FADCR + | 0b00000u, 0b10011u -> R.FAUCR + | 0b00000u, 0b10100u -> R.FMCR + | 0b00000u, 0b11000u -> R.GFPGFR + | 0b00000u, 0b10110u -> R.GPLYA + | 0b00000u, 0b10111u -> R.GPLYB + | _, 0b00011u when is0xxxx crHi -> R.ICR + | _, 0b00100u when is0xxxx crHi -> R.IER + | 0b00000u, 0b11111u -> R.IERR + | 0b00000u, 0b00010u -> R.IFR + | 0b00010u, 0b00010u -> R.IFR + | 0b00000u, 0b01101u -> R.ILC + | _, 0b00110u when is0xxxx crHi -> R.IRP + | _, 0b00010u when is0xxxx crHi -> R.ISR + | _, 0b00101u when is0xxxx crHi -> R.ISTP + | 0b00000u, 0b11011u -> R.ITSR + | _, 0b00111u when is0xxxx crHi -> R.NRP + | 0b00000u, 0b11100u -> R.NTSR + | 0b00000u, 0b10000u -> R.PCE1 + | 0b10000u, 0b10000u -> R.PCE1 + | 0b00000u, 0b01111u -> R.REP + | 0b00000u, 0b01110u -> R.RILC + | 0b00000u, 0b10101u -> R.SSR + | 0b00000u, 0b01011u -> R.TSCH + | 0b00000u, 0b01010u -> R.TSCL + | 0b00000u, 0b11010u -> R.TSR + | _ -> Utils.impossible () + +/// Control Register to Register +let parseCtrlRegToReg bin opcode unit = + let o1 = getCtrlReg (extract bin 17u 13u) (extract bin 22u 18u) |> OpReg + let o2 = translateOperand unit (OperandInfo (extract bin 27u 23u, UInt)) + struct (opcode, unit, TwoOperands (o1, o2)) + +/// Register to Control Register +let parseRegToCtrlReg bin opcode unit = + let o1 = translateOperand unit (OperandInfo (extract bin 22u 18u, XUInt)) + let o2 = getCtrlReg (extract bin 17u 13u) (extract bin 27u 23u) |> OpReg + struct (opcode, unit, TwoOperands (o1, o2)) + +let private getDUnit s x = + match s, x with + | 0b0u, 0b0u -> D1Unit + | 0b0u, 0b1u -> D1XUnit + | 0b1u, 0b0u -> D2Unit + | _ (* 0b1u, 0b1u *) -> D2XUnit + +/// Appendix C. page 724. Fig. C-1 +let private parseDUnitSrcs bin = + let unit = getDUnit (sBit bin) 0u + match extract bin 12u 7u with + | 0b000000u -> parseSc5Si2 bin Op.MVK unit + | 0b010000u -> parseSiSiSi bin Op.ADD unit + | 0b010001u -> parseSiSiSi bin Op.SUB unit + | 0b010010u when isSrc1Zero bin -> parseSiSi bin Op.MV unit + | 0b010010u -> parseSiUc5Si bin Op.ADD unit + | 0b010011u -> parseSiUc5Si bin Op.SUB unit + | 0b110000u -> parseSiSiSi bin Op.ADDAB unit + | 0b110001u -> parseSiSiSi bin Op.SUBAB unit + | 0b110010u -> parseSiUc5Si bin Op.ADDAB unit + | 0b110011u -> parseSiUc5Si bin Op.SUBAB unit + | 0b110100u -> parseSiSiSi bin Op.ADDAH unit + | 0b110101u -> parseSiSiSi bin Op.SUBAH unit + | 0b110110u -> parseSiUc5Si bin Op.ADDAH unit + | 0b110111u -> parseSiUc5Si bin Op.SUBAH unit + | 0b111000u -> parseSiSiSi bin Op.ADDAW unit + | 0b111001u -> parseSiSiSi bin Op.SUBAW unit + | 0b111010u -> parseSiUc5Si bin Op.ADDAW unit + | 0b111011u -> parseSiUc5Si bin Op.SUBAW unit + | 0b111100u -> parseSiSiSi bin Op.ADDAD unit + | 0b111101u -> parseSiUc5Si bin Op.ADDAD unit + | _ -> Utils.impossible () + +/// Appendix C. page 724. Fig. C-2 +let private parseDUnitSrcsExt bin = + let unit = getDUnit (sBit bin) (xBit bin) + match extract bin 9u 6u with + | 0b0000u -> parseUiXUiUi bin Op.ANDN unit + | 0b0010u -> parseUiXUiUi bin Op.OR unit + | 0b0011u when isSrc1Zero bin -> parseXUiUi bin Op.MV unit + | 0b0011u -> parseSc5XUiUi bin Op.OR unit + | 0b0100u -> parseI2Xi2I2 bin Op.ADD2 unit + | 0b0101u -> parseI2Xi2I2 bin Op.SUB2 unit + | 0b0110u -> parseUiXUiUi bin Op.AND unit + | 0b0111u -> parseSc5XUiUi bin Op.AND unit + | 0b1010u -> parseSiXSiSi bin Op.ADD unit + | 0b1011u -> parseSc5XSiSi bin Op.ADD unit + | 0b1100u -> parseSiXSiSi bin Op.SUB unit + | 0b1110u -> parseUiXUiUi bin Op.XOR unit + | 0b1111u when isSrc111111 bin -> parseXUiUi bin Op.NOT unit + | 0b1111u -> parseSc5XUiUi bin Op.XOR unit + | _ -> Utils.impossible () + +/// Appendix C. page 724. Fig. C-3 +let private parseDUnitADDLongImm bin = + let unit = getDUnit (sBit bin) 0u + match extract bin 6u 4u with + | 0b011u -> parseB14B15Uc15Si bin Op.ADDAB unit + | 0b101u -> parseB14B15Uc15Si bin Op.ADDAH unit + | 0b111u -> parseB14B15Uc15Si bin Op.ADDAW unit + | _ -> Utils.impossible () + +/// Appendix C. page 724. Fig. C-4 +let private parseDUnitLSBasic bin = + let unit = getDUnit (yBit bin) 0u + match extract bin 6u 4u with + | 0b000u -> parseDUnitLSBasicOperands bin Op.LDHU unit MemReg + | 0b001u -> parseDUnitLSBasicOperands bin Op.LDBU unit MemReg + | 0b010u -> parseDUnitLSBasicOperands bin Op.LDB unit MemReg + | 0b011u -> parseDUnitLSBasicOperands bin Op.STB unit RegMem + | 0b100u -> parseDUnitLSBasicOperands bin Op.LDH unit MemReg + | 0b101u -> parseDUnitLSBasicOperands bin Op.STH unit RegMem + | 0b110u -> parseDUnitLSBasicOperands bin Op.LDW unit MemReg + | 0b111u -> parseDUnitLSBasicOperands bin Op.STW unit RegMem + | _ -> Utils.impossible () + +/// Appendix C. page 724. Fig. C-5 +let private parseDUnitLSLongImm bin = + match extract bin 6u 4u with + | 0b000u -> parseDUnitLSLongImmOperands bin Op.LDHU D2Unit MemReg + | 0b001u -> parseDUnitLSLongImmOperands bin Op.LDBU D2Unit MemReg + | 0b010u -> parseDUnitLSLongImmOperands bin Op.LDB D2Unit MemReg + | 0b011u -> parseDUnitLSLongImmOperands bin Op.STB D2Unit RegMem + | 0b100u -> parseDUnitLSLongImmOperands bin Op.LDH D2Unit MemReg + | 0b101u -> parseDUnitLSLongImmOperands bin Op.STH D2Unit RegMem + | 0b110u -> parseDUnitLSLongImmOperands bin Op.LDW D2Unit MemReg + | 0b111u -> parseDUnitLSLongImmOperands bin Op.STW D2Unit RegMem + | _ -> Utils.impossible () + +/// Appendix C. page 724. Fig. C-6 +let private parseDUnitLSDWord bin = struct (Op.InvalOP, NoUnit, NoOperand) + +/// Appendix C. page 724. Fig. C-7 +let private parseDUnitLSNonalignDWord bin = + struct (Op.InvalOP, NoUnit, NoOperand) + +let private getLUnit s x = + match s, x with + | 0b0u, 0b0u -> L1Unit + | 0b0u, 0b1u -> L1XUnit + | 0b1u, 0b0u -> L2Unit + | _ (* 0b1u, 0b1u *) -> L2XUnit + +let private getSUnit s x = + match s, x with + | 0b0u, 0b0u -> S1Unit + | 0b0u, 0b1u -> S1XUnit + | 0b1u, 0b0u -> S2Unit + | _ (* 0b1u, 0b1u *) -> S2XUnit + +/// Appendix D. page 735. Fig. D-1 +let private parseLUnitSrcs bin = struct (Op.InvalOP, NoUnit, NoOperand) + +/// Appendix D. page 735. Fig. D-2 +let private parseLUnitUnary bin = + let unit = getLUnit (sBit bin) (xBit bin) + match extract bin 17u 13u with + | 0b00000u -> parseXSiSi bin Op.ABS unit + | 0b00001u -> parseXU4U4 bin Op.SWAP4 unit + | 0b00010u -> parseXU4U2 bin Op.UNPKLU4 unit + | 0b00011u -> parseXU4U2 bin Op.UNPKHU4 unit + | 0b00100u -> parseXs2S2 bin Op.ABS2 unit + | 0b00101u -> parseSc5Si1 bin Op.MVK unit + | _ -> Utils.impossible () + +/// Appendix D. page 735. Fig. D-3 +let private parseLUnitNonCond bin = struct (Op.InvalOP, NoUnit, NoOperand) + +let private getMUnit s x = + match s, x with + | 0b0u, 0b0u -> M1Unit + | 0b0u, 0b1u -> M1XUnit + | 0b1u, 0b0u -> M2Unit + | _ (* 0b1u, 0b1u *) -> M2XUnit + +/// Appendix E. page 743. Fig. E-1 +let private parseMUnitCompound bin = + let unit = getMUnit (sBit bin) (xBit bin) + match extract bin 10u 6u with + | 0b00000u -> parseS2XS2Ull bin Op.MPY2 unit + | 0b00001u -> parseS2XS2Sll bin Op.SMPY2 unit + | 0b00010u -> parseS4XU4Int bin Op.DOTPSU4 unit (* DOTPUS4 *) + | 0b00100u -> parseU4XU4DWU4 bin Op.MPYU4 unit + | 0b00101u -> parseS4XU4DWS4 bin Op.MPYSU4 unit (* MPYUS4 *) + | 0b00110u -> parseU4XU4Ui bin Op.DOTPU4 unit + | 0b00111u -> parseS2XU2Int bin Op.DOTPNRSU2 unit (* DOTPNRUS2 *) + | 0b01001u -> parseS2XS2Int bin Op.DOTPN2 unit + | 0b01101u -> parseS2XU2Int bin Op.DOTPRSU2 unit (* DOTPRUS2 *) + | 0b01011u -> parseS2XS2Sll bin Op.DOTP2 unit + | 0b01100u -> parseS2XS2Int bin Op.DOTP2 unit + | 0b01110u -> parseIntXiInt bin Op.MPYLIR unit (* MPYILR *) + | 0b10000u -> parseIntXiInt bin Op.MPYHIR unit (* MPYIHR *) + | 0b10001u -> parseU4XU4U4 bin Op.GMPY4 unit + | 0b10010u -> parseU4XU4U4 bin Op.AVGU4 unit + | 0b10011u -> parseS2XS2S2 bin Op.AVG2 unit + | 0b10100u -> parseIntXiSll bin Op.MPYHI unit (* MPYIH *) + | 0b10101u -> parseIntXiSll bin Op.MPYLI unit (* MPYIL *) + | 0b10110u -> parseSpXDpDp bin Op.MPYSPDP unit + | 0b10111u -> parseSpXSpDp bin Op.MPYSP2DP unit + | 0b11000u -> parseUiXUiDUi bin Op.MPY32U unit + | 0b11001u -> parseUiXiDi bin Op.MPY32US unit + | 0b11010u -> parseXiIntInt bin Op.SSHVR unit + | 0b11100u -> parseXiIntInt bin Op.SSHVL unit + | 0b11101u -> parseXUiUiUi bin Op.ROTL unit + | 0b11110u -> parseXUiUc5Ui bin Op.ROTL unit + | _ -> Utils.impossible () + +/// Appendix E. page 743. Fig. E-2 +let private parseMUnitUnaryExt bin = + let unit = getMUnit (sBit bin) (xBit bin) + match extract bin 17u 13u with + | 0b11010u -> parseXiInt bin Op.MVD unit + | 0b11000u -> parseXUiUi bin Op.XPND4 unit + | 0b11001u -> parseXUiUi bin Op.XPND2 unit + | 0b11101u -> parseXUiUi bin Op.DEAL unit + | 0b11100u -> parseXUiUi bin Op.SHFL unit + | 0b11110u -> parseXU4U4 bin Op.BITC4 unit + | 0b11111u -> parseXUiUi bin Op.BITR unit + | _ -> Utils.impossible () + +/// Appendix E. page 743. Fig. E-3 +let private parseMUnitNonCond bin = + let unit = getMUnit (sBit bin) (xBit bin) + match extract bin 10u 6u with + | 0b01010u -> parseS2XS2Di bin Op.CMPY unit + | 0b01011u -> parseS2XS2S2 bin Op.CMPYR unit + | 0b01100u -> parseS2XS2S2 bin Op.CMPYR1 unit + | 0b01111u -> parseIntXiDi bin Op.MPY2IR unit (* E-1, Exceptional case. *) + | 0b10100u -> parseDS2XS2S2 bin Op.DDOTPL2R unit + | 0b10101u -> parseDS2XS2S2 bin Op.DDOTPH2R unit + | 0b10110u -> parseDS2XS2Di bin Op.DDOTPL2 unit + | 0b10111u -> parseDS2XS2Di bin Op.DDOTPH2 unit + | 0b11000u -> parseS2XS4Di bin Op.DDOTP4 unit + | 0b11001u -> parseIntXiInt bin Op.SMPY32 unit + | 0b11011u -> parseUiXUiUi bin Op.XORMPY unit + | 0b11111u -> parseUiUiUi bin Op.GMPY unit + | _ -> Utils.impossible () + +/// Appendix E. page 743. Fig. E-4 +let private parseMUnitMPY bin = + let unit = getMUnit (sBit bin) (xBit bin) + match extract bin 11u 7u with + | 0b00001u -> parseSmsb16XSmsb16Si bin Op.MPYH unit + | 0b00010u -> parseSmsb16XSmsb16Si bin Op.SMPYH unit + | 0b00011u -> parseSmsb16XUmsb16Si bin Op.MPYHSU unit + | 0b00100u -> parseSiXSiSi bin Op.MPYI unit + | 0b00101u -> parseUmsb16XSmsb16Si bin Op.MPYHUS unit + | 0b00110u -> parseC5XSiSi bin Op.MPYI unit + | 0b00111u -> parseUmsb16XUmsb16Ui bin Op.MPYHU unit + | 0b01000u -> parseSiXSiSDi bin Op.MPYID unit + | 0b01001u -> parseSmsb16XSlsb16Si bin Op.MPYHL unit + | 0b01010u -> parseSmsb16XSlsb16Si bin Op.SMPYHL unit + | 0b01011u -> parseSmsb16XUlsb16Si bin Op.MPYHSLU unit + | 0b01100u -> parseC5XSiSDi bin Op.MPYID unit + | 0b01101u -> parseUmsb16XSlsb16Si bin Op.MPYHULS unit + | 0b01110u -> parseDpXDpDp bin Op.MPYDP unit + | 0b01111u -> parseUmsb16XUlsb16Ui bin Op.MPYHLU unit + | 0b10000u -> parseIntXiInt bin Op.MPY32 unit + | 0b10001u -> parseSlsb16XSmsb16Si bin Op.MPYLH unit + | 0b10010u -> parseSlsb16XSmsb16Si bin Op.SMPYLH unit + | 0b10011u -> parseSlsb16XUmsb16Si bin Op.MPYLSHU unit + | 0b10100u -> parseIntXiDi bin Op.MPY32 unit + | 0b10101u -> parseUlsb16XSmsb16Si bin Op.MPYLUHS unit + | 0b10110u -> parseIntXUiDi bin Op.MPY32SU unit + | 0b10111u -> parseUlsb16XUmsb16Ui bin Op.MPYLHU unit + | 0b11000u -> parseSc5XSlsb16Si bin Op.MPY unit + | 0b11001u -> parseSlsb16XSlsb16Si bin Op.MPY unit + | 0b11010u -> parseSlsb16XSlsb16Si bin Op.SMPY unit + | 0b11011u -> parseSlsb16XUlsb16Si bin Op.MPYSU unit + | 0b11100u -> parseSpXSpSp bin Op.MPYSP unit + | 0b11101u -> parseUlsb16XSlsb16Si bin Op.MPYUS unit + | 0b11110u -> parseSc5XUlsb16Si bin Op.MPYSU unit + | 0b11111u -> parseUlsb16XUlsb16Ui bin Op.MPYU unit + | _ -> Utils.impossible () + +/// Appendix F. page 747. Fig. F-1 +let private parseSUnitSrcs bin = + let unit = getSUnit (sBit bin) (xBit bin) + match extract bin 11u 6u with + | 0b000001u -> parseI2Xi2I2 bin Op.ADD2 unit + | 0b000010u -> parseXSpDp bin Op.SPDP unit + | 0b000110u when isSrc1Zero bin -> parseXSiSi bin Op.MV unit + | 0b000110u -> parseSc5XSiSi bin Op.ADD unit + | 0b000111u -> parseSiXSiSi bin Op.ADD unit + | 0b001000u -> parseI2Xi2I2 bin Op.PACKHL2 unit + | 0b001001u -> parseI2Xi2I2 bin Op.PACKH2 unit + | 0b001010u when isSrc111111 bin -> parseXUiUi bin Op.NOT unit + | 0b001010u -> parseSc5XUiUi bin Op.XOR unit + | 0b001011u -> parseUiXUiUi bin Op.XOR unit + | 0b001110u -> parseRegToCtrlReg bin Op.MVC unit + | 0b001111u -> parseCtrlRegToReg bin Op.MVC unit + | 0b010000u when isSrc100010 bin -> parseS2S2 bin Op.SWAP2 unit // FIXME + | 0b010000u -> parseI2Xi2I2 bin Op.PACKLH2 unit + | 0b010001u -> parseI2Xi2I2 bin Op.SUB2 unit + | 0b010010u -> parseXUiUc5Ul bin Op.SHL unit + | 0b010011u -> parseXUiUiUl2 bin Op.SHL unit + | 0b010100u -> parseS2XS2Bv2 bin Op.CMPGT2 unit (* CMPLT2 src2, src1, dst *) + | 0b010101u -> parseU4XU4Bv4 bin Op.CMPGTU4 unit (* CMPLTU4 src2, src1, dst *) + | 0b010110u when isSrc1Zero bin -> parseXSiSi bin Op.NEG unit + | 0b010110u -> parseSc5XSiSi bin Op.SUB unit + | 0b010111u -> parseSiXSiSi bin Op.SUB unit + | 0b011000u -> parseXS2Uc5S2 bin Op.SHR2 unit + | 0b011001u -> parseXU2Uc5U2 bin Op.SHRU2 unit + | 0b011010u -> parseSc5XUiUi bin Op.OR unit + | 0b011011u -> parseUiXUiUi bin Op.OR unit + | 0b011100u -> parseS4XS4Bv4 bin Op.CMPEQ4 unit + | 0b011101u -> parseS2XS2Bv2 bin Op.CMPEQ2 unit + | 0b011110u -> parseSc5XUiUi bin Op.AND unit + | 0b011111u -> parseUiXUiUi bin Op.AND unit + | 0b100000u -> parseSiXSiSi bin Op.SADD unit + | 0b100010u -> parseXSiUc5Si bin Op.SSHL unit + | 0b100011u -> parseXSiUiSi bin Op.SSHL unit + | 0b100100u -> parseUlUc5Ul bin Op.SHRU unit + | 0b100101u -> parseUlUiUl bin Op.SHRU unit + | 0b100110u -> parseXUiUc5Ui bin Op.SHRU unit + | 0b100111u -> parseXUiUiUi bin Op.SHRU unit + | 0b101000u -> parseDpXDpSi bin Op.CMPEQDP unit + | 0b101001u -> parseDpXDpSi bin Op.CMPGTDP unit + | 0b101010u -> parseDpXDpSi bin Op.CMPLTDP unit + | 0b101011u -> parseXUiUiUi bin Op.EXTU unit + | 0b101100u -> parseXDpDp bin Op.ABSDP unit + | 0b101101u -> parseDpDp bin Op.RCPDP unit + | 0b101110u -> parseDpDp bin Op.RSQRDP unit + | 0b101111u -> parseXSiUiSi bin Op.EXT unit + | 0b110000u -> parseSlUc5Sl bin Op.SHL unit + | 0b110001u -> parseSlUiSl bin Op.SHL unit + | 0b110010u -> parseXSiUc5Si bin Op.SHL unit + | 0b110011u -> parseXSiUiSi bin Op.SHL unit + | 0b110100u -> parseSlUc5Sl bin Op.SHR unit + | 0b110101u -> parseSlUiSl bin Op.SHR unit + | 0b110110u -> parseXSiUc5Si bin Op.SHR unit + | 0b110111u -> parseXSiUiSi bin Op.SHR unit + | 0b111000u -> parseSpXSpSi bin Op.CMPEQSP unit + | 0b111001u -> parseSpXSpSi bin Op.CMPGTSP unit + | 0b111010u -> parseSpXSpSi bin Op.CMPLTSP unit + | 0b111011u -> parseXUiUiUi bin Op.SET unit + | 0b111110u -> parseXSpSp bin Op.RSQRSP unit + | 0b111111u -> parseXUiUiUi bin Op.CLR unit + | _ -> Utils.impossible () + +/// Appendix F. page 747. Fig. F-2 +let private parseSUnitAddSubFloat bin = struct (Op.InvalOP, NoUnit, NoOperand) + +/// Appendix F. page 747. Fig. F-3 +let private parseSUnitADDK bin = + parseSc16Ui bin Op.ADDK (getSUnit (sBit bin) 0u) + +/// Appendix F. page 748. Fig. F-4 +let private parseSUnitADDKPC bin = + parseSc7Uc3Ui bin Op.ADDKPC (getSUnit (sBit bin) 0u) + +/// Appendix F. page 748. Fig. F-5 +let private parseSUnitSrcsExt bin = + let unit = getSUnit (sBit bin) (xBit bin) + match extract bin 9u 6u with + | 0b0000u -> parseS2XS2S2 bin Op.SADD2 unit + | 0b0001u -> parseU2XS2U2 bin Op.SADDUS2 unit (* SADDSU2 *) + | 0b0010u -> parseIntXiS2 bin Op.SPACK2 unit + | 0b0011u -> parseU4XU4U4 bin Op.SADDU4 unit + | 0b0100u -> parseS2XS2U4 bin Op.SPACKU4 unit + | 0b0101u -> parseXSiSiSi2 bin Op.SUB unit + | 0b0110u -> parseUiXUiUi bin Op.ANDN unit + | 0b0111u -> parseXS2UiS2 bin Op.SHR2 unit + | 0b1000u -> parseXU2UiU2 bin Op.SHRU2 unit + | 0b1001u -> parseU4XU4U4 bin Op.SHLMB unit + | 0b1010u -> parseU4XU4U4 bin Op.SHRMB unit + | 0b1011u -> parseSiXSiDi bin Op.DMV unit + | 0b1100u -> parseS2XS2S2 bin Op.MIN2 unit + | 0b1101u -> parseS2XS2S2 bin Op.MAX2 unit + | 0b1111u -> parseI2Xi2I2 bin Op.PACK2 unit + | _ -> Utils.impossible () + +/// Appendix F. page 748. Fig. F-6 +let private parseSUnitBrDisp bin = + parseSc21 bin Op.B (getSUnit (sBit bin) 0u) // FIXME: label + +/// Appendix F. page 748. Fig. F-7 +let private parseSUnitBrRegWithoutNOP bin = + parseXUi bin Op.B (getSUnit (sBit bin) (xBit bin)) + +/// Appendix F. page 748. Fig. F-8 +let private parseSUnitBrPointer bin = struct (Op.InvalOP, NoUnit, NoOperand) + +/// Appendix F. page 748. Fig. F-9 +let private parseSUnitBdecBpos bin = + let unit = getSUnit (sBit bin) 0u + match pickBit bin 12u with + | 0b1u -> parseSc10Int bin Op.BDEC unit + | _ (* 0b0u *) -> parseSc10Int bin Op.BPOS unit + +/// Appendix F. page 748. Fig. F-10 +let private parseSUnitBrDispNOP bin = + parseSc12Uc3 bin Op.BNOP (getSUnit (sBit bin) 0u) + +/// Appendix F. page 748. Fig. F-11 +let private parseSUnitBrRegNOP bin = + parseXUiUc3 bin Op.BNOP (getSUnit (sBit bin) (xBit bin)) + +/// Appendix F. page 749. Fig. F-12 +let private parseSUnitNonCondImm bin = + parseSc21 bin Op.CALLP (getSUnit (sBit bin) 0u) // FIXME: label + +/// Appendix F. page 749. Fig. F-13 +let private parseSUnitMoveConst bin = + match pickBit bin 6u with + | 0b0u -> parseSc16Si bin Op.MVK (getSUnit (sBit bin) 0u) + | _ (* 0b01 *) -> parseUSc16Si bin Op.MVKH (getSUnit (sBit bin) 0u) // FIXME + +/// Appendix F. page 749. Fig. F-14 +let private parseSUnitNonCond bin = + let unit = getSUnit (sBit bin) (xBit bin) + match extract bin 9u 6u with + | 0b1011u -> parseSiXSiS2 bin Op.RPACK2 unit + | _ -> Utils.impossible () + +/// Appendix F. page 749. Fig. F-15 +let private parseSUnitUnary bin = + let unit = getSUnit (sBit bin) (xBit bin) + match extract bin 17u 13u with + | 0b00000u -> parseXSpSp bin Op.ABSSP unit + | 0b00010u -> parseXU4U2 bin Op.UNPKLU4 unit + | 0b00011u -> parseXU4U2 bin Op.UNPKHU4 unit + | _ -> Utils.impossible () + +/// Appendix F. page 749. Fig. F-16 +let private parseSUnitFieldOps bin = + match extract bin 7u 6u with + | 0b00u -> parseUiUc5Uc5Ui bin Op.EXTU (getSUnit (sBit bin) 0u) + | 0b01u -> parseSiUc5Uc5Si bin Op.EXT (getSUnit (sBit bin) 0u) + | 0b10u -> parseUiUc5Uc5Ui bin Op.SET (getSUnit (sBit bin) 0u) + | 0b11u -> parseUiUc5Uc5Ui bin Op.CLR (getSUnit (sBit bin) 0u) + | _ -> Utils.impossible () + +/// Appendix H. page 765. Fig. H-1 +let private parseNoUnitDINT bin = + match extract bin 16u 13u with + | 0b0000u -> struct (Op.SWE, NoUnit, NoOperand) + | 0b0001u -> struct (Op.SWENR, NoUnit, NoOperand) + | 0b0010u -> struct (Op.DINT, NoUnit, NoOperand) + | 0b0011u -> struct (Op.RINT, NoUnit, NoOperand) + | _ -> Utils.impossible () + +/// Appendix H. page 765. Fig. H-2 +let private parseNoUnitIdleNop bin = + match extract bin 16u 13u with + | 0b1111u -> struct (Op.IDLE, NoUnit, NoOperand) + | _ -> parseUc4 bin Op.NOP NoUnit + +/// Appendix H. page 765. Fig. H-3 +let private parseNoUnitLoopNonCond bin = struct (Op.InvalOP, NoUnit, NoOperand) + +/// Appendix H. page 765. Fig. H-4 +let private parseNoUnitLoop bin = struct (Op.InvalOP, NoUnit, NoOperand) + +let private parseNoUnitCase0 bin = + match extract bin 31u 28u with + | 0b0000u -> parseNoUnitIdleNop bin + | 0b0001u -> parseNoUnitDINT bin + | _ -> Utils.impossible () + +let private parseNoUnitCase1 bin = + match extract bin 31u 28u with + | 0b0000u -> parseNoUnitLoopNonCond bin + | _ -> parseNoUnitLoop bin + +let private parseNoUnit bin = + match pickBit bin 17u with + | 0b0u -> parseNoUnitCase0 bin + | _ (* 0b1u *) -> parseNoUnitCase1 bin + +let private parseCase00000 bin = + match extract bin 12u 7u with + | 0b000000u -> parseNoUnit bin + | _ -> parseMUnitMPY bin + +let private parseCase0000 bin = + match pickBit bin 6u with + | 0b1u -> parseDUnitSrcs bin + | _ (* 0b0u *) -> parseCase00000 bin + +let private parseCase00100 bin = + match extract bin 31u 28u with + | 0b0001u -> parseSUnitNonCondImm bin + | _ -> parseSUnitBrDisp bin + +let private parseCase0100 bin = + match pickBit bin 6u with + | 0b0u -> parseCase00100 bin + | _ (* 0b1u *) -> parseSUnitADDK bin + +let private parseSUnitBrReg bin = + match pickBit bin 23u with + | 0b0u -> parseSUnitBrRegWithoutNOP bin + | _ (* 0b1u *) -> parseSUnitBrRegNOP bin + +let private parseCase1000 bin = + match extract bin 11u 6u with + | 0b000000u -> parseSUnitBdecBpos bin + | 0b000011u -> parseSUnitBrPointer bin + | 0b000100u -> parseSUnitBrDispNOP bin + | 0b000101u -> parseSUnitADDKPC bin + | 0b111100u -> parseSUnitUnary bin + | 0b001101u -> parseSUnitBrReg bin + | _ -> parseSUnitSrcs bin + +let parseMUnitSub bin = + match extract bin 31u 28u with + | 0b0001u -> parseMUnitNonCond bin + | _ -> parseMUnitCompound bin + +let private parseMUnit bin = + match extract bin 10u 6u with + | 0b00011u -> parseMUnitUnaryExt bin + | _ -> parseMUnitSub bin + +let parseCase111100 bin = + match extract bin 31u 28u with + | 0b0001u -> parseSUnitNonCond bin + | _ -> parseSUnitSrcsExt bin + +let private parseCase11100 bin = + match pickBit bin 10u with + | 0b0u -> parseDUnitSrcsExt bin + | _ (* 0b1u *) -> parseCase111100 bin + +let private parseCase1100 bin = + match pickBit bin 11u with + | 0b0u -> parseMUnit bin + | _ (* 0b1u *) -> parseCase11100 bin + +let private parseCase00 bin = + match extract bin 5u 4u with + | 0b00u -> parseCase0000 bin + | 0b01u -> parseCase0100 bin + | 0b10u -> parseCase1000 bin + | _ (* 0b11 *) -> parseCase1100 bin + +let private parseCase010 bin = + match pickBit bin 5u with + | 0b0u -> parseSUnitFieldOps bin + | _ (* 0b1u *) -> parseSUnitMoveConst bin + +let private parseCase110 bin = + let x, s = xBit bin, sBit bin + let creg = extract bin 31u 29u + match extract bin 11u 5u with + | 0b0011010u -> parseLUnitUnary bin + (* parseLUnitNonCond, D-3 *) + | 0b0001110u when creg = 0b0001u -> + parseSiXSiDi bin Op.SADDSUB (getLUnit s x) + | 0b0001111u when creg = 0b0001u -> + parseSiXSiDi bin Op.SADDSUB2 (getLUnit s x) + | 0b0110011u -> parseSiXSiDi bin Op.DPACKX2 (getLUnit s x) + | 0b0110100u -> parseSiXSiDi bin Op.DPACK2 (getLUnit s x) + | 0b0110110u -> parseSiXSiDi bin Op.SHFL3 (getLUnit s x) + (* parseLUnitSrcs, D-1 *) + | 0b0000000u -> parseI2Xi2I2 bin Op.PACK2 (getLUnit s x) + | 0b0000001u -> parseDpSi bin Op.DPTRUNC (getLUnit s x) + | 0b0000011u -> parseSiXSiSi bin Op.ADD (getLUnit s x) + | 0b0000010u when isSrc1Zero bin -> parseXSiSi bin Op.MV (getLUnit s x) + | 0b0000010u -> parseSc5XSiSi bin Op.ADD (getLUnit s x) + | 0b0000100u -> parseI2Xi2I2 bin Op.SUB2 (getLUnit s x) + | 0b0000101u -> parseI2Xi2I2 bin Op.ADD2 (getLUnit s x) + | 0b0000110u when isSrc1Zero bin -> parseXSiSi bin Op.NEG (getLUnit s x) + | 0b0000110u -> parseSc5XSiSi bin Op.SUB (getLUnit s x) + | 0b0000111u when isEqualSrc1Src2 bin -> parseSi bin Op.ZERO (getLUnit s x) + | 0b0000111u -> parseSiXSiSi bin Op.SUB (getLUnit s x) + | 0b0001000u -> parseDpSi bin Op.DPINT (getLUnit s x) + | 0b0001001u -> parseDpSp bin Op.DPSP (getLUnit s x) + | 0b0001010u -> parseXSpSi bin Op.SPINT (getLUnit s x) + | 0b0001011u -> parseXSpSi bin Op.SPTRUNC (getLUnit s x) + | 0b0001100u -> parseSiXSiDi bin Op.ADDSUB (getLUnit s x) + | 0b0001101u -> parseSiXSiDi bin Op.ADDSUB2 (getLUnit s x) + | 0b0001110u -> parseSc5XSiSi bin Op.SSUB (getLUnit s x) + | 0b0001111u -> parseSiXSiSi bin Op.SSUB (getLUnit s x) + | 0b0010000u -> parseSpXSpSp bin Op.ADDSP (getLUnit s x) + | 0b0010001u -> parseSpXSpSp bin Op.SUBSP (getLUnit s x) + | 0b0010010u -> parseSc5XSiSi bin Op.SADD (getLUnit s x) + | 0b0010011u -> parseSiXSiSi bin Op.SADD (getLUnit s x) + | 0b0010101u -> parseXSpSpSp bin Op.SUBSP (getLUnit s x) + | 0b0010111u -> parseXSiSiSi1 bin Op.SUB (getLUnit s x) + | 0b0011000u -> parseDpXDpDp bin Op.ADDDP (getLUnit s x) + | 0b0011001u -> parseDpXDpDp bin Op.SUBDP (getLUnit s x) + | 0b0011011u when isSrc100010 bin -> parseS2S2 bin Op.SWAP2 (getLUnit s x) + | 0b0011011u -> parseI2Xi2I2 bin Op.PACKLH2 (getLUnit s x) + | 0b0011100u -> parseI2Xi2I2 bin Op.PACKHL2 (getLUnit s x) + | 0b0011101u -> parseXDpDpDp bin Op.SUBDP (getLUnit s x) + | 0b0011110u -> parseI2Xi2I2 bin Op.PACKH2 (getLUnit s x) + | 0b0011111u -> parseXSiSiSi1 bin Op.SSUB (getLUnit s x) + | 0b0100000u when isSrc1Zero bin -> parseSlSl bin Op.MV (getLUnit s 0u) + | 0b0100000u -> parseSc5SlSl bin Op.ADD (getLUnit s x) + | 0b0100001u -> parseXSiSlSl bin Op.ADD (getLUnit s x) + | 0b0100011u -> parseSiXSiSl bin Op.ADD (getLUnit s x) + | 0b0100100u when isSrc1Zero bin -> parseSlSl bin Op.NEG (getLUnit s x) + | 0b0100100u -> parseSc5SlSl bin Op.SUB (getLUnit s x) + | 0b0100111u when isEqualSrc1Src2 bin -> parseSl bin Op.ZERO (getLUnit s x) + | 0b0100111u -> parseSiXSiSl bin Op.SUB (getLUnit s x) + | 0b0101001u -> parseXUiUlUl bin Op.ADDU (getLUnit s x) + | 0b0101011u -> parseUiXUiUl bin Op.ADDU (getLUnit s x) + | 0b0101100u -> parseSc5SlSl bin Op.SSUB (getLUnit s x) + | 0b0101111u -> parseUiXUiUl bin Op.SUBU (getLUnit s x) + | 0b0110000u -> parseSc5SlSl bin Op.SADD (getLUnit s x) + | 0b0110001u -> parseXSiSlSl bin Op.SADD (getLUnit s x) + | 0b0110111u when isEqualSrc1Src2 bin -> parseSl bin Op.ZERO (getLUnit s x) + | 0b0110111u -> parseXSiSiSl bin Op.SUB (getLUnit s x) + | 0b0111000u -> parseSlSl bin Op.ABS (getLUnit s x) + | 0b0111001u -> parseXSiDp bin Op.INTDP (getLUnit s x) + | 0b0111011u -> parseXUiDp bin Op.INTDPU (getLUnit s x) + | 0b0111111u -> parseXUiUiUl1 bin Op.SUBU (getLUnit s x) + | 0b1000000u -> parseSlSi bin Op.SAT (getLUnit s x) + | 0b1000001u -> parseS2XS2S2 bin Op.MIN2 (getLUnit s x) + | 0b1000010u -> parseS2XS2S2 bin Op.MAX2 (getLUnit s x) + | 0b1000011u -> parseU4XU4U4 bin Op.MAXU4 (getLUnit s x) + | 0b1000100u -> parseSc5SlUi bin Op.CMPGT (getLUnit s x) + | 0b1000101u -> parseXSiSlUi bin Op.CMPGT (getLUnit s x) + | 0b1000110u -> parseSc5XSiUi bin Op.CMPGT (getLUnit s x) + | 0b1000111u -> parseSiXSiUi bin Op.CMPGT (getLUnit s x) + | 0b1001000u -> parseU4XU4U4 bin Op.MINU4 (getLUnit s x) + | 0b1001001u -> parseXUiSp bin Op.INTSPU (getLUnit s x) + | 0b1001010u -> parseXSiSp bin Op.INTSP (getLUnit s x) + | 0b1001011u -> parseUiXUiUi bin Op.SUBC (getLUnit s x) + | 0b1001100u -> parseUc4UlUi bin Op.CMPGTU (getLUnit s x) + | 0b1001101u -> parseXUiUlUi bin Op.CMPGTU (getLUnit s x) + | 0b1001110u -> parseUc4XUiUi bin Op.CMPGTU (getLUnit s x) + | 0b1001111u -> parseUiXUiUi bin Op.CMPGTU (getLUnit s x) + | 0b1010000u -> parseSc5SlUi bin Op.CMPEQ (getLUnit s x) + | 0b1010001u -> parseXSiSlUi bin Op.CMPEQ (getLUnit s x) + | 0b1010010u -> parseSc5XSiUi bin Op.CMPEQ (getLUnit s x) + | 0b1010011u -> parseSiXSiUi bin Op.CMPEQ (getLUnit s x) + | 0b1010100u -> parseSc5SlUi bin Op.CMPLT (getLUnit s x) + | 0b1010101u -> parseXSiSlUi bin Op.CMPLT (getLUnit s x) + | 0b1010110u -> parseSc5XSiUi bin Op.CMPLT (getLUnit s x) + | 0b1010111u -> parseSiXSiUi bin Op.CMPLT (getLUnit s x) + | 0b1011010u -> parseU4XU4U4 bin Op.SUBABS4 (getLUnit s x) + | 0b1011100u -> parseUc4UlUi bin Op.CMPGTU (getLUnit s x) + | 0b1011101u -> parseXUiUlUi bin Op.CMPGTU (getLUnit s x) + | 0b1011110u -> parseUc4XUiUi bin Op.CMPGTU (getLUnit s x) + | 0b1011111u -> parseUiXUiUi bin Op.CMPGTU (getLUnit s x) + | 0b1100000u -> parseSlUi bin Op.NORM (getLUnit s x) + | 0b1100001u -> parseU4XU4U4 bin Op.SHLMB (getLUnit s x) + | 0b1100010u -> parseU4XU4U4 bin Op.SHRMB (getLUnit s x) + | 0b1100011u -> parseXSiUi bin Op.NORM (getLUnit s x) + | 0b1100100u -> parseS2XS2S2 bin Op.SSUB2 (getLUnit s x) + | 0b1100101u -> parseI4Xi4I4 bin Op.ADD4 (getLUnit s x) + | 0b1100110u -> parseI4Xi4I4 bin Op.SUB4 (getLUnit s x) + | 0b1101000u -> parseI4Xi4I4 bin Op.PACKL4 (getLUnit s x) + | 0b1101001u -> parseI4Xi4I4 bin Op.PACKH4 (getLUnit s x) + | 0b1101010u -> parseC5XUiUi bin Op.LMBD (getLUnit s x) + | 0b1101011u -> parseUiXUiUi bin Op.LMBD (getLUnit s x) + | 0b1101110u when isSrc111111 bin -> parseXUiUi bin Op.NOT (getLUnit s x) + | 0b1101110u -> parseSc5XUiUi bin Op.XOR (getLUnit s x) + | 0b1101111u -> parseUiXUiUi bin Op.XOR (getLUnit s x) + | 0b1111010u -> parseSc5XUiUi bin Op.AND (getLUnit s x) + | 0b1111011u -> parseUiXUiUi bin Op.AND (getLUnit s x) + | 0b1111100u -> parseUiXUiUi bin Op.ANDN (getLUnit s x) + | 0b1111110u when isSrc1Zero bin -> parseXUiUi bin Op.MV (getLUnit s x) + | 0b1111110u -> parseSc5XUiUi bin Op.OR (getLUnit s x) + | 0b1111111u -> parseUiXUiUi bin Op.OR (getLUnit s x) + (* parseSUnitAddSubFloat, F-2 *) + | 0b1110000u -> parseSpXSpSp bin Op.ADDSP (getSUnit s x) + | 0b1110001u -> parseSpXSpSp bin Op.SUBSP (getSUnit s x) + | 0b1110010u -> parseDpXDpDp bin Op.ADDDP (getSUnit s x) + | 0b1110011u -> parseDpXDpDp bin Op.SUBDP (getSUnit s x) + | 0b1110101u -> parseSpXSpSp bin Op.SUBSP (getSUnit s x) (* src2 - src1 *) + | 0b1110111u -> parseDpXDpDp bin Op.SUBDP (getSUnit s x) (* src2 - src1 *) + | _ -> Utils.impossible () + +let private parseCase10 bin = + match pickBit bin 4u with + | 0b0u -> parseCase010 bin + | _ (* 0b1u *) -> parseCase110 bin + +let private parseDUnitDWord bin = + let unit = getDUnit (yBit bin) 0u + match extract bin 6u 4u with + (* parseDUnitLSBasic, C-4. Exceptional case. *) + | 0b011u -> parseDUnitLSBasicOperands bin Op.LDNW unit MemReg + | 0b101u -> parseDUnitLSBasicOperands bin Op.STNW unit RegMem + (* parseDUnitLSDWord, C-6 *) + | 0b100u -> parseDUnitDWordOperands bin Op.STDW unit RegMem + | 0b110u -> parseDUnitDWordOperands bin Op.LDDW unit MemReg + (* parseDUnitLSNonalignDWord C-7 *) + | 0b010u -> parseDUnitDWordOperands bin Op.LDNDW unit MemReg + | 0b111u -> parseDUnitDWordOperands bin Op.STNDW unit RegMem + | _ -> Utils.impossible () + +let private parseDUnitLoadStore bin = + match pickBit bin 8u with + | 0b1u -> parseDUnitDWord bin + | _ (* 0b0u *) -> parseDUnitLSBasic bin + +let private parseDUnitLongImm bin = + match extract bin 31u 28u with + | 0b0001u -> parseDUnitADDLongImm bin + | _ -> parseDUnitLSLongImm bin + +let private parseInstruction bin = + match extract bin 3u 2u with + | 0b00u -> parseCase00 bin + | 0b10u -> parseCase10 bin + | 0b01u -> parseDUnitLoadStore bin + | _ (* 0b11u *) -> parseDUnitLongImm bin + +let parse (span: ByteSpan) reader (inParallel: byref) addr = + let bin = (reader: IBinReader).ReadUInt32 (span, 0) + let struct (opcode, unit, operands) = parseInstruction bin + let insInfo = + { Address = addr + NumBytes = 4u + Opcode = opcode + Operands = operands + FunctionalUnit = unit + OperationSize = 32 // FIXME + IsParallel = inParallel + EffectiveAddress = 0UL } + inParallel <- pBit bin <> 0u + TMS320C6000Instruction (addr, 4u, insInfo) + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs index cdbe4931..094d6d4e 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegExprs.fs @@ -25,16 +25,17 @@ namespace B2R2.FrontEnd.BinLifter.TMS320C6000 open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type internal RegExprs (wordSize) = - let var sz t name = AST.var sz t name (TMS320C6000RegisterSet.singleton t) +type RegExprs (wordSize) = + let var sz t name = AST.var sz t name (* Registers *) let regType = WordSize.toRegType wordSize member __.GetRegVar (name) = match name with - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs index c0ee6d45..5718075e 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000Register.fs @@ -136,7 +136,7 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "a0" -> R.A0 | "a1" -> R.A1 | "a2" -> R.A2 diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterBay.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterFactory.fs similarity index 91% rename from src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterBay.fs rename to src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterFactory.fs index 77ac8995..2dec951e 100644 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterBay.fs +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterFactory.fs @@ -28,9 +28,8 @@ open B2R2 open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type TMS320C6000RegisterBay () = - - inherit RegisterBay () +type TMS320C6000RegisterFactory () = + inherit RegisterFactory () override __.GetAllRegExprs () = Utils.futureFeature () @@ -40,9 +39,9 @@ type TMS320C6000RegisterBay () = override __.RegIDFromRegExpr (e) = match e.E with - | Var (_, id, _ ,_) -> id - | PCVar (_, _) -> Register.toRegID Register.PCE1 - | _ -> failwith "not a register expression" + | Var (_, id, _) -> id + | PCVar _ -> Register.toRegID Register.PCE1 + | _ -> raise InvalidRegisterException override __.RegIDToRegExpr (id) = Utils.futureFeature () override __.StrToRegExpr _s = Utils.futureFeature () diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterSet.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterSet.fs deleted file mode 100644 index c9ecdd39..00000000 --- a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000RegisterSet.fs +++ /dev/null @@ -1,59 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.BinLifter.TMS320C6000 - -open B2R2 - -module private RegisterSetLiteral = - let [] ArrLen = 2 - -open RegisterSetLiteral - -type TMS320C6000RegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = - TMS320C6000RegisterSet (RegisterSet.MakeInternalBitArray ArrLen, Set.empty) - - override __.Tag = RegisterSetTag.TMS320C6000 - - override __.ArrSize = ArrLen - - override __.New arr s = new TMS320C6000RegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | _ -> Utils.futureFeature () - - override __.IndexToRegID _index: RegisterID = - Utils.futureFeature () - - override __.ToString () = - sprintf "TMS320C6000RegisterSet<%x, %x>" __.BitArray[0] __.BitArray[1] - -[] -module TMS320C6000RegisterSet = - let singleton rid = TMS320C6000RegisterSet().Add(rid) - let empty = TMS320C6000RegisterSet () :> RegisterSet diff --git a/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000TranslationContext.fs b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000TranslationContext.fs new file mode 100644 index 00000000..2ec6d977 --- /dev/null +++ b/src/FrontEnd/BinLifter/TMS320C6000/TMS320C6000TranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.TMS320C6000 + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for TMS320C6000 instructions. +type TMS320C6000TranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs isa.WordSize + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () diff --git a/src/FrontEnd/BinLifter/WASM/B2R2.FrontEnd.BinLifter.WASM.fsproj b/src/FrontEnd/BinLifter/WASM/B2R2.FrontEnd.BinLifter.WASM.fsproj index bda4599d..c32ade51 100644 --- a/src/FrontEnd/BinLifter/WASM/B2R2.FrontEnd.BinLifter.WASM.fsproj +++ b/src/FrontEnd/BinLifter/WASM/B2R2.FrontEnd.BinLifter.WASM.fsproj @@ -9,13 +9,13 @@ - - + + - + diff --git a/src/FrontEnd/BinLifter/WASM/WASM.fs b/src/FrontEnd/BinLifter/WASM/WASM.fs deleted file mode 100644 index cdde3cc6..00000000 --- a/src/FrontEnd/BinLifter/WASM/WASM.fs +++ /dev/null @@ -1,38 +0,0 @@ -namespace B2R2.FrontEnd.BinLifter.WASM - -open System -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for WASM instructions. -type WASMTranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - /// Register expressions. - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = failwith "Implement" - -/// Parser for WASM instructions. Parser will return a platform-agnostic -/// instruction type (Instruction). -type WASMParser (wordSize) = - inherit Parser () - let reader = BinReader.binReaderLE - - override __.Parse (bs: byte[], addr) = - let span = ReadOnlySpan bs - Parser.parse span reader addr :> Instruction - - override __.Parse (span: ByteSpan, addr) = - Parser.parse span reader addr :> Instruction - - override __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () - -module Basis = - let init (isa: ISA) = - let regexprs = RegExprs () - struct ( - WASMTranslationContext (isa, regexprs) :> TranslationContext, - WASMRegisterBay () :> RegisterBay - ) - -// vim: set tw=80 sts=2 sw=2: \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/WASM/WASMDisasm.fs b/src/FrontEnd/BinLifter/WASM/WASMDisasm.fs index e405daa4..19a279f5 100644 --- a/src/FrontEnd/BinLifter/WASM/WASMDisasm.fs +++ b/src/FrontEnd/BinLifter/WASM/WASMDisasm.fs @@ -1,3 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + module internal B2R2.FrontEnd.BinLifter.WASM.Disasm open B2R2 @@ -525,11 +549,11 @@ let opcodeToString = function | I64AtomicRmw16CmpxchgU -> "i64.atomic.rmw16.cmpxchg_u" | I64AtomicRmw32CmpxchgU -> "i64.atomic.rmw32.cmpxchg_u" -let inline buildOpcode insInfo (builder: DisasmBuilder<_>) = +let inline buildOpcode insInfo (builder: DisasmBuilder) = let opcode = opcodeToString insInfo.Opcode builder.Accumulate AsmWordKind.Mnemonic opcode -let oprToString opr delim (builder: DisasmBuilder<_>) = +let oprToString opr delim (builder: DisasmBuilder) = match opr with | Type t -> builder.Accumulate AsmWordKind.String delim @@ -552,13 +576,13 @@ let oprToString opr delim (builder: DisasmBuilder<_>) = | V128 (i32One, i32Two, i32Three, i32Four) -> builder.Accumulate AsmWordKind.String delim builder.Accumulate AsmWordKind.String "i32x4:" - builder.Accumulate AsmWordKind.Value (BitVector.valToString i32One) + builder.Accumulate AsmWordKind.Value (BitVector.ValToString i32One) builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (BitVector.valToString i32Two) + builder.Accumulate AsmWordKind.Value (BitVector.ValToString i32Two) builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (BitVector.valToString i32Three) + builder.Accumulate AsmWordKind.Value (BitVector.ValToString i32Three) builder.Accumulate AsmWordKind.String delim - builder.Accumulate AsmWordKind.Value (BitVector.valToString i32Four) + builder.Accumulate AsmWordKind.Value (BitVector.ValToString i32Four) | Alignment align -> builder.Accumulate AsmWordKind.String delim builder.Accumulate AsmWordKind.Value (align |> string) @@ -575,7 +599,7 @@ let oprToString opr delim (builder: DisasmBuilder<_>) = builder.Accumulate AsmWordKind.String delim builder.Accumulate AsmWordKind.Value (reftype |> string) -let buildOperands insInfo (builder: DisasmBuilder<_>) = +let buildOperands insInfo (builder: DisasmBuilder) = match insInfo.Operands with | NoOperand -> () | OneOperand opr -> @@ -595,7 +619,7 @@ let buildOperands insInfo (builder: DisasmBuilder<_>) = auxOprsToString (List.tail oprs) builder auxOprsToString oprs builder -let disasm insInfo (builder: DisasmBuilder<_>) = +let disasm insInfo (builder: DisasmBuilder) = if builder.ShowAddr then builder.AccumulateAddr () else () buildOpcode insInfo builder buildOperands insInfo builder diff --git a/src/FrontEnd/BinLifter/WASM/WASMInstruction.fs b/src/FrontEnd/BinLifter/WASM/WASMInstruction.fs index 61a7ddd0..4afc9f8c 100644 --- a/src/FrontEnd/BinLifter/WASM/WASMInstruction.fs +++ b/src/FrontEnd/BinLifter/WASM/WASMInstruction.fs @@ -1,3 +1,27 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + namespace B2R2.FrontEnd.BinLifter.WASM open B2R2 @@ -58,23 +82,23 @@ type WASMInstruction (addr, numBytes, insInfo) = override __.TranslateToList ctxt = Utils.futureFeature() - override __.Disasm (showAddr, _resolveSymbol, _fileInfo) = + override __.Disasm (showAddr, _) = let builder = DisasmStringBuilder (showAddr, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Disasm () = let builder = DisasmStringBuilder (false, false, WordSize.Bit32, addr, numBytes) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToString () override __.Decompose (showAddr) = let builder = DisasmWordBuilder (showAddr, false, WordSize.Bit32, addr, numBytes, 8) Disasm.disasm __.Info builder - builder.Finalize () + builder.ToArray () override __.IsInlinedAssembly () = false diff --git a/src/FrontEnd/BinLifter/WASM/WASMParser.fs b/src/FrontEnd/BinLifter/WASM/WASMParser.fs index 2d9770db..fc941551 100644 --- a/src/FrontEnd/BinLifter/WASM/WASMParser.fs +++ b/src/FrontEnd/BinLifter/WASM/WASMParser.fs @@ -1,727 +1,46 @@ -module B2R2.FrontEnd.BinLifter.WASM.Parser +(* + B2R2 - the Next-Generation Reversing Platform -open B2R2 -open B2R2.FrontEnd.BinLifter - -let isPrefix = function - | 0xfc | 0xfd | 0xfe -> true - | _ -> false - -let private readIndex (span: ByteSpan) (reader: IBinReader) pos = - let value, cnt = reader.ReadUInt32LEB128 (span, pos) - struct (value |> Index, pos + cnt) - -let private readType (span: ByteSpan) (reader: IBinReader) pos = - let t, cnt = reader.ReadInt32LEB128 (span, pos) - struct (t |> Type, pos + cnt) - -let private readAlignment (span: ByteSpan) (reader: IBinReader) pos = - let alignment, cnt = reader.ReadUInt32LEB128 (span, pos) - struct (alignment |> Alignment, pos + cnt) - -let private readAddress (span: ByteSpan) (reader: IBinReader) pos = - let address, cnt = reader.ReadUInt32LEB128 (span, pos) - struct (address |> Address, pos + cnt) - -let private readLane (span: ByteSpan) (reader: IBinReader) pos = - let lane = reader.ReadUInt8 (span, pos) - struct (lane |> LaneIndex, pos + 1) - -let private parseU32LEB128 (span: ByteSpan) (reader: IBinReader) pos opcode = - let value, cnt = reader.ReadUInt32LEB128 (span, pos) - struct (opcode, OneOperand (value |> I32), uint32 (pos + cnt)) - -let private parseU64LEB128 (span: ByteSpan) (reader: IBinReader) pos opcode = - let value, cnt = reader.ReadUInt64LEB128 (span, pos) - struct (opcode, OneOperand (value |> I64), uint32 (pos + cnt)) - -let private parseF32 (span: ByteSpan) (reader: IBinReader) pos opcode = - let value = reader.ReadUInt32 (span, pos) - let value = BitVector.ofUInt32 value 32 - struct (opcode, OneOperand (value |> F32), uint32 (pos + 4)) - -let private parseF64 (span: ByteSpan) (reader: IBinReader) pos opcode = - let value = reader.ReadUInt64 (span, pos) - let value = BitVector.ofUInt64 value 64 - struct (opcode, OneOperand (value |> F64), uint32 (pos + 8)) - -let private parseV128 (span: ByteSpan) (reader: IBinReader) pos opcode = - let i32One = reader.ReadUInt32 (span, pos) - let i32One = BitVector.ofUInt32 i32One 32 - let i32Two = reader.ReadUInt32 (span, pos + 4) - let i32Two = BitVector.ofUInt32 i32Two 32 - let i32Three = reader.ReadUInt32 (span, pos + 8) - let i32Three = BitVector.ofUInt32 i32Three 32 - let i32Four = reader.ReadUInt32 (span, pos + 12) - let i32Four = BitVector.ofUInt32 i32Four 32 - let v128 = (i32One, i32Two, i32Three, i32Four) |> V128 - struct (opcode, OneOperand v128, uint32 pos + 16u) - -(* XXX: readIndex *) -let private parseIndex (span: ByteSpan) (reader: IBinReader) pos opcode = - let index, cnt = reader.ReadUInt32LEB128 (span, pos) - struct (opcode, OneOperand (index |> Index), uint32 (pos + cnt)) + Copyright (c) SoftSec Lab. @ KAIST, since 2016 -(* XXX: readType *) -let private parseType (span: ByteSpan) (reader: IBinReader) pos opcode = - let t, cnt = reader.ReadInt32LEB128 (span, pos) - struct (opcode, OneOperand (t |> Type), uint32 (pos + cnt)) + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -let private parseLoad span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - let operands = TwoOperands (alignment, offset) - struct (opcode, operands, uint32 nextPos) + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. -let private parseStore span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - let operands = TwoOperands (alignment, offset) - struct (opcode, operands, uint32 nextPos) + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) -let rec private parseTypes span reader pos cnt ret = - if cnt = 0 then struct (ret, uint32 (pos + 1)) - else - let struct (t, nextPos) = readType span reader pos - parseTypes span reader nextPos (cnt - 1) (ret @ [t]) (* XXX *) +namespace B2R2.FrontEnd.BinLifter.WASM -let rec private parseIndices span reader pos cnt ret = - if cnt = 0 then struct (ret, uint32 (pos + 1)) - else - let struct (index, nextPos) = readIndex span reader pos - parseIndices span reader nextPos (cnt - 1) (ret @ [index]) (* XXX *) - -let private parseCount (span: ByteSpan) (reader: IBinReader) pos = - let cnt, bcnt = reader.ReadInt32LEB128 (span, pos) - struct (cnt, uint32 (pos + bcnt)) - -let private parseSimdLane span reader pos opcode = - let struct (lane, nextPos) = readLane span reader pos - struct (opcode, OneOperand lane, uint32 nextPos) - -let private parseSimdLoadLane span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - let struct (lane, nextPos) = readLane span reader nextPos - struct (opcode, ThreeOperands (alignment, offset, lane), uint32 nextPos) - -let private parseSimdLoadZero span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) - -let private parseSimdStoreLane span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - let struct (lane, nextPos) = readLane span reader nextPos - struct (opcode, ThreeOperands (alignment, offset, lane), uint32 nextPos) - -let private parseSimdShuffle span reader pos opcode = - parseV128 span reader pos opcode - -let private parseSimdSplat span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) - -let private parseAtomicNotify span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) - -let private parseAtomicFence (span: ByteSpan) (reader: IBinReader) pos opcode = - let consistencyModel = reader.ReadUInt8 (span, pos) - struct (opcode, OneOperand (consistencyModel |> ConsistencyModel), - uint32 pos + 1u) - -let private parseAtomicLoad span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) - -let private parseAtomicStore span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) +open System +open B2R2 +open B2R2.FrontEnd.BinLifter -let private parseAtomicWait span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) +/// Parser for WASM instructions. Parser will return a platform-agnostic +/// instruction type (Instruction). +type WASMParser (_wordSize) = + let reader = BinReader.Init Endian.Little -let private parseAtomicRmw span reader pos opcode = - let struct (alignment, nextPos) = readAlignment span reader pos - let struct (offset, nextPos) = readAddress span reader nextPos - struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + interface IInstructionParsable with + member __.Parse (bs: byte[], addr) = + let span = ReadOnlySpan bs + ParsingMain.parse span reader addr :> Instruction -let private parseInstruction (span: ByteSpan) (reader: IBinReader) = - let bin = reader.ReadByte (span, 0) - match bin with - | 0xfcuy -> - let bin = reader.ReadByte (span, 1) - match bin with - | 0x00uy -> struct (I32TruncSatF32S, NoOperand, 2u) - | 0x01uy -> struct (I32TruncSatF32U, NoOperand, 2u) - | 0x02uy -> struct (I32TruncSatF64S, NoOperand, 2u) - | 0x03uy -> struct (I32TruncSatF64U, NoOperand, 2u) - | 0x04uy -> struct (I64TruncSatF32S, NoOperand, 2u) - | 0x05uy -> struct (I64TruncSatF32U, NoOperand, 2u) - | 0x06uy -> struct (I64TruncSatF64S, NoOperand, 2u) - | 0x07uy -> struct (I64TruncSatF64U, NoOperand, 2u) - | 0x08uy -> - let struct (segment, pos) = readIndex span reader 2 - let struct (memIndex, pos) = readIndex span reader pos - struct (MemoryInit, TwoOperands (segment, memIndex), uint32 pos) - | 0x09uy -> parseIndex span reader 2 DataDrop - | 0x0auy -> - let struct (destMemIndex, pos) = readIndex span reader 2 - let struct (srcMemIndex, pos) = readIndex span reader pos - struct (MemoryCopy, TwoOperands (destMemIndex, srcMemIndex), uint32 pos) - | 0x0buy -> parseIndex span reader 2 MemoryFill - | 0x0cuy -> - let struct (segment, pos) = readIndex span reader 2 - let struct (tableIndex, pos) = readIndex span reader pos - struct (TableInit, TwoOperands (segment, tableIndex), uint32 pos) - | 0x0duy -> struct (ElemDrop, NoOperand, 2u) - | 0x0euy -> - let struct (destTable, pos) = readIndex span reader 2 - let struct (srcTable, pos) = readIndex span reader pos - struct (TableCopy, TwoOperands (destTable, srcTable), uint32 pos) - | 0x0fuy -> parseIndex span reader 2 TableGrow - | 0x10uy -> parseIndex span reader 2 TableSize - | 0x11uy -> parseIndex span reader 2 TableFill - | _ -> raise ParsingFailureException - | 0xfduy -> - let bin = reader.ReadByte (span, 1) - match bin with - | 0x00uy -> parseLoad span reader 2 V128Load - | 0x01uy -> parseLoad span reader 2 V128Load8X8S - | 0x02uy -> parseLoad span reader 2 V128Load8X8U - | 0x03uy -> parseLoad span reader 2 V128Load16X4S - | 0x04uy -> parseLoad span reader 2 V128Load16X4U - | 0x05uy -> parseLoad span reader 2 V128Load32X2S - | 0x06uy -> parseLoad span reader 2 V128Load32X2U - | 0x07uy -> parseSimdSplat span reader 2 V128Load8Splat - | 0x08uy -> parseSimdSplat span reader 2 V128Load16Splat - | 0x09uy -> parseSimdSplat span reader 2 V128Load32Splat - | 0x0auy -> parseSimdSplat span reader 2 V128Load64Splat - | 0x0buy -> parseStore span reader 2 V128Store - | 0x0cuy -> parseV128 span reader 2 V128Const - | 0x0duy -> parseSimdShuffle span reader 2 I8X16Shuffle - | 0x0euy -> struct (I8X16Swizzle, NoOperand, 2u) - | 0x0fuy -> parseSimdSplat span reader 2 I8X16Splat - | 0x10uy -> parseSimdSplat span reader 2 I16X8Splat - | 0x11uy -> parseSimdSplat span reader 2 I32X4Splat - | 0x12uy -> parseSimdSplat span reader 2 I64X2Splat - | 0x13uy -> parseSimdSplat span reader 2 F32X4Splat - | 0x14uy -> parseSimdSplat span reader 2 F64X2Splat - | 0x15uy -> parseSimdLane span reader 2 I8X16ExtractLaneS - | 0x16uy -> parseSimdLane span reader 2 I8X16ExtractLaneU - | 0x17uy -> parseSimdLane span reader 2 I8X16ReplaceLane - | 0x18uy -> parseSimdLane span reader 2 I16X8ExtractLaneS - | 0x19uy -> parseSimdLane span reader 2 I16X8ExtractLaneU - | 0x1auy -> parseSimdLane span reader 2 I16X8ReplaceLane - | 0x1buy -> parseSimdLane span reader 2 I32X4ExtractLane - | 0x1cuy -> parseSimdLane span reader 2 I32X4ReplaceLane - | 0x1duy -> parseSimdLane span reader 2 I64X2ExtractLane - | 0x1euy -> parseSimdLane span reader 2 I64X2ReplaceLane - | 0x1fuy -> parseSimdLane span reader 2 F32X4ExtractLane - | 0x20uy -> parseSimdLane span reader 2 F32X4ReplaceLane - | 0x21uy -> parseSimdLane span reader 2 F64X2ExtractLane - | 0x22uy -> parseSimdLane span reader 2 F64X2ReplaceLane - | 0x23uy -> struct (I8X16Eq, NoOperand, 2u) - | 0x24uy -> struct (I8X16Ne, NoOperand, 2u) - | 0x25uy -> struct (I8X16LtS, NoOperand, 2u) - | 0x26uy -> struct (I8X16LtU, NoOperand, 2u) - | 0x27uy -> struct (I8X16GtS, NoOperand, 2u) - | 0x28uy -> struct (I8X16GtU, NoOperand, 2u) - | 0x29uy -> struct (I8X16LeS, NoOperand, 2u) - | 0x2auy -> struct (I8X16LeU, NoOperand, 2u) - | 0x2buy -> struct (I8X16GeS, NoOperand, 2u) - | 0x2cuy -> struct (I8X16GeU, NoOperand, 2u) - | 0x2duy -> struct (I16X8Eq, NoOperand, 2u) - | 0x2euy -> struct (I16X8Ne, NoOperand, 2u) - | 0x2fuy -> struct (I16X8LtS, NoOperand, 2u) - | 0x30uy -> struct (I16X8LtU, NoOperand, 2u) - | 0x31uy -> struct (I16X8GtS, NoOperand, 2u) - | 0x32uy -> struct (I16X8GtU, NoOperand, 2u) - | 0x33uy -> struct (I16X8LeS, NoOperand, 2u) - | 0x34uy -> struct (I16X8LeU, NoOperand, 2u) - | 0x35uy -> struct (I16X8GeS, NoOperand, 2u) - | 0x36uy -> struct (I16X8GeU, NoOperand, 2u) - | 0x37uy -> struct (I32X4Eq, NoOperand, 2u) - | 0x38uy -> struct (I32X4Ne, NoOperand, 2u) - | 0x39uy -> struct (I32X4LtS, NoOperand, 2u) - | 0x3auy -> struct (I32X4LtU, NoOperand, 2u) - | 0x3buy -> struct (I32X4GtS, NoOperand, 2u) - | 0x3cuy -> struct (I32X4GtU, NoOperand, 2u) - | 0x3duy -> struct (I32X4LeS, NoOperand, 2u) - | 0x3euy -> struct (I32X4LeU, NoOperand, 2u) - | 0x3fuy -> struct (I32X4GeS, NoOperand, 2u) - | 0x40uy -> struct (I32X4GeU, NoOperand, 2u) - | 0x41uy -> struct (F32X4Eq, NoOperand, 2u) - | 0x42uy -> struct (F32X4Ne, NoOperand, 2u) - | 0x43uy -> struct (F32X4Lt, NoOperand, 2u) - | 0x44uy -> struct (F32X4Gt, NoOperand, 2u) - | 0x45uy -> struct (F32X4Le, NoOperand, 2u) - | 0x46uy -> struct (F32X4Ge, NoOperand, 2u) - | 0x47uy -> struct (F64X2Eq, NoOperand, 2u) - | 0x48uy -> struct (F64X2Ne, NoOperand, 2u) - | 0x49uy -> struct (F64X2Lt, NoOperand, 2u) - | 0x4auy -> struct (F64X2Gt, NoOperand, 2u) - | 0x4buy -> struct (F64X2Le, NoOperand, 2u) - | 0x4cuy -> struct (F64X2Ge, NoOperand, 2u) - | 0x4duy -> struct (V128Not, NoOperand, 2u) - | 0x4euy -> struct (V128And, NoOperand, 2u) - | 0x4fuy -> struct (V128Andnot, NoOperand, 2u) - | 0x50uy -> struct (V128Or, NoOperand, 2u) - | 0x51uy -> struct (V128Xor, NoOperand, 2u) - | 0x52uy -> struct (V128BitSelect, NoOperand, 2u) - | 0x53uy -> struct (V128AnyTrue, NoOperand, 2u) - | 0x54uy -> parseSimdLoadLane span reader 2 V128Load8Lane - | 0x55uy -> parseSimdLoadLane span reader 2 V128Load16Lane - | 0x56uy -> parseSimdLoadLane span reader 2 V128Load32Lane - | 0x57uy -> parseSimdLoadLane span reader 2 V128Load64Lane - | 0x58uy -> parseSimdStoreLane span reader 2 V128Store8Lane - | 0x59uy -> parseSimdStoreLane span reader 2 V128Store16Lane - | 0x5auy -> parseSimdStoreLane span reader 2 V128Store32Lane - | 0x5buy -> parseSimdStoreLane span reader 2 V128Store64Lane - | 0x5cuy -> parseSimdLoadZero span reader 2 V128Load32Zero - | 0x5duy -> parseSimdLoadZero span reader 2 V128Load64Zero - | 0x5euy -> struct (F32X4DemoteF64X2Zero, NoOperand, 2u) - | 0x5fuy -> struct (F64X2PromoteLowF32X4, NoOperand, 2u) - | 0x60uy -> struct (I8X16Abs, NoOperand, 2u) - | 0x61uy -> struct (I8X16Neg, NoOperand, 2u) - | 0x62uy -> struct (I8X16Popcnt, NoOperand, 2u) - | 0x63uy -> struct (I8X16AllTrue, NoOperand, 2u) - | 0x64uy -> struct (I8X16Bitmask, NoOperand, 2u) - | 0x65uy -> struct (I8X16NarrowI16X8S, NoOperand, 2u) - | 0x66uy -> struct (I8X16NarrowI16X8U, NoOperand, 2u) - | 0x6buy -> struct (I8X16Shl, NoOperand, 2u) - | 0x6cuy -> struct (I8X16ShrS, NoOperand, 2u) - | 0x6duy -> struct (I8X16ShrU, NoOperand, 2u) - | 0x6euy -> struct (I8X16Add, NoOperand, 2u) - | 0x6fuy -> struct (I8X16AddSatS, NoOperand, 2u) - | 0x70uy -> struct (I8X16AddSatU, NoOperand, 2u) - | 0x71uy -> struct (I8X16Sub, NoOperand, 2u) - | 0x72uy -> struct (I8X16SubSatS, NoOperand, 2u) - | 0x73uy -> struct (I8X16SubSatU, NoOperand, 2u) - | 0x76uy -> struct (I8X16MinS, NoOperand, 2u) - | 0x77uy -> struct (I8X16MinU, NoOperand, 2u) - | 0x78uy -> struct (I8X16MaxS, NoOperand, 2u) - | 0x79uy -> struct (I8X16MaxU, NoOperand, 2u) - | 0x7buy -> struct (I8X16AvgrU, NoOperand, 2u) - | 0x7cuy -> struct (I16X8ExtaddPairwiseI8X16S, NoOperand, 2u) - | 0x7duy -> struct (I16X8ExtaddPairwiseI8X16U, NoOperand, 2u) - | 0x7euy -> struct (I32X4ExtaddPairwiseI16X8S, NoOperand, 2u) - | 0x7fuy -> struct (I32X4ExtaddPairwiseI16X8U, NoOperand, 2u) - | 0x80uy -> struct (I16X8Abs, NoOperand, 2u) - | 0x81uy -> struct (I16X8Neg, NoOperand, 2u) - | 0x82uy -> struct (I16X8Q15mulrSatS, NoOperand, 2u) - | 0x83uy -> struct (I16X8AllTrue, NoOperand, 2u) - | 0x84uy -> struct (I16X8Bitmask, NoOperand, 2u) - | 0x85uy -> struct (I16X8NarrowI32X4S, NoOperand, 2u) - | 0x86uy -> struct (I16X8NarrowI32X4U, NoOperand, 2u) - | 0x87uy -> struct (I16X8ExtendLowI8X16S, NoOperand, 2u) - | 0x88uy -> struct (I16X8ExtendHighI8X16S, NoOperand, 2u) - | 0x89uy -> struct (I16X8ExtendLowI8X16U, NoOperand, 2u) - | 0x8auy -> struct (I16X8ExtendHighI8X16U, NoOperand, 2u) - | 0x8buy -> struct (I16X8Shl, NoOperand, 2u) - | 0x8cuy -> struct (I16X8ShrS, NoOperand, 2u) - | 0x8duy -> struct (I16X8ShrU, NoOperand, 2u) - | 0x8euy -> struct (I16X8Add, NoOperand, 2u) - | 0x8fuy -> struct (I16X8AddSatS, NoOperand, 2u) - | 0x90uy -> struct (I16X8AddSatU, NoOperand, 2u) - | 0x91uy -> struct (I16X8Sub, NoOperand, 2u) - | 0x92uy -> struct (I16X8SubSatS, NoOperand, 2u) - | 0x93uy -> struct (I16X8SubSatU, NoOperand, 2u) - | 0x95uy -> struct (I16X8Mul, NoOperand, 2u) - | 0x96uy -> struct (I16X8MinS, NoOperand, 2u) - | 0x97uy -> struct (I16X8MinU, NoOperand, 2u) - | 0x98uy -> struct (I16X8MaxS, NoOperand, 2u) - | 0x99uy -> struct (I16X8MaxU, NoOperand, 2u) - | 0x9buy -> struct (I16X8AvgrU, NoOperand, 2u) - | 0x9cuy -> struct (I16X8ExtmulLowI8X16S, NoOperand, 2u) - | 0x9duy -> struct (I16X8ExtmulHighI8X16S, NoOperand, 2u) - | 0x9euy -> struct (I16X8ExtmulLowI8X16U, NoOperand, 2u) - | 0x9fuy -> struct (I16X8ExtmulHighI8X16U, NoOperand, 2u) - | 0xa0uy -> struct (I32X4Abs, NoOperand, 2u) - | 0xa1uy -> struct (I32X4Neg, NoOperand, 2u) - | 0xa3uy -> struct (I32X4AllTrue, NoOperand, 2u) - | 0xa4uy -> struct (I32X4Bitmask, NoOperand, 2u) - | 0xa7uy -> struct (I32X4ExtendLowI16X8S, NoOperand, 2u) - | 0xa8uy -> struct (I32X4ExtendHighI16X8S, NoOperand, 2u) - | 0xa9uy -> struct (I32X4ExtendLowI16X8U, NoOperand, 2u) - | 0xaauy -> struct (I32X4ExtendHighI16X8U, NoOperand, 2u) - | 0xabuy -> struct (I32X4Shl, NoOperand, 2u) - | 0xacuy -> struct (I32X4ShrS, NoOperand, 2u) - | 0xaduy -> struct (I32X4ShrU, NoOperand, 2u) - | 0xaeuy -> struct (I32X4Add, NoOperand, 2u) - | 0xb1uy -> struct (I32X4Sub, NoOperand, 2u) - | 0xb5uy -> struct (I32X4Mul, NoOperand, 2u) - | 0xb6uy -> struct (I32X4MinS, NoOperand, 2u) - | 0xb7uy -> struct (I32X4MinU, NoOperand, 2u) - | 0xb8uy -> struct (I32X4MaxS, NoOperand, 2u) - | 0xb9uy -> struct (I32X4MaxU, NoOperand, 2u) - | 0xbauy -> struct (I32X4DotI16X8S, NoOperand, 2u) - | 0xbcuy -> struct (I32X4ExtmulLowI16X8S, NoOperand, 2u) - | 0xbduy -> struct (I32X4ExtmulHighI16X8S, NoOperand, 2u) - | 0xbeuy -> struct (I32X4ExtmulLowI16X8U, NoOperand, 2u) - | 0xbfuy -> struct (I32X4ExtmulHighI16X8U, NoOperand, 2u) - | 0xc0uy -> struct (I64X2Abs, NoOperand, 2u) - | 0xc1uy -> struct (I64X2Neg, NoOperand, 2u) - | 0xc3uy -> struct (I64X2AllTrue, NoOperand, 2u) - | 0xc4uy -> struct (I64X2Bitmask, NoOperand, 2u) - | 0xc7uy -> struct (I64X2ExtendLowI32X4S, NoOperand, 2u) - | 0xc8uy -> struct (I64X2ExtendHighI32X4S, NoOperand, 2u) - | 0xc9uy -> struct (I64X2ExtendLowI32X4U, NoOperand, 2u) - | 0xcauy -> struct (I64X2ExtendHighI32X4U, NoOperand, 2u) - | 0xcbuy -> struct (I64X2Shl, NoOperand, 2u) - | 0xccuy -> struct (I64X2ShrS, NoOperand, 2u) - | 0xcduy -> struct (I64X2ShrU, NoOperand, 2u) - | 0xceuy -> struct (I64X2Add, NoOperand, 2u) - | 0xd1uy -> struct (I64X2Sub, NoOperand, 2u) - | 0xd5uy -> struct (I64X2Mul, NoOperand, 2u) - | 0xd6uy -> struct (I64X2Eq, NoOperand, 2u) - | 0xd7uy -> struct (I64X2Ne, NoOperand, 2u) - | 0xd8uy -> struct (I64X2LtS, NoOperand, 2u) - | 0xd9uy -> struct (I64X2GtS, NoOperand, 2u) - | 0xdauy -> struct (I64X2LeS, NoOperand, 2u) - | 0xdbuy -> struct (I64X2GeS, NoOperand, 2u) - | 0xdcuy -> struct (I64X2ExtmulLowI32X4S, NoOperand, 2u) - | 0xdduy -> struct (I64X2ExtmulHighI32X4S, NoOperand, 2u) - | 0xdeuy -> struct (I64X2ExtmulLowI32X4U, NoOperand, 2u) - | 0xdfuy -> struct (I64X2ExtmulHighI32X4U, NoOperand, 2u) - | 0x67uy -> struct (F32X4Ceil, NoOperand, 2u) - | 0x68uy -> struct (F32X4Floor, NoOperand, 2u) - | 0x69uy -> struct (F32X4Trunc, NoOperand, 2u) - | 0x6auy -> struct (F32X4Nearest, NoOperand, 2u) - | 0x74uy -> struct (F64X2Ceil, NoOperand, 2u) - | 0x75uy -> struct (F64X2Floor, NoOperand, 2u) - | 0x7auy -> struct (F64X2Trunc, NoOperand, 2u) - | 0x94uy -> struct (F64X2Nearest, NoOperand, 2u) - | 0xe0uy -> struct (F32X4Abs, NoOperand, 2u) - | 0xe1uy -> struct (F32X4Neg, NoOperand, 2u) - | 0xe3uy -> struct (F32X4Sqrt, NoOperand, 2u) - | 0xe4uy -> struct (F32X4Add, NoOperand, 2u) - | 0xe5uy -> struct (F32X4Sub, NoOperand, 2u) - | 0xe6uy -> struct (F32X4Mul, NoOperand, 2u) - | 0xe7uy -> struct (F32X4Div, NoOperand, 2u) - | 0xe8uy -> struct (F32X4Min, NoOperand, 2u) - | 0xe9uy -> struct (F32X4Max, NoOperand, 2u) - | 0xeauy -> struct (F32X4PMin, NoOperand, 2u) - | 0xebuy -> struct (F32X4PMax, NoOperand, 2u) - | 0xecuy -> struct (F64X2Abs, NoOperand, 2u) - | 0xeduy -> struct (F64X2Neg, NoOperand, 2u) - | 0xefuy -> struct (F64X2Sqrt, NoOperand, 2u) - | 0xf0uy -> struct (F64X2Add, NoOperand, 2u) - | 0xf1uy -> struct (F64X2Sub, NoOperand, 2u) - | 0xf2uy -> struct (F64X2Mul, NoOperand, 2u) - | 0xf3uy -> struct (F64X2Div, NoOperand, 2u) - | 0xf4uy -> struct (F64X2Min, NoOperand, 2u) - | 0xf5uy -> struct (F64X2Max, NoOperand, 2u) - | 0xf6uy -> struct (F64X2PMin, NoOperand, 2u) - | 0xf7uy -> struct (F64X2PMax, NoOperand, 2u) - | 0xf8uy -> struct (I32X4TruncSatF32X4S, NoOperand, 2u) - | 0xf9uy -> struct (I32X4TruncSatF32X4U, NoOperand, 2u) - | 0xfauy -> struct (F32X4ConvertI32X4S, NoOperand, 2u) - | 0xfbuy -> struct (F32X4ConvertI32X4U, NoOperand, 2u) - | 0xfcuy -> struct (I32X4TruncSatF64X2SZero, NoOperand, 2u) - | 0xfduy -> struct (I32X4TruncSatF64X2UZero, NoOperand, 2u) - | 0xfeuy -> struct (F64X2ConvertLowI32X4S, NoOperand, 2u) - | 0xffuy -> struct (F64X2ConvertLowI32X4U, NoOperand, 2u) - | _ -> raise ParsingFailureException - | 0xfeuy -> - let bin = reader.ReadByte (span, 1) - match bin with - | 0x00uy -> parseAtomicNotify span reader 2 MemoryAtomicNotify - | 0x01uy -> parseAtomicWait span reader 2 MemoryAtomicWait32 - | 0x02uy -> parseAtomicWait span reader 2 MemoryAtomicWait64 - | 0x03uy -> parseAtomicFence span reader 2 AtomicFence - | 0x10uy -> parseAtomicLoad span reader 2 I32AtomicLoad - | 0x11uy -> parseAtomicLoad span reader 2 I64AtomicLoad - | 0x12uy -> parseAtomicLoad span reader 2 I32AtomicLoad8U - | 0x13uy -> parseAtomicLoad span reader 2 I32AtomicLoad16U - | 0x14uy -> parseAtomicLoad span reader 2 I64AtomicLoad8U - | 0x15uy -> parseAtomicLoad span reader 2 I64AtomicLoad16U - | 0x16uy -> parseAtomicLoad span reader 2 I64AtomicLoad32U - | 0x17uy -> parseAtomicStore span reader 2 I32AtomicStore - | 0x18uy -> parseAtomicStore span reader 2 I64AtomicStore - | 0x19uy -> parseAtomicStore span reader 2 I32AtomicStore8 - | 0x1auy -> parseAtomicStore span reader 2 I32AtomicStore16 - | 0x1buy -> parseAtomicStore span reader 2 I64AtomicStore8 - | 0x1cuy -> parseAtomicStore span reader 2 I64AtomicStore16 - | 0x1duy -> parseAtomicStore span reader 2 I64AtomicStore32 - | 0x1euy -> parseAtomicRmw span reader 2 I32AtomicRmwAdd - | 0x1fuy -> parseAtomicRmw span reader 2 I64AtomicRmwAdd - | 0x20uy -> parseAtomicRmw span reader 2 I32AtomicRmw8AddU - | 0x21uy -> parseAtomicRmw span reader 2 I32AtomicRmw16AddU - | 0x22uy -> parseAtomicRmw span reader 2 I64AtomicRmw8AddU - | 0x23uy -> parseAtomicRmw span reader 2 I64AtomicRmw16AddU - | 0x24uy -> parseAtomicRmw span reader 2 I64AtomicRmw32AddU - | 0x25uy -> parseAtomicRmw span reader 2 I32AtomicRmwSub - | 0x26uy -> parseAtomicRmw span reader 2 I64AtomicRmw8SubU - | 0x27uy -> parseAtomicRmw span reader 2 I32AtomicRmw8SubU - | 0x28uy -> parseAtomicRmw span reader 2 I32AtomicRmw16SubU - | 0x29uy -> parseAtomicRmw span reader 2 I64AtomicRmw8SubU - | 0x2auy -> parseAtomicRmw span reader 2 I64AtomicRmw16SubU - | 0x2buy -> parseAtomicRmw span reader 2 I64AtomicRmw32SubU - | 0x2cuy -> parseAtomicRmw span reader 2 I32AtomicRmwAnd - | 0x2duy -> parseAtomicRmw span reader 2 I64AtomicRmwAnd - | 0x2euy -> parseAtomicRmw span reader 2 I32AtomicRmw8AndU - | 0x2fuy -> parseAtomicRmw span reader 2 I32AtomicRmw16AndU - | 0x30uy -> parseAtomicRmw span reader 2 I64AtomicRmw8AndU - | 0x31uy -> parseAtomicRmw span reader 2 I64AtomicRmw16AndU - | 0x32uy -> parseAtomicRmw span reader 2 I64AtomicRmw32AndU - | 0x33uy -> parseAtomicRmw span reader 2 I32AtomicRmwOr - | 0x34uy -> parseAtomicRmw span reader 2 I64AtomicRmwOr - | 0x35uy -> parseAtomicRmw span reader 2 I32AtomicRmw8OrU - | 0x36uy -> parseAtomicRmw span reader 2 I32AtomicRmw16OrU - | 0x37uy -> parseAtomicRmw span reader 2 I64AtomicRmw8OrU - | 0x38uy -> parseAtomicRmw span reader 2 I64AtomicRmw16OrU - | 0x39uy -> parseAtomicRmw span reader 2 I64AtomicRmw32OrU - | 0x3auy -> parseAtomicRmw span reader 2 I32AtomicRmwXor - | 0x3buy -> parseAtomicRmw span reader 2 I64AtomicRmwXor - | 0x3cuy -> parseAtomicRmw span reader 2 I32AtomicRmw8XorU - | 0x3duy -> parseAtomicRmw span reader 2 I32AtomicRmw16XorU - | 0x3euy -> parseAtomicRmw span reader 2 I64AtomicRmw8XorU - | 0x3fuy -> parseAtomicRmw span reader 2 I64AtomicRmw16XorU - | 0x40uy -> parseAtomicRmw span reader 2 I64AtomicRmw32XorU - | 0x41uy -> parseAtomicRmw span reader 2 I32AtomicRmwXchg - | 0x42uy -> parseAtomicRmw span reader 2 I64AtomicRmwXchg - | 0x43uy -> parseAtomicRmw span reader 2 I32AtomicRmw8XchgU - | 0x44uy -> parseAtomicRmw span reader 2 I32AtomicRmw16XchgU - | 0x45uy -> parseAtomicRmw span reader 2 I64AtomicRmw8XchgU - | 0x46uy -> parseAtomicRmw span reader 2 I64AtomicRmw16XchgU - | 0x47uy -> parseAtomicRmw span reader 2 I64AtomicRmw32XchgU - | 0x48uy -> parseAtomicRmw span reader 2 I32AtomicRmwCmpxchg - | 0x49uy -> parseAtomicRmw span reader 2 I64AtomicRmwCmpxchg - | 0x4auy -> parseAtomicRmw span reader 2 I32AtomicRmw8CmpxchgU - | 0x4buy -> parseAtomicRmw span reader 2 I32AtomicRmw16CmpxchgU - | 0x4cuy -> parseAtomicRmw span reader 2 I64AtomicRmw8CmpxchgU - | 0x4duy -> parseAtomicRmw span reader 2 I64AtomicRmw16CmpxchgU - | 0x4euy -> parseAtomicRmw span reader 2 I64AtomicRmw32CmpxchgU - | _ -> raise ParsingFailureException - | 0x00uy -> struct (Unreachable, NoOperand, 1u) - | 0x01uy -> struct (Nop, NoOperand, 1u) - | 0x02uy -> parseType span reader 1 Block - | 0x03uy -> parseType span reader 1 Loop - | 0x04uy -> parseType span reader 1 If - | 0x05uy -> struct (Else, NoOperand, 1u) - | 0x06uy -> parseType span reader 1 Try - | 0x07uy -> parseIndex span reader 1 Catch - | 0x08uy -> parseIndex span reader 1 Throw - | 0x09uy -> parseIndex span reader 1 Rethrow - | 0x0buy -> struct (End, NoOperand, 1u) - | 0x0cuy -> parseIndex span reader 1 Br - | 0x0duy -> parseIndex span reader 1 BrIf - | 0x0euy -> - let struct (count, pos) = parseCount span reader 1 - let struct (operands, pos) = parseIndices span reader (int pos) count [] - struct (BrTable, Operands operands, pos) - | 0x0fuy -> struct (Return, NoOperand, 1u) - | 0x10uy -> parseIndex span reader 1 Call - | 0x11uy -> - let struct (sigIndex, pos) = readIndex span reader 1 - let struct (tableIndex, pos) = readIndex span reader pos - struct (CallIndirect, TwoOperands (sigIndex, tableIndex), uint32 pos) - | 0x12uy -> parseIndex span reader 1 ReturnCall - | 0x13uy -> - let struct (sigIndex, pos) = readIndex span reader 1 - let struct (tableIndex, pos) = readIndex span reader pos - struct (ReturnCallIndirect, TwoOperands (sigIndex, tableIndex), uint32 pos) - | 0x14uy -> struct (CallRef, NoOperand, 1u) - | 0x18uy -> parseIndex span reader 1 Delegate - | 0x19uy -> struct (CatchAll, NoOperand, 1u) - | 0x1auy -> struct (Drop, NoOperand, 1u) - | 0x1buy -> struct (Select, NoOperand, 1u) - | 0x1cuy -> - let struct (cnt, pos) = parseCount span reader 1 - let struct (operands, pos) = parseTypes span reader (int pos) cnt [] - struct (SelectT, Operands operands, pos) - | 0x20uy -> parseIndex span reader 1 LocalGet - | 0x21uy -> parseIndex span reader 1 LocalSet - | 0x22uy -> parseIndex span reader 1 LocalTee - | 0x23uy -> parseIndex span reader 1 GlobalGet - | 0x24uy -> parseIndex span reader 1 GlobalSet - | 0x28uy -> parseLoad span reader 1 I32Load - | 0x29uy -> parseLoad span reader 1 I64Load - | 0x2auy -> parseLoad span reader 1 F32Load - | 0x2buy -> parseLoad span reader 1 F64Load - | 0x2cuy -> parseLoad span reader 1 I32Load8S - | 0x2duy -> parseLoad span reader 1 I32Load8U - | 0x2euy -> parseLoad span reader 1 I32Load16S - | 0x2fuy -> parseLoad span reader 1 I32Load16U - | 0x30uy -> parseLoad span reader 1 I64Load8S - | 0x31uy -> parseLoad span reader 1 I64Load8U - | 0x32uy -> parseLoad span reader 1 I64Load16S - | 0x33uy -> parseLoad span reader 1 I64Load16U - | 0x34uy -> parseLoad span reader 1 I64Load32S - | 0x35uy -> parseLoad span reader 1 I64Load32U - | 0x36uy -> parseStore span reader 1 I32Store - | 0x37uy -> parseStore span reader 1 I64Store - | 0x38uy -> parseStore span reader 1 F32Store - | 0x39uy -> parseStore span reader 1 F64Store - | 0x3auy -> parseStore span reader 1 I32Store8 - | 0x3buy -> parseStore span reader 1 I32Store16 - | 0x3cuy -> parseStore span reader 1 I64Store8 - | 0x3duy -> parseStore span reader 1 I64Store16 - | 0x3euy -> parseStore span reader 1 I64Store32 - | 0x3fuy -> parseIndex span reader 1 MemorySize - | 0x40uy -> parseIndex span reader 1 MemoryGrow - | 0x41uy -> parseU32LEB128 span reader 1 I32Const - | 0x42uy -> parseU64LEB128 span reader 1 I64Const - | 0x43uy -> parseF32 span reader 1 F32Const - | 0x44uy -> parseF64 span reader 1 F64Const - | 0x45uy -> struct (I32Eqz, NoOperand, 1u) - | 0x46uy -> struct (I32Eq, NoOperand, 1u) - | 0x47uy -> struct (I32Ne, NoOperand, 1u) - | 0x48uy -> struct (I32LtS, NoOperand, 1u) - | 0x49uy -> struct (I32LtU, NoOperand, 1u) - | 0x4auy -> struct (I32GtS, NoOperand, 1u) - | 0x4buy -> struct (I32GtU, NoOperand, 1u) - | 0x4cuy -> struct (I32LeS, NoOperand, 1u) - | 0x4duy -> struct (I32LeU, NoOperand, 1u) - | 0x4euy -> struct (I32GeS, NoOperand, 1u) - | 0x4fuy -> struct (I32GeU, NoOperand, 1u) - | 0x50uy -> struct (I64Eqz, NoOperand, 1u) - | 0x51uy -> struct (I64Eq, NoOperand, 1u) - | 0x52uy -> struct (I64Ne, NoOperand, 1u) - | 0x53uy -> struct (I64LtS, NoOperand, 1u) - | 0x54uy -> struct (I64LtU, NoOperand, 1u) - | 0x55uy -> struct (I64GtS, NoOperand, 1u) - | 0x56uy -> struct (I64GtU, NoOperand, 1u) - | 0x57uy -> struct (I64LeS, NoOperand, 1u) - | 0x58uy -> struct (I64LeU, NoOperand, 1u) - | 0x59uy -> struct (I64GeS, NoOperand, 1u) - | 0x5auy -> struct (I64GeU, NoOperand, 1u) - | 0x5buy -> struct (F32Eq, NoOperand, 1u) - | 0x5cuy -> struct (F32Ne, NoOperand, 1u) - | 0x5duy -> struct (F32Lt, NoOperand, 1u) - | 0x5euy -> struct (F32Gt, NoOperand, 1u) - | 0x5fuy -> struct (F32Le, NoOperand, 1u) - | 0x60uy -> struct (F32Ge, NoOperand, 1u) - | 0x61uy -> struct (F64Eq, NoOperand, 1u) - | 0x62uy -> struct (F64Ne, NoOperand, 1u) - | 0x63uy -> struct (F64Lt, NoOperand, 1u) - | 0x64uy -> struct (F64Gt, NoOperand, 1u) - | 0x65uy -> struct (F64Le, NoOperand, 1u) - | 0x66uy -> struct (F64Ge, NoOperand, 1u) - | 0x67uy -> struct (I32Clz, NoOperand, 1u) - | 0x68uy -> struct (I32Ctz, NoOperand, 1u) - | 0x69uy -> struct (I32Popcnt, NoOperand, 1u) - | 0x6auy -> struct (I32Add, NoOperand, 1u) - | 0x6buy -> struct (I32Sub, NoOperand, 1u) - | 0x6cuy -> struct (I32Mul, NoOperand, 1u) - | 0x6duy -> struct (I32DivS, NoOperand, 1u) - | 0x6euy -> struct (I32DivU, NoOperand, 1u) - | 0x6fuy -> struct (I32RemS, NoOperand, 1u) - | 0x70uy -> struct (I32RemU, NoOperand, 1u) - | 0x71uy -> struct (I32And, NoOperand, 1u) - | 0x72uy -> struct (I32Or, NoOperand, 1u) - | 0x73uy -> struct (I32Xor, NoOperand, 1u) - | 0x74uy -> struct (I32Shl, NoOperand, 1u) - | 0x75uy -> struct (I32ShrS, NoOperand, 1u) - | 0x76uy -> struct (I32ShrU, NoOperand, 1u) - | 0x77uy -> struct (I32Rotl, NoOperand, 1u) - | 0x78uy -> struct (I32Rotr, NoOperand, 1u) - | 0x79uy -> struct (I64Clz, NoOperand, 1u) - | 0x7auy -> struct (I64Ctz, NoOperand, 1u) - | 0x7buy -> struct (I64Popcnt, NoOperand, 1u) - | 0x7cuy -> struct (I64Add, NoOperand, 1u) - | 0x7duy -> struct (I64Sub, NoOperand, 1u) - | 0x7euy -> struct (I64Mul, NoOperand, 1u) - | 0x7fuy -> struct (I64DivS, NoOperand, 1u) - | 0x80uy -> struct (I64DivU, NoOperand, 1u) - | 0x81uy -> struct (I64RemS, NoOperand, 1u) - | 0x82uy -> struct (I64RemU, NoOperand, 1u) - | 0x83uy -> struct (I64And, NoOperand, 1u) - | 0x84uy -> struct (I64Or, NoOperand, 1u) - | 0x85uy -> struct (I64Xor, NoOperand, 1u) - | 0x86uy -> struct (I64Shl, NoOperand, 1u) - | 0x87uy -> struct (I64ShrS, NoOperand, 1u) - | 0x88uy -> struct (I64ShrU, NoOperand, 1u) - | 0x89uy -> struct (I64Rotl, NoOperand, 1u) - | 0x8auy -> struct (I64Rotr, NoOperand, 1u) - | 0x8buy -> struct (F32Abs, NoOperand, 1u) - | 0x8cuy -> struct (F32Neg, NoOperand, 1u) - | 0x8duy -> struct (F32Ceil, NoOperand, 1u) - | 0x8euy -> struct (F32Floor, NoOperand, 1u) - | 0x8fuy -> struct (F32Trunc, NoOperand, 1u) - | 0x90uy -> struct (F32Nearest, NoOperand, 1u) - | 0x91uy -> struct (F32Sqrt, NoOperand, 1u) - | 0x92uy -> struct (F32Add, NoOperand, 1u) - | 0x93uy -> struct (F32Sub, NoOperand, 1u) - | 0x94uy -> struct (F32Mul, NoOperand, 1u) - | 0x95uy -> struct (F32Div, NoOperand, 1u) - | 0x96uy -> struct (F32Min, NoOperand, 1u) - | 0x97uy -> struct (F32Max, NoOperand, 1u) - | 0x98uy -> struct (F32Copysign, NoOperand, 1u) - | 0x99uy -> struct (F64Abs, NoOperand, 1u) - | 0x9auy -> struct (F64Neg, NoOperand, 1u) - | 0x9buy -> struct (F64Ceil, NoOperand, 1u) - | 0x9cuy -> struct (F64Floor, NoOperand, 1u) - | 0x9duy -> struct (F64Trunc, NoOperand, 1u) - | 0x9euy -> struct (F64Nearest, NoOperand, 1u) - | 0x9fuy -> struct (F64Sqrt, NoOperand, 1u) - | 0xa0uy -> struct (F64Add, NoOperand, 1u) - | 0xa1uy -> struct (F64Sub, NoOperand, 1u) - | 0xa2uy -> struct (F64Mul, NoOperand, 1u) - | 0xa3uy -> struct (F64Div, NoOperand, 1u) - | 0xa4uy -> struct (F64Min, NoOperand, 1u) - | 0xa5uy -> struct (F64Max, NoOperand, 1u) - | 0xa6uy -> struct (F64Copysign, NoOperand, 1u) - | 0xa7uy -> struct (I32WrapI64, NoOperand, 1u) - | 0xa8uy -> struct (I32TruncF32S, NoOperand, 1u) - | 0xa9uy -> struct (I32TruncF32U, NoOperand, 1u) - | 0xaauy -> struct (I32TruncF64S, NoOperand, 1u) - | 0xabuy -> struct (I32TruncF64U, NoOperand, 1u) - | 0xacuy -> struct (I64ExtendI32S, NoOperand, 1u) - | 0xaduy -> struct (I64ExtendI32U, NoOperand, 1u) - | 0xaeuy -> struct (I64TruncF32S, NoOperand, 1u) - | 0xafuy -> struct (I64TruncF32U, NoOperand, 1u) - | 0xb0uy -> struct (I64TruncF64S, NoOperand, 1u) - | 0xb1uy -> struct (I64TruncF64U, NoOperand, 1u) - | 0xb2uy -> struct (F32ConvertI32S, NoOperand, 1u) - | 0xb3uy -> struct (F32ConvertI32U, NoOperand, 1u) - | 0xb4uy -> struct (F32ConvertI64S, NoOperand, 1u) - | 0xb5uy -> struct (F32ConvertI64U, NoOperand, 1u) - | 0xb6uy -> struct (F32DemoteF64, NoOperand, 1u) - | 0xb7uy -> struct (F64ConvertI32S, NoOperand, 1u) - | 0xb8uy -> struct (F64ConvertI32U, NoOperand, 1u) - | 0xb9uy -> struct (F64ConvertI64S, NoOperand, 1u) - | 0xbauy -> struct (F64ConvertI64U, NoOperand, 1u) - | 0xbbuy -> struct (F64PromoteF32, NoOperand, 1u) - | 0xbcuy -> struct (I32ReinterpretF32, NoOperand, 1u) - | 0xbduy -> struct (I64ReinterpretF64, NoOperand, 1u) - | 0xbeuy -> struct (F32ReinterpretI32, NoOperand, 1u) - | 0xbfuy -> struct (F64ReinterpretI64, NoOperand, 1u) - | 0xc0uy -> struct (I32Extend8S, NoOperand, 1u) - | 0xc1uy -> struct (I32Extend16S, NoOperand, 1u) - | 0xc2uy -> struct (I64Extend8S, NoOperand, 1u) - | 0xc3uy -> struct (I64Extend16S, NoOperand, 1u) - | 0xc4uy -> struct (I64Extend32S, NoOperand, 1u) - | 0xe0uy -> struct (InterpAlloca, NoOperand, 1u) - | 0xe1uy -> struct (InterpBrUnless, NoOperand, 1u) - | 0xe2uy -> struct (InterpCallImport, NoOperand, 1u) - | 0xe3uy -> struct (InterpData, NoOperand, 1u) - | 0xe4uy -> struct (InterpDropKeep, NoOperand, 1u) - | 0xe5uy -> struct (InterpCatchDrop, NoOperand, 1u) - | 0xe6uy -> struct (InterpAdjustFrameForReturnCall, NoOperand, 1u) - | 0x25uy -> parseIndex span reader 1 TableGet - | 0x26uy -> parseIndex span reader 1 TableSet - | 0xd0uy -> struct (RefNull, NoOperand, 1u) - | 0xd1uy -> struct (RefIsNull, NoOperand, 1u) - | 0xd2uy -> parseIndex span reader 1 RefFunc - | _ -> raise ParsingFailureException + member __.Parse (span: ByteSpan, addr) = + ParsingMain.parse span reader addr :> Instruction -let parse (span: ByteSpan) (reader: IBinReader) addr = - let struct (opcode, operands, instrLen) = parseInstruction span reader - let insInfo = - { Address = addr - NumBytes = instrLen - Opcode = opcode - Operands = operands } - WASMInstruction (addr, instrLen, insInfo) + member __.MaxInstructionSize = 9 -// vim: set tw=80 sts=2 sw=2: + member __.OperationMode with get() = ArchOperationMode.NoMode and set _ = () diff --git a/src/FrontEnd/BinLifter/WASM/WASMParsingMain.fs b/src/FrontEnd/BinLifter/WASM/WASMParsingMain.fs new file mode 100644 index 00000000..29342adc --- /dev/null +++ b/src/FrontEnd/BinLifter/WASM/WASMParsingMain.fs @@ -0,0 +1,745 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.BinLifter.WASM.ParsingMain + +open B2R2 +open B2R2.FrontEnd.BinLifter + +let isPrefix = function + | 0xfc | 0xfd | 0xfe -> true + | _ -> false + +let private readIndex (span: ByteSpan) (reader: IBinReader) pos = + let value, cnt = reader.ReadUInt32LEB128 (span, pos) + struct (value |> Index, pos + cnt) + +let private readType (span: ByteSpan) (reader: IBinReader) pos = + let t, cnt = reader.ReadInt32LEB128 (span, pos) + struct (t |> Type, pos + cnt) + +let private readAlignment (span: ByteSpan) (reader: IBinReader) pos = + let alignment, cnt = reader.ReadUInt32LEB128 (span, pos) + struct (alignment |> Alignment, pos + cnt) + +let private readAddress (span: ByteSpan) (reader: IBinReader) pos = + let address, cnt = reader.ReadUInt32LEB128 (span, pos) + struct (address |> Address, pos + cnt) + +let private readLane (span: ByteSpan) (reader: IBinReader) pos = + let lane = reader.ReadUInt8 (span, pos) + struct (lane |> LaneIndex, pos + 1) + +let private parseU32LEB128 (span: ByteSpan) (reader: IBinReader) pos opcode = + let value, cnt = reader.ReadUInt32LEB128 (span, pos) + struct (opcode, OneOperand (value |> I32), uint32 (pos + cnt)) + +let private parseU64LEB128 (span: ByteSpan) (reader: IBinReader) pos opcode = + let value, cnt = reader.ReadUInt64LEB128 (span, pos) + struct (opcode, OneOperand (value |> I64), uint32 (pos + cnt)) + +let private parseF32 (span: ByteSpan) (reader: IBinReader) pos opcode = + let value = reader.ReadUInt32 (span, pos) + let value = BitVector.OfUInt32 value 32 + struct (opcode, OneOperand (value |> F32), uint32 (pos + 4)) + +let private parseF64 (span: ByteSpan) (reader: IBinReader) pos opcode = + let value = reader.ReadUInt64 (span, pos) + let value = BitVector.OfUInt64 value 64 + struct (opcode, OneOperand (value |> F64), uint32 (pos + 8)) + +let private parseV128 (span: ByteSpan) (reader: IBinReader) pos opcode = + let i32One = reader.ReadUInt32 (span, pos) + let i32One = BitVector.OfUInt32 i32One 32 + let i32Two = reader.ReadUInt32 (span, pos + 4) + let i32Two = BitVector.OfUInt32 i32Two 32 + let i32Three = reader.ReadUInt32 (span, pos + 8) + let i32Three = BitVector.OfUInt32 i32Three 32 + let i32Four = reader.ReadUInt32 (span, pos + 12) + let i32Four = BitVector.OfUInt32 i32Four 32 + let v128 = (i32One, i32Two, i32Three, i32Four) |> V128 + struct (opcode, OneOperand v128, uint32 pos + 16u) + +(* XXX: readIndex *) +let private parseIndex (span: ByteSpan) (reader: IBinReader) pos opcode = + let index, cnt = reader.ReadUInt32LEB128 (span, pos) + struct (opcode, OneOperand (index |> Index), uint32 (pos + cnt)) + +(* XXX: readType *) +let private parseType (span: ByteSpan) (reader: IBinReader) pos opcode = + let t, cnt = reader.ReadInt32LEB128 (span, pos) + struct (opcode, OneOperand (t |> Type), uint32 (pos + cnt)) + +let private parseLoad span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + let operands = TwoOperands (alignment, offset) + struct (opcode, operands, uint32 nextPos) + +let private parseStore span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + let operands = TwoOperands (alignment, offset) + struct (opcode, operands, uint32 nextPos) + +let rec private parseTypes span reader pos cnt ret = + if cnt = 0 then struct (ret, uint32 (pos + 1)) + else + let struct (t, nextPos) = readType span reader pos + parseTypes span reader nextPos (cnt - 1) (ret @ [t]) (* XXX *) + +let rec private parseIndices span reader pos cnt ret = + if cnt = 0 then struct (ret, uint32 (pos + 1)) + else + let struct (index, nextPos) = readIndex span reader pos + parseIndices span reader nextPos (cnt - 1) (ret @ [index]) (* XXX *) + +let private parseCount (span: ByteSpan) (reader: IBinReader) pos = + let cnt, bcnt = reader.ReadInt32LEB128 (span, pos) + struct (cnt, uint32 (pos + bcnt)) + +let private parseSimdLane span reader pos opcode = + let struct (lane, nextPos) = readLane span reader pos + struct (opcode, OneOperand lane, uint32 nextPos) + +let private parseSimdLoadLane span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + let struct (lane, nextPos) = readLane span reader nextPos + struct (opcode, ThreeOperands (alignment, offset, lane), uint32 nextPos) + +let private parseSimdLoadZero span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseSimdStoreLane span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + let struct (lane, nextPos) = readLane span reader nextPos + struct (opcode, ThreeOperands (alignment, offset, lane), uint32 nextPos) + +let private parseSimdShuffle span reader pos opcode = + parseV128 span reader pos opcode + +let private parseSimdSplat span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseAtomicNotify span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseAtomicFence (span: ByteSpan) (reader: IBinReader) pos opcode = + let consistencyModel = reader.ReadUInt8 (span, pos) + struct (opcode, OneOperand (consistencyModel |> ConsistencyModel), + uint32 pos + 1u) + +let private parseAtomicLoad span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseAtomicStore span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseAtomicWait span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseAtomicRmw span reader pos opcode = + let struct (alignment, nextPos) = readAlignment span reader pos + let struct (offset, nextPos) = readAddress span reader nextPos + struct (opcode, TwoOperands (alignment, offset), uint32 nextPos) + +let private parseInstruction (span: ByteSpan) (reader: IBinReader) = + match span[0] with + | 0xfcuy -> + match span[1] with + | 0x00uy -> struct (I32TruncSatF32S, NoOperand, 2u) + | 0x01uy -> struct (I32TruncSatF32U, NoOperand, 2u) + | 0x02uy -> struct (I32TruncSatF64S, NoOperand, 2u) + | 0x03uy -> struct (I32TruncSatF64U, NoOperand, 2u) + | 0x04uy -> struct (I64TruncSatF32S, NoOperand, 2u) + | 0x05uy -> struct (I64TruncSatF32U, NoOperand, 2u) + | 0x06uy -> struct (I64TruncSatF64S, NoOperand, 2u) + | 0x07uy -> struct (I64TruncSatF64U, NoOperand, 2u) + | 0x08uy -> + let struct (segment, pos) = readIndex span reader 2 + let struct (memIndex, pos) = readIndex span reader pos + struct (MemoryInit, TwoOperands (segment, memIndex), uint32 pos) + | 0x09uy -> parseIndex span reader 2 DataDrop + | 0x0auy -> + let struct (destMemIndex, pos) = readIndex span reader 2 + let struct (srcMemIndex, pos) = readIndex span reader pos + struct (MemoryCopy, TwoOperands (destMemIndex, srcMemIndex), uint32 pos) + | 0x0buy -> parseIndex span reader 2 MemoryFill + | 0x0cuy -> + let struct (segment, pos) = readIndex span reader 2 + let struct (tableIndex, pos) = readIndex span reader pos + struct (TableInit, TwoOperands (segment, tableIndex), uint32 pos) + | 0x0duy -> struct (ElemDrop, NoOperand, 2u) + | 0x0euy -> + let struct (destTable, pos) = readIndex span reader 2 + let struct (srcTable, pos) = readIndex span reader pos + struct (TableCopy, TwoOperands (destTable, srcTable), uint32 pos) + | 0x0fuy -> parseIndex span reader 2 TableGrow + | 0x10uy -> parseIndex span reader 2 TableSize + | 0x11uy -> parseIndex span reader 2 TableFill + | _ -> raise ParsingFailureException + | 0xfduy -> + match span[1] with + | 0x00uy -> parseLoad span reader 2 V128Load + | 0x01uy -> parseLoad span reader 2 V128Load8X8S + | 0x02uy -> parseLoad span reader 2 V128Load8X8U + | 0x03uy -> parseLoad span reader 2 V128Load16X4S + | 0x04uy -> parseLoad span reader 2 V128Load16X4U + | 0x05uy -> parseLoad span reader 2 V128Load32X2S + | 0x06uy -> parseLoad span reader 2 V128Load32X2U + | 0x07uy -> parseSimdSplat span reader 2 V128Load8Splat + | 0x08uy -> parseSimdSplat span reader 2 V128Load16Splat + | 0x09uy -> parseSimdSplat span reader 2 V128Load32Splat + | 0x0auy -> parseSimdSplat span reader 2 V128Load64Splat + | 0x0buy -> parseStore span reader 2 V128Store + | 0x0cuy -> parseV128 span reader 2 V128Const + | 0x0duy -> parseSimdShuffle span reader 2 I8X16Shuffle + | 0x0euy -> struct (I8X16Swizzle, NoOperand, 2u) + | 0x0fuy -> parseSimdSplat span reader 2 I8X16Splat + | 0x10uy -> parseSimdSplat span reader 2 I16X8Splat + | 0x11uy -> parseSimdSplat span reader 2 I32X4Splat + | 0x12uy -> parseSimdSplat span reader 2 I64X2Splat + | 0x13uy -> parseSimdSplat span reader 2 F32X4Splat + | 0x14uy -> parseSimdSplat span reader 2 F64X2Splat + | 0x15uy -> parseSimdLane span reader 2 I8X16ExtractLaneS + | 0x16uy -> parseSimdLane span reader 2 I8X16ExtractLaneU + | 0x17uy -> parseSimdLane span reader 2 I8X16ReplaceLane + | 0x18uy -> parseSimdLane span reader 2 I16X8ExtractLaneS + | 0x19uy -> parseSimdLane span reader 2 I16X8ExtractLaneU + | 0x1auy -> parseSimdLane span reader 2 I16X8ReplaceLane + | 0x1buy -> parseSimdLane span reader 2 I32X4ExtractLane + | 0x1cuy -> parseSimdLane span reader 2 I32X4ReplaceLane + | 0x1duy -> parseSimdLane span reader 2 I64X2ExtractLane + | 0x1euy -> parseSimdLane span reader 2 I64X2ReplaceLane + | 0x1fuy -> parseSimdLane span reader 2 F32X4ExtractLane + | 0x20uy -> parseSimdLane span reader 2 F32X4ReplaceLane + | 0x21uy -> parseSimdLane span reader 2 F64X2ExtractLane + | 0x22uy -> parseSimdLane span reader 2 F64X2ReplaceLane + | 0x23uy -> struct (I8X16Eq, NoOperand, 2u) + | 0x24uy -> struct (I8X16Ne, NoOperand, 2u) + | 0x25uy -> struct (I8X16LtS, NoOperand, 2u) + | 0x26uy -> struct (I8X16LtU, NoOperand, 2u) + | 0x27uy -> struct (I8X16GtS, NoOperand, 2u) + | 0x28uy -> struct (I8X16GtU, NoOperand, 2u) + | 0x29uy -> struct (I8X16LeS, NoOperand, 2u) + | 0x2auy -> struct (I8X16LeU, NoOperand, 2u) + | 0x2buy -> struct (I8X16GeS, NoOperand, 2u) + | 0x2cuy -> struct (I8X16GeU, NoOperand, 2u) + | 0x2duy -> struct (I16X8Eq, NoOperand, 2u) + | 0x2euy -> struct (I16X8Ne, NoOperand, 2u) + | 0x2fuy -> struct (I16X8LtS, NoOperand, 2u) + | 0x30uy -> struct (I16X8LtU, NoOperand, 2u) + | 0x31uy -> struct (I16X8GtS, NoOperand, 2u) + | 0x32uy -> struct (I16X8GtU, NoOperand, 2u) + | 0x33uy -> struct (I16X8LeS, NoOperand, 2u) + | 0x34uy -> struct (I16X8LeU, NoOperand, 2u) + | 0x35uy -> struct (I16X8GeS, NoOperand, 2u) + | 0x36uy -> struct (I16X8GeU, NoOperand, 2u) + | 0x37uy -> struct (I32X4Eq, NoOperand, 2u) + | 0x38uy -> struct (I32X4Ne, NoOperand, 2u) + | 0x39uy -> struct (I32X4LtS, NoOperand, 2u) + | 0x3auy -> struct (I32X4LtU, NoOperand, 2u) + | 0x3buy -> struct (I32X4GtS, NoOperand, 2u) + | 0x3cuy -> struct (I32X4GtU, NoOperand, 2u) + | 0x3duy -> struct (I32X4LeS, NoOperand, 2u) + | 0x3euy -> struct (I32X4LeU, NoOperand, 2u) + | 0x3fuy -> struct (I32X4GeS, NoOperand, 2u) + | 0x40uy -> struct (I32X4GeU, NoOperand, 2u) + | 0x41uy -> struct (F32X4Eq, NoOperand, 2u) + | 0x42uy -> struct (F32X4Ne, NoOperand, 2u) + | 0x43uy -> struct (F32X4Lt, NoOperand, 2u) + | 0x44uy -> struct (F32X4Gt, NoOperand, 2u) + | 0x45uy -> struct (F32X4Le, NoOperand, 2u) + | 0x46uy -> struct (F32X4Ge, NoOperand, 2u) + | 0x47uy -> struct (F64X2Eq, NoOperand, 2u) + | 0x48uy -> struct (F64X2Ne, NoOperand, 2u) + | 0x49uy -> struct (F64X2Lt, NoOperand, 2u) + | 0x4auy -> struct (F64X2Gt, NoOperand, 2u) + | 0x4buy -> struct (F64X2Le, NoOperand, 2u) + | 0x4cuy -> struct (F64X2Ge, NoOperand, 2u) + | 0x4duy -> struct (V128Not, NoOperand, 2u) + | 0x4euy -> struct (V128And, NoOperand, 2u) + | 0x4fuy -> struct (V128Andnot, NoOperand, 2u) + | 0x50uy -> struct (V128Or, NoOperand, 2u) + | 0x51uy -> struct (V128Xor, NoOperand, 2u) + | 0x52uy -> struct (V128BitSelect, NoOperand, 2u) + | 0x53uy -> struct (V128AnyTrue, NoOperand, 2u) + | 0x54uy -> parseSimdLoadLane span reader 2 V128Load8Lane + | 0x55uy -> parseSimdLoadLane span reader 2 V128Load16Lane + | 0x56uy -> parseSimdLoadLane span reader 2 V128Load32Lane + | 0x57uy -> parseSimdLoadLane span reader 2 V128Load64Lane + | 0x58uy -> parseSimdStoreLane span reader 2 V128Store8Lane + | 0x59uy -> parseSimdStoreLane span reader 2 V128Store16Lane + | 0x5auy -> parseSimdStoreLane span reader 2 V128Store32Lane + | 0x5buy -> parseSimdStoreLane span reader 2 V128Store64Lane + | 0x5cuy -> parseSimdLoadZero span reader 2 V128Load32Zero + | 0x5duy -> parseSimdLoadZero span reader 2 V128Load64Zero + | 0x5euy -> struct (F32X4DemoteF64X2Zero, NoOperand, 2u) + | 0x5fuy -> struct (F64X2PromoteLowF32X4, NoOperand, 2u) + | 0x60uy -> struct (I8X16Abs, NoOperand, 2u) + | 0x61uy -> struct (I8X16Neg, NoOperand, 2u) + | 0x62uy -> struct (I8X16Popcnt, NoOperand, 2u) + | 0x63uy -> struct (I8X16AllTrue, NoOperand, 2u) + | 0x64uy -> struct (I8X16Bitmask, NoOperand, 2u) + | 0x65uy -> struct (I8X16NarrowI16X8S, NoOperand, 2u) + | 0x66uy -> struct (I8X16NarrowI16X8U, NoOperand, 2u) + | 0x6buy -> struct (I8X16Shl, NoOperand, 2u) + | 0x6cuy -> struct (I8X16ShrS, NoOperand, 2u) + | 0x6duy -> struct (I8X16ShrU, NoOperand, 2u) + | 0x6euy -> struct (I8X16Add, NoOperand, 2u) + | 0x6fuy -> struct (I8X16AddSatS, NoOperand, 2u) + | 0x70uy -> struct (I8X16AddSatU, NoOperand, 2u) + | 0x71uy -> struct (I8X16Sub, NoOperand, 2u) + | 0x72uy -> struct (I8X16SubSatS, NoOperand, 2u) + | 0x73uy -> struct (I8X16SubSatU, NoOperand, 2u) + | 0x76uy -> struct (I8X16MinS, NoOperand, 2u) + | 0x77uy -> struct (I8X16MinU, NoOperand, 2u) + | 0x78uy -> struct (I8X16MaxS, NoOperand, 2u) + | 0x79uy -> struct (I8X16MaxU, NoOperand, 2u) + | 0x7buy -> struct (I8X16AvgrU, NoOperand, 2u) + | 0x7cuy -> struct (I16X8ExtaddPairwiseI8X16S, NoOperand, 2u) + | 0x7duy -> struct (I16X8ExtaddPairwiseI8X16U, NoOperand, 2u) + | 0x7euy -> struct (I32X4ExtaddPairwiseI16X8S, NoOperand, 2u) + | 0x7fuy -> struct (I32X4ExtaddPairwiseI16X8U, NoOperand, 2u) + | 0x80uy -> struct (I16X8Abs, NoOperand, 2u) + | 0x81uy -> struct (I16X8Neg, NoOperand, 2u) + | 0x82uy -> struct (I16X8Q15mulrSatS, NoOperand, 2u) + | 0x83uy -> struct (I16X8AllTrue, NoOperand, 2u) + | 0x84uy -> struct (I16X8Bitmask, NoOperand, 2u) + | 0x85uy -> struct (I16X8NarrowI32X4S, NoOperand, 2u) + | 0x86uy -> struct (I16X8NarrowI32X4U, NoOperand, 2u) + | 0x87uy -> struct (I16X8ExtendLowI8X16S, NoOperand, 2u) + | 0x88uy -> struct (I16X8ExtendHighI8X16S, NoOperand, 2u) + | 0x89uy -> struct (I16X8ExtendLowI8X16U, NoOperand, 2u) + | 0x8auy -> struct (I16X8ExtendHighI8X16U, NoOperand, 2u) + | 0x8buy -> struct (I16X8Shl, NoOperand, 2u) + | 0x8cuy -> struct (I16X8ShrS, NoOperand, 2u) + | 0x8duy -> struct (I16X8ShrU, NoOperand, 2u) + | 0x8euy -> struct (I16X8Add, NoOperand, 2u) + | 0x8fuy -> struct (I16X8AddSatS, NoOperand, 2u) + | 0x90uy -> struct (I16X8AddSatU, NoOperand, 2u) + | 0x91uy -> struct (I16X8Sub, NoOperand, 2u) + | 0x92uy -> struct (I16X8SubSatS, NoOperand, 2u) + | 0x93uy -> struct (I16X8SubSatU, NoOperand, 2u) + | 0x95uy -> struct (I16X8Mul, NoOperand, 2u) + | 0x96uy -> struct (I16X8MinS, NoOperand, 2u) + | 0x97uy -> struct (I16X8MinU, NoOperand, 2u) + | 0x98uy -> struct (I16X8MaxS, NoOperand, 2u) + | 0x99uy -> struct (I16X8MaxU, NoOperand, 2u) + | 0x9buy -> struct (I16X8AvgrU, NoOperand, 2u) + | 0x9cuy -> struct (I16X8ExtmulLowI8X16S, NoOperand, 2u) + | 0x9duy -> struct (I16X8ExtmulHighI8X16S, NoOperand, 2u) + | 0x9euy -> struct (I16X8ExtmulLowI8X16U, NoOperand, 2u) + | 0x9fuy -> struct (I16X8ExtmulHighI8X16U, NoOperand, 2u) + | 0xa0uy -> struct (I32X4Abs, NoOperand, 2u) + | 0xa1uy -> struct (I32X4Neg, NoOperand, 2u) + | 0xa3uy -> struct (I32X4AllTrue, NoOperand, 2u) + | 0xa4uy -> struct (I32X4Bitmask, NoOperand, 2u) + | 0xa7uy -> struct (I32X4ExtendLowI16X8S, NoOperand, 2u) + | 0xa8uy -> struct (I32X4ExtendHighI16X8S, NoOperand, 2u) + | 0xa9uy -> struct (I32X4ExtendLowI16X8U, NoOperand, 2u) + | 0xaauy -> struct (I32X4ExtendHighI16X8U, NoOperand, 2u) + | 0xabuy -> struct (I32X4Shl, NoOperand, 2u) + | 0xacuy -> struct (I32X4ShrS, NoOperand, 2u) + | 0xaduy -> struct (I32X4ShrU, NoOperand, 2u) + | 0xaeuy -> struct (I32X4Add, NoOperand, 2u) + | 0xb1uy -> struct (I32X4Sub, NoOperand, 2u) + | 0xb5uy -> struct (I32X4Mul, NoOperand, 2u) + | 0xb6uy -> struct (I32X4MinS, NoOperand, 2u) + | 0xb7uy -> struct (I32X4MinU, NoOperand, 2u) + | 0xb8uy -> struct (I32X4MaxS, NoOperand, 2u) + | 0xb9uy -> struct (I32X4MaxU, NoOperand, 2u) + | 0xbauy -> struct (I32X4DotI16X8S, NoOperand, 2u) + | 0xbcuy -> struct (I32X4ExtmulLowI16X8S, NoOperand, 2u) + | 0xbduy -> struct (I32X4ExtmulHighI16X8S, NoOperand, 2u) + | 0xbeuy -> struct (I32X4ExtmulLowI16X8U, NoOperand, 2u) + | 0xbfuy -> struct (I32X4ExtmulHighI16X8U, NoOperand, 2u) + | 0xc0uy -> struct (I64X2Abs, NoOperand, 2u) + | 0xc1uy -> struct (I64X2Neg, NoOperand, 2u) + | 0xc3uy -> struct (I64X2AllTrue, NoOperand, 2u) + | 0xc4uy -> struct (I64X2Bitmask, NoOperand, 2u) + | 0xc7uy -> struct (I64X2ExtendLowI32X4S, NoOperand, 2u) + | 0xc8uy -> struct (I64X2ExtendHighI32X4S, NoOperand, 2u) + | 0xc9uy -> struct (I64X2ExtendLowI32X4U, NoOperand, 2u) + | 0xcauy -> struct (I64X2ExtendHighI32X4U, NoOperand, 2u) + | 0xcbuy -> struct (I64X2Shl, NoOperand, 2u) + | 0xccuy -> struct (I64X2ShrS, NoOperand, 2u) + | 0xcduy -> struct (I64X2ShrU, NoOperand, 2u) + | 0xceuy -> struct (I64X2Add, NoOperand, 2u) + | 0xd1uy -> struct (I64X2Sub, NoOperand, 2u) + | 0xd5uy -> struct (I64X2Mul, NoOperand, 2u) + | 0xd6uy -> struct (I64X2Eq, NoOperand, 2u) + | 0xd7uy -> struct (I64X2Ne, NoOperand, 2u) + | 0xd8uy -> struct (I64X2LtS, NoOperand, 2u) + | 0xd9uy -> struct (I64X2GtS, NoOperand, 2u) + | 0xdauy -> struct (I64X2LeS, NoOperand, 2u) + | 0xdbuy -> struct (I64X2GeS, NoOperand, 2u) + | 0xdcuy -> struct (I64X2ExtmulLowI32X4S, NoOperand, 2u) + | 0xdduy -> struct (I64X2ExtmulHighI32X4S, NoOperand, 2u) + | 0xdeuy -> struct (I64X2ExtmulLowI32X4U, NoOperand, 2u) + | 0xdfuy -> struct (I64X2ExtmulHighI32X4U, NoOperand, 2u) + | 0x67uy -> struct (F32X4Ceil, NoOperand, 2u) + | 0x68uy -> struct (F32X4Floor, NoOperand, 2u) + | 0x69uy -> struct (F32X4Trunc, NoOperand, 2u) + | 0x6auy -> struct (F32X4Nearest, NoOperand, 2u) + | 0x74uy -> struct (F64X2Ceil, NoOperand, 2u) + | 0x75uy -> struct (F64X2Floor, NoOperand, 2u) + | 0x7auy -> struct (F64X2Trunc, NoOperand, 2u) + | 0x94uy -> struct (F64X2Nearest, NoOperand, 2u) + | 0xe0uy -> struct (F32X4Abs, NoOperand, 2u) + | 0xe1uy -> struct (F32X4Neg, NoOperand, 2u) + | 0xe3uy -> struct (F32X4Sqrt, NoOperand, 2u) + | 0xe4uy -> struct (F32X4Add, NoOperand, 2u) + | 0xe5uy -> struct (F32X4Sub, NoOperand, 2u) + | 0xe6uy -> struct (F32X4Mul, NoOperand, 2u) + | 0xe7uy -> struct (F32X4Div, NoOperand, 2u) + | 0xe8uy -> struct (F32X4Min, NoOperand, 2u) + | 0xe9uy -> struct (F32X4Max, NoOperand, 2u) + | 0xeauy -> struct (F32X4PMin, NoOperand, 2u) + | 0xebuy -> struct (F32X4PMax, NoOperand, 2u) + | 0xecuy -> struct (F64X2Abs, NoOperand, 2u) + | 0xeduy -> struct (F64X2Neg, NoOperand, 2u) + | 0xefuy -> struct (F64X2Sqrt, NoOperand, 2u) + | 0xf0uy -> struct (F64X2Add, NoOperand, 2u) + | 0xf1uy -> struct (F64X2Sub, NoOperand, 2u) + | 0xf2uy -> struct (F64X2Mul, NoOperand, 2u) + | 0xf3uy -> struct (F64X2Div, NoOperand, 2u) + | 0xf4uy -> struct (F64X2Min, NoOperand, 2u) + | 0xf5uy -> struct (F64X2Max, NoOperand, 2u) + | 0xf6uy -> struct (F64X2PMin, NoOperand, 2u) + | 0xf7uy -> struct (F64X2PMax, NoOperand, 2u) + | 0xf8uy -> struct (I32X4TruncSatF32X4S, NoOperand, 2u) + | 0xf9uy -> struct (I32X4TruncSatF32X4U, NoOperand, 2u) + | 0xfauy -> struct (F32X4ConvertI32X4S, NoOperand, 2u) + | 0xfbuy -> struct (F32X4ConvertI32X4U, NoOperand, 2u) + | 0xfcuy -> struct (I32X4TruncSatF64X2SZero, NoOperand, 2u) + | 0xfduy -> struct (I32X4TruncSatF64X2UZero, NoOperand, 2u) + | 0xfeuy -> struct (F64X2ConvertLowI32X4S, NoOperand, 2u) + | 0xffuy -> struct (F64X2ConvertLowI32X4U, NoOperand, 2u) + | _ -> raise ParsingFailureException + | 0xfeuy -> + match span[1] with + | 0x00uy -> parseAtomicNotify span reader 2 MemoryAtomicNotify + | 0x01uy -> parseAtomicWait span reader 2 MemoryAtomicWait32 + | 0x02uy -> parseAtomicWait span reader 2 MemoryAtomicWait64 + | 0x03uy -> parseAtomicFence span reader 2 AtomicFence + | 0x10uy -> parseAtomicLoad span reader 2 I32AtomicLoad + | 0x11uy -> parseAtomicLoad span reader 2 I64AtomicLoad + | 0x12uy -> parseAtomicLoad span reader 2 I32AtomicLoad8U + | 0x13uy -> parseAtomicLoad span reader 2 I32AtomicLoad16U + | 0x14uy -> parseAtomicLoad span reader 2 I64AtomicLoad8U + | 0x15uy -> parseAtomicLoad span reader 2 I64AtomicLoad16U + | 0x16uy -> parseAtomicLoad span reader 2 I64AtomicLoad32U + | 0x17uy -> parseAtomicStore span reader 2 I32AtomicStore + | 0x18uy -> parseAtomicStore span reader 2 I64AtomicStore + | 0x19uy -> parseAtomicStore span reader 2 I32AtomicStore8 + | 0x1auy -> parseAtomicStore span reader 2 I32AtomicStore16 + | 0x1buy -> parseAtomicStore span reader 2 I64AtomicStore8 + | 0x1cuy -> parseAtomicStore span reader 2 I64AtomicStore16 + | 0x1duy -> parseAtomicStore span reader 2 I64AtomicStore32 + | 0x1euy -> parseAtomicRmw span reader 2 I32AtomicRmwAdd + | 0x1fuy -> parseAtomicRmw span reader 2 I64AtomicRmwAdd + | 0x20uy -> parseAtomicRmw span reader 2 I32AtomicRmw8AddU + | 0x21uy -> parseAtomicRmw span reader 2 I32AtomicRmw16AddU + | 0x22uy -> parseAtomicRmw span reader 2 I64AtomicRmw8AddU + | 0x23uy -> parseAtomicRmw span reader 2 I64AtomicRmw16AddU + | 0x24uy -> parseAtomicRmw span reader 2 I64AtomicRmw32AddU + | 0x25uy -> parseAtomicRmw span reader 2 I32AtomicRmwSub + | 0x26uy -> parseAtomicRmw span reader 2 I64AtomicRmw8SubU + | 0x27uy -> parseAtomicRmw span reader 2 I32AtomicRmw8SubU + | 0x28uy -> parseAtomicRmw span reader 2 I32AtomicRmw16SubU + | 0x29uy -> parseAtomicRmw span reader 2 I64AtomicRmw8SubU + | 0x2auy -> parseAtomicRmw span reader 2 I64AtomicRmw16SubU + | 0x2buy -> parseAtomicRmw span reader 2 I64AtomicRmw32SubU + | 0x2cuy -> parseAtomicRmw span reader 2 I32AtomicRmwAnd + | 0x2duy -> parseAtomicRmw span reader 2 I64AtomicRmwAnd + | 0x2euy -> parseAtomicRmw span reader 2 I32AtomicRmw8AndU + | 0x2fuy -> parseAtomicRmw span reader 2 I32AtomicRmw16AndU + | 0x30uy -> parseAtomicRmw span reader 2 I64AtomicRmw8AndU + | 0x31uy -> parseAtomicRmw span reader 2 I64AtomicRmw16AndU + | 0x32uy -> parseAtomicRmw span reader 2 I64AtomicRmw32AndU + | 0x33uy -> parseAtomicRmw span reader 2 I32AtomicRmwOr + | 0x34uy -> parseAtomicRmw span reader 2 I64AtomicRmwOr + | 0x35uy -> parseAtomicRmw span reader 2 I32AtomicRmw8OrU + | 0x36uy -> parseAtomicRmw span reader 2 I32AtomicRmw16OrU + | 0x37uy -> parseAtomicRmw span reader 2 I64AtomicRmw8OrU + | 0x38uy -> parseAtomicRmw span reader 2 I64AtomicRmw16OrU + | 0x39uy -> parseAtomicRmw span reader 2 I64AtomicRmw32OrU + | 0x3auy -> parseAtomicRmw span reader 2 I32AtomicRmwXor + | 0x3buy -> parseAtomicRmw span reader 2 I64AtomicRmwXor + | 0x3cuy -> parseAtomicRmw span reader 2 I32AtomicRmw8XorU + | 0x3duy -> parseAtomicRmw span reader 2 I32AtomicRmw16XorU + | 0x3euy -> parseAtomicRmw span reader 2 I64AtomicRmw8XorU + | 0x3fuy -> parseAtomicRmw span reader 2 I64AtomicRmw16XorU + | 0x40uy -> parseAtomicRmw span reader 2 I64AtomicRmw32XorU + | 0x41uy -> parseAtomicRmw span reader 2 I32AtomicRmwXchg + | 0x42uy -> parseAtomicRmw span reader 2 I64AtomicRmwXchg + | 0x43uy -> parseAtomicRmw span reader 2 I32AtomicRmw8XchgU + | 0x44uy -> parseAtomicRmw span reader 2 I32AtomicRmw16XchgU + | 0x45uy -> parseAtomicRmw span reader 2 I64AtomicRmw8XchgU + | 0x46uy -> parseAtomicRmw span reader 2 I64AtomicRmw16XchgU + | 0x47uy -> parseAtomicRmw span reader 2 I64AtomicRmw32XchgU + | 0x48uy -> parseAtomicRmw span reader 2 I32AtomicRmwCmpxchg + | 0x49uy -> parseAtomicRmw span reader 2 I64AtomicRmwCmpxchg + | 0x4auy -> parseAtomicRmw span reader 2 I32AtomicRmw8CmpxchgU + | 0x4buy -> parseAtomicRmw span reader 2 I32AtomicRmw16CmpxchgU + | 0x4cuy -> parseAtomicRmw span reader 2 I64AtomicRmw8CmpxchgU + | 0x4duy -> parseAtomicRmw span reader 2 I64AtomicRmw16CmpxchgU + | 0x4euy -> parseAtomicRmw span reader 2 I64AtomicRmw32CmpxchgU + | _ -> raise ParsingFailureException + | 0x00uy -> struct (Unreachable, NoOperand, 1u) + | 0x01uy -> struct (Nop, NoOperand, 1u) + | 0x02uy -> parseType span reader 1 Block + | 0x03uy -> parseType span reader 1 Loop + | 0x04uy -> parseType span reader 1 If + | 0x05uy -> struct (Else, NoOperand, 1u) + | 0x06uy -> parseType span reader 1 Try + | 0x07uy -> parseIndex span reader 1 Catch + | 0x08uy -> parseIndex span reader 1 Throw + | 0x09uy -> parseIndex span reader 1 Rethrow + | 0x0buy -> struct (End, NoOperand, 1u) + | 0x0cuy -> parseIndex span reader 1 Br + | 0x0duy -> parseIndex span reader 1 BrIf + | 0x0euy -> + let struct (count, pos) = parseCount span reader 1 + let struct (operands, pos) = parseIndices span reader (int pos) count [] + struct (BrTable, Operands operands, pos) + | 0x0fuy -> struct (Return, NoOperand, 1u) + | 0x10uy -> parseIndex span reader 1 Call + | 0x11uy -> + let struct (sigIndex, pos) = readIndex span reader 1 + let struct (tableIndex, pos) = readIndex span reader pos + struct (CallIndirect, TwoOperands (sigIndex, tableIndex), uint32 pos) + | 0x12uy -> parseIndex span reader 1 ReturnCall + | 0x13uy -> + let struct (sigIndex, pos) = readIndex span reader 1 + let struct (tableIndex, pos) = readIndex span reader pos + struct (ReturnCallIndirect, TwoOperands (sigIndex, tableIndex), uint32 pos) + | 0x14uy -> struct (CallRef, NoOperand, 1u) + | 0x18uy -> parseIndex span reader 1 Delegate + | 0x19uy -> struct (CatchAll, NoOperand, 1u) + | 0x1auy -> struct (Drop, NoOperand, 1u) + | 0x1buy -> struct (Select, NoOperand, 1u) + | 0x1cuy -> + let struct (cnt, pos) = parseCount span reader 1 + let struct (operands, pos) = parseTypes span reader (int pos) cnt [] + struct (SelectT, Operands operands, pos) + | 0x20uy -> parseIndex span reader 1 LocalGet + | 0x21uy -> parseIndex span reader 1 LocalSet + | 0x22uy -> parseIndex span reader 1 LocalTee + | 0x23uy -> parseIndex span reader 1 GlobalGet + | 0x24uy -> parseIndex span reader 1 GlobalSet + | 0x28uy -> parseLoad span reader 1 I32Load + | 0x29uy -> parseLoad span reader 1 I64Load + | 0x2auy -> parseLoad span reader 1 F32Load + | 0x2buy -> parseLoad span reader 1 F64Load + | 0x2cuy -> parseLoad span reader 1 I32Load8S + | 0x2duy -> parseLoad span reader 1 I32Load8U + | 0x2euy -> parseLoad span reader 1 I32Load16S + | 0x2fuy -> parseLoad span reader 1 I32Load16U + | 0x30uy -> parseLoad span reader 1 I64Load8S + | 0x31uy -> parseLoad span reader 1 I64Load8U + | 0x32uy -> parseLoad span reader 1 I64Load16S + | 0x33uy -> parseLoad span reader 1 I64Load16U + | 0x34uy -> parseLoad span reader 1 I64Load32S + | 0x35uy -> parseLoad span reader 1 I64Load32U + | 0x36uy -> parseStore span reader 1 I32Store + | 0x37uy -> parseStore span reader 1 I64Store + | 0x38uy -> parseStore span reader 1 F32Store + | 0x39uy -> parseStore span reader 1 F64Store + | 0x3auy -> parseStore span reader 1 I32Store8 + | 0x3buy -> parseStore span reader 1 I32Store16 + | 0x3cuy -> parseStore span reader 1 I64Store8 + | 0x3duy -> parseStore span reader 1 I64Store16 + | 0x3euy -> parseStore span reader 1 I64Store32 + | 0x3fuy -> parseIndex span reader 1 MemorySize + | 0x40uy -> parseIndex span reader 1 MemoryGrow + | 0x41uy -> parseU32LEB128 span reader 1 I32Const + | 0x42uy -> parseU64LEB128 span reader 1 I64Const + | 0x43uy -> parseF32 span reader 1 F32Const + | 0x44uy -> parseF64 span reader 1 F64Const + | 0x45uy -> struct (I32Eqz, NoOperand, 1u) + | 0x46uy -> struct (I32Eq, NoOperand, 1u) + | 0x47uy -> struct (I32Ne, NoOperand, 1u) + | 0x48uy -> struct (I32LtS, NoOperand, 1u) + | 0x49uy -> struct (I32LtU, NoOperand, 1u) + | 0x4auy -> struct (I32GtS, NoOperand, 1u) + | 0x4buy -> struct (I32GtU, NoOperand, 1u) + | 0x4cuy -> struct (I32LeS, NoOperand, 1u) + | 0x4duy -> struct (I32LeU, NoOperand, 1u) + | 0x4euy -> struct (I32GeS, NoOperand, 1u) + | 0x4fuy -> struct (I32GeU, NoOperand, 1u) + | 0x50uy -> struct (I64Eqz, NoOperand, 1u) + | 0x51uy -> struct (I64Eq, NoOperand, 1u) + | 0x52uy -> struct (I64Ne, NoOperand, 1u) + | 0x53uy -> struct (I64LtS, NoOperand, 1u) + | 0x54uy -> struct (I64LtU, NoOperand, 1u) + | 0x55uy -> struct (I64GtS, NoOperand, 1u) + | 0x56uy -> struct (I64GtU, NoOperand, 1u) + | 0x57uy -> struct (I64LeS, NoOperand, 1u) + | 0x58uy -> struct (I64LeU, NoOperand, 1u) + | 0x59uy -> struct (I64GeS, NoOperand, 1u) + | 0x5auy -> struct (I64GeU, NoOperand, 1u) + | 0x5buy -> struct (F32Eq, NoOperand, 1u) + | 0x5cuy -> struct (F32Ne, NoOperand, 1u) + | 0x5duy -> struct (F32Lt, NoOperand, 1u) + | 0x5euy -> struct (F32Gt, NoOperand, 1u) + | 0x5fuy -> struct (F32Le, NoOperand, 1u) + | 0x60uy -> struct (F32Ge, NoOperand, 1u) + | 0x61uy -> struct (F64Eq, NoOperand, 1u) + | 0x62uy -> struct (F64Ne, NoOperand, 1u) + | 0x63uy -> struct (F64Lt, NoOperand, 1u) + | 0x64uy -> struct (F64Gt, NoOperand, 1u) + | 0x65uy -> struct (F64Le, NoOperand, 1u) + | 0x66uy -> struct (F64Ge, NoOperand, 1u) + | 0x67uy -> struct (I32Clz, NoOperand, 1u) + | 0x68uy -> struct (I32Ctz, NoOperand, 1u) + | 0x69uy -> struct (I32Popcnt, NoOperand, 1u) + | 0x6auy -> struct (I32Add, NoOperand, 1u) + | 0x6buy -> struct (I32Sub, NoOperand, 1u) + | 0x6cuy -> struct (I32Mul, NoOperand, 1u) + | 0x6duy -> struct (I32DivS, NoOperand, 1u) + | 0x6euy -> struct (I32DivU, NoOperand, 1u) + | 0x6fuy -> struct (I32RemS, NoOperand, 1u) + | 0x70uy -> struct (I32RemU, NoOperand, 1u) + | 0x71uy -> struct (I32And, NoOperand, 1u) + | 0x72uy -> struct (I32Or, NoOperand, 1u) + | 0x73uy -> struct (I32Xor, NoOperand, 1u) + | 0x74uy -> struct (I32Shl, NoOperand, 1u) + | 0x75uy -> struct (I32ShrS, NoOperand, 1u) + | 0x76uy -> struct (I32ShrU, NoOperand, 1u) + | 0x77uy -> struct (I32Rotl, NoOperand, 1u) + | 0x78uy -> struct (I32Rotr, NoOperand, 1u) + | 0x79uy -> struct (I64Clz, NoOperand, 1u) + | 0x7auy -> struct (I64Ctz, NoOperand, 1u) + | 0x7buy -> struct (I64Popcnt, NoOperand, 1u) + | 0x7cuy -> struct (I64Add, NoOperand, 1u) + | 0x7duy -> struct (I64Sub, NoOperand, 1u) + | 0x7euy -> struct (I64Mul, NoOperand, 1u) + | 0x7fuy -> struct (I64DivS, NoOperand, 1u) + | 0x80uy -> struct (I64DivU, NoOperand, 1u) + | 0x81uy -> struct (I64RemS, NoOperand, 1u) + | 0x82uy -> struct (I64RemU, NoOperand, 1u) + | 0x83uy -> struct (I64And, NoOperand, 1u) + | 0x84uy -> struct (I64Or, NoOperand, 1u) + | 0x85uy -> struct (I64Xor, NoOperand, 1u) + | 0x86uy -> struct (I64Shl, NoOperand, 1u) + | 0x87uy -> struct (I64ShrS, NoOperand, 1u) + | 0x88uy -> struct (I64ShrU, NoOperand, 1u) + | 0x89uy -> struct (I64Rotl, NoOperand, 1u) + | 0x8auy -> struct (I64Rotr, NoOperand, 1u) + | 0x8buy -> struct (F32Abs, NoOperand, 1u) + | 0x8cuy -> struct (F32Neg, NoOperand, 1u) + | 0x8duy -> struct (F32Ceil, NoOperand, 1u) + | 0x8euy -> struct (F32Floor, NoOperand, 1u) + | 0x8fuy -> struct (F32Trunc, NoOperand, 1u) + | 0x90uy -> struct (F32Nearest, NoOperand, 1u) + | 0x91uy -> struct (F32Sqrt, NoOperand, 1u) + | 0x92uy -> struct (F32Add, NoOperand, 1u) + | 0x93uy -> struct (F32Sub, NoOperand, 1u) + | 0x94uy -> struct (F32Mul, NoOperand, 1u) + | 0x95uy -> struct (F32Div, NoOperand, 1u) + | 0x96uy -> struct (F32Min, NoOperand, 1u) + | 0x97uy -> struct (F32Max, NoOperand, 1u) + | 0x98uy -> struct (F32Copysign, NoOperand, 1u) + | 0x99uy -> struct (F64Abs, NoOperand, 1u) + | 0x9auy -> struct (F64Neg, NoOperand, 1u) + | 0x9buy -> struct (F64Ceil, NoOperand, 1u) + | 0x9cuy -> struct (F64Floor, NoOperand, 1u) + | 0x9duy -> struct (F64Trunc, NoOperand, 1u) + | 0x9euy -> struct (F64Nearest, NoOperand, 1u) + | 0x9fuy -> struct (F64Sqrt, NoOperand, 1u) + | 0xa0uy -> struct (F64Add, NoOperand, 1u) + | 0xa1uy -> struct (F64Sub, NoOperand, 1u) + | 0xa2uy -> struct (F64Mul, NoOperand, 1u) + | 0xa3uy -> struct (F64Div, NoOperand, 1u) + | 0xa4uy -> struct (F64Min, NoOperand, 1u) + | 0xa5uy -> struct (F64Max, NoOperand, 1u) + | 0xa6uy -> struct (F64Copysign, NoOperand, 1u) + | 0xa7uy -> struct (I32WrapI64, NoOperand, 1u) + | 0xa8uy -> struct (I32TruncF32S, NoOperand, 1u) + | 0xa9uy -> struct (I32TruncF32U, NoOperand, 1u) + | 0xaauy -> struct (I32TruncF64S, NoOperand, 1u) + | 0xabuy -> struct (I32TruncF64U, NoOperand, 1u) + | 0xacuy -> struct (I64ExtendI32S, NoOperand, 1u) + | 0xaduy -> struct (I64ExtendI32U, NoOperand, 1u) + | 0xaeuy -> struct (I64TruncF32S, NoOperand, 1u) + | 0xafuy -> struct (I64TruncF32U, NoOperand, 1u) + | 0xb0uy -> struct (I64TruncF64S, NoOperand, 1u) + | 0xb1uy -> struct (I64TruncF64U, NoOperand, 1u) + | 0xb2uy -> struct (F32ConvertI32S, NoOperand, 1u) + | 0xb3uy -> struct (F32ConvertI32U, NoOperand, 1u) + | 0xb4uy -> struct (F32ConvertI64S, NoOperand, 1u) + | 0xb5uy -> struct (F32ConvertI64U, NoOperand, 1u) + | 0xb6uy -> struct (F32DemoteF64, NoOperand, 1u) + | 0xb7uy -> struct (F64ConvertI32S, NoOperand, 1u) + | 0xb8uy -> struct (F64ConvertI32U, NoOperand, 1u) + | 0xb9uy -> struct (F64ConvertI64S, NoOperand, 1u) + | 0xbauy -> struct (F64ConvertI64U, NoOperand, 1u) + | 0xbbuy -> struct (F64PromoteF32, NoOperand, 1u) + | 0xbcuy -> struct (I32ReinterpretF32, NoOperand, 1u) + | 0xbduy -> struct (I64ReinterpretF64, NoOperand, 1u) + | 0xbeuy -> struct (F32ReinterpretI32, NoOperand, 1u) + | 0xbfuy -> struct (F64ReinterpretI64, NoOperand, 1u) + | 0xc0uy -> struct (I32Extend8S, NoOperand, 1u) + | 0xc1uy -> struct (I32Extend16S, NoOperand, 1u) + | 0xc2uy -> struct (I64Extend8S, NoOperand, 1u) + | 0xc3uy -> struct (I64Extend16S, NoOperand, 1u) + | 0xc4uy -> struct (I64Extend32S, NoOperand, 1u) + | 0xe0uy -> struct (InterpAlloca, NoOperand, 1u) + | 0xe1uy -> struct (InterpBrUnless, NoOperand, 1u) + | 0xe2uy -> struct (InterpCallImport, NoOperand, 1u) + | 0xe3uy -> struct (InterpData, NoOperand, 1u) + | 0xe4uy -> struct (InterpDropKeep, NoOperand, 1u) + | 0xe5uy -> struct (InterpCatchDrop, NoOperand, 1u) + | 0xe6uy -> struct (InterpAdjustFrameForReturnCall, NoOperand, 1u) + | 0x25uy -> parseIndex span reader 1 TableGet + | 0x26uy -> parseIndex span reader 1 TableSet + | 0xd0uy -> struct (RefNull, NoOperand, 1u) + | 0xd1uy -> struct (RefIsNull, NoOperand, 1u) + | 0xd2uy -> parseIndex span reader 1 RefFunc + | _ -> raise ParsingFailureException + +let parse (span: ByteSpan) (reader: IBinReader) addr = + let struct (opcode, operands, instrLen) = parseInstruction span reader + let insInfo = + { Address = addr + NumBytes = instrLen + Opcode = opcode + Operands = operands } + WASMInstruction (addr, instrLen, insInfo) diff --git a/src/FrontEnd/BinLifter/WASM/WASMRegExprs.fs b/src/FrontEnd/BinLifter/WASM/WASMRegExprs.fs index ae20634b..0e58a14f 100644 --- a/src/FrontEnd/BinLifter/WASM/WASMRegExprs.fs +++ b/src/FrontEnd/BinLifter/WASM/WASMRegExprs.fs @@ -1,13 +1,37 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + namespace B2R2.FrontEnd.BinLifter.WASM -open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.BinIR.LowUIR -type internal RegExprs () = - let var sz t name = AST.var sz t name (WASMRegisterSet.singleton t) +type RegExprs () = + let var sz t name = AST.var sz t name member __.GetRegVar (name) = match name with - | _ -> raise B2R2.FrontEnd.BinLifter.UnhandledRegExprException + | _ -> raise UnhandledRegExprException // vim: set tw=80 sts=2 sw=2: \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/WASM/WASMRegisterBay.fs b/src/FrontEnd/BinLifter/WASM/WASMRegisterBay.fs deleted file mode 100644 index a321dd5c..00000000 --- a/src/FrontEnd/BinLifter/WASM/WASMRegisterBay.fs +++ /dev/null @@ -1,47 +0,0 @@ -namespace B2R2.FrontEnd.BinLifter.WASM - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR.LowUIR - -type WASMRegisterBay () = - inherit RegisterBay () - - override __.GetAllRegExprs () = Utils.futureFeature () - - override __.GetAllRegNames () = [] - - override __.GetGeneralRegExprs () = Utils.futureFeature () - - override __.RegIDFromRegExpr (e) = - match e.E with - | _ -> failwith "not a register expression" - - override __.RegIDToRegExpr (id) = Utils.impossible () - - override __.StrToRegExpr _s = Utils.impossible () - - override __.RegIDFromString str = - Register.ofString str |> Register.toRegID - - override __.RegIDToString rid = - Register.ofRegID rid |> Register.toString - - override __.RegIDToRegType rid = - Register.ofRegID rid |> Register.toRegType - - override __.GetRegisterAliases _ = Utils.futureFeature () - - override __.ProgramCounter = Utils.impossible() - - override __.StackPointer = Utils.futureFeature () - - override __.FramePointer = Utils.impossible () - - override __.IsProgramCounter regid = Utils.futureFeature () - - override __.IsStackPointer regid = Utils.futureFeature () - - override __.IsFramePointer _ = Utils.impossible () - -// vim: set tw=80 sts=2 sw=2: \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/SH4/SH4RegisterBay.fs b/src/FrontEnd/BinLifter/WASM/WASMRegisterFactory.fs similarity index 74% rename from src/FrontEnd/BinLifter/SH4/SH4RegisterBay.fs rename to src/FrontEnd/BinLifter/WASM/WASMRegisterFactory.fs index b2014f33..8a9eb07b 100644 --- a/src/FrontEnd/BinLifter/SH4/SH4RegisterBay.fs +++ b/src/FrontEnd/BinLifter/WASM/WASMRegisterFactory.fs @@ -22,15 +22,13 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.SH4 +namespace B2R2.FrontEnd.BinLifter.WASM open B2R2 open B2R2.FrontEnd.BinLifter -open B2R2.BinIR.LowUIR -type SH4RegisterBay () = - - inherit RegisterBay () +type WASMRegisterFactory () = + inherit RegisterFactory () override __.GetAllRegExprs () = Utils.futureFeature () @@ -38,12 +36,9 @@ type SH4RegisterBay () = override __.GetGeneralRegExprs () = Utils.futureFeature () - override __.RegIDFromRegExpr (e) = - match e.E with - | Var (_, id, _ ,_) -> id - | _ -> failwith "not a register expression" + override __.RegIDFromRegExpr (_e) = Utils.futureFeature () - override __.RegIDToRegExpr (id) = Utils.impossible () + override __.RegIDToRegExpr (_id) = Utils.impossible () override __.StrToRegExpr _s = Utils.impossible () @@ -58,16 +53,16 @@ type SH4RegisterBay () = override __.GetRegisterAliases _ = Utils.futureFeature () - override __.ProgramCounter = Utils.futureFeature () + override __.ProgramCounter = Utils.impossible() override __.StackPointer = Utils.futureFeature () - override __.FramePointer = Utils.futureFeature () + override __.FramePointer = Utils.impossible () + + override __.IsProgramCounter regid = Utils.futureFeature () - override __.IsProgramCounter regid = - __.ProgramCounter = regid + override __.IsStackPointer regid = Utils.futureFeature () - override __.IsStackPointer regid = - (__.StackPointer |> Option.get) = regid + override __.IsFramePointer _ = Utils.impossible () - override __.IsFramePointer _ = false +// vim: set tw=80 sts=2 sw=2: \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/WASM/WASMRegisterSet.fs b/src/FrontEnd/BinLifter/WASM/WASMRegisterSet.fs deleted file mode 100644 index b3686451..00000000 --- a/src/FrontEnd/BinLifter/WASM/WASMRegisterSet.fs +++ /dev/null @@ -1,37 +0,0 @@ -namespace B2R2.FrontEnd.BinLifter.WASM - -open B2R2 - -module private RegisterSetLiteral = - let [] arrLen = 2 - -open RegisterSetLiteral - -type WASMRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = WASMRegisterSet (RegisterSet.MakeInternalBitArray arrLen, Set.empty) - - override __.Tag = RegisterSetTag.WASM - - override __.ArrSize = arrLen - - override __.New arr s = new WASMRegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - match Register.ofRegID rid with - | _ -> Utils.futureFeature () - - override __.IndexToRegID index = - match index with - | _ -> Utils.impossible () - - override __.ToString () = - sprintf "WASMReisterSet<%x, %x>" __.BitArray.[0] __.BitArray.[1] - -[] -module WASMRegisterSet = - let singleton rid = WASMRegisterSet().Add(rid) - let empty = WASMRegisterSet () :> RegisterSet - -// vim: set tw=80 sts=2 sw=2: \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/WASM/WASMTranslationContext.fs b/src/FrontEnd/BinLifter/WASM/WASMTranslationContext.fs new file mode 100644 index 00000000..1643f473 --- /dev/null +++ b/src/FrontEnd/BinLifter/WASM/WASMTranslationContext.fs @@ -0,0 +1,42 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.BinLifter.WASM + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Translation context for WASM instructions. +type WASMTranslationContext (isa) = + inherit TranslationContext (isa) + + let regExprs = RegExprs () + + member __.RegExprs with get() = regExprs + + override __.GetRegVar id = + Register.ofRegID id |> regExprs.GetRegVar + + override __.GetPseudoRegVar _id _pos = + Utils.impossible () \ No newline at end of file diff --git a/src/FrontEnd/BinLifter/WASM/WASMTypes.fs b/src/FrontEnd/BinLifter/WASM/WASMTypes.fs index 990e61a9..d233050f 100644 --- a/src/FrontEnd/BinLifter/WASM/WASMTypes.fs +++ b/src/FrontEnd/BinLifter/WASM/WASMTypes.fs @@ -1,7 +1,30 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + namespace B2R2.FrontEnd.BinLifter.WASM open B2R2 -open System.Runtime.CompilerServices type Register = // Stack pointer @@ -25,7 +48,7 @@ module Register = LanguagePrimitives.EnumToValue (reg) |> RegisterID.create let ofString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "SP" -> R.SP | _ -> Utils.impossible () diff --git a/src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj b/src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj similarity index 94% rename from src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj rename to src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj index f5c8b553..ed54fc27 100644 --- a/src/FrontEnd/BinInterface/B2R2.FrontEnd.BinInterface.fsproj +++ b/src/FrontEnd/Core/B2R2.FrontEnd.Core.fsproj @@ -5,6 +5,7 @@ b2r2-240x240.png README.md B2R2 frontend main interface. + $(OtherFlags)--warnon:3390 @@ -33,10 +34,11 @@ - - + + + diff --git a/src/FrontEnd/Core/Basis.fs b/src/FrontEnd/Core/Basis.fs new file mode 100644 index 00000000..6b40fa04 --- /dev/null +++ b/src/FrontEnd/Core/Basis.fs @@ -0,0 +1,145 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +[] +module B2R2.FrontEnd.Basis + +open B2R2 +open B2R2.FrontEnd.BinLifter + +/// Load a translation context for the given architecture. +[] +let loadTranslationContext isa = + match isa.Arch with + | Architecture.IntelX64 + | Architecture.IntelX86 -> + Intel.IntelTranslationContext isa :> TranslationContext + | Architecture.ARMv7 | Architecture.AARCH32 -> + ARM32.ARM32TranslationContext isa :> TranslationContext + | Architecture.AARCH64 -> + ARM64.ARM64TranslationContext isa :> TranslationContext + | Architecture.AVR -> + AVR.AVRTranslationContext isa :> TranslationContext + | Architecture.EVM -> + EVM.EVMTranslationContext isa :> TranslationContext + | Architecture.TMS320C6000 -> + TMS320C6000.TMS320C6000TranslationContext isa :> TranslationContext + | Architecture.MIPS32 | Architecture.MIPS64 -> + MIPS.MIPSTranslationContext isa :> TranslationContext + | Architecture.PPC32 -> + PPC32.PPC32TranslationContext isa :> TranslationContext + | Architecture.RISCV64 -> + RISCV.RISCV64TranslationContext isa :> TranslationContext + | Architecture.SH4 -> + SH4.SH4TranslationContext isa :> TranslationContext + | Architecture.SPARC -> + SPARC.SPARCTranslationContext isa :> TranslationContext + | _ -> Utils.futureFeature () + +/// Load a register factory for the given architecture. +[] +let loadRegisterFactory isa = + match isa.Arch with + | Architecture.IntelX64 + | Architecture.IntelX86 -> + Intel.IntelRegisterFactory (isa.WordSize, Intel.RegExprs isa.WordSize) + :> RegisterFactory + | Architecture.ARMv7 | Architecture.AARCH32 -> + ARM32.ARM32RegisterFactory (ARM32.RegExprs ()) :> RegisterFactory + | Architecture.AARCH64 -> + ARM64.ARM64RegisterFactory (ARM64.RegExprs ()) :> RegisterFactory + | Architecture.AVR -> + AVR.AVRRegisterFactory () :> RegisterFactory + | Architecture.EVM -> + EVM.EVMRegisterFactory () :> RegisterFactory + | Architecture.TMS320C6000 -> + TMS320C6000.TMS320C6000RegisterFactory () :> RegisterFactory + | Architecture.MIPS32 | Architecture.MIPS64 -> + MIPS.MIPSRegisterFactory (isa.WordSize, MIPS.RegExprs isa.WordSize) + :> RegisterFactory + | Architecture.PPC32 -> + PPC32.PPC32RegisterFactory (isa.WordSize, PPC32.RegExprs isa.WordSize) + :> RegisterFactory + | Architecture.RISCV64 -> + RISCV.RISCV64RegisterFactory (isa.WordSize, RISCV.RegExprs isa.WordSize) + :> RegisterFactory + | Architecture.SH4 -> + SH4.SH4RegisterFactory (SH4.RegExprs isa.WordSize) + :> RegisterFactory + | Architecture.SPARC -> + SPARC.SPARCRegisterFactory () + :> RegisterFactory + | _ -> Utils.futureFeature () + +/// Load both a translation context and a register factory for the given +/// architecture. This is a recommended way to load both data structures. +[] +let load isa = + match isa.Arch with + | Architecture.IntelX64 + | Architecture.IntelX86 -> + let ctxt = Intel.IntelTranslationContext isa + let factory = Intel.IntelRegisterFactory (isa.WordSize, ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.ARMv7 | Architecture.AARCH32 -> + let ctxt = ARM32.ARM32TranslationContext isa + let factory = ARM32.ARM32RegisterFactory (ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.AARCH64 -> + let ctxt = ARM64.ARM64TranslationContext isa + let factory = ARM64.ARM64RegisterFactory (ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.AVR -> + let ctxt = AVR.AVRTranslationContext isa + let factory = AVR.AVRRegisterFactory () + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.EVM -> + let ctxt = EVM.EVMTranslationContext isa + let factory = EVM.EVMRegisterFactory () + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.TMS320C6000 -> + let ctxt = TMS320C6000.TMS320C6000TranslationContext isa + let factory = TMS320C6000.TMS320C6000RegisterFactory () + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.MIPS32 | Architecture.MIPS64 -> + let ctxt = MIPS.MIPSTranslationContext isa + let factory = MIPS.MIPSRegisterFactory (isa.WordSize, ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.PPC32 -> + let ctxt = PPC32.PPC32TranslationContext isa + let factory = PPC32.PPC32RegisterFactory (isa.WordSize, ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.RISCV64 -> + let ctxt = RISCV.RISCV64TranslationContext isa + let factory = RISCV.RISCV64RegisterFactory (isa.WordSize, ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.SH4 -> + let ctxt = SH4.SH4TranslationContext isa + let factory = SH4.SH4RegisterFactory (ctxt.RegExprs) + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | Architecture.SPARC -> + let ctxt = SPARC.SPARCTranslationContext isa + let factory = SPARC.SPARCRegisterFactory () + struct (ctxt :> TranslationContext, factory :> RegisterFactory) + | _ -> Utils.futureFeature () diff --git a/src/FrontEnd/Core/BinHandle.fs b/src/FrontEnd/Core/BinHandle.fs new file mode 100644 index 00000000..963cfae0 --- /dev/null +++ b/src/FrontEnd/Core/BinHandle.fs @@ -0,0 +1,235 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd + +open System.IO +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter +open B2R2.FrontEnd.Helper +open type FileFormat +open type ArchOperationMode + +type BinHandle private (path, bytes, fmt, isa, mode, baseAddrOpt) = + let struct (ctxt, regFactory) = Basis.load isa + let binFile = FileFactory.load path bytes fmt isa regFactory baseAddrOpt + let parser = Parser.init binFile.ISA mode binFile.EntryPoint + + new (path, isa, mode, baseAddrOpt) = + let bytes = File.ReadAllBytes path + let struct (fmt, isa) = FormatDetector.identify bytes isa + BinHandle (path, bytes, fmt, isa, mode, baseAddrOpt) + + new (path, isa, baseAddrOpt) = + BinHandle (path=path, isa=isa, mode=NoMode, baseAddrOpt=baseAddrOpt) + + new (path, isa) = + BinHandle (path=path, isa=isa, mode=NoMode, baseAddrOpt=None) + + new (bytes, isa, mode, baseAddrOpt, detectFormat) = + if detectFormat then + let struct (fmt, isa) = FormatDetector.identify bytes isa + BinHandle ("", bytes, fmt, isa, mode, baseAddrOpt) + else + BinHandle ("", bytes, RawBinary, isa, mode, baseAddrOpt) + + new (isa) = + BinHandle ([||], isa, NoMode, None, false) + + /// Return the `IBinFile` object. + member __.File with get(): IBinFile = binFile + + member __.TranslationContext with get(): TranslationContext = ctxt + + member __.Parser with get(): IInstructionParsable = parser + + member __.RegisterFactory with get(): RegisterFactory = regFactory + + member __.TryReadBytes (addr: Addr, nBytes) = + let range = AddrRange (addr, addr + uint64 nBytes - 1UL) + if binFile.IsInFileRange range then + let slice = binFile.Slice (addr, nBytes) + slice.ToArray () |> Ok + elif binFile.IsValidRange range then + binFile.GetNotInFileIntervals range + |> classifyRanges range + |> List.fold (fun bs (range, isInFile) -> + let len = (range.Max - range.Min |> int) + 1 + if isInFile then + let slice = binFile.Slice (range.Min, len) + Array.append bs (slice.ToArray ()) + else Array.create len 0uy |> Array.append bs + ) [||] + |> Ok + else Error ErrorCase.InvalidMemoryRead + + member __.TryReadBytes (ptr: BinFilePointer, nBytes) = + if BinFilePointer.IsValidAccess ptr nBytes then + let slice = binFile.Slice (ptr, nBytes) + slice.ToArray () |> Ok + else Error ErrorCase.InvalidMemoryRead + + member __.ReadBytes (addr: Addr, nBytes) = + match __.TryReadBytes (addr, nBytes) with + | Ok bs -> bs + | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) + + member __.ReadBytes (ptr: BinFilePointer, nBytes) = + match __.TryReadBytes (ptr, nBytes) with + | Ok bs -> bs + | Error e -> invalidArg (nameof ptr) (ErrorCase.toString e) + + member __.TryReadInt (addr: Addr, size) = + let pos = binFile.GetOffset addr + if (pos + size) > binFile.Length || (pos < 0) then + Error ErrorCase.InvalidMemoryRead + else + let span = binFile.Slice (offset=pos) + readIntBySize binFile.Reader span size + + member __.TryReadInt (ptr: BinFilePointer, size) = + if BinFilePointer.IsValidAccess ptr size then + let span = binFile.Slice (offset=ptr.Offset) + readIntBySize binFile.Reader span size + else Error ErrorCase.InvalidMemoryRead + + member __.ReadInt (addr: Addr, size) = + match __.TryReadInt (addr, size) with + | Ok i -> i + | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) + + member __.ReadInt (ptr: BinFilePointer, size) = + match __.TryReadInt (ptr, size) with + | Ok i -> i + | Error e -> invalidArg (nameof ptr) (ErrorCase.toString e) + + member __.TryReadUInt (addr: Addr, size) = + let pos = binFile.GetOffset addr + if (pos + size) > binFile.Length || (pos < 0) then + Error ErrorCase.InvalidMemoryRead + else + let span = binFile.Slice (offset=pos) + readUIntBySize binFile.Reader span size + + member __.TryReadUInt (ptr: BinFilePointer, size) = + if BinFilePointer.IsValidAccess ptr size then + let span = binFile.Slice (offset=ptr.Offset) + readUIntBySize binFile.Reader span size + else Error ErrorCase.InvalidMemoryRead + + member __.ReadUInt (addr: Addr, size) = + match __.TryReadUInt (addr, size) with + | Ok i -> i + | Error e -> invalidArg (nameof addr) (ErrorCase.toString e) + + member __.ReadUInt (ptr: BinFilePointer, size) = + match __.TryReadUInt (ptr, size) with + | Ok i -> i + | Error e -> invalidArg (nameof ptr) (ErrorCase.toString e) + + member __.ReadASCII (addr: Addr) = + let bs = binFile.GetOffset addr |> readASCII binFile + ByteArray.extractCString bs 0 + + member __.ReadASCII (ptr: BinFilePointer) = + let bs = readASCII binFile ptr.Offset + ByteArray.extractCString bs 0 + + member __.ParseInstr (addr: Addr) = + parser.Parse (binFile.Slice (addr), addr) + + member __.ParseInstr (ptr: BinFilePointer) = + parseInstrFromBinPtr binFile parser ptr + + member __.TryParseInstr (addr) = + tryParseInstrFromAddr binFile parser addr + + member __.TryParseInstr (ptr: BinFilePointer) = + tryParseInstrFromBinPtr binFile parser ptr + + member __.ParseBBlock (addr) = + parseBBLFromAddr binFile parser addr + + member __.ParseBBlock (ptr) = + parseBBLFromBinPtr binFile parser ptr + + member __.LiftInstr (addr: Addr) = + let ins = parser.Parse (binFile.Slice addr, addr) + ins.Translate ctxt + + member __.LiftInstr (ptr: BinFilePointer) = + let ins = parseInstrFromBinPtr binFile parser ptr + ins.Translate ctxt + + member __.LiftInstr (ins: Instruction) = + ins.Translate ctxt + + member __.LiftOptimizedInstr (addr: Addr) = + __.LiftInstr addr |> LocalOptimizer.Optimize + + member __.LiftOptimizedInstr (ptr: BinFilePointer) = + __.LiftInstr ptr |> LocalOptimizer.Optimize + + member __.LiftOptimizedInstr (ins: Instruction) = + ins.Translate ctxt |> LocalOptimizer.Optimize + + member __.LiftBBlock (addr: Addr) = + liftBBLFromAddr binFile parser ctxt addr + + member __.LiftBBlock (ptr: BinFilePointer) = + liftBBLFromBinPtr binFile parser ctxt ptr + + member __.DisasmInstr (addr: Addr, showAddr, resolveSymbol) = + let ins = parser.Parse (binFile.Slice addr, addr) + let reader = if resolveSymbol then binFile :> INameReadable else null + ins.Disasm (showAddr, reader) + + member __.DisasmInstr (ptr: BinFilePointer, showAddr, resolveSymbol) = + let ins = parseInstrFromBinPtr binFile parser ptr + let reader = if resolveSymbol then binFile :> INameReadable else null + ins.Disasm (showAddr, reader) + + member __.DisasmInstr (ins: Instruction, showAddr, resolveSymbol) = + let reader = if resolveSymbol then binFile :> INameReadable else null + ins.Disasm (showAddr, reader) + + member __.DisasmInstr (addr: Addr) = + let ins = parser.Parse (binFile.Slice addr, addr) + ins.Disasm () + + member __.DisasmInstr (ptr: BinFilePointer) = + let ins = parseInstrFromBinPtr binFile parser ptr + ins.Disasm () + + member inline __.DisasmInstr (ins: Instruction) = + ins.Disasm () + + member __.DisasmBBlock (addr, showAddr, resolveSymbol) = + disasmBBLFromAddr binFile parser showAddr resolveSymbol addr + + member __.DisasmBBlock (ptr, showAddr, resolveSymbol) = + disasmBBLFromBinPtr binFile parser showAddr resolveSymbol ptr + +// vim: set tw=80 sts=2 sw=2: diff --git a/src/FrontEnd/Core/BinHandle.fsi b/src/FrontEnd/Core/BinHandle.fsi new file mode 100644 index 00000000..495d3f66 --- /dev/null +++ b/src/FrontEnd/Core/BinHandle.fsi @@ -0,0 +1,385 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd + +open B2R2 +open B2R2.BinIR +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter + +/// The main handle for reading/parsing a binary code. `BinHandle` essentially +/// provides an interface for a chunk of binary code for parsing instructions, +/// lifting instructions, or reading data from it. +type BinHandle = + /// Construct a BinHandle from a given file path, ISA, optional base + /// address (baseAddrOpt), and ArchOperationMode. File format will be + /// automatically detected. + new: path: string + * isa: ISA + * mode: ArchOperationMode + * baseAddrOpt: Addr option + -> BinHandle + + /// Construct a BinHandle from a given file path, ISA, and optional base + /// address (baseAddrOpt). ArchOperationMode is set to NoMode. + new: path: string * isa: ISA * baseAddrOpt: Addr option -> BinHandle + + /// Construct a BinHandle from a given file path and ISA. ArchOperationMode + /// is set to NoMode. + new: path: string * isa: ISA -> BinHandle + + /// Construct a BinHandle from a given byte array. File format detection is + /// performed only if detectFormat is set to true. + new: bytes: byte[] + * isa: ISA + * mode: ArchOperationMode + * baseAddrOpt: Addr option + * detectFormat: bool + -> BinHandle + + /// Construct an empty BinHandle. + new: isa: ISA -> BinHandle + + /// File handle. + member File: IBinFile + + /// Translation context. + member TranslationContext: TranslationContext + + /// Parser. + member Parser: IInstructionParsable + + /// Register factory. + member RegisterFactory: RegisterFactory + + /// + /// Return the byte array of size (nBytes) located at the address (addr). + /// + /// The address. + /// The size of the byte array (in bytes). + /// + /// Return (byte[]) if succeeded, (ErrorCase) otherwise. + /// + member TryReadBytes: + addr: Addr * nBytes: int -> Result + + /// + /// Return the byte array of size (nBytes) pointed to by the pointer (ptr). + /// + /// The binary pointer. + /// The size of the byte array (in bytes). + /// + /// Return (byte[]) if succeeded, (ErrorCase) otherwise. + /// + member TryReadBytes: + ptr: BinFilePointer * nBytes: int -> Result + + /// + /// Return the byte array of size (nBytes) at the addr from the current + /// binary. + /// + /// The address. + /// The size of the byte array (in bytes). + /// + /// Return the byte array if succeed. Otherwise, raise an exception. + /// + member ReadBytes: addr: Addr * nBytes: int -> byte [] + + /// + /// Return the byte array of size (nBytes) pointed to by the binary file + /// pointer (ptr). + /// + /// BInaryPointer. + /// The size of the byte array (in bytes). + /// + /// Return the byte array if succeed. Otherwise, raise an exception. + /// + member ReadBytes: ptr: BinFilePointer * nBytes: int -> byte [] + + /// + /// Return the corresponding integer of the size from the given address. + /// + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding value (int64) if the address and the size is + /// valid. Otherwise ErrorCase. + /// + member TryReadInt: + addr: Addr * size: int -> Result + + /// + /// Return the corresponding integer of the size from the given address + /// pointed to by the binary pointer (ptr). + /// + /// BinFilePointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding value (int64) if the address and the size is + /// valid. Otherwise ErrorCase. + /// + member TryReadInt: + ptr: BinFilePointer * size: int -> Result + + /// + /// Return the corresponding integer value at the addr of the size from the + /// current binary. + /// + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding integer (int64). + /// + member ReadInt: addr: Addr * size: int -> int64 + + /// + /// Return the corresponding integer value of the size from the current + /// binary, which is pointed to by the binary file pointer (ptr). + /// + /// The binary pointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding integer (int64). + /// + member ReadInt: ptr: BinFilePointer * size: int -> int64 + + /// + /// Return the corresponding unsigned integer of the size from the given + /// address. + /// + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64) if the address and + /// the size is valid. Otherwise, ErrorCase. + /// + member TryReadUInt: + addr: Addr * size: int -> Result + + /// + /// Return the corresponding unsigned integer of the size from the address + /// pointed to by the binary file pointer (ptr). + /// + /// BinFilePointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64) if the address and + /// the size is valid. Otherwise, ErrorCase. + /// + member TryReadUInt: + ptr: BinFilePointer * size: int -> Result + + /// + /// Return the corresponding unsigned integer value at the addr of the size + /// from the binary. + /// + /// The address. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64). + /// + member ReadUInt: addr: Addr * size: int -> uint64 + + /// + /// Return the corresponding unsigned integer value of the size from the + /// binary, which is pointed to by the binary file pointer (ptr). + /// + /// BinFilePointer. + /// The size of the integer in bytes. Maximum 8 bytes is + /// possible. + /// + /// Return the corresponding unsigned integer (uint64). + /// + member ReadUInt: ptr: BinFilePointer * size: int -> uint64 + + /// + /// Return the ASCII string at the addr from the given BinHandle. + /// + /// The address. + /// + /// Return the corresponding ASCII string. + /// + member ReadASCII: addr: Addr -> string + + /// + /// Return the ASCII string pointed to by the binary file pointer from the + /// given BinHandle. + /// + /// BinFilePointer. + /// + /// Return the corresponding ASCII string. + /// + member ReadASCII: ptr: BinFilePointer -> string + + /// + /// Parse one instruction at the given address (addr), and return the + /// corresponding instruction. This function raises an exception if the + /// parsing process fails. + /// + /// The address. + /// + /// Parsed instruction. + /// + member ParseInstr: addr: Addr -> Instruction + + /// + /// Parse one instruction pointed to by the binary file pointer (ptr), and + /// return the corresponding instruction. This function raises an exception + /// if the parsing process fails. + /// + /// BinFilePointer. + /// + /// Parsed instruction. + /// + member ParseInstr: ptr: BinFilePointer -> Instruction + + /// + /// Parse one instruction at the given address (addr), and return the + /// corresponding instruction. + /// + /// The address. + /// + /// Parsed instruction if succeeded, ErrorCase if otherwise. + /// + member TryParseInstr: addr: Addr -> Result + + /// + /// Parse one instruction pointed to by the binary file pointer (ptr), and + /// return the corresponding instruction. + /// + /// BinFilePointer. + /// + /// Parsed instruction if succeeded, ErrorCase if otherwise. + /// + member TryParseInstr: ptr: BinFilePointer -> Result + + /// Parse a basic block from the given address, and return the sequence of the + /// instructions of the basic block. This function may return an incomplete + /// basic block as an Error type. This function can be safely used for any + /// ISAs, and thus, this should be the main parsing function. + member ParseBBlock: + addr: Addr -> Result + + /// Parse a basic block pointed to by the binary file pointer (ptr), and + /// return the sequence of the instructions of the basic block. This function + /// may return an incomplete basic block as an Error type. This function can + /// be safely used for any ISAs, and thus, this should be the main parsing + /// function. + member ParseBBlock: + ptr: BinFilePointer -> Result + + /// Lift an instruction located at the given address to produce an array of IR + /// statements. + member LiftInstr: addr: Addr -> LowUIR.Stmt [] + + /// Lift an instruction pointed to by the given binary file pointer to produce + /// an array of IR statements. + member LiftInstr: ptr: BinFilePointer -> LowUIR.Stmt [] + + /// Lift the given instruction to produce an array of IR statements. + member LiftInstr: ins: Instruction -> LowUIR.Stmt [] + + /// Lift an instruction located at the given address to produce an array of + /// optimized IR statements. + member LiftOptimizedInstr: addr: Addr -> LowUIR.Stmt [] + + /// Lift an instruction pointed to by the given binary file pointer to produce + /// an array of optimized IR statements. + member LiftOptimizedInstr: ptr: BinFilePointer -> LowUIR.Stmt [] + + /// Lift a parsed instruction (Instruction) to produce an array of optimized + /// IR statements from a given BinHandle. + member LiftOptimizedInstr: ins: Instruction -> LowUIR.Stmt [] + + /// Return the lifted IR (an array of statements) of a basic block at the + /// given address. This function returns a partial bblock with Error, if the + /// parsing of the bblock was not successful. + member LiftBBlock: + addr: Addr -> Result<(LowUIR.Stmt [] * Addr), (LowUIR.Stmt [] * Addr)> + + /// Return the lifted IR (an array of statements) of a basic block pointed to + /// by the binary file pointer (ptr). This function returns a partial bblock + /// with Error, if the parsing of the bblock was not successful. + member LiftBBlock: + ptr: BinFilePointer + -> Result<(LowUIR.Stmt [] * BinFilePointer), + (LowUIR.Stmt [] * BinFilePointer)> + + /// Return a disassembled string of an instruction located at the given + /// address. The disassembled string contains the instruction address and + /// symbols if the corresponding options are set to true. + member DisasmInstr: + addr: Addr * showAddr: bool * resolveSymbol: bool -> string + + /// Return a disassembled string of an instruction pointed to by the binary + /// file pointer. The disassembled string contains the instruction address and + /// symbols if the corresponding options are set to true. + member DisasmInstr: + ptr: BinFilePointer * showAddr: bool * resolveSymbol: bool -> string + + /// Return a disassembled string of the given instruction. The disassembled + /// string contains the instruction address and symbols if the corresponding + /// options are set to true. + member DisasmInstr: + ins: Instruction * showAddr: bool * resolveSymbol: bool -> string + + /// Return a disassembled string of an instruction located at the given + /// address without the instruction address nor symbols. + member DisasmInstr: addr: Addr -> string + + /// Return a disassembled string of an instruction pointed to by the binary + /// file pointer without the instruction address nor symbols. + member DisasmInstr: ptr: BinFilePointer -> string + + /// Return a disassembled string of the given instruction without the + /// instruction address nor symbols. + member inline DisasmInstr: ins: Instruction -> string + + /// Return the disassembled string for a basic block starting at the given + /// address along with the fall-through address of the block. This function + /// returns a partial disassembly if parsing of the bblock was not successful. + member DisasmBBlock: + addr: Addr + * showAddr:bool + * resolveSymbol: bool + -> Result<(string * Addr), (string * Addr)> + + /// Return the disassembled string for a basic block starting at address + /// pointed to by the binary pointer (ptr) along with the fall-through address + /// of the block. This function returns a partial disassembly if parsing of + /// the bblock was not successful. + member DisasmBBlock: + ptr: BinFilePointer + * showAddr:bool + * resolveSymbol: bool + -> Result<(string * BinFilePointer), + (string * BinFilePointer)> diff --git a/src/FrontEnd/BinInterface/CallingConvention.fs b/src/FrontEnd/Core/CallingConvention.fs similarity index 80% rename from src/FrontEnd/BinInterface/CallingConvention.fs rename to src/FrontEnd/Core/CallingConvention.fs index 73bfb7fa..74c83d6a 100644 --- a/src/FrontEnd/BinInterface/CallingConvention.fs +++ b/src/FrontEnd/Core/CallingConvention.fs @@ -22,74 +22,56 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinInterface.CallingConvention +module B2R2.FrontEnd.CallingConvention open B2R2 open B2R2.FrontEnd.BinLifter [] -let volatileRegisters hdl = - match hdl.ISA.Arch with - | Arch.IntelX86 -> +let volatileRegisters (hdl: BinHandle) = + match hdl.File.ISA.Arch with + | Architecture.IntelX86 -> [ Intel.Register.EAX; Intel.Register.ECX; Intel.Register.EDX ] |> List.map Intel.Register.toRegID - | Arch.IntelX64 -> + | Architecture.IntelX64 -> [ Intel.Register.RAX; Intel.Register.RCX; Intel.Register.RDX; Intel.Register.R8; Intel.Register.R9; Intel.Register.R10; Intel.Register.R11 ] |> List.map Intel.Register.toRegID - | Arch.ARMv7 - | Arch.AARCH32 -> + | Architecture.ARMv7 + | Architecture.AARCH32 -> [ ARM32.Register.R0; ARM32.Register.R1; ARM32.Register.R2; ARM32.Register.R3 ] |> List.map ARM32.Register.toRegID | _ -> Utils.futureFeature () [] -let returnRegister hdl = - match hdl.ISA.Arch with +let returnRegister (hdl: BinHandle) = + match hdl.File.ISA.Arch with | Architecture.IntelX86 -> Intel.Register.EAX |> Intel.Register.toRegID | Architecture.IntelX64 -> Intel.Register.RAX |> Intel.Register.toRegID | Architecture.ARMv7 | Architecture.AARCH32 -> ARM32.Register.R0 |> ARM32.Register.toRegID | Architecture.AARCH64 -> ARM64.Register.X0 |> ARM64.Register.toRegID - | Architecture.MIPS1 - | Architecture.MIPS2 - | Architecture.MIPS3 - | Architecture.MIPS4 - | Architecture.MIPS5 - | Architecture.MIPS32 - | Architecture.MIPS32R2 - | Architecture.MIPS32R6 - | Architecture.MIPS64 - | Architecture.MIPS64R2 - | Architecture.MIPS64R6 -> MIPS.Register.R2 |> MIPS.Register.toRegID + | Architecture.MIPS32 | Architecture.MIPS64 -> + MIPS.Register.R2 |> MIPS.Register.toRegID | _ -> Utils.futureFeature () [] -let syscallNumRegister hdl = - match hdl.ISA.Arch with +let syscallNumRegister (hdl: BinHandle) = + match hdl.File.ISA.Arch with | Architecture.IntelX86 -> Intel.Register.EAX |> Intel.Register.toRegID | Architecture.IntelX64 -> Intel.Register.RAX |> Intel.Register.toRegID | Architecture.ARMv7 | Architecture.AARCH32 -> ARM32.Register.R7 |> ARM32.Register.toRegID | Architecture.AARCH64 -> ARM64.Register.X8 |> ARM64.Register.toRegID - | Architecture.MIPS1 - | Architecture.MIPS2 - | Architecture.MIPS3 - | Architecture.MIPS4 - | Architecture.MIPS5 - | Architecture.MIPS32 - | Architecture.MIPS32R2 - | Architecture.MIPS32R6 - | Architecture.MIPS64 - | Architecture.MIPS64R2 - | Architecture.MIPS64R6 -> MIPS.Register.R2 |> MIPS.Register.toRegID + | Architecture.MIPS32 | Architecture.MIPS64 -> + MIPS.Register.R2 |> MIPS.Register.toRegID | _ -> Utils.futureFeature () [] -let syscallArgRegister hdl num = - match hdl.OS, hdl.ISA.Arch with +let syscallArgRegister (hdl: BinHandle) os num = + match os, hdl.File.ISA.Arch with | OS.Linux, Architecture.IntelX86 -> match num with | 1 -> Intel.Register.EBX |> Intel.Register.toRegID @@ -127,17 +109,7 @@ let syscallArgRegister hdl num = | 5 -> ARM64.Register.X4 |> ARM64.Register.toRegID | 6 -> ARM64.Register.X5 |> ARM64.Register.toRegID | _ -> Utils.impossible () - | OS.Linux, Architecture.MIPS1 - | OS.Linux, Architecture.MIPS2 - | OS.Linux, Architecture.MIPS3 - | OS.Linux, Architecture.MIPS4 - | OS.Linux, Architecture.MIPS5 - | OS.Linux, Architecture.MIPS32 - | OS.Linux, Architecture.MIPS32R2 - | OS.Linux, Architecture.MIPS32R6 - | OS.Linux, Architecture.MIPS64 - | OS.Linux, Architecture.MIPS64R2 - | OS.Linux, Architecture.MIPS64R6 -> + | OS.Linux, Architecture.MIPS32 | OS.Linux, Architecture.MIPS64 -> match num with | 1 -> MIPS.Register.R4 |> MIPS.Register.toRegID | 2 -> MIPS.Register.R5 |> MIPS.Register.toRegID @@ -149,8 +121,8 @@ let syscallArgRegister hdl num = | _ -> Utils.futureFeature () [] -let functionArgRegister hdl num = - match hdl.OS, hdl.ISA.Arch with +let functionArgRegister (hdl: BinHandle) os num = + match os, hdl.File.ISA.Arch with | OS.Windows, Architecture.IntelX86 -> (* fast call *) match num with | 1 -> Intel.Register.ECX |> Intel.Register.toRegID @@ -175,14 +147,14 @@ let functionArgRegister hdl num = | _ -> Utils.futureFeature () [] -let isNonVolatile hdl rid = - match hdl.OS, hdl.ISA.Arch with - | OS.Linux, Arch.IntelX86 -> (* CDECL *) +let isNonVolatile (hdl: BinHandle) os rid = + match os, hdl.File.ISA.Arch with + | OS.Linux, Architecture.IntelX86 -> (* CDECL *) rid = (Intel.Register.EBP |> Intel.Register.toRegID) || rid = (Intel.Register.EBX |> Intel.Register.toRegID) || rid = (Intel.Register.ESI |> Intel.Register.toRegID) || rid = (Intel.Register.EDI |> Intel.Register.toRegID) - | OS.Linux, Arch.IntelX64 -> (* CDECL *) + | OS.Linux, Architecture.IntelX64 -> (* CDECL *) rid = (Intel.Register.RBX |> Intel.Register.toRegID) || rid = (Intel.Register.RSP |> Intel.Register.toRegID) || rid = (Intel.Register.RBP |> Intel.Register.toRegID) @@ -190,7 +162,7 @@ let isNonVolatile hdl rid = || rid = (Intel.Register.R13 |> Intel.Register.toRegID) || rid = (Intel.Register.R14 |> Intel.Register.toRegID) || rid = (Intel.Register.R15 |> Intel.Register.toRegID) - | OS.Linux, Arch.ARMv7 -> (* EABI *) + | OS.Linux, Architecture.ARMv7 -> (* EABI *) rid = (ARM32.Register.R4 |> ARM32.Register.toRegID) || rid = (ARM32.Register.R5 |> ARM32.Register.toRegID) || rid = (ARM32.Register.R6 |> ARM32.Register.toRegID) @@ -198,7 +170,7 @@ let isNonVolatile hdl rid = || rid = (ARM32.Register.R8 |> ARM32.Register.toRegID) || rid = (ARM32.Register.SL |> ARM32.Register.toRegID) || rid = (ARM32.Register.FP |> ARM32.Register.toRegID) - | OS.Linux, Arch.AARCH64 -> (* EABI *) + | OS.Linux, Architecture.AARCH64 -> (* EABI *) rid = (ARM64.Register.X19 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X20 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X21 |> ARM64.Register.toRegID) @@ -210,17 +182,7 @@ let isNonVolatile hdl rid = || rid = (ARM64.Register.X27 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X28 |> ARM64.Register.toRegID) || rid = (ARM64.Register.X29 |> ARM64.Register.toRegID) - | OS.Linux, Arch.MIPS1 - | OS.Linux, Arch.MIPS2 - | OS.Linux, Arch.MIPS3 - | OS.Linux, Arch.MIPS32 - | OS.Linux, Arch.MIPS32R2 - | OS.Linux, Arch.MIPS32R6 - | OS.Linux, Arch.MIPS4 - | OS.Linux, Arch.MIPS5 - | OS.Linux, Arch.MIPS64 - | OS.Linux, Arch.MIPS64R2 - | OS.Linux, Arch.MIPS64R6 -> + | OS.Linux, Architecture.MIPS32 | OS.Linux, Architecture.MIPS64 -> rid = (MIPS.Register.R16 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R17 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R18 |> MIPS.Register.toRegID) @@ -230,7 +192,7 @@ let isNonVolatile hdl rid = || rid = (MIPS.Register.R22 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R23 |> MIPS.Register.toRegID) || rid = (MIPS.Register.R30 |> MIPS.Register.toRegID) - | OS.Windows, Arch.IntelX64 -> (* Microsoft x64 *) + | OS.Windows, Architecture.IntelX64 -> (* Microsoft x64 *) rid = (Intel.Register.RBX |> Intel.Register.toRegID) || rid = (Intel.Register.RSP |> Intel.Register.toRegID) || rid = (Intel.Register.RBP |> Intel.Register.toRegID) diff --git a/src/FrontEnd/BinInterface/CallingConvention.fsi b/src/FrontEnd/Core/CallingConvention.fsi similarity index 90% rename from src/FrontEnd/BinInterface/CallingConvention.fsi rename to src/FrontEnd/Core/CallingConvention.fsi index 9e1847d8..e29e5cb9 100644 --- a/src/FrontEnd/BinInterface/CallingConvention.fsi +++ b/src/FrontEnd/Core/CallingConvention.fsi @@ -22,7 +22,7 @@ SOFTWARE. *) -module B2R2.FrontEnd.BinInterface.CallingConvention +module B2R2.FrontEnd.CallingConvention open B2R2 @@ -40,17 +40,17 @@ val syscallNumRegister: BinHandle -> RegisterID /// Obtain the register ID used for the nth syscall parameter. [] -val syscallArgRegister: BinHandle -> int -> RegisterID +val syscallArgRegister: BinHandle -> OS -> int -> RegisterID /// Obtain the register ID used for the nth function call parameter. Since /// actual calling convention may vary depending on the binaries, this function /// only returns a generally used register for the given architecture and the /// file format. [] -val functionArgRegister: BinHandle -> int -> RegisterID +val functionArgRegister: BinHandle -> OS -> int -> RegisterID /// Check if the given register is non-volatile register in the given binary. /// Non-volatile registers are preserved by callee, i.e., callee-saved /// registers. [] -val isNonVolatile: BinHandle -> RegisterID -> bool +val isNonVolatile: BinHandle -> OS -> RegisterID -> bool diff --git a/src/FrontEnd/Core/Helper.fs b/src/FrontEnd/Core/Helper.fs new file mode 100644 index 00000000..ea5f490d --- /dev/null +++ b/src/FrontEnd/Core/Helper.fs @@ -0,0 +1,178 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module internal B2R2.FrontEnd.Helper + +open System.Text +open B2R2 +open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinLifter + +/// Classify ranges to be either in-file or not-in-file. The second parameter +/// (notinfiles) is a sequence of (exclusive) ranges within the myrange, which +/// represent the not-in-file ranges. This function will simply divide the +/// myrange into subranges where each subrange is labeled with either true or +/// false, where true means in-file, and false means not-in-file. +let classifyRanges myrange notinfiles = + notinfiles + |> Seq.fold (fun (infiles, saddr) r -> + let l = AddrRange.GetMin r + let h = AddrRange.GetMax r + if saddr = l then (r, false) :: infiles, h + else (r, false) :: ((AddrRange (saddr, l), true) :: infiles), h + ) ([], AddrRange.GetMin myrange) + |> (fun (infiles, saddr) -> + if saddr = myrange.Max then infiles + else ((AddrRange (saddr, myrange.Max), true) :: infiles)) + |> List.rev + +let inline readIntBySize (r: IBinReader) (span: ByteSpan) size = + match size with + | 1 -> r.ReadInt8 (span, 0) |> int64 |> Ok + | 2 -> r.ReadInt16 (span, 0) |> int64 |> Ok + | 4 -> r.ReadInt32 (span, 0) |> int64 |> Ok + | 8 -> r.ReadInt64 (span, 0) |> Ok + | _ -> Error ErrorCase.InvalidMemoryRead + +let inline readUIntBySize (r: IBinReader) (span: ByteSpan) size = + match size with + | 1 -> r.ReadUInt8 (span, 0) |> uint64 |> Ok + | 2 -> r.ReadUInt16 (span, 0) |> uint64 |> Ok + | 4 -> r.ReadUInt32 (span, 0) |> uint64 |> Ok + | 8 -> r.ReadUInt64 (span, 0) |> Ok + | _ -> Error ErrorCase.InvalidMemoryRead + +let inline readASCII (file: IBinFile) offset = + let rec loop acc offset = + let b = file.ReadByte (offset=offset) + if b = 0uy then List.rev (b :: acc) |> List.toArray + else loop (b :: acc) (offset + 1) + loop [] offset + +let inline tryParseInstrFromAddr (file: IBinFile) parser addr = + try (parser: IInstructionParsable).Parse (file.Slice (addr=addr), addr) |> Ok + with _ -> Error ErrorCase.ParsingFailure + +let inline tryParseInstrFromBinPtr (file: IBinFile) p (ptr: BinFilePointer) = + try + let span = file.Slice ptr.Offset + let ins = (p :> IInstructionParsable).Parse (span, ptr.Addr) + if BinFilePointer.IsValidAccess ptr (int ins.Length) then Ok ins + else Error ErrorCase.ParsingFailure + with _ -> + Error ErrorCase.ParsingFailure + +let inline parseInstrFromBinPtr (file: IBinFile) parser (ptr: BinFilePointer) = + match tryParseInstrFromBinPtr file parser ptr with + | Ok ins -> ins + | Error _ -> raise ParsingFailureException + +let advanceAddr addr len = + addr + uint64 len + +let rec parseLoopByAddr file parser addr acc = + match tryParseInstrFromAddr file parser addr with + | Ok ins -> + if ins.IsBBLEnd () then Ok (List.rev (ins :: acc)) + else + let addr = addr + (uint64 ins.Length) + parseLoopByAddr file parser addr (ins :: acc) + | Error _ -> Error <| List.rev acc + +let inline parseBBLFromAddr (file: IBinFile) parser addr = + parseLoopByAddr file parser addr [] + +let rec parseLoopByPtr file parser ptr acc = + match tryParseInstrFromBinPtr file parser ptr with + | Ok (ins: Instruction) -> + if ins.IsBBLEnd () then Ok (List.rev (ins :: acc)) + else + let ptr = BinFilePointer.Advance ptr (int ins.Length) + parseLoopByPtr file parser ptr (ins :: acc) + | Error _ -> Error <| List.rev acc + +let inline parseBBLFromBinPtr (file: IBinFile) parser ptr = + parseLoopByPtr file parser ptr [] + +let rec liftBBLAux acc advanceFn trctxt addr = function + | (ins: Instruction) :: rest -> + let addr = advanceFn addr (int ins.Length) + liftBBLAux (ins.Translate trctxt :: acc) advanceFn trctxt addr rest + | [] -> struct (List.rev acc |> Array.concat, addr) + +let inline liftBBLFromAddr file parser trctxt addr = + match parseBBLFromAddr file parser addr with + | Ok bbl -> + let struct (stmts, addr) = liftBBLAux [] advanceAddr trctxt addr bbl + Ok (stmts, addr) + | Error bbl -> + let struct (stmts, addr) = liftBBLAux [] advanceAddr trctxt addr bbl + Error (stmts, addr) + +let inline liftBBLFromBinPtr file parser trctxt ptr = + match parseBBLFromBinPtr file parser ptr with + | Ok bbl -> + let struct (stmts, ptr) = + liftBBLAux [] BinFilePointer.Advance trctxt ptr bbl + Ok (stmts, ptr) + | Error bbl -> + let struct (stmts, ptr) = + liftBBLAux [] BinFilePointer.Advance trctxt ptr bbl + Error (stmts, ptr) + +let rec disasmBBLAux sb advanceFn showAddr reader addr = function + | (ins: Instruction) :: rest -> + let s = ins.Disasm (showAddr, reader) + let s = + if (sb: StringBuilder).Length = 0 then s + else System.Environment.NewLine + s + let addr = advanceFn addr (int ins.Length) + disasmBBLAux (sb.Append (s)) advanceFn showAddr reader addr rest + | [] -> struct (sb.ToString (), addr) + +let disasmBBLFromAddr file parser showAddr resolve addr = + let reader = if resolve then file :> INameReadable else null + match parseBBLFromAddr file parser addr with + | Ok bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) advanceAddr showAddr reader addr bbl + Ok (str, addr) + | Error bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) advanceAddr showAddr reader addr bbl + Error (str, addr) + +let disasmBBLFromBinPtr file parser showAddr resolve ptr = + let reader = if resolve then file :> INameReadable else null + match parseBBLFromBinPtr file parser ptr with + | Ok bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) + BinFilePointer.Advance showAddr reader ptr bbl + Ok (str, addr) + | Error bbl -> + let struct (str, addr) = + disasmBBLAux (StringBuilder ()) + BinFilePointer.Advance showAddr reader ptr bbl + Error (str, addr) diff --git a/src/FrontEnd/BinInterface/Parser.fs b/src/FrontEnd/Core/Parser.fs similarity index 56% rename from src/FrontEnd/BinInterface/Parser.fs rename to src/FrontEnd/Core/Parser.fs index 384fe7c0..8f65d279 100644 --- a/src/FrontEnd/BinInterface/Parser.fs +++ b/src/FrontEnd/Core/Parser.fs @@ -23,7 +23,7 @@ *) [] -module B2R2.FrontEnd.BinInterface.Parser +module B2R2.FrontEnd.Parser open B2R2 open B2R2.FrontEnd.BinLifter @@ -33,20 +33,30 @@ open B2R2.FrontEnd.BinLifter [] let init (isa: ISA) mode (entryPoint: Addr option) = match isa.Arch with - | Arch.IntelX64 - | Arch.IntelX86 -> Intel.IntelParser (isa.WordSize) :> Parser - | Arch.ARMv7 | Arch.AARCH32 -> - ARM32.ARM32Parser (isa, mode, entryPoint) :> Parser - | Arch.AARCH64 -> ARM64.ARM64Parser (isa) :> Parser - | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 - | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 - | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> - MIPS.MIPSParser (isa) :> Parser - | Arch.EVM -> EVM.EVMParser (isa) :> Parser - | Arch.TMS320C6000 -> TMS320C6000.TMS320C6000Parser () :> Parser - | Arch.CILOnly -> CIL.CILParser () :> Parser - | Arch.AVR -> AVR.AVRParser () :> Parser - | Arch.SH4 -> SH4.SH4Parser (isa) :> Parser - | Arch.PPC32 -> PPC32.PPC32Parser (isa) :> Parser - | Arch.RISCV64 -> RISCV.RISCV64Parser (isa) :> Parser - | _ -> Utils.futureFeature () + | Architecture.IntelX64 + | Architecture.IntelX86 -> + Intel.IntelParser (isa.WordSize) :> IInstructionParsable + | Architecture.ARMv7 | Architecture.AARCH32 -> + ARM32.ARM32Parser (isa, mode, entryPoint) :> IInstructionParsable + | Architecture.AARCH64 -> + ARM64.ARM64Parser (isa) :> IInstructionParsable + | Architecture.MIPS32 | Architecture.MIPS64 -> + MIPS.MIPSParser (isa) :> IInstructionParsable + | Architecture.EVM -> + EVM.EVMParser (isa) :> IInstructionParsable + | Architecture.TMS320C6000 -> + TMS320C6000.TMS320C6000Parser () :> IInstructionParsable + | Architecture.CILOnly -> + CIL.CILParser () :> IInstructionParsable + | Architecture.AVR -> + AVR.AVRParser () :> IInstructionParsable + | Architecture.SH4 -> + SH4.SH4Parser (isa) :> IInstructionParsable + | Architecture.PPC32 -> + PPC32.PPC32Parser (isa) :> IInstructionParsable + | Architecture.RISCV64 -> + RISCV.RISCV64Parser (isa) :> IInstructionParsable + | Architecture.SPARC -> + SPARC.SPARCParser (isa) :> IInstructionParsable + | _ -> + Utils.futureFeature () diff --git a/src/FrontEnd/BinInterface/README.md b/src/FrontEnd/Core/README.md similarity index 68% rename from src/FrontEnd/BinInterface/README.md rename to src/FrontEnd/Core/README.md index 628f7ab3..02678b9f 100644 --- a/src/FrontEnd/BinInterface/README.md +++ b/src/FrontEnd/Core/README.md @@ -1,4 +1,4 @@ -# B2R2.FrontEnd.BinInterface +# B2R2.FrontEnd.Core ### B2R2? @@ -6,8 +6,8 @@ B2R2 is a binary analysis and reversing framework written purely in F#. Since it does not rely on any native (unmanaged) code, it is readily usable in any platform or OS that .NET runs on. -### B2R2.FrontEnd.BinInterface Package? +### B2R2.FrontEnd.Core Package? -`B2R2.FrontEnd.BinInterface` is the main interface for B2R2's front-end. In most +`B2R2.FrontEnd.Core` is the main interface for B2R2's front-end. In most cases, it should suffice to import just this package because all the other front-end packages will be loaded by this one. diff --git a/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj b/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj index 4df6445d..34e702be 100644 --- a/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj +++ b/src/FrontEnd/NameMangling.Tests/B2R2.FrontEnd.NameMangling.Tests.fsproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/src/FrontEnd/NameMangling.Tests/ItaniumTests.fs b/src/FrontEnd/NameMangling.Tests/ItaniumTests.fs index a5708921..c9eefc52 100644 --- a/src/FrontEnd/NameMangling.Tests/ItaniumTests.fs +++ b/src/FrontEnd/NameMangling.Tests/ItaniumTests.fs @@ -34,183 +34,183 @@ type ItaniumTests () = member __.``ItaniumDemangler: Simple Function``() = let mangled = "_Z4funcibc" let result = "func(int, bool, char)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Simple Function, CV qualifiers 1 ``() = let mangled = "_Z4funcPKibPVc" let result = "func(int const*, bool, char volatile*)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Simple Function, CV qualifiers 2 ``() = let mangled = "_Z4funcPVKibPVKPc" let result = "func(int const volatile*, bool, char* const volatile*)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Simple Function, Reference qualifiers ``() = let mangled = "_Z4funcRibOVc" let result = "func(int&, bool, char volatile&&)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Simple Function, Qualifiers ``() = let mangled = "_Z4funcRVPVKPibOKPc" let result = "func(int* const volatile* volatile&, bool, char* const&&)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names``() = let mangled = "_ZN5first6second5thirdE" let result = "first::second::third" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names with arguments``() = let mangled = "_ZN5first6second5thirdEidb3arg" let result = "first::second::third(int, double, bool, arg)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Simple Templates``() = let mangled = "_Z9somethingI3argifE" let result = "something" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Template Arguments with qualifiers``() = let mangled = "_Z9somethingIPV3argRKiPVPfE" let result = "something" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Templates with return``() = let mangled = "_Z9somethingIPV3argRKiPVPfEPVibc" let result = "int volatile* something(bool, char)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Array Pointer``() = let mangled = "_Z4funcPA30_A40_Pi" let result = "func(int* (*) [30][40])" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Literals inside Template``() = let mangled = "_Z4funcILi42ELb3ELb0EE" let result = "func<42, true, false>" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names And Templates 1``() = let mangled = "_ZN4some3anyIibcE4funcE" let result = "some::any::func" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names And Templates 2``() = let mangled = "_ZN4some3anyI4arg1N4name5classEE4funcE" let result = "some::any::func" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names And Templates 3``() = let mangled = "_ZN5funcA5funcBI4arg1N5funcC5funcDI4arg2EE4arg3E5funcEE" let result = "funcA::funcB, arg3>::funcE" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names Constructors, Destructors 1``() = let mangled = "_ZN5funcA5funcBI4arg1icEC1E" let result = "funcA::funcB::funcB" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names Constructors, Destructors 2``() = let mangled = "_ZN5funcA5funcBI4arg1icE5funcCD1E" let result = "funcA::funcB::funcC::~funcC" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Names, Return and Arguments``() = let mangled = "_ZN5funcA5funcBI4arg1dsEERVK5funcCIiEPKbi" let result = "funcC const volatile& funcA::funcB\ (bool const*, int)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Function Pointers``() = let mangled = "_Z4funcPFicE" let result = "func(int (*)(char))" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Function Pointers``() = let mangled = "_Z4funcPFPFPFicEbEdE" let result = "func(int (*(*(*)(double))(bool))(char))" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Function Pointers with qualifiers``() = let mangled = "_Z4funcPKPFPrVPPFPFicEbEdE" let result = "func(int (*(** volatile __restrict__*(* const*)(double))(bool))(char))" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Binary Operator inside Templates``() = let mangled = "_ZN5funcA5funcB5funcCI4arg1EEi5funcDIXpl4arg24arg3EE" let result = "int funcA::funcB::funcC(funcD<(arg2)+(arg3)>)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Unary Operator inside Templates``() = let mangled = "_Z5funcAIRVPKiEPbN5funcB5funcCIXad5funcDIPcEEEE" let result = "bool* funcA(funcB::funcC<&(funcD)>)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Nested Expression inside Templates``() = let mangled = "_Z5funcAIXntaaLb42ELb0EEE" let result = "funcA" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Sx abbreviation 1``() = let mangled = "_ZNSo5funcA5funcBE" let result = "std::basic_ostream >::funcA::funcB" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Sx abbreviation 2``() = let mangled = "_ZSt5funcAIPiPrKP5funcBIPiEE" let result = "std::funcA* const __restrict__*>" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: General Substitution 1``() = let mangled = "_ZN5funcA5funcB5funcCIN5funcD5funcEEE5funcFES2_S4_" let result = "funcA::funcB::funcC::funcF(funcD, funcA::\ funcB::funcC)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: General Substitution 2``() = let mangled = "_Z5funcAPVKPKiRKbPV4arg1S0_S4_S5_" let result = "funcA(int const* const volatile*, bool const&, arg1 \ volatile*, int const*, bool const&, arg1)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Template Substitution``() = let mangled = "_Z5funcAI4arg1iPKb4arg2IcEEiT_T0_T2_" let result = "int funcA >\ (arg1, int, arg2)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Complex Test 1``() = @@ -219,7 +219,7 @@ type ItaniumTests () = let result = "__gnu_cxx::__normal_iterator*, \ std::vector, std::allocator\ > > >::__normal_iterator(std::pair* const&)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Complex Test 2``() = @@ -233,7 +233,7 @@ type ItaniumTests () = , std::allocator > > > const&, \ __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > > const&)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Complex Test 3``() = @@ -249,13 +249,13 @@ type ItaniumTests () = std::less, std::allocator > >*&, std::\ map, std::allocator > >*&)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: RTTI and Virtual Table``() = let mangled = "_ZTI14GTKFDIOManager" let result = "typeinfo for GTKFDIOManager" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Clone``() = @@ -263,7 +263,7 @@ type ItaniumTests () = "_ZN12wxAuiToolBar11OnRightDownER12wxMouseEvent.localalias.159" let result = "wxAuiToolBar::OnRightDown(wxMouseEvent&) [clone .localalias.159]" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Scope Encoding``() = @@ -273,7 +273,7 @@ type ItaniumTests () = let result = "wxBaseObjectArray::RemoveAt(unsigned long, unsigned long)::__FUNCTION__" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Member Pointer``() = @@ -282,7 +282,7 @@ type ItaniumTests () = let result = "wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)\ (wxEvent&), wxEvent&) const" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Anonymous namespace``() = @@ -292,7 +292,7 @@ type ItaniumTests () = let result = "wxPrivate::wxVectorComparator<(anonymous namespace)::wxAuiLayoutObject>\ ::Compare(void const*, void const*, void const*)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Scope Encoding: Return values``() = @@ -300,7 +300,7 @@ type ItaniumTests () = "_ZZ11wxCheckCastI18wxAuiMDIChildFrameEPT_PKvE12__FUNCTION__" let result = "wxCheckCast(void const*)::__FUNCTION__" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Guard Variables: Scope Encoding``() = @@ -311,13 +311,13 @@ type ItaniumTests () = "guard variable for (anonymous namespace)::ParseFormatAt(wxString::\ const_iterator&, wxString::const_iterator const&, wxString const&, \ wxString const&)::dtDef" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Scope Encoding: Discriminator values``() = let mangled = "_ZZL17wx_add_idle_hooksvE14hook_installed_0" let result = "wx_add_idle_hooks()::hook_installed" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: RTTI values: TC``() = @@ -325,7 +325,7 @@ type ItaniumTests () = let result = "construction vtable for std::basic_ostream \ >-in-wxStdOutputStream" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Pointer to Member Function as Argument``() = @@ -336,20 +336,20 @@ type ItaniumTests () = "OptionSet<(anonymous namespace)::OptionsBaan>::DefineProperty\ (char const*, bool (anonymous namespace)::OptionsBaan::*, std::__cxx11\ ::basic_string, std::allocator >)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: ABI Tags``() = let mangled = "_ZN8Document17TransformLineEndsB5cxx11EPKcmi" let result = "Document::TransformLineEnds[abi:cxx11](char const*, unsigned long, int)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Cast Operator``() = let mangled = "_ZNK21wxArgNormalizedStringcv8wxStringEv" let result = "wxArgNormalizedString::operator wxString() const" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Template Substitution, Repeating variables``() = @@ -361,7 +361,7 @@ type ItaniumTests () = double, double, double, double, double, double, double, double, double, \ double, double, double, double, double, double, double, double, double, \ double, double)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Argument Packs``() = @@ -388,7 +388,7 @@ type ItaniumTests () = OptionSet::Option> >, std::piecewise_construct_t const&, \ std::tuple, \ std::allocator >&&>&&, std::tuple<>&&) [clone .isra.74]" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Arrays``() = @@ -415,7 +415,7 @@ type ItaniumTests () = std::allocator, \ std::allocator > > > >, __gnu_cxx::__ops::_Iter_equals_val, std::random_access_iterator_tag)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Testing for Void 1``() = @@ -424,11 +424,11 @@ type ItaniumTests () = let result = "void wxPrivate::OnScopeExit >(wxObjScopeGuardImp\ l0&)" - test mangled result + testItanium mangled result [] member __.``ItaniumDemangler: Testing for Void 2``() = let mangled = "_ZN9wxPrivate11OnScopeExitI17wxScopeGuardImpl0IPFvvEEEEvRT_" let result = "void wxPrivate::OnScopeExit >\ (wxScopeGuardImpl0&)" - test mangled result + testItanium mangled result diff --git a/src/FrontEnd/NameMangling.Tests/MSTests.fs b/src/FrontEnd/NameMangling.Tests/MSTests.fs index 74fce164..ff5cb97b 100644 --- a/src/FrontEnd/NameMangling.Tests/MSTests.fs +++ b/src/FrontEnd/NameMangling.Tests/MSTests.fs @@ -33,159 +33,159 @@ type MSTests () = member __.``MSDemangler: Nesting Test with simple names and types``() = let mangled = "?dog@animal@life@@YAGHF_N@Z" let result = "unsigned short __cdecl life::animal::dog(int,short,bool)" - test mangled result + testMS mangled result [] member __.``MSDemangler: Pointer test``() = let mangled = "?something@@YAXHPAPAPAPAPAG@Z" let result = "void __cdecl something(int,unsigned short * * * * *)" - test mangled result + testMS mangled result [] member __.``MSDemangler: Simple template argument test``() = let mangled = "?xyz@?$abc@HPAX@@YAXXZ" let result = "void __cdecl abc::xyz(void)" - test mangled result + testMS mangled result [] member __.``MSDemangler: Nested Templates as type and as parent class``() = let mangled = "?xyz@?$abc@V?$something@H@@PAX@@YAXXZ" let result = "void __cdecl abc,void *>::xyz(void)" - test mangled result + testMS mangled result [] member __.``MSDemangler: A pointer to a complex Type mangled``() = let mangled = "??$abc@PAV?$def@H@@PAX@@" let result = "abc *,void *>" - test mangled result + testMS mangled result [] member __.``MSDemangler: A pointer to a complex type as parent class``() = let mangled = "?Something@?$abc@PAU?$def@H@@PAX@@YADHG@Z" let result = "char __cdecl abc *,void *>\ ::Something(int,unsigned short)" - test mangled result + testMS mangled result [] member __.``MSDemangler: A pointer to a function ``() = let mangled = "?something@@YAHP6ADD@Z@Z" let result = "int __cdecl something(char (__cdecl*)(char))" - test mangled result + testMS mangled result [] member __.``MSDemangler: A double pointer to a function``() = let mangled = "?something@@YAHPAP6ADD@Z@Z" let result = "int __cdecl something(char (__cdecl* *)(char))" - test mangled result + testMS mangled result [] member __.``MSDemangler: A nested complex type and template function``() = let mangled = "?something@?$abc@DV?$another@U?$def@H@@@@PAH@@YAHG@Z" let result = "int __cdecl abc>,int *>\ ::something(unsigned short)" - test mangled result + testMS mangled result [] member __.``MSDemangler: A special name function``() = let mangled = "??_G@QAFXD@Z" let result = "public: void __thiscall `scalar deleting destructor'(char)" - test mangled result + testMS mangled result [] member __.``MSDemangler: An RTTI code function ``() = let mangled = "??_R13AFD@37something@@QAGF@Z" let result = "public: short __stdcall something\ ::'RTTI Base Class Descriptor at (4,83,4,8)'()" - test mangled result + testMS mangled result [] - member __.``MSDemangler: A nested function mangled ``() = + member __.``MSDemangler: A nested function mangled``() = let mangled = "?abc@??abc@@YAXXZ@YAH_FJ@Z" let result = "int __cdecl `void __cdecl abc(void)'::abc(__int16,long)" - test mangled result + testMS mangled result [] - member __.``MSDemangler: Operator mangled ``() = + member __.``MSDemangler: Operator mangled``() = let mangled = "??_PC@YAD_F@Z" let result = "char __cdecl 'udt returning'operator->(__int16)" - test mangled result + testMS mangled result [] - member __.``MSDemangler: Enumerated type mangled ``() = + member __.``MSDemangler: Enumerated type mangled``() = let mangled = "?something@@YAW7?$this@HG@nest@@HG@Z" let result = "enum unsigned long nest::this \ __cdecl something(int,unsigned short)" - test mangled result + testMS mangled result [] - member __.``MSDemangler: Pointer to pointer mangled ``() = + member __.``MSDemangler: Pointer to pointer mangled``() = let mangled = "?something@@YAGQBQBPBPBPCG@Z" let result = "unsigned short __cdecl something\ (unsigned short volatile * const * const * const * const * const)" - test mangled result + testMS mangled result [] member __.``MSDemangler: Pointer and class mangled``() = let mangled = "?something@@YAGPAQAQAQAPAGHVthisClass@@@Z" let result = "unsigned short __cdecl something\ (unsigned short * * * * *,int,class thisClass)" - test mangled result + testMS mangled result [] - member __.``MSDemangler: Different type of pointer mangled with modifiers ``() = + member __.``MSDemangler: Different type of ptr mangled with modifiers``() = let mangled = "?something@@YAHQFIFFKF@Z" let result = "int __cdecl something\ (short volatile __unaligned __unaligned __unaligned * __restrict const)" - test mangled result + testMS mangled result [] - member __.``MSDemangler: Simple name back referencing mangled ``() = + member __.``MSDemangler: Simple name back referencing mangled``() = let mangled = "?something@nested@0@YAGFD@Z" let result = "unsigned short __cdecl something::\ nested::something(short,char)" - test mangled result + testMS mangled result [] - member __.`` MSDemangler: Deconstructor and number namespace mangled ``() = + member __.`` MSDemangler: Deconstructor and number namespace mangled``() = let mangled = "??1?$someting@GFG@?1somethingOther@@YADFG@Z" let result = "char __cdecl somethingOther::`2'::someting::~someting\ (short,unsigned short)" - test mangled result + testMS mangled result [] - member __.`` MSDemangler: Function return type modifier mangled ``() = + member __.`` MSDemangler: Function return type modifier mangled``() = let mangled = "?something@@YA?EFFEEICDJK@Z" let result = "char volatile __unaligned __unaligned __ptr64 \ __ptr64 __ptr64 __restrict __cdecl something(long,unsigned long)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Rvalue Reference mangled to a complex type ``() = let mangled = "?abc@@YAD$$QEFAV?$soemthing@D@@@Z" let result = "char __cdecl abc(class soemthing \ __unaligned && __ptr64)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Tuple as a template arguement``() = let mangled = "??$abc@$G5ABC@HGD@@other@@YADGH@Z" let result = "char __cdecl other::abc<{6,18,1891}>(unsigned short,int)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Mangled String as a templateArguement``() = let mangled = "??$abc@$1?somethign@@YADF@Z@other@@YADGH@Z" let result = "char __cdecl other::abc<&char __cdecl \ somethign(short) >(unsigned short,int)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Constructor check``() = let mangled = "??0?$abc@_J@something@@YADFG@Z" let result = "char __cdecl something::abc<__int64>::\ abc<__int64>(short,unsigned short)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Name Back Referencing update check``() = @@ -196,91 +196,92 @@ type MSTests () = char_traits>::operator<<(class std::basic_ostream> & (__cdecl*)(class std::basic_ostream> &))" - test mangled result + testMS mangled result [] member __.``MSDemangler: Constructor in template and substitutions``() = - let mangled = "??$?0U?$default_delete@V_Facet_base@std@@@std@@$0A@@?$unique_\ + let mangled = + "??$?0U?$default_delete@V_Facet_base@std@@@std@@$0A@@?$unique_\ ptr@V_Facet_base@std@@U?$default_delete@V_Facet_base@std@@@2@@std@@QAE@\ PAV_Facet_base@1@@Z" let result = "public: __thiscall std::unique_ptr>::unique_ptr>,0>(class std::_Facet_base *)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: nested nameOnly inside a value(not a function)``() = let mangled = "?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" let result = "unsigned __int64 `__local_stdio_printf_options'::`2'\ ::_OptionsStorage" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Type Back Ref check``() = let mangled = "?something@@YADV?$defType@D@std@@PAF0@Z" let result = "char __cdecl something(class std::defType,short *,\ class std::defType)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Variable modifier check (not function) ``() = let mangled = "??_R4_Facet_base@std@@6B@" let result = "const std::_Facet_base::'RTTI Complete Object Locator'" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Function pointer as a return Type check``() = let mangled = "?thisTest4@@YAPBPAP6ADD@Z@Z" let result = "char (__cdecl* * const * __cdecl thisTest4())(char)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Function pointer returning function check``() = let mangled = "?thisTest4@@YADPBPAP6AP7EF_KDD@Z@Z@Z" let result = "char __cdecl thisTest4(short (__thiscall*(__cdecl* * const *)\ ())(unsigned __int64,char,char))" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Array Type check``() = let mangled = "?something@@YAD_OEEEB_OB_OAH@Z" let result = "char __cdecl something(int const __ptr64 __ptr64 __ptr64[]\ [][])" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Pointer to an Array type check``() = let mangled = "?swapcol@@YAXPAY2DC@HHHH@HHH@D@Z" let result = "void __cdecl swapcol(char (*)[50][30583][1911])" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Ignored __based cvModifier``() = let mangled = "?something@@YADPM5G@Z" let result = "char __cdecl something(unsigned short)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: __based cvModified pointer to name ``() = let mangled = "?something@@YADPM2something@nested@@G@Z" let result = "char __cdecl something(unsigned short __based(nested::\ something)*)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: cvModified pointer to a member ``() = let mangled = "?something@@YADFQQfunc@parent@@_K@Z" let result = "char __cdecl something(short,unsigned __int64 parent::\ func::* const)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Function pointer with ignored pointer types ``() = let mangled = "?something@@QEADPAQEEEAPAQ6CDH@Z@Z" let result = "public: char (__pascal* * * __ptr64 __ptr64 __ptr64 * \ __pascal something() __ptr64)(int)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Substitution check for extended types ``() = @@ -288,19 +289,19 @@ type MSTests () = let result = "void __cdecl func(std::nullptr_t,bool,int (__cdecl* * const \ volatile *)(int,std::nullptr_t),int (__cdecl*)(std::nullptr_t),class std::\ someother,bool)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Return type operator updated``() = let mangled = "??Bstd@netbase@@YADF@Z" let result = "__cdecl netbase::std::operator char(short)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Mangled string constant``() = let mangled = "??_C@_0O@EMEFIAMJ@?6Enter?5data?3?5@" let result = "`string'" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Different access level data test``() = @@ -308,21 +309,21 @@ type MSTests () = @@2PBVfacet@locale@1@B" let result = "public: static class _Facetptr>::\ locale::facet const * const std::_Facetptr>::_Psave" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Dynamic special Name bug test``() = let mangled = "??__E?ms_classInfo@wxAuiToolBar@@2VwxClassInfo@@A@@YAXXZ" let result = "void __cdecl `dynamic initializer for 'public: static class \ wxClassInfo wxAuiToolBar::ms_classInfo''(void)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Dynamic special Name bug test 2``() = let mangled = "??__EwxEVT_AUITOOLBAR_TOOL_DROPDOWN@@YAXXZ" let result = "void __cdecl `dynamic initializer for 'wxEVT_AUITOOLBAR_TOOL\ _DROPDOWN''(void)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Member function pointer bug test``() = @@ -333,21 +334,21 @@ type MSTests () = xEventFunctorMethod,class wxEvtHand\ ler,class wxEvent,class wxEvtHandler>::GetEvtMethod(void) const)(class wxEv\ ent &)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Thunk adjustor Function check``() = let mangled = "??_EwxSizer@@X7BAPAXI@Z" let result = "[thunk]:public: virtual void * __cdecl wxSizer::`vector \ deleting destructor'`adjustor{8}'(unsigned int) const" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Anonymous namespace check``() = let mangled = "?MergeLayout@wxAuiLayoutObject@?A0x7605e013@@QAEXABV12@@Z" let result = "public: void __thiscall `anonymous namespace'::wxAuiLayoutOb\ ject::MergeLayout(class A0x7605e013::wxAuiLayoutObject const &)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Function pointer substitution bug test``() = @@ -360,7 +361,7 @@ type MSTests () = int>>(class wxScopeGuardImpl3 &)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Dynamic special name on value bug check``() = @@ -369,14 +370,14 @@ type MSTests () = let result = "void __cdecl `dynamic atexit destructor for 'private: static \ struct wxEventTableEntry const * const wxAuiToolBar::sm_eventTableEntries''\ (void)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Incomplete function parameter pack check``() = let mangled = "?DoPrintfWchar@wxString@@AAAHPB_WZZ" let result = "private: int __cdecl wxString::DoPrintfWchar(wchar_t const \ *,...)" - test mangled result + testMS mangled result [] member __.`` MSDemangler: ReturnType operator and member pointer check``() = @@ -385,14 +386,14 @@ type MSTests () = let result = "public: __thiscall wxScopedPtr::\ operator class wxAnyValueTypeGlobals * (__thiscall wxScopedPtr::*)(void)const (void) const" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Thunk flat Function check``() = let mangled = "??_9wxMarkupParserOutput@@$B7AE" let result = "[thunk]: __thiscall wxMarkupParserOutput::`vcall'{8,{flat}}\ ' }'" - test mangled result + testMS mangled result [] member __.`` MSDemangler: Thunk vtor disp check``() = @@ -401,6 +402,6 @@ type MSTests () = let result = "[thunk]:public: virtual void * __thiscall std::basic_ofstream\ >::`vector deleting destructor'\ `vtordisp{4294967292,0}'(unsigned int)" - test mangled result + testMS mangled result diff --git a/src/FrontEnd/NameMangling.Tests/TestLib.fs b/src/FrontEnd/NameMangling.Tests/TestLib.fs index aee8f81f..d37b4f67 100644 --- a/src/FrontEnd/NameMangling.Tests/TestLib.fs +++ b/src/FrontEnd/NameMangling.Tests/TestLib.fs @@ -27,7 +27,15 @@ module B2R2.FrontEnd.NameMangling.Tests.TestLib open B2R2.FrontEnd.NameMangling open Microsoft.VisualStudio.TestTools.UnitTesting -let test mangled demangled = - match Demangler.demangle mangled with +let private testResult mangled demangled (demangler: IDemanglable) = + match demangler.Demangle mangled with | Ok result -> Assert.AreEqual (demangled, result) - | Error _ -> failwith "Demangling failure." + | Error _ -> invalidOp "Demangling failure." + +let testMS mangled demangled = + MSDemangler () :> IDemanglable + |> testResult mangled demangled + +let testItanium mangled demangled = + ItaniumDemangler () :> IDemanglable + |> testResult mangled demangled diff --git a/src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj b/src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj index ff436ddd..5c120ba3 100644 --- a/src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj +++ b/src/FrontEnd/NameMangling/B2R2.FrontEnd.NameMangling.fsproj @@ -1,4 +1,4 @@ - + LICENSE.md @@ -8,7 +8,8 @@ - + + @@ -25,6 +26,10 @@ + + + + diff --git a/src/FrontEnd/NameMangling/Demangle.fs b/src/FrontEnd/NameMangling/Demangle.fs index f1f20ba2..c3dfa587 100644 --- a/src/FrontEnd/NameMangling/Demangle.fs +++ b/src/FrontEnd/NameMangling/Demangle.fs @@ -24,17 +24,9 @@ SOFTWARE. namespace B2R2.FrontEnd.NameMangling -[] module Demangler = [] let detect str = if MSDemangler.IsWellFormed str then MSMangler elif ItaniumDemangler.IsWellFormed str then ItaniumMangler else UnknownMangler - - [] - let demangle str = - match detect str with - | MSMangler -> MSDemangler().Run str - | ItaniumMangler -> ItaniumDemangler().Run str - | UnknownMangler-> Error InvalidFormat diff --git a/src/FrontEnd/NameMangling/DemangleTypes.fs b/src/FrontEnd/NameMangling/DemangleTypes.fs deleted file mode 100644 index 4111521a..00000000 --- a/src/FrontEnd/NameMangling/DemangleTypes.fs +++ /dev/null @@ -1,50 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.FrontEnd.NameMangling - -/// Name mangling schemes. -type ManglingScheme = - /// Microsoft Visual C++ name mangling. - | MSMangler - /// Itanium CXX name mangling scheme used by GCC 3.x and higher, Clang 1.x and - /// higher. - | ItaniumMangler - /// Unknown mangling scheme. - | UnknownMangler - -/// Demangler error types. -type DemanglerError = - /// Unknown demangled string format encountered. - | InvalidFormat - /// Parsing failed in the middle. - | ParsingFailure - /// Parsing didn't consume all the string; there is/are trailing char(s). - | TrailingChars - -/// The main demangler interface. -[] -type Demangler () = - /// Take a string as input and return a demangled string as output. - abstract Run: string -> Result diff --git a/src/MiddleEnd/ControlFlowGraph/ControlFlowGraph.fs b/src/FrontEnd/NameMangling/IDemanglable.fs similarity index 82% rename from src/MiddleEnd/ControlFlowGraph/ControlFlowGraph.fs rename to src/FrontEnd/NameMangling/IDemanglable.fs index c776a969..1e9bd66c 100644 --- a/src/MiddleEnd/ControlFlowGraph/ControlFlowGraph.fs +++ b/src/FrontEnd/NameMangling/IDemanglable.fs @@ -22,12 +22,11 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.ControlFlowGraph +namespace B2R2.FrontEnd.NameMangling -open B2R2.MiddleEnd.BinGraph +open B2R2 -type ControlFlowGraph<'D, 'E when 'D :> BasicBlock and 'D : equality> - (core: GraphCore<'D, 'E, DiGraph<'D, 'E>>) = - inherit DiGraph<'D, 'E> (core) - -// vim: set tw=80 sts=2 sw=2: +/// The main demangler interface. +type IDemanglable = + /// Take a string as input and return a demangled string as output. + abstract Demangle: string -> Result diff --git a/src/FrontEnd/NameMangling/ItaniumDemangler.fs b/src/FrontEnd/NameMangling/ItaniumDemangler.fs index b981d6d4..ab8f1d1a 100644 --- a/src/FrontEnd/NameMangling/ItaniumDemangler.fs +++ b/src/FrontEnd/NameMangling/ItaniumDemangler.fs @@ -26,12 +26,11 @@ namespace B2R2.FrontEnd.NameMangling open FParsec open System +open B2R2 open B2R2.FrontEnd.NameMangling.ItaniumTables open B2R2.FrontEnd.NameMangling.ItaniumUtils type ItaniumDemangler () = - inherit Demangler () - let charListtoStr a = String (List.toArray a) let rec convertbase36todecimal idx res input = @@ -92,7 +91,7 @@ type ItaniumDemangler () = |>> Vendor let builtinsingle = - satisfy (fun c -> if (getTypeS c <>"") then true else false) + satisfy (fun c -> getTypeS c <> "") |>> string |>> BuiltinTypeIndicator.ofString let builtindouble = @@ -498,17 +497,17 @@ type ItaniumDemangler () = |>> FunctionBegin do - pTemplateref := - saveandreturn ( - ((attempt pABITag <|> name <|> attempt psxname <|> pOperator - <|> attempt pSxoperator <|> attempt pConsOrDes) >>= addtoNamelist - <|> attempt pSxsubstitution <|> namebackrefS <|> (namebackrefT)) - .>> clearCarry .>> pchar 'I' .>>. (pIarguments) .>> pchar 'E' - >>= checkBeginning - |>> Template - ) - - pNestedNameref := + pTemplateref.Value <- + saveandreturn ( + ((attempt pABITag <|> name <|> attempt psxname <|> pOperator + <|> attempt pSxoperator <|> attempt pConsOrDes) >>= addtoNamelist + <|> attempt pSxsubstitution <|> namebackrefS <|> (namebackrefT)) + .>> clearCarry .>> pchar 'I' .>>. (pIarguments) .>> pchar 'E' + >>= checkBeginning + |>> Template + ) + + pNestedNameref.Value <- pchar 'N' >>. (pCVR <|> preturn (Name "")) .>>. (attempt (pNestedBeginning) @@ -518,13 +517,13 @@ type ItaniumDemangler () = |>> fun (a, (b, c)) -> (a, b :: c) |>> NestedName - pPointerArgref := + pPointerArgref.Value <- (pstring "P" .>>. (opt (pRCVqualifier <|> pCVqualifier) ) .>>. (pNormalArg <|> pLambda <|> pUnnamedType <|> pDecltype)) |>> (fun ((a, b), c) -> (a, b, c)) |>> PointerArg >>= addargumenttolist .>> clearCarry - pfuncref := + pfuncref.Value <- ((nparse <|> pReference) <|> preturn (Name "")) .>>. (opt pCVqualifier) .>> pchar 'F' .>>. pFunctionArg .>>. pArguments .>> pchar 'E' @@ -532,18 +531,18 @@ type ItaniumDemangler () = |>> FunctionPointer >>= addfunctionptolist .>> clearCarry - prefArgref := + prefArgref.Value <- pReferenceArg .>>. (attempt pNormalArg <|> pfunc <|> pLambda <|> pDecltype) |>> RefArg >>= addargumenttolist - pExpressionRef := + pExpressionRef.Value <- attempt pBinaryExpr <|> attempt pUnaryExpr <|> attempt pCallExpr <|> attempt pConversionOneArg <|> pDotExpr <|> pDotPointerExpr <|> pConversionMoreArg <|> pCastingExpr <|> pTypeMeasure <|> pExprMeasure <|> pExpressionArgPack - scopeEncodingref := + scopeEncodingref.Value <- pchar 'Z' >>. (attempt pFunctionRetArgs <|> scopeEncoding <|> namebackrefS <|> attempt pGuardVariable <|> pTransactionSafeFunc @@ -551,7 +550,7 @@ type ItaniumDemangler () = <|> (attempt pVirtualThunk <|> attempt pVirtualThunkRet) <|> pTC ) .>> pchar 'E' |>> Scope - stmtref := + stmtref.Value <- attempt pGuardVariable <|> pReferenceTemporary <|> pTransactionSafeFunc <|> attempt pRTTiVirtualTable @@ -559,15 +558,16 @@ type ItaniumDemangler () = <|> attempt (pScope .>> pDiscard) <|> attempt (pFunctionRetArgs) - override __.Run str = - match runParserOnString (stmt) ItaniumUserState.Default "" str[2..] with - | Success (result, _, pos) -> - if pos.Column = int64(str.Length) - 1L then - Result.Ok <| ItaniumInterpreter.interpret result - else Result.Error TrailingChars - | Failure (e, _, _) -> - Result.Error ParsingFailure - /// Check if the given string is a well-formed mangled string. static member IsWellFormed (str: string) = str.Length > 2 && str[0 .. 1] = "_Z" + + interface IDemanglable with + member __.Demangle str = + match runParserOnString (stmt) ItaniumUserState.Default "" str[2..] with + | Success (result, _, pos) -> + if pos.Column = int64(str.Length) - 1L then + Result.Ok <| ItaniumInterpreter.interpret result + else Result.Error ErrorCase.ParsingFailure (* Didn't consume all. *) + | Failure (e, _, _) -> + Result.Error ErrorCase.ParsingFailure diff --git a/src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs b/src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs index a6a14e1a..0ca1ecf4 100644 --- a/src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs +++ b/src/FrontEnd/NameMangling/ItaniumFunctionPointer.fs @@ -63,13 +63,13 @@ let rec getList input index result = if index >= len then result else - let first, new_idx = getArgs input (index + 1) 1 "(" - let second, n_idx = getArgs input (new_idx + 1) 1 "(" - if n_idx < len && (input[n_idx + 1] = 'c' || input[n_idx + 1] = 'v') then - let a1, a2 = getQualifier input (n_idx + 1) + let first, nIdx = getArgs input (index + 1) 1 "(" + let second, nIdx = getArgs input (nIdx + 1) 1 "(" + if nIdx < len && (input[nIdx + 1] = 'c' || input[nIdx + 1] = 'v') then + let a1, a2 = getQualifier input (nIdx + 1) getList input (a2 + 1) ((second + " " + a1) :: first :: result) else - getList input (n_idx + 1) (second :: first :: result) + getList input (nIdx + 1) (second :: first :: result) /// Getting return and argument list. let getReturnList input = @@ -88,9 +88,9 @@ let rec combine input cur res = combine tail len (res + hd1 + hd2) else let len = (String.length hd1) - 1 - let other_len = String.length res + let otherLen = String.length res let result = - res[0 .. (cur)] + hd1 + hd2 + res[(cur + 1) .. other_len - 1] + res[0 .. (cur)] + hd1 + hd2 + res[(cur + 1) .. otherLen - 1] combine tail (cur + len) result | _ -> ("", 0) @@ -102,16 +102,16 @@ let rec getPointers input cur res flag = match d with | [] -> res | hd :: tail -> - let new_cur = hd :: cur - let new_begin = FunctionBegin (Some [], Pointer new_cur) - let new_item = FunctionPointer (new_begin, k, b, c) - let next_begin = FunctionBegin (Some [], Pointer tail) - let next_item = FunctionPointer (next_begin, k, b, c) + let newCur = hd :: cur + let newBegin = FunctionBegin (Some [], Pointer newCur) + let newItem = FunctionPointer (newBegin, k, b, c) + let nextBegin = FunctionBegin (Some [], Pointer tail) + let nextItem = FunctionPointer (nextBegin, k, b, c) if flag = 1 then let help = FunctionPointer (Name "", k, b, c) - getPointers next_item (new_cur) (new_item :: help :: res) 0 + getPointers nextItem (newCur) (newItem :: help :: res) 0 else - getPointers next_item (new_cur) (new_item :: res) 0 + getPointers nextItem (newCur) (newItem :: res) 0 | _ -> res /// Seperating pointers associated with qualifiers. @@ -123,14 +123,14 @@ let rec getQualifierandP input cur res = match p with | [] -> res | hd :: tail2 -> - let new_cur = hd :: cur - let new_value = ConstVolatile (Pointer new_cur, dis) :: tail1 - let new_begin = FunctionBegin (Some new_value, d) - let new_item = FunctionPointer (new_begin, k, b, c) - let next_value = ConstVolatile (Pointer tail2, dis) :: tail1 - let next_begin = FunctionBegin (Some next_value, d) - let next_item = FunctionPointer (next_begin, k, b, c) - getQualifierandP (next_item) (new_cur) (new_item :: res) + let newCur = hd :: cur + let newValue = ConstVolatile (Pointer newCur, dis) :: tail1 + let newBegin = FunctionBegin (Some newValue, d) + let newItem = FunctionPointer (newBegin, k, b, c) + let nextValue = ConstVolatile (Pointer tail2, dis) :: tail1 + let nextBegin = FunctionBegin (Some nextValue, d) + let nextItem = FunctionPointer (nextBegin, k, b, c) + getQualifierandP (nextItem) (newCur) (newItem :: res) | _ -> res /// Applying previous function for every element in the list part of @@ -141,16 +141,16 @@ let rec merge input cur res = match List.rev value with | [] -> res | ConstVolatile (Pointer p, dis) :: tail1 -> - let new_value = ConstVolatile (Pointer [], dis) :: cur - let new_begin = FunctionBegin (Some new_value, d) - let new_res = FunctionPointer(new_begin, k, b, c) :: res - let new_cur = ConstVolatile (Pointer p, dis) :: cur - let next_begin = FunctionBegin (Some new_cur, d) - let next_input = FunctionPointer (next_begin, k, b, c) - let result = getQualifierandP next_input [] new_res - let last_begin = FunctionBegin (Some (List.rev tail1), d) - let last_item = FunctionPointer(last_begin, k, b, c) - merge last_item new_cur (result) + let newValue = ConstVolatile (Pointer [], dis) :: cur + let newBegin = FunctionBegin (Some newValue, d) + let newRes = FunctionPointer(newBegin, k, b, c) :: res + let newCur = ConstVolatile (Pointer p, dis) :: cur + let nextBegin = FunctionBegin (Some newCur, d) + let nextInput = FunctionPointer (nextBegin, k, b, c) + let result = getQualifierandP nextInput [] newRes + let lastBegin = FunctionBegin (Some (List.rev tail1), d) + let lastItem = FunctionPointer(lastBegin, k, b, c) + merge lastItem newCur (result) | _ -> res | _ -> res diff --git a/src/FrontEnd/NameMangling/ItaniumInterpreter.fs b/src/FrontEnd/NameMangling/ItaniumInterpreter.fs index fed524a6..efa93d08 100644 --- a/src/FrontEnd/NameMangling/ItaniumInterpreter.fs +++ b/src/FrontEnd/NameMangling/ItaniumInterpreter.fs @@ -30,24 +30,15 @@ open B2R2.FrontEnd.NameMangling.ItaniumFunctionPointer let rec interpret (input: ItaniumExpr) = match input with | Name (x) -> x - | ABITag (a, b) -> a + "[abi:" + b + "]" - | Sxsubstitution sx -> Sxabbreviation.toString sx - | Sxname (a, b) -> interpret a + "::" + interpret b - | Sxoperator (a, b) -> interpret a + "::" + interpret b - | Reference a -> ReferenceQualifier.toString a - | CVR (cvqualifier, refqualifier) -> interpret cvqualifier + interpret refqualifier - | Restrict a -> RestrictQualifier.toString a - | CVqualifier a -> ConsTandVolatile.toString a - | PointerArg (a, None, arg) -> let a = if (a = "") then "" else "*" match arg with @@ -59,9 +50,15 @@ let rec interpret (input: ItaniumExpr) = | Some value -> interpret value | None -> "" let retandargs = - interpret a2 + - " (" + interpret a1 + a + ")" + - "(" + args + ")" + qualifier + interpret a2 + + " (" + + interpret a1 + + a + + ")" + + "(" + + args + + ")" + + qualifier let ret, arglist = getReturnList retandargs let final, _ = combine (List.rev arglist) 0 "" ret + " " + final @@ -69,7 +66,6 @@ let rec interpret (input: ItaniumExpr) = | _ -> let a = if (a = "") then "" else "*" interpret arg + a - | PointerArg (a, Some cvqualifier, arg) -> let a = if (a = "") then "" else "*" match arg with @@ -81,63 +77,61 @@ let rec interpret (input: ItaniumExpr) = | Some value -> interpret value | None -> "" let retandargs = - interpret a2 + - " (" + interpret a1 + interpret cvqualifier + a + ")" + - "(" + args + ")" + qualifier + interpret a2 + + " (" + + interpret a1 + + interpret cvqualifier + + a + + ")" + + "(" + + args + + ")" + + qualifier let ret, arglist = getReturnList retandargs let final, _ = combine (List.rev arglist) 0 "" ret + " " + final | TemplateSub (c, _) -> interpret (PointerArg (a, Some cvqualifier, c)) - | _ -> - interpret arg + interpret cvqualifier + a - + | _ -> interpret arg + interpret cvqualifier + a | Arguments args -> let f = - List.fold ( - fun acc elem -> + List.fold + (fun acc elem -> let add = if (acc = "") then "" else ", " match elem with - | FunctionPointer (_, _, _, _) -> + | FunctionPointer _ -> let retandargs = interpret elem let ret, arglist = getReturnList retandargs let final, _ = combine (List.rev arglist) 0 "" acc + add + (ret + " " + final) | _ -> let elem = interpret elem - acc + add + elem) "" args - if f = "" then - f - elif f[f.Length - 1] = ' ' then - f[.. f.Length - 3] - else - f - - | Num x -> string(x) - - | Num64 x -> string(x) - + acc + add + elem) + "" + args + if f = "" then f + elif f[f.Length - 1] = ' ' then f[.. f.Length - 3] + else f + | Num x -> string (x) + | Num64 x -> string (x) | ReferenceArg (ref, None) -> interpret ref - | ReferenceArg (ref, Some cvqualifier) -> interpret cvqualifier + interpret ref - | SingleArg a -> match a with - | FunctionPointer (_, _, _, _) -> + | FunctionPointer _ -> let retandargs = interpret a let ret, arglist = getReturnList retandargs let final, _ = combine (List.rev arglist) 0 "" ret + " " + final | _ -> interpret a - | RefArg (ref, arg) -> match arg with - | Functionarg - (None, RefArg (ReferenceArg (Reference LValueReference, _), _)) -> - interpret arg - | Functionarg - (None, RefArg (ReferenceArg (Reference RvalueReference, _), _)) -> - interpret arg + | Functionarg (None, + RefArg (ReferenceArg (Reference LValueReference, _), _)) -> + interpret arg + | Functionarg (None, + RefArg (ReferenceArg (Reference RvalueReference, _), _)) -> + interpret arg | SingleArg a -> interpret (RefArg (ref, a)) | Functionarg (None, a) -> interpret (RefArg (ref, a)) | FunctionPointer (a1, k, a2, a3) -> @@ -148,23 +142,29 @@ let rec interpret (input: ItaniumExpr) = | Some value -> interpret value | None -> "" let retandargs = - interpret a2 + - " (" + interpret a1 + interpret ref + ")" + - "(" + args + ")" + qualifier + interpret a2 + + " (" + + interpret a1 + + interpret ref + + ")" + + "(" + + args + + ")" + + qualifier let ret, arglist = getReturnList retandargs let final, _ = combine (List.rev arglist) 0 "" ret + " " + final | ArrayPointer (Some value, a, b) -> let flag = interpret value let array = - List.fold (fun acc elem -> acc + "[" + interpret(elem) + "]") "" a + List.fold (fun acc elem -> acc + "[" + interpret (elem) + "]") "" a if flag[flag.Length - 1] = '&' then interpret b + " (" + flag + ") " + array else interpret b + " (" + flag + interpret ref + ") " + array | ArrayPointer (None, a, b) -> let array = - List.fold (fun acc elem -> acc + "[" + interpret(elem) + "]") "" a + List.fold (fun acc elem -> acc + "[" + interpret (elem) + "]") "" a match ref with | ReferenceArg (c, Some d) -> interpret b + interpret d + " (" + interpret c + ") " + array @@ -172,44 +172,29 @@ let rec interpret (input: ItaniumExpr) = | TemplateSub (a, _) -> interpret (RefArg (ref, a)) | _ -> let arg = interpret arg - if arg <> "" && arg[String.length arg - 1] = '&' then - arg - else - arg + interpret ref - + if arg <> "" && arg[String.length arg - 1] = '&' then arg + else arg + interpret ref | ConsOrDes a1 -> ConstructorDestructor.toChar a1 - | Literal (a, Num b) -> let a = interpret a - if a = "bool" && b<>0 then - "true" - elif a ="bool" then - "false" - elif a = "int" then - string(b) - elif a = "unsigned int" then - string(b) + "u" - elif a = "unsigned long" then - string(b) + "ul" - else - "(" + a + ")" + string(b) - + if a = "bool" && b <> 0 then "true" + elif a = "bool" then "false" + elif a = "int" then string (b) + elif a = "unsigned int" then string (b) + "u" + elif a = "unsigned long" then string (b) + "ul" + else "(" + a + ")" + string (b) | Literal (a, Num64 b) -> let a = interpret a - if a = "unsigned long" then - string(b) + "ul" - else - "(" + a + ")" + string(b) - + if a = "unsigned long" then string (b) + "ul" + else "(" + a + ")" + string (b) | Literal (a, b) -> let a = interpret a let b = interpret b "(" + a + ")" + b - | NestedName (a, namelist) -> let nestedname, _ = - List.fold ( - fun acc elem -> + List.fold + (fun acc elem -> let add = if (fst acc = "") then "" else "::" let idx = snd acc let prev = if (idx = 0) then Dummy "" else namelist[idx - 1] @@ -243,8 +228,14 @@ let rec interpret (input: ItaniumExpr) = let elem = interpret (ConsOrDes a) let help = interpret b let help = if (help[help.Length - 1] = '>') then (" >") else ">" - fst acc + add + elem + Sxabbreviation.get sx - + "<" + interpret b + help, (idx + 1) + fst acc + + add + + elem + + Sxabbreviation.get sx + + "<" + + interpret b + + help, + (idx + 1) | Template (ConsOrDes a, b), Template (c, _) -> let elem = interpret (ConsOrDes a) let prev = interpret c @@ -259,15 +250,16 @@ let rec interpret (input: ItaniumExpr) = fst acc + add + elem + prev + "<" + interpret b + help, (idx + 1) | _ -> let elem = interpret elem - if elem.Length >= 10 && elem[0 .. 9] = "_GLOBAL__N" then + if elem.Length >= 10 && elem[0..9] = "_GLOBAL__N" then fst acc + add + "(anonymous namespace)", (idx + 1) else - fst acc + add + elem, (idx + 1)) ("", 0) namelist + fst acc + add + elem, (idx + 1)) + ("", 0) + namelist match a with | CVR (c, Reference b) -> nestedname + interpret (c) + " " + interpret (Reference b) | _ -> nestedname + interpret a - | Template (name, tempargs) -> let help = interpret tempargs let name = interpret name @@ -277,30 +269,28 @@ let rec interpret (input: ItaniumExpr) = else let help = if (help[help.Length - 1] = '>') then (" >") else ">" name + helper + (interpret tempargs) + help - | Clone (exprlist) -> let a = List.fold (fun acc elem -> match elem with - | Name x -> - acc + "]" + " " + "[" + "clone ." + x + | Name x -> acc + "]" + " " + "[" + "clone ." + x | Num x -> - if acc = "" then acc + " [clone ." + string(x) - else acc + "." + string(x) - | _ -> acc) "" exprlist + if acc = "" then + acc + " [clone ." + string (x) + else + acc + "." + string (x) + | _ -> acc) + "" + exprlist if a = "" then "" elif a[0] = ']' then a[1 .. (String.length a) - 1] + "]" else a + "]" - | Function (scope, a, Name "", Name "", clone) -> let scope = List.fold (fun acc elem -> acc + interpret elem + "::") "" scope let clone = interpret clone - if clone = "" then - scope + interpret a - else - "not mangled properly" - + if clone = "" then scope + interpret a + else "not mangled properly" | Function (scope, a, ret, arglist, clone) -> let scope1 = List.fold (fun acc elem -> acc + interpret elem + "::") "" scope @@ -320,25 +310,30 @@ let rec interpret (input: ItaniumExpr) = elif ret <> Name "" then let args = if (args = "void") then "" else args match ret with - | FunctionPointer (_, _, _ , _) | - SingleArg (FunctionPointer (_, _, _, _)) | - Functionarg(_, SingleArg (FunctionPointer (_, _, _, _)))-> + | FunctionPointer _ + | SingleArg (FunctionPointer _) + | Functionarg (_, SingleArg (FunctionPointer _)) -> let funcpointer = interpret ret let returned, arguments = getReturnList funcpointer let all, index = combine (List.rev arguments) 0 "" let fullname = name + "(" + (args) + ")" + add let len = String.length all - let final = all[0 .. index] + fullname + all[(index + 1) .. len - 1] + let final = all[0..index] + fullname + all[(index + 1) .. len - 1] returned + " " + scope1 + final + interpret clone - | TemplateSub (a, _) -> - interpret (Function (scope, a, a, arglist, clone)) - | _-> - (interpret ret) + " " + scope1 + name + "(" + (args) + ")" + add + - interpret clone + | TemplateSub (a, _) -> interpret (Function (scope, a, a, arglist, clone)) + | _ -> + (interpret ret) + + " " + + scope1 + + name + + "(" + + (args) + + ")" + + add + + interpret clone else let args = if (args = "void") then "" else args scope1 + name + "(" + args + ")" + add + interpret clone - | UnaryExpr (a, b) -> let operator = interpret a let len = String.length operator @@ -351,201 +346,158 @@ let rec interpret (input: ItaniumExpr) = operator + "(" + b + ")" else operator + b - elif operator = "*" then - operator + interpret b - else - operator + "(" + interpret b + ")" - + elif operator = "*" then operator + interpret b + else operator + "(" + interpret b + ")" | BinaryExpr (a, b, c) -> let operator = interpret a let len = String.length operator let operator = operator[8 .. (len - 1)] - if operator = "::" then - interpret b + operator + interpret c - else - "(" + interpret b + ")" + operator + "(" + interpret c + ")" - + if operator = "::" then interpret b + operator + interpret c + else "(" + interpret b + ")" + operator + "(" + interpret c + ")" | Operators a -> "operator" + OperatorIndicator.toString a - | CastOperator (a, b) -> if a = "cv" || a = "v" then "operator " + interpret b else "operator\"\" " + interpret b - - | BuiltinType a-> BuiltinTypeIndicator.toString a - + | BuiltinType a -> BuiltinTypeIndicator.toString a | Pointer v -> List.fold (fun acc elem -> acc + interpret elem) "" v - | FunctionBegin (Some qualifiers, pointer) -> let p = interpret pointer let a2 = List.rev qualifiers let qualifier = List.fold (fun acc elem -> acc + interpret elem) "" a2 p + qualifier - | ConstVolatile (a, b) -> interpret b + interpret a - | FunctionPointer (pcv, Some value, ret, args) -> let args = interpret args let args = if (args = "void") then "" else args - interpret ret + " (" + interpret pcv + ")" + "(" + args + ")" + interpret ret + + " (" + + interpret pcv + + ")" + + "(" + + args + + ")" + interpret value - | FunctionPointer (pcv, None, ret, args) -> let args = interpret args let args = if (args = "void") then "" else args interpret ret + " (" + interpret pcv + ")" + "(" + args + ")" - | Vendor s -> s - | SingleP _ -> "*" - | ArrayPointer (None, a, b) -> let array = - List.fold (fun acc elem -> acc + "[" + interpret(elem) + "]") "" a + List.fold (fun acc elem -> acc + "[" + interpret (elem) + "]") "" a interpret b + " " + array - | ArrayPointer (Some value, a, b) -> let array = - List.fold (fun acc elem -> acc + "[" + interpret(elem) + "]") "" a + List.fold (fun acc elem -> acc + "[" + interpret (elem) + "]") "" a interpret b + " (" + interpret value + ") " + array - - | Functionarg (Some value, b) -> - interpret b + interpret value - + | Functionarg (Some value, b) -> interpret b + interpret value | Functionarg (None, a) -> match a with - | FunctionPointer (_, _, _, _) -> + | FunctionPointer _ -> let retandargs = interpret a let ret, arglist = getReturnList retandargs let final, _ = combine (List.rev arglist) 0 "" ret + " " + final | _ -> interpret a - | RTTIandVirtualTable (a, b) -> RTTIVirtualTable.toString a + interpret b - | CallOffset (a) -> CallOffSet.toString a - | VirtualThunk (a, b) -> interpret a + interpret b - | VirtualThunkRet a -> "covariant return thunk to " + interpret a - | ConstructionVtable (a, b) -> "construction vtable for " + interpret b + "-in-" + interpret a - | GuardVariable (a, b) -> let scope = List.fold (fun acc elem -> acc + interpret elem + "::") "" a "guard variable for " + scope + interpret b - | TransactionSafeFunction a -> "transaction clone for " + interpret a - | ReferenceTemporary (a, b) -> "reference temporary #" + interpret b + " for " + interpret a - - | ScopeEncoding (a, b) -> - interpret a + "::" + interpret b - + | ScopeEncoding (a, b) -> interpret a + "::" + interpret b | MemberPointer (a) -> interpret a + "::*" - | MemberPAsArgument (a, b) -> interpret b + " " + interpret a - | Scope a -> match a with | Function (a1, a2, _, a4, a5) -> let b = Function (a1, a2, Name "", a4, a5) interpret b | _ -> interpret a - | Vector (a, b) -> interpret b + " __vector(" + interpret a + ")" - | LambdaExpression (a, b) -> let num = interpret b - let num = if (num = "") then "1" else (string(int(num) + 2)) + let num = if (num = "") then "1" else (string (int (num) + 2)) let a = interpret a let a = if (a = "void") then ("") else a "{lambda(" + a + ")#" + num + "}" - | UnnamedType (a) -> let num = interpret a - let num = if (num = "") then "1" else (string(int(num) + 2)) + let num = if (num = "") then "1" else (string (int (num) + 2)) "{unnamed type#" + num + "}" - | ParameterRef a -> let num = interpret a - let num = if (num = "") then "1" else (string(int(num) + 2)) + let num = if (num = "") then "1" else (string (int (num) + 2)) "{parm#" + num + "}" - | ScopedLambda (a, Some value, b) -> let num = interpret value - let num = if (num = "") then "1" else (string(int(num) + 2)) + let num = if (num = "") then "1" else (string (int (num) + 2)) interpret a + "::" + "{default arg#" + num + "}::" + interpret b - | ScopedLambda (a, None, b) -> interpret a + "::" + interpret b - | ExternalName a -> match a with | Function (a1, a2, _, _, _) -> - let a2_t = interpret a2 - if a2_t.IndexOf("::") = -1 then - interpret a - else - interpret (Function (a1, a2, Name "", Name "", Name "")) + let a2t = interpret a2 + if a2t.IndexOf ("::") = -1 then interpret a + else interpret (Function (a1, a2, Name "", Name "", Name "")) | _ -> interpret a - | CallExpr a -> let first = a[0] - let rest = a[1 ..] + let rest = a[1..] let rest = List.fold (fun acc elem -> let add = if (acc = "") then "" else ", " - acc + add + interpret elem - ) "" rest + acc + add + interpret elem) + "" + rest let a = interpret first - if a.IndexOf('<') <> -1 || a.IndexOf('.') <> -1 then + if a.IndexOf ('<') <> -1 || a.IndexOf ('.') <> -1 then "(" + a + ")" + "(" + rest + ")" else a + "(" + rest + ")" - - | ConversionOne (a, b) -> - "(" + interpret a + ")" + interpret b - + | ConversionOne (a, b) -> "(" + interpret a + ")" + interpret b | ConversionMore (a, b) -> let rest = List.fold (fun acc elem -> let add = if (acc = "") then "" else ", " - acc + add + interpret elem - ) "" b + acc + add + interpret elem) + "" + b "(" + interpret a + ")" + "(" + rest + ")" - | DeclType a -> "decltype " + "(" + interpret a + ")" - | DotExpr (a, b) -> let first = interpret a - if first.IndexOf('.') <> -1 || first.IndexOf('(') <> -1 || - first.IndexOf('<') <> -1 then + if first.IndexOf ('.') <> -1 + || first.IndexOf ('(') <> -1 + || first.IndexOf ('<') <> -1 + then "(" + interpret a + ")" + "." + interpret b else interpret a + "." + interpret b - | DotPointerExpr (a, b) -> let first = interpret a - if first.IndexOf('.') <> -1 || first.IndexOf('(') <> -1 || - first.IndexOf('<') <> -1 || first.IndexOf('{') <> -1 then + if first.IndexOf ('.') <> -1 + || first.IndexOf ('(') <> -1 + || first.IndexOf ('<') <> -1 + || first.IndexOf ('{') <> -1 + then "(" + interpret a + ")" + ".*" + interpret b else interpret a + ".*" + interpret b - | CastingExpr (a, b, c) -> CasTing.toString a + "<" + interpret b + ">(" + interpret c + ")" - | TypeMeasure (a, b) -> MeasureType.toString a + "(" + interpret b + ")" - | ExprMeasure (a, b) -> MeasureExpr.toString a + "(" + interpret b + ")" - | TemplateSub (a, _) -> interpret (SingleArg (a)) - | ExpressionArgPack a -> interpret a - | Dummy _ -> "???" - | _ -> "" diff --git a/src/FrontEnd/NameMangling/ItaniumUtils.fs b/src/FrontEnd/NameMangling/ItaniumUtils.fs index 8867d1e9..4720f90e 100644 --- a/src/FrontEnd/NameMangling/ItaniumUtils.fs +++ b/src/FrontEnd/NameMangling/ItaniumUtils.fs @@ -137,7 +137,7 @@ let addTemplate expr = updateUserState (fun us -> match expr with - | Template (_, _) -> { us with Namelist = expr :: us.Namelist } + | Template _ -> { us with Namelist = expr :: us.Namelist } | _ -> us ) >>. preturn expr @@ -208,8 +208,8 @@ let addOnCondition expr = | RefArg (a, Arguments b) | RefArg (a, TemplateSub (Arguments b, _)) -> if b <> [] then let add = RefArg (a, b[b.Length - 1]) - let new_add = Arguments (addtoList a b []) - { us with Namelist = new_add :: add :: us.Namelist } + let newAdd = Arguments (addtoList a b []) + { us with Namelist = newAdd :: add :: us.Namelist } else { us with Namelist = Arguments b :: Name "" :: us.Namelist } | _ -> us @@ -270,8 +270,7 @@ let expandCL expr = | CallExpr a -> match a[0] with | Arguments arglist -> - let CLlist = Arguments (createCLexprs a.Tail arglist []) - preturn CLlist + Arguments (createCLexprs a.Tail arglist []) |> preturn | _ -> preturn expr | _ -> preturn expr @@ -287,7 +286,6 @@ let expandDT expr = | DotExpr (a, b) -> match a with | Arguments arglist -> - let DTlist = Arguments (createDTexprs b arglist []) - preturn DTlist + Arguments (createDTexprs b arglist []) |> preturn | _ -> preturn expr | _ -> preturn expr diff --git a/src/FrontEnd/NameMangling/MSDemangler.fs b/src/FrontEnd/NameMangling/MSDemangler.fs index 9c16af11..8e32079e 100644 --- a/src/FrontEnd/NameMangling/MSDemangler.fs +++ b/src/FrontEnd/NameMangling/MSDemangler.fs @@ -26,10 +26,10 @@ namespace B2R2.FrontEnd.NameMangling open System open FParsec +open B2R2 open B2R2.FrontEnd.NameMangling.MSUtils type MSDemangler () = - inherit Demangler () (* Helper functions for updating the UserState. *) let addToNameList c = updateUserState ( fun us -> { us with NameList = c :: us.NameList }) @@ -56,7 +56,7 @@ type MSDemangler () = let phex = many1 upper .>> pchar '@' |>> List.map getHexChar |>> List.map string - |>> List.fold (fun s d -> s + d) "0x" + |>> List.fold (+) "0x" |>> int64 /// Parses the encodedNumber in an MSMangled string. @@ -495,28 +495,28 @@ type MSDemangler () = (* -------------Tying the knot for the references created-----------------*) do - nameFragmentRef := + nameFragmentRef.Value <- nameBackRef <|> pnameAndAt <|> attempt pTemplate <|> attempt nestedFunc <|> attempt pRTTICode <|> attempt numName <|> pSpecialName <|> attempt constructedName - fullNameRef := + fullNameRef.Value <- smartParseName .>>. many (pAnonymousNameSpace <|> smartParseName ) |>> (fun (fst, rst) -> FullName (fst :: rst)) - possibleTypeRef := + possibleTypeRef.Value <- attempt allFuncPointers <|> attempt arrayPtr <|> attempt complexType <|> enumType <|> attempt arrayType <|> normalBuiltInType <|> extendedBuiltInType <|> basicPointerTypes <|> typeBackRef - pFuncRef := + pFuncRef.Value <- functionFullName .>> pchar '@' .>>. fInfo |>> (fun (name, (scope, modifier, callT, tList, rtMod)) -> (scope, modifier, callT, name, tList.Head, tList.Tail, rtMod) |> FunctionT) - pTemplateRef := + pTemplateRef.Value <- saveScopeAndReturn ( clearUserState >>.pstring "?$" >>. (pnameAndAt >>= addToNameList <|> pSpecialName ) @@ -524,7 +524,7 @@ type MSDemangler () = .>> pchar '@' |>> Template ) - returnTypeOperatorRef := + returnTypeOperatorRef.Value <- fullName .>> pchar '@' .>>. fInfo |>> (fun (name, (scope, mods, callT, tList, rtMod)) -> let newName = FullName [ConcatT [Name "operator "; tList.Head]; name] @@ -532,20 +532,22 @@ type MSDemangler () = FunctionT (scope, mods, callT, newName, newReturn, tList.Tail, rtMod) ) - (*---------------All Expressions from a mangled string------------------*) - let allExpressions = + (* ---------------All Expressions from a mangled string------------------ *) + let allExprs = attempt pFunc <|> attempt nonFunctionString <|> attempt allThunkFunc <|> attempt pTemplate <|> fullName - override __.Run str = - match runParserOnString allExpressions MSUserState.Default "" str[1..] with - | Success (result, _, _) -> - let result = MSInterpreter.interpret result - Result.Ok <| result.Trim () - | Failure (_, _, _) -> - Result.Error ParsingFailure - /// Check if the given string is a well-formed mangled string. static member IsWellFormed (str: string) = let str = str.Trim () str.Length <> 0 && str.StartsWith "?" && str.Contains "@" + + interface IDemanglable with + member __.Demangle str = + match runParserOnString allExprs MSUserState.Default "" str[1..] with + | Success (result, _, _) -> + let result = MSInterpreter.interpret result + Result.Ok <| result.Trim () + | Failure _ -> + Result.Error ErrorCase.ParsingFailure + diff --git a/src/FrontEnd/NameMangling/MSTypes.fs b/src/FrontEnd/NameMangling/MSTypes.fs index 538ce84e..05631310 100644 --- a/src/FrontEnd/NameMangling/MSTypes.fs +++ b/src/FrontEnd/NameMangling/MSTypes.fs @@ -367,7 +367,7 @@ type InterpHelperString = string /// Indicates the dimension(length) of the array. type ArrayLength = int -/// AST for microsoft mangled expressions. +/// AST for Microsoft mangled expressions. type MSExpr = /// A name without type information. | Name of string diff --git a/src/FrontEnd/NameMangling/ManglingScheme.fs b/src/FrontEnd/NameMangling/ManglingScheme.fs new file mode 100644 index 00000000..963d41db --- /dev/null +++ b/src/FrontEnd/NameMangling/ManglingScheme.fs @@ -0,0 +1,35 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.FrontEnd.NameMangling + +/// Name mangling schemes. +type ManglingScheme = + /// Microsoft Visual C++ name mangling. + | MSMangler + /// Itanium CXX name mangling scheme used by GCC 3.x and higher, Clang 1.x and + /// higher. + | ItaniumMangler + /// Unknown mangling scheme. + | UnknownMangler diff --git a/src/MiddleEnd/BinEssence.Tests/B2R2.MiddleEnd.BinEssence.Tests.fsproj b/src/MiddleEnd/BinEssence.Tests/B2R2.MiddleEnd.BinEssence.Tests.fsproj deleted file mode 100644 index b14a5435..00000000 --- a/src/MiddleEnd/BinEssence.Tests/B2R2.MiddleEnd.BinEssence.Tests.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - false - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/BinEssence.Tests/CFG.Tests.fs b/src/MiddleEnd/BinEssence.Tests/CFG.Tests.fs deleted file mode 100644 index 8e5c7a13..00000000 --- a/src/MiddleEnd/BinEssence.Tests/CFG.Tests.fs +++ /dev/null @@ -1,634 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.Tests - -open B2R2 -open B2R2.BinIR.LowUIR -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.ControlFlowAnalysis -open B2R2.MiddleEnd.BinEssence -open Microsoft.VisualStudio.TestTools.UnitTesting - -module Utils = - type IRNode = Vertex - - let foldVertexNoFake m (v: IRNode) = - if v.VData.IsFakeBlock () then m - else Map.add v.VData.PPoint v m - - let foldEdge m (v1: IRNode) (v2: IRNode) e = - Map.add (v1.VData.PPoint, v2.VData.PPoint) e m - - let foldEdgeNoFake m (v1: IRNode) (v2: IRNode) e = - if v1.VData.IsFakeBlock () || v2.VData.IsFakeBlock () then m - else Map.add (v1.VData.PPoint, v2.VData.PPoint) e m - -[] -type CFGTest1 () = - - /// This is a raw x86-64 binary code generated from the following C code: - /// int foo(int a); - /// void bar(int a); - /// - /// void _start() - /// { - /// int x = 42; - /// - /// if (x * foo(1) % 42 == 0) { - /// x = 1; - /// } else { - /// x = foo(2) + x; - /// } - /// - /// bar(x); - /// } - /// - /// int foo(int a) - /// { - /// return a + 42; - /// } - /// - /// void bar(int a) - /// { - /// asm ( "mov $60, %rax" ); - /// asm ( "syscall" ); - /// } - /// - /// binary: 554889e54883ec10c745fc2a000000bf01000000e8490000000faf45fc89c1ba310cc33089c8f7eac1fa0389c8c1f81f29c289d06bc02a29c189c885c07509c745fc01000000eb0dbf02000000e8100000000145fc8b45fc89c7e81200000090c9c3554889e5897dfc8b45fc83c02a5dc3554889e5897dfc48c7c03c0000000f05905dc3 - - let binary = - [| 0x55uy; 0x48uy; 0x89uy; 0xe5uy; 0x48uy; 0x83uy; 0xecuy; 0x10uy; 0xc7uy; - 0x45uy; 0xfcuy; 0x2auy; 0x00uy; 0x00uy; 0x00uy; 0xbfuy; 0x01uy; 0x00uy; - 0x00uy; 0x00uy; 0xe8uy; 0x49uy; 0x00uy; 0x00uy; 0x00uy; 0x0fuy; 0xafuy; - 0x45uy; 0xfcuy; 0x89uy; 0xc1uy; 0xbauy; 0x31uy; 0x0cuy; 0xc3uy; 0x30uy; - 0x89uy; 0xc8uy; 0xf7uy; 0xeauy; 0xc1uy; 0xfauy; 0x03uy; 0x89uy; 0xc8uy; - 0xc1uy; 0xf8uy; 0x1fuy; 0x29uy; 0xc2uy; 0x89uy; 0xd0uy; 0x6buy; 0xc0uy; - 0x2auy; 0x29uy; 0xc1uy; 0x89uy; 0xc8uy; 0x85uy; 0xc0uy; 0x75uy; 0x09uy; - 0xc7uy; 0x45uy; 0xfcuy; 0x01uy; 0x00uy; 0x00uy; 0x00uy; 0xebuy; 0x0duy; - 0xbfuy; 0x02uy; 0x00uy; 0x00uy; 0x00uy; 0xe8uy; 0x10uy; 0x00uy; 0x00uy; - 0x00uy; 0x01uy; 0x45uy; 0xfcuy; 0x8buy; 0x45uy; 0xfcuy; 0x89uy; 0xc7uy; - 0xe8uy; 0x12uy; 0x00uy; 0x00uy; 0x00uy; 0x90uy; 0xc9uy; 0xc3uy; 0x55uy; - 0x48uy; 0x89uy; 0xe5uy; 0x89uy; 0x7duy; 0xfcuy; 0x8buy; 0x45uy; 0xfcuy; - 0x83uy; 0xc0uy; 0x2auy; 0x5duy; 0xc3uy; 0x55uy; 0x48uy; 0x89uy; 0xe5uy; - 0x89uy; 0x7duy; 0xfcuy; 0x48uy; 0xc7uy; 0xc0uy; 0x3cuy; 0x00uy; 0x00uy; - 0x00uy; 0x0fuy; 0x05uy; 0x90uy; 0x5duy; 0xc3uy; |] - - let isa = ISA.Init Architecture.IntelX64 Endian.Little - let hdl = BinHandle.Init (isa, binary) - let ess = BinEssence.init hdl [] [] [] - - [] - member __.``CFGInfo: Instruction Map Test`` () = - Assert.AreEqual (41, ess.CodeManager.InstructionCount) - let expected = - [ (0x00UL, 0x00UL); (0x01UL, 0x00UL); (0x04UL, 0x00UL); (0x08UL, 0x00UL); - (0x0fUL, 0x00UL); (0x14UL, 0x00UL); (0x19UL, 0x19UL); (0x1dUL, 0x19UL); - (0x1fUL, 0x19UL); (0x24UL, 0x19UL); (0x26UL, 0x19UL); (0x28UL, 0x19UL); - (0x2bUL, 0x19UL); (0x2dUL, 0x19UL); (0x30UL, 0x19UL); (0x32UL, 0x19UL); - (0x34UL, 0x19UL); (0x37UL, 0x19UL); (0x39UL, 0x19UL); (0x3bUL, 0x19UL); - (0x3dUL, 0x19UL); (0x3fUL, 0x3fUL); (0x46UL, 0x3fUL); (0x48UL, 0x48UL); - (0x4dUL, 0x48UL); (0x52UL, 0x52UL); (0x55UL, 0x55UL); (0x58UL, 0x55UL); - (0x5aUL, 0x55UL); (0x62UL, 0x62UL); (0x63UL, 0x62UL); (0x66UL, 0x62UL); - (0x69UL, 0x62UL); (0x6cUL, 0x62UL); (0x6fUL, 0x62UL); (0x70UL, 0x62UL); - (0x71UL, 0x71UL); (0x72UL, 0x71UL); (0x75UL, 0x71UL); (0x78UL, 0x71UL); - (0x7fUL, 0x71UL) ] - |> List.toArray - let actual = - ess.CodeManager.FoldInstructions (fun acc (KeyValue (insAddr, bbl)) -> - Set.add (insAddr, bbl.BBLAddr) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFGInfo: Instruction BBLMap Test`` () = - Assert.AreEqual (8, ess.CodeManager.BBLCount) - (* BlkRange Test *) - let expected = - [ (0x00UL, 0x18UL); (0x19UL, 0x3eUL); (0x3fUL, 0x47UL); (0x48UL, 0x51UL); - (0x52UL, 0x54UL); (0x55UL, 0x5eUL); (0x62UL, 0x70UL); (0x71UL, 0x80UL) ] - |> List.toArray - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (_, bblInfo)) -> - let range = bblInfo.BlkRange - Set.add (range.Min, range.Max) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - let expectedBBLAddrs = - [| 0x00UL; 0x19UL; 0x3fUL; 0x48UL; 0x52UL; 0x55UL; 0x62UL; 0x71UL |] - let actualBBLAddrs = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, _)) -> - Set.add addr acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expectedBBLAddrs, actualBBLAddrs) - (* InstrAddrs Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| 0x00UL; 0x01UL; 0x04UL; 0x08UL; 0x0fUL; 0x14UL |] - |> Map.add 0x19UL [| 0x19UL; 0x1dUL; 0x1fUL; 0x24UL; 0x26UL; 0x28UL; - 0x2bUL; 0x2dUL; 0x30UL; 0x32UL; 0x34UL; 0x37UL; - 0x39UL; 0x3bUL; 0x3dUL |] - |> Map.add 0x3fUL [| 0x3fUL; 0x46UL |] - |> Map.add 0x48UL [| 0x48UL; 0x4dUL |] - |> Map.add 0x52UL [| 0x52UL |] - |> Map.add 0x55UL [| 0x55UL; 0x58UL; 0x5aUL |] - |> Map.add 0x62UL [| 0x62UL; 0x63UL; 0x66UL; 0x69UL; 0x6cUL; 0x6fUL; - 0x70UL |] - |> Map.add 0x71UL [| 0x71UL; 0x72UL; 0x75UL; 0x78UL; 0x7fUL |] - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - Map.add addr (Set.toArray bblInfo.InstrAddrs) acc) Map.empty - [ 0x00UL; 0x19UL; 0x3fUL; 0x48UL; 0x52UL; 0x55UL; 0x62UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* IRLeaders Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| (0x00UL, 0) |] - |> Map.add 0x19UL [| (0x19UL, 0) |] - |> Map.add 0x3fUL [| (0x3fUL, 0) |] - |> Map.add 0x48UL [| (0x48UL, 0) |] - |> Map.add 0x52UL [| (0x52UL, 0) |] - |> Map.add 0x55UL [| (0x55UL, 0) |] - |> Map.add 0x62UL [| (0x62UL, 0) |] - |> Map.add 0x71UL [| (0x71UL, 0) |] - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - let leaders = - bblInfo.IRLeaders - |> Set.map (fun pp -> pp.Address, pp.Position) - |> Set.toArray - Map.add addr leaders acc) Map.empty - [ 0x00UL; 0x19UL; 0x3fUL; 0x48UL; 0x52UL; 0x55UL; 0x62UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* Entry Test*) - let expected = - [ (0x00UL, 0x00UL); (0x19UL, 0x00UL); (0x3fUL, 0x00UL); (0x48UL, 0x00UL); - (0x52UL, 0x00UL); (0x55UL, 0x00UL); (0x62UL, 0x62UL); (0x71UL, 0x71UL) ] - |> List.toArray - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - Set.add (addr, bblInfo.FunctionEntry) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFGInfo: IRLevelBBLs Test`` () = - let cnt = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun cnt f -> f.CountRegularVertices + cnt) 0 - Assert.AreEqual (8, cnt) - let expected = - [ (0x00UL, 0); (0x19UL, 0); (0x3fUL, 0); (0x48UL, 0); (0x52UL, 0); - (0x55UL, 0); (0x62UL, 0); (0x71UL, 0) ] - |> List.toArray - let actual = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc f -> - f.FoldRegularVertices (fun acc (KeyValue (pp,_)) -> - Set.add (pp.Address, pp.Position) acc) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFGInfo: BBLBounds Test`` () = - let expected = - [ (0x00UL, 0x18UL); (0x19UL, 0x3EUL); (0x3FUL, 0x47UL); (0x48UL, 0x51UL); - (0x52UL, 0x54UL); (0x55UL, 0x5EUL); (0x62UL, 0x70UL); (0x71UL, 0x80UL) ] - |> List.toArray - expected - |> Array.iter (fun (minAddr, maxAddr) -> - let bbl = ess.CodeManager.GetBBL minAddr - let f = ess.CodeManager.FunctionMaintainer.FindRegular bbl.FunctionEntry - for addr in minAddr .. maxAddr - 1UL do - Assert.IsTrue (f.IsAddressCovered addr) - ) - - [] - member __.``CFGInfo: Funcs Test`` () = - Assert.AreEqual (3, ess.CodeManager.FunctionMaintainer.Count) - (* Entry test *) - let expected = [ 0UL; 0x62UL; 0x71UL ] |> List.toArray - let actual = ess.CodeManager.FunctionMaintainer.Entries |> Seq.toArray - CollectionAssert.AreEqual (expected, actual) - (* Function test except CFG *) - (* CallEdges Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| (0x14UL, RegularCallee 0x62UL); - (0x4dUL, RegularCallee 0x62UL); - (0x5aUL, RegularCallee 0x71UL) |] - |> Map.add 0x62UL [| |] - |> Map.add 0x71UL [| |] - let actual = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc func -> - Map.add func.Entry func.CallEdges acc) Map.empty - [ 0x00UL; 0x62UL; 0x71UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* Callers Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| |] - |> Map.add 0x62UL [| 0x00UL |] - |> Map.add 0x71UL [| 0x00UL |] - let actual = - ess.CodeManager.FunctionMaintainer.Functions - |> Seq.fold (fun acc func -> - Map.add func.Entry (Seq.toArray func.Callers) acc) Map.empty - [ 0x00UL; 0x62UL; 0x71UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* SyscallSites Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| |] - |> Map.add 0x62UL [| |] - |> Map.add 0x71UL [| 0x7fUL |] - let actual = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc func -> - let syscallSites = func.SyscallSites |> Seq.toArray - Map.add func.Entry syscallSites acc) Map.empty - [ 0x00UL; 0x62UL; 0x71UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - - [] - member __.``CFG Vertex Test: _start`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0UL |> Result.get - Assert.AreEqual (9, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - Assert.AreEqual (6, vMap.Count) - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x19UL, 0); - ProgramPoint (0x3FUL, 0); ProgramPoint (0x48UL, 0); - ProgramPoint (0x52UL, 0); ProgramPoint (0x55UL, 0); |] - let actual = leaders |> Array.map (fun l -> (Map.find l vMap).VData.Range) - let expected = - [| AddrRange (0x00UL, 0x18UL); AddrRange (0x19UL, 0x3EUL); - AddrRange (0x3FUL, 0x47UL); AddrRange (0x48UL, 0x51UL); - AddrRange (0x52UL, 0x54UL); AddrRange (0x55UL, 0x5EUL); |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFG Edge Test: _start`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0UL |> Result.get - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x19UL, 0); - ProgramPoint (0x3FUL, 0); ProgramPoint (0x48UL, 0); - ProgramPoint (0x52UL, 0); ProgramPoint (0x55UL, 0); |] - let vertices = leaders |> Array.map (fun l -> Map.find l vMap) - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (11, eMap.Count) - let eMap = DiGraph.foldEdge cfg Utils.foldEdgeNoFake Map.empty - Assert.AreEqual (6, eMap.Count) - [ ProgramPoint (0x00UL, 0), ProgramPoint (0x19UL, 0); - ProgramPoint (0x19UL, 0), ProgramPoint (0x3FUL, 0); - ProgramPoint (0x19UL, 0), ProgramPoint (0x48UL, 0); - ProgramPoint (0x3FUL, 0), ProgramPoint (0x55UL, 0); - ProgramPoint (0x48UL, 0), ProgramPoint (0x52UL, 0); - ProgramPoint (0x52UL, 0), ProgramPoint (0x55UL, 0); ] - |> List.iter (fun x -> Assert.IsTrue <| Map.containsKey x eMap) - let actual = - [| cfg.FindEdgeData vertices[0] vertices[1] - cfg.FindEdgeData vertices[1] vertices[2] - cfg.FindEdgeData vertices[1] vertices[3] - cfg.FindEdgeData vertices[2] vertices[5] - cfg.FindEdgeData vertices[3] vertices[4] - cfg.FindEdgeData vertices[4] vertices[5] |] - let expected = - [| CallFallThroughEdge; InterCJmpFalseEdge; InterCJmpTrueEdge; - InterJmpEdge; CallFallThroughEdge; FallThroughEdge; |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFG Vertex Test: foo`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0x62UL |> Result.get - Assert.AreEqual (1, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = [| ProgramPoint (0x62UL, 0) |] - let actual = leaders |> Array.map (fun l -> (Map.find l vMap).VData.Range) - let expected = [| AddrRange (0x62UL, 0x70UL) |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFG Edge Test: foo`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0x62UL |> Result.get - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (0, eMap.Count) - - [] - member __.``CFG Vertex Test: bar`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0x71UL |> Result.get - Assert.AreEqual (1, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = [| ProgramPoint (0x71UL, 0) |] - let actual = leaders |> Array.map (fun l -> (Map.find l vMap).VData.Range) - let expected = [| AddrRange (0x71UL, 0x80UL) |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFG Edge Test: bar`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0x71UL |> Result.get - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (0, eMap.Count) - - [] - member __.``CFG SSAGraph Vertex Test: _start`` () = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let struct (ssacfg, _) = SSACFG.ofIRCFG hdl cfg root - Assert.AreEqual (9, DiGraph.getSize ssacfg) - -[] -type CFGTest2 () = - - /// This is a raw x86 binary code generated from the following C code: - /// static inline void *copy(void *d, const void *s, unsigned int n) { - /// asm volatile ("rep movsb" - /// : "=D" (d), - /// "=S" (s), - /// "=c" (n) - /// : "0" (d), - /// "1" (s), - /// "2" (n) - /// : "memory"); - /// return d; - /// } - /// - /// void _start(void) - /// { - /// char buf[32]; - /// copy(buf, "hello world", 32); - /// return; - /// } - /// binary: 5756b920000000e81800000005341e000083ec2089e78db0e8e1fffff3a483c4205e5fc38b0424c3 - - let binary = - [| 0x57uy; 0x56uy; 0xb9uy; 0x20uy; 0x00uy; 0x00uy; 0x00uy; 0xe8uy; 0x18uy; - 0x00uy; 0x00uy; 0x00uy; 0x05uy; 0x34uy; 0x1euy; 0x00uy; 0x00uy; 0x83uy; - 0xecuy; 0x20uy; 0x89uy; 0xe7uy; 0x8duy; 0xb0uy; 0xe8uy; 0xe1uy; 0xffuy; - 0xffuy; 0xf3uy; 0xa4uy; 0x83uy; 0xc4uy; 0x20uy; 0x5euy; 0x5fuy; 0xc3uy; - 0x8buy; 0x04uy; 0x24uy; 0xc3uy; |] - - let isa = ISA.Init Architecture.IntelX86 Endian.Little - let hdl = BinHandle.Init (isa, binary) - let ess = BinEssence.init hdl [] [] [] - - [] - member __.``CFGInfo: Instruction Map Test`` () = - Assert.AreEqual (15, ess.CodeManager.InstructionCount) - let expected = - [ (0x00UL, 0x00UL); (0x01UL, 0x00UL); (0x02UL, 0x00UL); (0x07UL, 0x00UL); - (0x0cUL, 0x0cUL); (0x11UL, 0x0cUL); (0x14UL, 0x0cUL); (0x16UL, 0x0cUL); - (0x1cUL, 0x0cUL); (0x1eUL, 0x0cUL); (0x21UL, 0x0cUL); (0x22UL, 0x0cUL); - (0x23UL, 0x0cUL); (0x24UL, 0x24UL); (0x27UL, 0x24UL) ] - |> List.toArray - let actual = - ess.CodeManager.FoldInstructions (fun acc (KeyValue (insAddr, bbl)) -> - Set.add (insAddr, bbl.BBLAddr) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFGInfo: Instruction BBLMap Test`` () = - Assert.AreEqual (3, ess.CodeManager.BBLCount) - (* BlkRange Test *) - let expected = - [ (0x00UL, 0x0bUL); (0x0cUL, 0x23UL); (0x24UL, 0x27UL) ] - |> List.toArray - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (_, bblInfo)) -> - let range = bblInfo.BlkRange - Set.add (range.Min, range.Max) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - let expectedBBLAddrs = - [| 0x00UL; 0x0cUL; 0x24UL |] - let actualBBLAddrs = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, _)) -> - Set.add addr acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expectedBBLAddrs, actualBBLAddrs) - (* InstrAddrs Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| 0x00UL; 0x01UL; 0x02UL; 0x07UL |] - |> Map.add 0x0cUL [| 0x0cUL; 0x11UL; 0x14UL; 0x16UL; 0x1cUL; 0x1eUL; - 0x21UL; 0x22UL; 0x23UL |] - |> Map.add 0x24UL [| 0x24UL; 0x27UL |] - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - Map.add addr (Set.toArray bblInfo.InstrAddrs) acc) Map.empty - [ 0x00UL; 0x0cUL; 0x24UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* IRLeaders Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| (0x00UL, 0) |] - |> Map.add 0x0cUL [| (0x0cUL, 0); (0x1cUL, 0); (0x1cUL, 2); (0x1cUL, 8); - (0x1eUL, 0) |] - |> Map.add 0x24UL [| (0x24UL, 0) |] - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - let leaders = - bblInfo.IRLeaders - |> Set.map (fun pp -> pp.Address, pp.Position) - |> Set.toArray - Map.add addr leaders acc) Map.empty - [ 0x00UL; 0x0cUL; 0x24UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* Entry Test*) - let expected = - [ (0x00UL, 0x00UL); (0x0cUL, 0x00UL); (0x24UL, 0x24UL) ] - |> List.toArray - let actual = - ess.CodeManager.FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - Set.add (addr, bblInfo.FunctionEntry) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFGInfo: IRLevelBBLs Test`` () = - let cnt = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun cnt f -> f.CountRegularVertices + cnt) 0 - Assert.AreEqual (7, cnt) - let expected = - [ (0x00UL, 0); (0x0cUL, 0); (0x1cUL, 0); (0x1cUL, 2); (0x1cUL, 8); - (0x1eUL, 0); (0x24UL, 0) ] - |> List.toArray - let actual = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc f -> - f.FoldRegularVertices (fun acc (KeyValue (pp,_)) -> - Set.add (pp.Address, pp.Position) acc) acc) Set.empty - |> Set.toArray - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFGInfo: BBLBounds Test`` () = - let expected = - [ (0x00UL, 0x0bUL); (0x0cUL, 0x23UL); (0x24UL, 0x27UL) ] - |> List.toArray - expected - |> Array.iter (fun (minAddr, maxAddr) -> - let bbl = ess.CodeManager.GetBBL minAddr - let f = ess.CodeManager.FunctionMaintainer.FindRegular bbl.FunctionEntry - for addr in minAddr .. maxAddr - 1UL do - Assert.IsTrue (f.IsAddressCovered addr) - ) - - [] - member __.``CFGInfo: Funcs Test`` () = - Assert.AreEqual (2, ess.CodeManager.FunctionMaintainer.Count) - (* Entry test *) - let expected = [ 0UL; 0x24UL ] |> List.toArray - let actual = ess.CodeManager.FunctionMaintainer.Entries |> Seq.toArray - CollectionAssert.AreEqual (expected, actual) - (* Function test except CFG *) - (* CallEdges Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| (0x07UL, RegularCallee 0x24UL) |] - |> Map.add 0x24UL [| |] - let actual = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc func -> - Map.add func.Entry func.CallEdges acc) Map.empty - [ 0x00UL; 0x24UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* Callers Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| |] - |> Map.add 0x24UL [| 0x00UL |] - let actual = - ess.CodeManager.FunctionMaintainer.Functions - |> Seq.fold (fun acc func -> - Map.add func.Entry (Seq.toArray func.Callers) acc) Map.empty - [ 0x00UL; 0x24UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - (* SyscallSites Test *) - let expected = - Map.empty - |> Map.add 0x00UL [| |] - |> Map.add 0x24UL [| |] - let actual = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc func -> - let syscallSites = func.SyscallSites |> Seq.toArray - Map.add func.Entry syscallSites acc) Map.empty - [ 0x00UL; 0x24UL ] - |> List.iter (fun addr -> - CollectionAssert.AreEqual (Map.find addr expected, Map.find addr actual)) - - [] - member __.``CFG Vertex Test: _start`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0UL |> Result.get - Assert.AreEqual (7, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x0CUL, 0); - ProgramPoint (0x1CUL, 0); ProgramPoint (0x1CUL, 2); - ProgramPoint (0x1CUL, 8); ProgramPoint (0x1EUL, 0) |] - let actual = - leaders - |> Array.map (fun l -> - match (Map.find l vMap).VData.LastStmt.S with - | IEMark _ -> 0 - | InterJmp _ -> 1 - | InterCJmp _ -> 2 - | Jmp _ -> 3 - | CJmp _ -> 4 - | _ -> -1) - let expected = - [| 1; 0; 4; 1; 1; 1 |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``CFG Edge Test: _start`` () = - let cfg, _ = BinEssence.getFunctionCFG ess 0UL |> Result.get - let vMap = DiGraph.foldVertex cfg Utils.foldVertexNoFake Map.empty - let leaders = - [| ProgramPoint (0x00UL, 0); ProgramPoint (0x0CUL, 0); - ProgramPoint (0x1CUL, 0); ProgramPoint (0x1CUL, 2); - ProgramPoint (0x1CUL, 8); ProgramPoint (0x1EUL, 0) |] - let vertices = leaders |> Array.map (fun l -> Map.find l vMap) - let eMap = DiGraph.foldEdge cfg Utils.foldEdge Map.empty - Assert.AreEqual (8, eMap.Count) - let eMap = DiGraph.foldEdge cfg Utils.foldEdgeNoFake Map.empty - Assert.AreEqual (6, eMap.Count) - [ (ProgramPoint (0x00UL, 0), ProgramPoint (0x0CUL, 0)); - (ProgramPoint (0x0CUL, 0), ProgramPoint (0x1CUL, 0)); - (ProgramPoint (0x1CUL, 0), ProgramPoint (0x1CUL, 2)); - (ProgramPoint (0x1CUL, 0), ProgramPoint (0x1CUL, 8)); - (ProgramPoint (0x1CUL, 2), ProgramPoint (0x1CUL, 0)); - (ProgramPoint (0x1CUL, 8), ProgramPoint (0x1EUL, 0)); ] - |> List.iter (fun x -> Assert.IsTrue <| Map.containsKey x eMap) - let actual = - [| cfg.FindEdgeData vertices[0] vertices[1] - cfg.FindEdgeData vertices[1] vertices[2] - cfg.FindEdgeData vertices[2] vertices[3] - cfg.FindEdgeData vertices[2] vertices[4] - cfg.FindEdgeData vertices[3] vertices[2] - cfg.FindEdgeData vertices[4] vertices[5] |] - let expected = - [| CallFallThroughEdge; FallThroughEdge; IntraCJmpFalseEdge; - IntraCJmpTrueEdge; InterJmpEdge; InterJmpEdge |] - CollectionAssert.AreEqual (expected, actual) - - [] - member __.``DisasmLens Test: _start`` () = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let cfg, _ = DisasmLens.filter ess.CodeManager cfg root - Assert.AreEqual (1, DiGraph.getSize cfg) - let vMap = DiGraph.foldVertex cfg (fun m v -> - Map.add v.VData.PPoint.Address v m) Map.empty - let leaders = [| 0x00UL |] - let vertices = leaders |> Array.map (fun l -> Map.find l vMap) - let disasmLens = [| 13 |] - Array.zip vertices disasmLens - |> Array.iter (fun (v, len) -> - Assert.AreEqual (len, v.VData.Disassemblies.Length)) - let eMap = DiGraph.foldEdge cfg (fun m v1 v2 e -> - let key = v1.VData.PPoint.Address, v2.VData.PPoint.Address - Map.add key e m) Map.empty - Assert.AreEqual (0, eMap.Count) - - [] - member __.``SSAGraph Vertex Test: _start`` () = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let struct (ssacfg, _) = SSACFG.ofIRCFG hdl cfg root - Assert.AreEqual (7, DiGraph.getSize ssacfg) diff --git a/src/MiddleEnd/BinEssence/B2R2.MiddleEnd.BinEssence.fsproj b/src/MiddleEnd/BinEssence/B2R2.MiddleEnd.BinEssence.fsproj deleted file mode 100644 index c51ca2bf..00000000 --- a/src/MiddleEnd/BinEssence/B2R2.MiddleEnd.BinEssence.fsproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - LICENSE.md - b2r2-240x240.png - README.md - B2R2 middle-end main interface. - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/BinEssence/BinEssence.fs b/src/MiddleEnd/BinEssence/BinEssence.fs deleted file mode 100644 index b85dbec7..00000000 --- a/src/MiddleEnd/BinEssence/BinEssence.fs +++ /dev/null @@ -1,146 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinEssence - -open B2R2 -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowAnalysis - -/// -/// BinEssence represents essential information about the binary at all -/// levels: a low-level interface for binary code and data, parsed -/// instructions, and recovered control-flow information including CFG itself. -/// Note that every field of BinEssence is *mutable*. -/// -type BinEssence = { - /// Low-level access to binary code and data. - BinHandle: BinHandle - /// Higher-level access to the code. It handles parsed instructions, lifted - /// IRs, basic blocks, functions, exception handlers, etc. - CodeManager: CodeManager - /// Higher-level access to the data. - DataManager: DataManager -} - -[] -module BinEssence = - - /// Retrieve the IR-level CFG at the given address (addr) from the BinEssence. - let getFunctionCFG ess (addr: Addr) = - match ess.CodeManager.FunctionMaintainer.TryFindRegular addr with - | Some func -> - let root = func.FindVertex (ProgramPoint (addr, 0)) - Ok (func.IRCFG, root) - | None -> Error () - - let private getFunctionOperationMode hdl entry = - match hdl.ISA.Arch with - | Arch.ARMv7 -> - if entry &&& 1UL = 1UL then - entry - 1UL, ArchOperationMode.ThumbMode - else entry, ArchOperationMode.ARMMode - | _ -> entry, ArchOperationMode.NoMode - - let private addEntriesFromExceptionTable (codeMgr: CodeManager) entries = - codeMgr.ExceptionTable.Fold (fun entries (KeyValue (entry, _)) -> - Set.add entry entries) entries - - /// This function returns an initial sequence of entry points obtained from - /// the binary itself (e.g., from its symbol information). Therefore, if the - /// binary is stripped, the returned sequence will be incomplete, and we need - /// to expand it during the other analyses. - let private getInitialEntryPoints ess = - let fi = ess.BinHandle.FileInfo - let entries = - fi.GetFunctionAddresses (true) (* XXX this will become false later. *) - |> Set.ofSeq - |> addEntriesFromExceptionTable ess.CodeManager - fi.EntryPoint - |> Option.fold (fun acc addr -> Set.add addr acc) entries - |> Set.toList - |> List.map (getFunctionOperationMode ess.BinHandle) - - let private initialize hdl = - { BinHandle = hdl - CodeManager = CodeManager (hdl) - DataManager = DataManager (hdl) } - - let private initialBuild ess (builder: CFGBuilder) = - let entries = getInitialEntryPoints ess - match builder.AddNewFunctions entries with - | Ok () -> Ok ess - | Error err -> Error err - - let private handlePluggableAnalysisResult ess name = function - | PluggableAnalysisOk -> - Ok ess - | PluggableAnalysisError -> - printfn "[*] %s failed." name - Ok ess - | PluggableAnalysisNewBinary hdl -> - let ess = initialize hdl - let builder = CFGBuilder (hdl, ess.CodeManager, ess.DataManager) - initialBuild ess builder - - let private runAnalyses builder analyses (ess: BinEssence) = - analyses - |> List.fold (fun ess (analysis: IPluggableAnalysis) -> - #if DEBUG - printfn "[*] %s started." analysis.Name - #endif - let ess = - analysis.Run builder ess.BinHandle ess.CodeManager ess.DataManager - |> handlePluggableAnalysisResult ess analysis.Name - match ess with - | Ok ess -> ess - | Error e -> - eprintfn "[*] Fatal error with %s" (CFGError.toString e) - Utils.impossible ()) ess - - let private analyzeAll preAnalyses mainAnalyses postAnalyses builder ess = - ess - |> runAnalyses builder preAnalyses - |> runAnalyses builder mainAnalyses - |> runAnalyses builder postAnalyses - - [] - let init hdl preAnalyses mainAnalyses postAnalyses = -#if DEBUG - let startTime = System.DateTime.Now -#endif - let ess = initialize hdl - let builder = CFGBuilder (hdl, ess.CodeManager, ess.DataManager) - match initialBuild ess builder with - | Ok ess -> - let ess = ess |> analyzeAll preAnalyses mainAnalyses postAnalyses builder -#if DEBUG - let endTime = System.DateTime.Now - endTime.Subtract(startTime).TotalSeconds - |> printfn "[*] All done in %f sec." -#endif - ess - | Error e -> - eprintfn "[*] Fatal error with %s" (CFGError.toString e) - Utils.impossible () diff --git a/src/MiddleEnd/BinEssence/CallGraphLens.fs b/src/MiddleEnd/BinEssence/CallGraphLens.fs deleted file mode 100644 index cf272f87..00000000 --- a/src/MiddleEnd/BinEssence/CallGraphLens.fs +++ /dev/null @@ -1,74 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinEssence - -open B2R2 -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.ControlFlowAnalysis -open System.Collections.Generic - -/// A mapping from an address to a CallCFG vertex. -type CallVMap = Dictionary - -/// A graph lens for obtaining CallGraph. -module CallGraphLens = - - let private getVertex ess vMap entry g = - match (vMap: CallVMap).TryGetValue entry with - | false, _ -> - let func = ess.CodeManager.FunctionMaintainer.Find entry - let id = func.FunctionID - let name = func.FunctionName - let ext = func.FunctionKind <> FunctionKind.Regular - let v, g = - DiGraph.addVertex g (CallGraphBlock (entry, id, name, false, ext)) - vMap.Add (entry, v) - v, g - | true, v -> v, g - - let private addEdge ess vMap entry target callCFG = - let src, callCFG = getVertex ess vMap entry callCFG - let dst, callCFG = getVertex ess vMap target callCFG - DiGraph.addEdge callCFG src dst CallEdge - - let private buildCG callCFG vMap ess = - ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.fold (fun callCFG func -> - func.CallEdges - |> Array.fold (fun callCFG (_, callee) -> - match callee with - | RegularCallee target -> addEdge ess vMap func.Entry target callCFG - | IndirectCallees targets -> - targets - |> Set.fold (fun callCFG target -> - addEdge ess vMap func.Entry target callCFG) callCFG - | UnresolvedIndirectCallees (_) | NullCallee -> callCFG - ) callCFG) callCFG - - let build ess = - let vMap = CallVMap () - let callCFG = buildCG (CallCFG.init PersistentGraph) vMap ess - callCFG, DiGraph.getUnreachables callCFG |> Seq.toList diff --git a/src/MiddleEnd/BinEssence/DisasmLens.fs b/src/MiddleEnd/BinEssence/DisasmLens.fs deleted file mode 100644 index 3281d6d5..00000000 --- a/src/MiddleEnd/BinEssence/DisasmLens.fs +++ /dev/null @@ -1,147 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph - -/// A mapping from an address to a DisasmCFG vertex. -type DisasmVMap = Dictionary - -/// A graph lens for obtaining DisasmCFG. -[] -module DisasmLens = - - let findBlockStart blockInfos addr = - Map.findKey (fun _ (range: AddrRange, _) -> - range.Min <= addr && addr <= range.Max) blockInfos - - let canBeMerged ircfg v = - DiGraph.getSuccs ircfg v - |> List.exists (fun w -> - DiGraph.findEdgeData ircfg v w = CallFallThroughEdge && - DiGraph.getPreds ircfg w |> List.length = 2) - - let getMergeMap blockInfos (ircfg: DiGraph) = - DiGraph.foldVertex ircfg (fun mergeMap v -> - if v.VData.IsFakeBlock () then mergeMap - elif canBeMerged ircfg v then - let bblAddr = findBlockStart blockInfos v.VData.PPoint.Address - let range, _ = Map.find bblAddr blockInfos - Map.add bblAddr (range.Max + 1UL) mergeMap - else mergeMap) Map.empty - - let getEdgeInfos blockInfos (ircfg: DiGraph) = - DiGraph.foldEdge ircfg (fun edgeInfo src dst e -> - if src.VData.IsFakeBlock () || dst.VData.IsFakeBlock () then edgeInfo - else - let srcBBLAddr = findBlockStart blockInfos src.VData.PPoint.Address - let dstBBLAddr = findBlockStart blockInfos dst.VData.PPoint.Address - if e = IntraCJmpFalseEdge || e = IntraCJmpTrueEdge || e = IntraJmpEdge then - edgeInfo - elif srcBBLAddr <> dstBBLAddr then - Map.add (srcBBLAddr, dstBBLAddr) e edgeInfo - elif dstBBLAddr = dst.VData.PPoint.Address then - Map.add (srcBBLAddr, dstBBLAddr) e edgeInfo - else edgeInfo) Map.empty - - let rec resolveMerge codeMgr blockInfo vertexInfo edgeInfo mergeMap addr next addrs = - let _, insAddrs = Map.find next blockInfo - let instrs = - insAddrs - |> Set.toArray - |> Array.map (fun addr -> - (codeMgr: CodeManager).GetInstruction(addr).Instruction) - |> Array.append (Map.find addr vertexInfo) - let vertexInfo = Map.add addr instrs vertexInfo - let edgeInfo = - Map.fold (fun edgeInfo (src, dst) e -> - if src = addr then edgeInfo - elif src = next then Map.add (addr, dst) e edgeInfo - else Map.add (src, dst) e edgeInfo) Map.empty edgeInfo - let mergeMap = - Map.fold (fun mergeMap fromAddr toAddr -> - if fromAddr = addr then mergeMap - elif fromAddr = next then Map.add addr toAddr mergeMap - else Map.add fromAddr toAddr mergeMap) Map.empty mergeMap - let addrs = List.filter (fun a -> a <> next) addrs - match Map.tryFind addr mergeMap with - | None -> vertexInfo, edgeInfo, mergeMap, addrs - | Some next -> - resolveMerge codeMgr blockInfo vertexInfo edgeInfo mergeMap addr next addrs - - let rec mergeInfosLoop codeMgr blockInfo vertexInfo edgeInfo mergeMap = function - | [] -> vertexInfo, edgeInfo - | addr :: addrs -> - let _, insAddrs = Map.find addr blockInfo - let instrs = - insAddrs - |> Set.toArray - |> Array.map (fun addr -> - (codeMgr: CodeManager).GetInstruction(addr).Instruction) - let vertexInfo = Map.add addr instrs vertexInfo - let vertexInfo, edgeInfo, mergeMap, addrs = - match Map.tryFind addr mergeMap with - | None -> vertexInfo, edgeInfo, mergeMap, addrs - | Some next -> - resolveMerge codeMgr blockInfo vertexInfo edgeInfo mergeMap addr next addrs - mergeInfosLoop codeMgr blockInfo vertexInfo edgeInfo mergeMap addrs - - let mergeInfos codeMgr blockInfos edgeInfos mergeMap = - let addrs = Map.toList blockInfos |> List.map fst - mergeInfosLoop codeMgr blockInfos Map.empty edgeInfos mergeMap addrs - - let addVertex (g, vMap: DisasmVMap) addr instrs = - let blk = DisasmBasicBlock (instrs, ProgramPoint (addr, 0)) - let v, g = DiGraph.addVertex g blk - vMap.Add (addr, v) - g, vMap - - let addEdge (vMap: DisasmVMap) g (src, dst) e = - let src = vMap[src] - let dst = vMap[dst] - DiGraph.addEdge g src dst e - - let private buildCFG codeMgr blockInfos ircfg vMap dcfg = - let mergeMap = getMergeMap blockInfos ircfg - let edgeInfos = getEdgeInfos blockInfos ircfg - let vertexInfo, edgeInfo = mergeInfos codeMgr blockInfos edgeInfos mergeMap - let dcfg, vMap = Map.fold addVertex (dcfg, vMap) vertexInfo - let dcfg = Map.fold (addEdge vMap) dcfg edgeInfo - dcfg - - let filter codeMgr (g: DiGraph<_, _>) (root: IRVertex) = - let blockInfos = - (codeMgr: CodeManager).FoldBBLs (fun acc (KeyValue (addr, bblInfo)) -> - if bblInfo.FunctionEntry = root.VData.PPoint.Address then - Map.add addr (bblInfo.BlkRange, bblInfo.InstrAddrs) acc - else acc) Map.empty - let newGraph = DisasmCFG.init g.ImplementationType - let vMap = DisasmVMap () - let newGraph = buildCFG codeMgr blockInfos g vMap newGraph - let root = vMap[(root: IRVertex).VData.PPoint.Address] - newGraph, root diff --git a/src/MiddleEnd/BinEssence/README.md b/src/MiddleEnd/BinEssence/README.md deleted file mode 100644 index e3d6f4f5..00000000 --- a/src/MiddleEnd/BinEssence/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# B2R2.MiddleEnd.BinEssence - -### B2R2? - -B2R2 is a binary analysis and reversing framework written purely in F#. Since it -does not rely on any native (unmanaged) code, it is readily usable in any -platform or OS that .NET runs on. - -### B2R2.MiddleEnd.BinEssence Package? - -`B2R2.MiddleEnd.BinEssence` provides the main interface for the B2R2's -middle-end. In most cases, it should suffice to import only -`B2R2.MiddleEnd.BinEssence` to utilize our middle features. diff --git a/src/MiddleEnd/BinGraph.Tests/B2R2.MiddleEnd.BinGraph.Tests.fsproj b/src/MiddleEnd/BinGraph.Tests/B2R2.MiddleEnd.BinGraph.Tests.fsproj deleted file mode 100644 index 34fef9b5..00000000 --- a/src/MiddleEnd/BinGraph.Tests/B2R2.MiddleEnd.BinGraph.Tests.fsproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - false - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/BinGraph.Tests/ImperativeGraph.Tests.fs b/src/MiddleEnd/BinGraph.Tests/ImperativeGraph.Tests.fs deleted file mode 100644 index ddf2ba49..00000000 --- a/src/MiddleEnd/BinGraph.Tests/ImperativeGraph.Tests.fs +++ /dev/null @@ -1,473 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph.Tests - -open B2R2 -open B2R2.MiddleEnd.BinGraph -open Microsoft.VisualStudio.TestTools.UnitTesting - -[] -type BasicImperativeGraphTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - let v9 = V (9, (AddrRange (9UL))) - let v10 = V (10, (AddrRange (10UL))) - let v11 = V (11, (AddrRange (11UL))) - let v12 = V (12, (AddrRange (12UL))) - let v13 = V (13, (AddrRange (13UL))) - - (* Graph example from Wikipedia. *) - let g1 = RangedDiGraph.init -1 ImperativeGraph - let n1, g1 = DiGraph.addVertex g1 v1 // Node 1 - let n2, g1 = DiGraph.addVertex g1 v2 // Node 2 - let n3, g1 = DiGraph.addVertex g1 v3 // Node 3 - let n4, g1 = DiGraph.addVertex g1 v4 // Node 4 - let n5, g1 = DiGraph.addVertex g1 v5 // Node 5 - let n6, g1 = DiGraph.addVertex g1 v6 // Node 6 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n2 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n6 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n4 n5 6 - let g1 = DiGraph.addEdge g1 n5 n2 7 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - (* Graph example from Tiger book. *) - let g2 = RangedDiGraph.init -1 ImperativeGraph - let n1, g2 = DiGraph.addVertex g2 v1 // Node 1 - let n2, g2 = DiGraph.addVertex g2 v2 // Node 2 - let n3, g2 = DiGraph.addVertex g2 v3 // Node 3 - let n4, g2 = DiGraph.addVertex g2 v4 // Node 4 - let n5, g2 = DiGraph.addVertex g2 v5 // Node 5 - let n6, g2 = DiGraph.addVertex g2 v6 // Node 6 - let g2 = DiGraph.addEdge g2 n1 n2 1 - let g2 = DiGraph.addEdge g2 n1 n3 2 - let g2 = DiGraph.addEdge g2 n3 n4 3 - let g2 = DiGraph.addEdge g2 n4 n5 4 - let g2 = DiGraph.addEdge g2 n4 n6 5 - let g2 = DiGraph.addEdge g2 n6 n4 6 - let g2root = n1 - let ctxt2 = Dominator.initDominatorContext g2 g2root - - (* Arbitrary graph example *) - let g3 = RangedDiGraph.init -1 ImperativeGraph - let n1, g3 = DiGraph.addVertex g3 v1 // Node 1 - let n2, g3 = DiGraph.addVertex g3 v2 // Node 2 - let n3, g3 = DiGraph.addVertex g3 v3 // Node 3 - let n4, g3 = DiGraph.addVertex g3 v4 // Node 4 - let n5, g3 = DiGraph.addVertex g3 v5 // Node 5 - let g3 = DiGraph.addEdge g3 n1 n2 1 - let g3 = DiGraph.addEdge g3 n1 n3 2 - let g3 = DiGraph.addEdge g3 n2 n4 3 - let g3 = DiGraph.addEdge g3 n3 n4 4 - let g3 = DiGraph.addEdge g3 n3 n5 5 - let g3root = n1 - let ctxt3 = Dominator.initDominatorContext g3 g3root - - (* Graph example from Tiger book (Fig. 19.5) *) - let g4 = RangedDiGraph.init -1 ImperativeGraph - let n1, g4 = DiGraph.addVertex g4 v1 - let n2, g4 = DiGraph.addVertex g4 v2 - let n3, g4 = DiGraph.addVertex g4 v3 - let n4, g4 = DiGraph.addVertex g4 v4 - let n5, g4 = DiGraph.addVertex g4 v5 - let n6, g4 = DiGraph.addVertex g4 v6 - let n7, g4 = DiGraph.addVertex g4 v7 - let n8, g4 = DiGraph.addVertex g4 v8 - let n9, g4 = DiGraph.addVertex g4 v9 - let n10, g4 = DiGraph.addVertex g4 v10 - let n11, g4 = DiGraph.addVertex g4 v11 - let n12, g4 = DiGraph.addVertex g4 v12 - let n13, g4 = DiGraph.addVertex g4 v13 - let g4 = DiGraph.addEdge g4 n1 n2 1 - let g4 = DiGraph.addEdge g4 n1 n5 2 - let g4 = DiGraph.addEdge g4 n1 n9 3 - let g4 = DiGraph.addEdge g4 n2 n3 4 - let g4 = DiGraph.addEdge g4 n3 n3 5 - let g4 = DiGraph.addEdge g4 n3 n4 6 - let g4 = DiGraph.addEdge g4 n4 n13 7 - let g4 = DiGraph.addEdge g4 n5 n6 8 - let g4 = DiGraph.addEdge g4 n5 n7 9 - let g4 = DiGraph.addEdge g4 n6 n4 10 - let g4 = DiGraph.addEdge g4 n6 n8 11 - let g4 = DiGraph.addEdge g4 n7 n8 12 - let g4 = DiGraph.addEdge g4 n7 n12 13 - let g4 = DiGraph.addEdge g4 n8 n5 14 - let g4 = DiGraph.addEdge g4 n8 n13 15 - let g4 = DiGraph.addEdge g4 n9 n10 16 - let g4 = DiGraph.addEdge g4 n9 n11 17 - let g4 = DiGraph.addEdge g4 n10 n12 18 - let g4 = DiGraph.addEdge g4 n11 n12 19 - let g4 = DiGraph.addEdge g4 n12 n13 20 - let g4root = n1 - let ctxt4 = Dominator.initDominatorContext g4 g4root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - let sum acc (v: Vertex) = v.VData.Val + acc - let inc acc _v1 _v2 e = acc + e - - [] - member __.``RangedDiGraph Traversal Test 1``() = - let s1 = Traversal.foldPostorder g1 [g1root] sum 0 - let s2 = Traversal.foldRevPostorder g1 [g1root] sum 0 - let s3 = Traversal.foldPreorder g1 [g1root] sum 0 - let s4 = DiGraph.foldVertex g1 sum 0 - let s5 = DiGraph.foldEdge g1 inc 0 - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - Assert.AreEqual (21, s3) - Assert.AreEqual (21, s4) - Assert.AreEqual (28, s5) - - [] - member __.``RangedDiGraph Traversal Test 2``() = - let s1 = - Traversal.foldPostorder g1 [g1root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s2 = - Traversal.foldPreorder g1 [g1root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s3 = - Traversal.foldPostorder g3 [g3root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s4 = - Traversal.foldPreorder g3 [g3root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - CollectionAssert.AreEqual ([| 5; 3; 4; 6; 2; 1 |], s1) - CollectionAssert.AreEqual ([| 1; 2; 3; 5; 4; 6 |], s2) - CollectionAssert.AreEqual ([| 4; 2; 5; 3; 1 |], s3) - CollectionAssert.AreEqual ([| 1; 2; 4; 3; 5 |], s4) - - [] - member __.``RangedDiGraph Removal Test``() = - let g2 = g1.Clone () - let g2root = DiGraph.findVertexByData g2 g1root.VData - let g2 = - (g2 :?> RangedDiGraph<_, _>).FindVertexByRange (AddrRange (3UL)) - |> DiGraph.removeVertex g2 - let s1 = Traversal.foldPreorder g1 [g1root] sum 0 - let s2 = Traversal.foldPreorder g2 [g2root] sum 0 - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (5, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (18, s2) - - [] - member __.``Graph Transposition Test``() = - let g2 = DiGraph.reverse g1 - let g2root = DiGraph.findVertexByData g2 v6 - let s1 = Traversal.foldPreorder g1 [g1root] sum 0 - let s2 = Traversal.foldPreorder g2 [g2root] sum 0 - let lst = - g2.FoldEdge (fun acc s d _ -> (s.VData.Val, d.VData.Val) :: acc) [] - let edges = List.sort lst |> List.toArray - let solution = [| (2, 1); (2, 5); (3, 2); (4, 2); (5, 3); (5, 4); (6, 2) |] - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (6, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - CollectionAssert.AreEqual (edges, solution) - - [] - member __.``Dominator Test 1``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.AreEqual (2, getVertexVal v) - - [] - member __.``Dominator Test 2``() = - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v4 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v5 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v6 - Assert.AreEqual (4, getVertexVal v) - - [] - member __.``Post-Dominator Test``() = - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (6, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.IsTrue (v.IsNone) - - [] - member __.``Post-Dominator Test 2``() = - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v2 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v3 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v4 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v5 - Assert.IsTrue (v.IsNone) - - [] - member __.``Dominance Frontier Test``() = - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v5 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|4; 5; 12; 13|]) - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v9 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|12|]) - - [] - member __.``Root Node Loop Test``() = - let g = RangedDiGraph.init -1 ImperativeGraph - let n1, g = DiGraph.addVertex g v1 // Node 1 - let n2, g = DiGraph.addVertex g v2 // Node 2 - let n3, g = DiGraph.addVertex g v3 // Node 3 - let n4, g = DiGraph.addVertex g v4 // Node 4 - let n5, g = DiGraph.addVertex g v5 // Node 5 - let n6, g = DiGraph.addVertex g v6 // Node 6 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n1 n3 2 - let g = DiGraph.addEdge g n2 n4 3 - let g = DiGraph.addEdge g n3 n4 4 - let g = DiGraph.addEdge g n3 n5 5 - let g = DiGraph.addEdge g n4 n6 6 - let g = DiGraph.addEdge g n5 n6 7 - let g = DiGraph.addEdge g n6 n1 8 // Back edge to the root node. - let ctxt = Dominator.initDominatorContext g n1 - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v4 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v5 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v6 - Assert.AreEqual (1, getVertexVal v) - - [] - member __.``Basic SCC Test``() = - let v = DiGraph.findVertexByData g3 v1 - let sccs = SCC.compute g3 v - Assert.AreEqual (5, Set.count sccs) - -[] -type ExtraImperativeDomTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - let v9 = V (9, (AddrRange (9UL))) - let v10 = V (10, (AddrRange (10UL))) - let v11 = V (11, (AddrRange (11UL))) - let v12 = V (12, (AddrRange (12UL))) - let v13 = V (13, (AddrRange (13UL))) - let v14 = V (14, (AddrRange (14UL))) - let v15 = V (15, (AddrRange (15UL))) - let v16 = V (16, (AddrRange (16UL))) - let v17 = V (17, (AddrRange (17UL))) - let v18 = V (18, (AddrRange (18UL))) - let v19 = V (19, (AddrRange (19UL))) - let v20 = V (20, (AddrRange (20UL))) - let v21 = V (21, (AddrRange (21UL))) - let v22 = V (22, (AddrRange (22UL))) - let v23 = V (23, (AddrRange (23UL))) - - let g1 = RangedDiGraph.init -1 ImperativeGraph - let n1, g1 = DiGraph.addVertex g1 v1 - let n2, g1 = DiGraph.addVertex g1 v2 - let n3, g1 = DiGraph.addVertex g1 v3 - let n4, g1 = DiGraph.addVertex g1 v4 - let n5, g1 = DiGraph.addVertex g1 v5 - let n6, g1 = DiGraph.addVertex g1 v6 - let n7, g1 = DiGraph.addVertex g1 v7 - let n8, g1 = DiGraph.addVertex g1 v8 - let n9, g1 = DiGraph.addVertex g1 v9 - let n10, g1 = DiGraph.addVertex g1 v10 - let n11, g1 = DiGraph.addVertex g1 v11 - let n12, g1 = DiGraph.addVertex g1 v12 - let n13, g1 = DiGraph.addVertex g1 v13 - let n14, g1 = DiGraph.addVertex g1 v14 - let n15, g1 = DiGraph.addVertex g1 v15 - let n16, g1 = DiGraph.addVertex g1 v16 - let n17, g1 = DiGraph.addVertex g1 v17 - let n18, g1 = DiGraph.addVertex g1 v18 - let n19, g1 = DiGraph.addVertex g1 v19 - let n20, g1 = DiGraph.addVertex g1 v20 - let n21, g1 = DiGraph.addVertex g1 v21 - let n22, g1 = DiGraph.addVertex g1 v22 - let n23, g1 = DiGraph.addVertex g1 v23 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n1 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n7 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n3 n6 6 - let g1 = DiGraph.addEdge g1 n4 n7 7 - let g1 = DiGraph.addEdge g1 n5 n8 8 - let g1 = DiGraph.addEdge g1 n5 n10 9 - let g1 = DiGraph.addEdge g1 n7 n9 10 - let g1 = DiGraph.addEdge g1 n7 n11 11 - let g1 = DiGraph.addEdge g1 n8 n10 12 - let g1 = DiGraph.addEdge g1 n9 n12 13 - let g1 = DiGraph.addEdge g1 n9 n13 14 - let g1 = DiGraph.addEdge g1 n10 n19 15 - let g1 = DiGraph.addEdge g1 n11 n22 16 - let g1 = DiGraph.addEdge g1 n12 n13 17 - let g1 = DiGraph.addEdge g1 n13 n14 18 - let g1 = DiGraph.addEdge g1 n13 n15 19 - let g1 = DiGraph.addEdge g1 n14 n16 20 - let g1 = DiGraph.addEdge g1 n15 n16 21 - let g1 = DiGraph.addEdge g1 n16 n17 22 - let g1 = DiGraph.addEdge g1 n16 n18 23 - let g1 = DiGraph.addEdge g1 n17 n18 24 - let g1 = DiGraph.addEdge g1 n18 n19 25 - let g1 = DiGraph.addEdge g1 n18 n20 26 - let g1 = DiGraph.addEdge g1 n19 n21 27 - let g1 = DiGraph.addEdge g1 n19 n23 28 - let g1 = DiGraph.addEdge g1 n20 n22 29 - let g1 = DiGraph.addEdge g1 n21 n22 30 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - [] - member __.``Dominator Test``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v19 - Assert.IsTrue (18 <> getVertexVal v) - -[] -type ImperativeSCCTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - - (* Example from article about Bourdoncle Components by Matt Elder *) - [] - member __.``Strongly Connected Component Test1`` () = - let g = RangedDiGraph.init -1 ImperativeGraph - let n1, g = DiGraph.addVertex g v1 - let n2, g = DiGraph.addVertex g v2 - let n3, g = DiGraph.addVertex g v3 - let n4, g = DiGraph.addVertex g v4 - let n5, g = DiGraph.addVertex g v5 - let n6, g = DiGraph.addVertex g v6 - let n7, g = DiGraph.addVertex g v7 - let n8, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n2 n3 2 - let g = DiGraph.addEdge g n3 n4 3 - let g = DiGraph.addEdge g n4 n5 4 - let g = DiGraph.addEdge g n5 n2 5 - let g = DiGraph.addEdge g n5 n6 6 - let g = DiGraph.addEdge g n6 n3 7 - let g = DiGraph.addEdge g n6 n7 8 - let g = DiGraph.addEdge g n7 n2 9 - let g = DiGraph.addEdge g n7 n8 10 - let sccs = SCC.compute g n1 - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.singleton n1 - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.singleton n8 - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ n2 ; n3 ; n4 ; n5 ; n6 ; n7 ] - Assert.IsTrue (Set.contains scc3 sccs) - - (* Example from Wikipedia *) - [] - member __.``Strongly Connected Component Test2`` () = - let g = RangedDiGraph.init -1 ImperativeGraph - let na, g = DiGraph.addVertex g v1 - let nb, g = DiGraph.addVertex g v2 - let nc, g = DiGraph.addVertex g v3 - let nd, g = DiGraph.addVertex g v4 - let ne, g = DiGraph.addVertex g v5 - let nf, g = DiGraph.addVertex g v6 - let ng, g = DiGraph.addVertex g v7 - let nh, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g na nb 1 - let g = DiGraph.addEdge g nb nc 2 - let g = DiGraph.addEdge g nb ne 3 - let g = DiGraph.addEdge g nb nf 4 - let g = DiGraph.addEdge g nc nd 5 - let g = DiGraph.addEdge g nc ng 6 - let g = DiGraph.addEdge g nd nc 7 - let g = DiGraph.addEdge g nd nh 8 - let g = DiGraph.addEdge g ne na 9 - let g = DiGraph.addEdge g ne nf 10 - let g = DiGraph.addEdge g nf ng 11 - let g = DiGraph.addEdge g ng nf 12 - let g = DiGraph.addEdge g nh nd 13 - let g = DiGraph.addEdge g nh ng 14 - let sccs = SCC.compute g na - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.ofList [ na ; nb ; ne ] - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.ofList [ nc ; nd ; nh ] - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ nf ; ng ] - Assert.IsTrue (Set.contains scc3 sccs) diff --git a/src/MiddleEnd/BinGraph.Tests/Loop.Tests.fs b/src/MiddleEnd/BinGraph.Tests/Loop.Tests.fs deleted file mode 100644 index 65a6be0e..00000000 --- a/src/MiddleEnd/BinGraph.Tests/Loop.Tests.fs +++ /dev/null @@ -1,85 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph.Tests - -open B2R2 -open B2R2.MiddleEnd.BinGraph -open Microsoft.VisualStudio.TestTools.UnitTesting - -[] -type LoopTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - let v9 = V (9, (AddrRange (9UL))) - let v10 = V (10, (AddrRange (10UL))) - - (* Graph example from Dragon Book (Fig. 9.38) *) - let g1 = RangedDiGraph.init -1 ImperativeGraph - let n1, g1 = DiGraph.addVertex g1 v1 // Node 1 - let n2, g1 = DiGraph.addVertex g1 v2 // Node 2 - let n3, g1 = DiGraph.addVertex g1 v3 // Node 3 - let n4, g1 = DiGraph.addVertex g1 v4 // Node 4 - let n5, g1 = DiGraph.addVertex g1 v5 // Node 5 - let n6, g1 = DiGraph.addVertex g1 v6 // Node 6 - let n7, g1 = DiGraph.addVertex g1 v7 // Node 7 - let n8, g1 = DiGraph.addVertex g1 v8 // Node 8 - let n9, g1 = DiGraph.addVertex g1 v9 // Node 9 - let n10, g1 = DiGraph.addVertex g1 v10// Node 10 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n1 n3 2 - let g1 = DiGraph.addEdge g1 n2 n3 3 - let g1 = DiGraph.addEdge g1 n3 n4 4 - let g1 = DiGraph.addEdge g1 n4 n3 5 - let g1 = DiGraph.addEdge g1 n4 n5 6 - let g1 = DiGraph.addEdge g1 n4 n6 7 - let g1 = DiGraph.addEdge g1 n5 n7 8 - let g1 = DiGraph.addEdge g1 n6 n7 9 - let g1 = DiGraph.addEdge g1 n7 n4 10 - let g1 = DiGraph.addEdge g1 n7 n8 11 - let g1 = DiGraph.addEdge g1 n8 n3 12 - let g1 = DiGraph.addEdge g1 n8 n9 13 - let g1 = DiGraph.addEdge g1 n8 n10 14 - let g1 = DiGraph.addEdge g1 n9 n1 15 - let g1 = DiGraph.addEdge g1 n10 n7 16 - let g1root = n1 - - [] - member __.`` Natural Loop Test ``() = - let s = - Loop.getNaturalLoops g1 g1root - |> Seq.toArray - - Assert.AreEqual (5, s.Length) - Assert.IsFalse (s[0].Contains n9) - Assert.IsTrue (s[1].Contains n10) - Assert.IsFalse (s[2].Contains n1) - Assert.IsTrue (s[3].Contains n7) - Assert.IsTrue (s[4].Contains n8) diff --git a/src/MiddleEnd/BinGraph.Tests/PersistentGraph.Tests.fs b/src/MiddleEnd/BinGraph.Tests/PersistentGraph.Tests.fs deleted file mode 100644 index 5a0737c8..00000000 --- a/src/MiddleEnd/BinGraph.Tests/PersistentGraph.Tests.fs +++ /dev/null @@ -1,473 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph.Tests - -open B2R2 -open B2R2.MiddleEnd.BinGraph -open Microsoft.VisualStudio.TestTools.UnitTesting - -[] -type BasicPersistentGraphTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - let v9 = V (9, (AddrRange (9UL))) - let v10 = V (10, (AddrRange (10UL))) - let v11 = V (11, (AddrRange (11UL))) - let v12 = V (12, (AddrRange (12UL))) - let v13 = V (13, (AddrRange (13UL))) - - (* Graph example from Wikipedia. *) - let g1 = RangedDiGraph.init -1 PersistentGraph - let n1, g1 = DiGraph.addVertex g1 v1 // Node 1 - let n2, g1 = DiGraph.addVertex g1 v2 // Node 2 - let n3, g1 = DiGraph.addVertex g1 v3 // Node 3 - let n4, g1 = DiGraph.addVertex g1 v4 // Node 4 - let n5, g1 = DiGraph.addVertex g1 v5 // Node 5 - let n6, g1 = DiGraph.addVertex g1 v6 // Node 6 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n2 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n6 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n4 n5 6 - let g1 = DiGraph.addEdge g1 n5 n2 7 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - (* Graph example from Tiger book. *) - let g2 = RangedDiGraph.init -1 PersistentGraph - let n1, g2 = DiGraph.addVertex g2 v1 // Node 1 - let n2, g2 = DiGraph.addVertex g2 v2 // Node 2 - let n3, g2 = DiGraph.addVertex g2 v3 // Node 3 - let n4, g2 = DiGraph.addVertex g2 v4 // Node 4 - let n5, g2 = DiGraph.addVertex g2 v5 // Node 5 - let n6, g2 = DiGraph.addVertex g2 v6 // Node 6 - let g2 = DiGraph.addEdge g2 n1 n2 1 - let g2 = DiGraph.addEdge g2 n1 n3 2 - let g2 = DiGraph.addEdge g2 n3 n4 3 - let g2 = DiGraph.addEdge g2 n4 n5 4 - let g2 = DiGraph.addEdge g2 n4 n6 5 - let g2 = DiGraph.addEdge g2 n6 n4 6 - let g2root = n1 - let ctxt2 = Dominator.initDominatorContext g2 g2root - - (* Arbitrary graph example *) - let g3 = RangedDiGraph.init -1 PersistentGraph - let n1, g3 = DiGraph.addVertex g3 v1 // Node 1 - let n2, g3 = DiGraph.addVertex g3 v2 // Node 2 - let n3, g3 = DiGraph.addVertex g3 v3 // Node 3 - let n4, g3 = DiGraph.addVertex g3 v4 // Node 4 - let n5, g3 = DiGraph.addVertex g3 v5 // Node 5 - let g3 = DiGraph.addEdge g3 n1 n2 1 - let g3 = DiGraph.addEdge g3 n1 n3 2 - let g3 = DiGraph.addEdge g3 n2 n4 3 - let g3 = DiGraph.addEdge g3 n3 n4 4 - let g3 = DiGraph.addEdge g3 n3 n5 5 - let g3root = n1 - let ctxt3 = Dominator.initDominatorContext g3 g3root - - (* Graph example from Tiger book (Fig. 19.5) *) - let g4 = RangedDiGraph.init -1 PersistentGraph - let n1, g4 = DiGraph.addVertex g4 v1 - let n2, g4 = DiGraph.addVertex g4 v2 - let n3, g4 = DiGraph.addVertex g4 v3 - let n4, g4 = DiGraph.addVertex g4 v4 - let n5, g4 = DiGraph.addVertex g4 v5 - let n6, g4 = DiGraph.addVertex g4 v6 - let n7, g4 = DiGraph.addVertex g4 v7 - let n8, g4 = DiGraph.addVertex g4 v8 - let n9, g4 = DiGraph.addVertex g4 v9 - let n10, g4 = DiGraph.addVertex g4 v10 - let n11, g4 = DiGraph.addVertex g4 v11 - let n12, g4 = DiGraph.addVertex g4 v12 - let n13, g4 = DiGraph.addVertex g4 v13 - let g4 = DiGraph.addEdge g4 n1 n2 1 - let g4 = DiGraph.addEdge g4 n1 n5 2 - let g4 = DiGraph.addEdge g4 n1 n9 3 - let g4 = DiGraph.addEdge g4 n2 n3 4 - let g4 = DiGraph.addEdge g4 n3 n3 5 - let g4 = DiGraph.addEdge g4 n3 n4 6 - let g4 = DiGraph.addEdge g4 n4 n13 7 - let g4 = DiGraph.addEdge g4 n5 n6 8 - let g4 = DiGraph.addEdge g4 n5 n7 9 - let g4 = DiGraph.addEdge g4 n6 n4 10 - let g4 = DiGraph.addEdge g4 n6 n8 11 - let g4 = DiGraph.addEdge g4 n7 n8 12 - let g4 = DiGraph.addEdge g4 n7 n12 13 - let g4 = DiGraph.addEdge g4 n8 n5 14 - let g4 = DiGraph.addEdge g4 n8 n13 15 - let g4 = DiGraph.addEdge g4 n9 n10 16 - let g4 = DiGraph.addEdge g4 n9 n11 17 - let g4 = DiGraph.addEdge g4 n10 n12 18 - let g4 = DiGraph.addEdge g4 n11 n12 19 - let g4 = DiGraph.addEdge g4 n12 n13 20 - let g4root = n1 - let ctxt4 = Dominator.initDominatorContext g4 g4root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - let sum acc (v: Vertex) = v.VData.Val + acc - let inc acc _v1 _v2 e = acc + e - - [] - member __.``RangedDiGraph Traversal Test 1``() = - let s1 = Traversal.foldPostorder g1 [g1root] sum 0 - let s2 = Traversal.foldRevPostorder g1 [g1root] sum 0 - let s3 = Traversal.foldPreorder g1 [g1root] sum 0 - let s4 = DiGraph.foldVertex g1 sum 0 - let s5 = DiGraph.foldEdge g1 inc 0 - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - Assert.AreEqual (21, s3) - Assert.AreEqual (21, s4) - Assert.AreEqual (28, s5) - - [] - member __.``RangedDiGraph Traversal Test 2``() = - let s1 = - Traversal.foldPostorder g1 [g1root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s2 = - Traversal.foldPreorder g1 [g1root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s3 = - Traversal.foldPostorder g3 [g3root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - let s4 = - Traversal.foldPreorder g3 [g3root] (fun acc v -> v.VData.Val :: acc) [] - |> List.rev |> List.toArray - CollectionAssert.AreEqual ([| 5; 3; 4; 6; 2; 1 |], s1) - CollectionAssert.AreEqual ([| 1; 2; 3; 5; 4; 6 |], s2) - CollectionAssert.AreEqual ([| 4; 2; 5; 3; 1 |], s3) - CollectionAssert.AreEqual ([| 1; 2; 4; 3; 5 |], s4) - - [] - member __.``RangedDiGraph Removal Test``() = - let g2 = g1.Clone () - let g2root = DiGraph.findVertexByData g2 g1root.VData - let g2 = - (g2 :?> RangedDiGraph<_, _>).FindVertexByRange (AddrRange (3UL)) - |> DiGraph.removeVertex g2 - let s1 = Traversal.foldPreorder g1 [g1root] sum 0 - let s2 = Traversal.foldPreorder g2 [g2root] sum 0 - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (5, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (18, s2) - - [] - member __.``Graph Transposition Test``() = - let g2 = DiGraph.reverse g1 - let g2root = DiGraph.findVertexByData g2 v6 - let s1 = Traversal.foldPreorder g1 [g1root] sum 0 - let s2 = Traversal.foldPreorder g2 [g2root] sum 0 - let lst = - g2.FoldEdge (fun acc s d _ -> (s.VData.Val, d.VData.Val) :: acc) [] - let edges = List.sort lst |> List.toArray - let solution = [| (2, 1); (2, 5); (3, 2); (4, 2); (5, 3); (5, 4); (6, 2) |] - Assert.AreEqual (6, DiGraph.getSize g1) - Assert.AreEqual (6, DiGraph.getSize g2) - Assert.AreEqual (21, s1) - Assert.AreEqual (21, s2) - CollectionAssert.AreEqual (edges, solution) - - [] - member __.``Dominator Test 1``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.AreEqual (2, getVertexVal v) - - [] - member __.``Dominator Test 2``() = - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v4 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v5 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.idom ctxt2 <| DiGraph.findVertexByData g2 v6 - Assert.AreEqual (4, getVertexVal v) - - [] - member __.``Post-Dominator Test``() = - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v1 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v2 - Assert.AreEqual (6, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v3 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v4 - Assert.AreEqual (5, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v5 - Assert.AreEqual (2, getVertexVal v) - let v = Dominator.ipdom ctxt1 <| DiGraph.findVertexByData g1 v6 - Assert.IsTrue (v.IsNone) - - [] - member __.``Post-Dominator Test 2``() = - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v2 - Assert.AreEqual (4, getVertexVal v) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v3 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v4 - Assert.IsTrue (v.IsNone) - let v = Dominator.ipdom ctxt3 <| DiGraph.findVertexByData g3 v5 - Assert.IsTrue (v.IsNone) - - [] - member __.``Dominance Frontier Test``() = - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v5 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|4; 5; 12; 13|]) - let df = - Dominator.frontier ctxt4 <| DiGraph.findVertexByData g4 v9 |> List.toArray - let df = df |> Array.map (fun v -> v.VData.Val) |> Array.sort - CollectionAssert.AreEqual (df, [|12|]) - - [] - member __.``Root Node Loop Test``() = - let g = RangedDiGraph.init -1 PersistentGraph - let n1, g = DiGraph.addVertex g v1 // Node 1 - let n2, g = DiGraph.addVertex g v2 // Node 2 - let n3, g = DiGraph.addVertex g v3 // Node 3 - let n4, g = DiGraph.addVertex g v4 // Node 4 - let n5, g = DiGraph.addVertex g v5 // Node 5 - let n6, g = DiGraph.addVertex g v6 // Node 6 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n1 n3 2 - let g = DiGraph.addEdge g n2 n4 3 - let g = DiGraph.addEdge g n3 n4 4 - let g = DiGraph.addEdge g n3 n5 5 - let g = DiGraph.addEdge g n4 n6 6 - let g = DiGraph.addEdge g n5 n6 7 - let g = DiGraph.addEdge g n6 n1 8 // Back edge to the root node. - let ctxt = Dominator.initDominatorContext g n1 - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v1 - Assert.IsTrue (v.IsNone) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v2 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v3 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v4 - Assert.AreEqual (1, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v5 - Assert.AreEqual (3, getVertexVal v) - let v = Dominator.idom ctxt <| DiGraph.findVertexByData g v6 - Assert.AreEqual (1, getVertexVal v) - - [] - member __.``Basic SCC Test``() = - let v = DiGraph.findVertexByData g3 v1 - let sccs = SCC.compute g3 v - Assert.AreEqual (5, Set.count sccs) - -[] -type ExtraPersistentDomTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - let v9 = V (9, (AddrRange (9UL))) - let v10 = V (10, (AddrRange (10UL))) - let v11 = V (11, (AddrRange (11UL))) - let v12 = V (12, (AddrRange (12UL))) - let v13 = V (13, (AddrRange (13UL))) - let v14 = V (14, (AddrRange (14UL))) - let v15 = V (15, (AddrRange (15UL))) - let v16 = V (16, (AddrRange (16UL))) - let v17 = V (17, (AddrRange (17UL))) - let v18 = V (18, (AddrRange (18UL))) - let v19 = V (19, (AddrRange (19UL))) - let v20 = V (20, (AddrRange (20UL))) - let v21 = V (21, (AddrRange (21UL))) - let v22 = V (22, (AddrRange (22UL))) - let v23 = V (23, (AddrRange (23UL))) - - let g1 = RangedDiGraph.init -1 PersistentGraph - let n1, g1 = DiGraph.addVertex g1 v1 - let n2, g1 = DiGraph.addVertex g1 v2 - let n3, g1 = DiGraph.addVertex g1 v3 - let n4, g1 = DiGraph.addVertex g1 v4 - let n5, g1 = DiGraph.addVertex g1 v5 - let n6, g1 = DiGraph.addVertex g1 v6 - let n7, g1 = DiGraph.addVertex g1 v7 - let n8, g1 = DiGraph.addVertex g1 v8 - let n9, g1 = DiGraph.addVertex g1 v9 - let n10, g1 = DiGraph.addVertex g1 v10 - let n11, g1 = DiGraph.addVertex g1 v11 - let n12, g1 = DiGraph.addVertex g1 v12 - let n13, g1 = DiGraph.addVertex g1 v13 - let n14, g1 = DiGraph.addVertex g1 v14 - let n15, g1 = DiGraph.addVertex g1 v15 - let n16, g1 = DiGraph.addVertex g1 v16 - let n17, g1 = DiGraph.addVertex g1 v17 - let n18, g1 = DiGraph.addVertex g1 v18 - let n19, g1 = DiGraph.addVertex g1 v19 - let n20, g1 = DiGraph.addVertex g1 v20 - let n21, g1 = DiGraph.addVertex g1 v21 - let n22, g1 = DiGraph.addVertex g1 v22 - let n23, g1 = DiGraph.addVertex g1 v23 - let g1 = DiGraph.addEdge g1 n1 n2 1 - let g1 = DiGraph.addEdge g1 n1 n3 2 - let g1 = DiGraph.addEdge g1 n2 n4 3 - let g1 = DiGraph.addEdge g1 n2 n7 4 - let g1 = DiGraph.addEdge g1 n3 n5 5 - let g1 = DiGraph.addEdge g1 n3 n6 6 - let g1 = DiGraph.addEdge g1 n4 n7 7 - let g1 = DiGraph.addEdge g1 n5 n8 8 - let g1 = DiGraph.addEdge g1 n5 n10 9 - let g1 = DiGraph.addEdge g1 n7 n9 10 - let g1 = DiGraph.addEdge g1 n7 n11 11 - let g1 = DiGraph.addEdge g1 n8 n10 12 - let g1 = DiGraph.addEdge g1 n9 n12 13 - let g1 = DiGraph.addEdge g1 n9 n13 14 - let g1 = DiGraph.addEdge g1 n10 n19 15 - let g1 = DiGraph.addEdge g1 n11 n22 16 - let g1 = DiGraph.addEdge g1 n12 n13 17 - let g1 = DiGraph.addEdge g1 n13 n14 18 - let g1 = DiGraph.addEdge g1 n13 n15 19 - let g1 = DiGraph.addEdge g1 n14 n16 20 - let g1 = DiGraph.addEdge g1 n15 n16 21 - let g1 = DiGraph.addEdge g1 n16 n17 22 - let g1 = DiGraph.addEdge g1 n16 n18 23 - let g1 = DiGraph.addEdge g1 n17 n18 24 - let g1 = DiGraph.addEdge g1 n18 n19 25 - let g1 = DiGraph.addEdge g1 n18 n20 26 - let g1 = DiGraph.addEdge g1 n19 n21 27 - let g1 = DiGraph.addEdge g1 n19 n23 28 - let g1 = DiGraph.addEdge g1 n20 n22 29 - let g1 = DiGraph.addEdge g1 n21 n22 30 - let g1root = n1 - let ctxt1 = Dominator.initDominatorContext g1 g1root - - let getVertexVal (v: Vertex option) = (Option.get v).VData.Val - - [] - member __.``Dominator Test``() = - let v = Dominator.idom ctxt1 <| DiGraph.findVertexByData g1 v19 - Assert.IsTrue (18 <> getVertexVal v) - -[] -type PersistentSCCTest () = - let v1 = V (1, (AddrRange (1UL))) - let v2 = V (2, (AddrRange (2UL))) - let v3 = V (3, (AddrRange (3UL))) - let v4 = V (4, (AddrRange (4UL))) - let v5 = V (5, (AddrRange (5UL))) - let v6 = V (6, (AddrRange (6UL))) - let v7 = V (7, (AddrRange (7UL))) - let v8 = V (8, (AddrRange (8UL))) - - (* Example from article about Bourdoncle Components by Matt Elder *) - [] - member __.``Strongly Connected Component Test1`` () = - let g = RangedDiGraph.init -1 PersistentGraph - let n1, g = DiGraph.addVertex g v1 - let n2, g = DiGraph.addVertex g v2 - let n3, g = DiGraph.addVertex g v3 - let n4, g = DiGraph.addVertex g v4 - let n5, g = DiGraph.addVertex g v5 - let n6, g = DiGraph.addVertex g v6 - let n7, g = DiGraph.addVertex g v7 - let n8, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g n1 n2 1 - let g = DiGraph.addEdge g n2 n3 2 - let g = DiGraph.addEdge g n3 n4 3 - let g = DiGraph.addEdge g n4 n5 4 - let g = DiGraph.addEdge g n5 n2 5 - let g = DiGraph.addEdge g n5 n6 6 - let g = DiGraph.addEdge g n6 n3 7 - let g = DiGraph.addEdge g n6 n7 8 - let g = DiGraph.addEdge g n7 n2 9 - let g = DiGraph.addEdge g n7 n8 10 - let sccs = SCC.compute g n1 - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.singleton n1 - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.singleton n8 - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ n2 ; n3 ; n4 ; n5 ; n6 ; n7 ] - Assert.IsTrue (Set.contains scc3 sccs) - - (* Example from Wikipedia *) - [] - member __.``Strongly Connected Component Test2`` () = - let g = RangedDiGraph.init -1 PersistentGraph - let na, g = DiGraph.addVertex g v1 - let nb, g = DiGraph.addVertex g v2 - let nc, g = DiGraph.addVertex g v3 - let nd, g = DiGraph.addVertex g v4 - let ne, g = DiGraph.addVertex g v5 - let nf, g = DiGraph.addVertex g v6 - let ng, g = DiGraph.addVertex g v7 - let nh, g = DiGraph.addVertex g v8 - let g = DiGraph.addEdge g na nb 1 - let g = DiGraph.addEdge g nb nc 2 - let g = DiGraph.addEdge g nb ne 3 - let g = DiGraph.addEdge g nb nf 4 - let g = DiGraph.addEdge g nc nd 5 - let g = DiGraph.addEdge g nc ng 6 - let g = DiGraph.addEdge g nd nc 7 - let g = DiGraph.addEdge g nd nh 8 - let g = DiGraph.addEdge g ne na 9 - let g = DiGraph.addEdge g ne nf 10 - let g = DiGraph.addEdge g nf ng 11 - let g = DiGraph.addEdge g ng nf 12 - let g = DiGraph.addEdge g nh nd 13 - let g = DiGraph.addEdge g nh ng 14 - let sccs = SCC.compute g na - Assert.AreEqual (3, Set.count sccs) - let scc1 = Set.ofList [ na ; nb ; ne ] - Assert.IsTrue (Set.contains scc1 sccs) - let scc2 = Set.ofList [ nc ; nd ; nh ] - Assert.IsTrue (Set.contains scc2 sccs) - let scc3 = Set.ofList [ nf ; ng ] - Assert.IsTrue (Set.contains scc3 sccs) diff --git a/src/MiddleEnd/BinGraph/B2R2.MiddleEnd.BinGraph.fsproj b/src/MiddleEnd/BinGraph/B2R2.MiddleEnd.BinGraph.fsproj deleted file mode 100644 index 0e104988..00000000 --- a/src/MiddleEnd/BinGraph/B2R2.MiddleEnd.BinGraph.fsproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - LICENSE.md - b2r2-240x240.png - README.md - B2R2 graph library. - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/BinGraph/DiGraph.fs b/src/MiddleEnd/BinGraph/DiGraph.fs deleted file mode 100644 index cd3d477d..00000000 --- a/src/MiddleEnd/BinGraph/DiGraph.fs +++ /dev/null @@ -1,283 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -[] -type DiGraph<'D, 'E when 'D :> VertexData and 'D : equality> - (core: GraphCore<'D, 'E, DiGraph<'D, 'E>>) = - inherit Graph<'D, 'E, DiGraph<'D, 'E>> () - - override __.ImplementationType = core.ImplementationType - - override __.IsEmpty () = core.GetSize () = 0 - - override __.GetSize () = core.GetSize () - - override __.AddVertex data = - let v, g = core.AddVertex __ data - v, g - - override __.RemoveVertex vid = - core.RemoveVertex __ vid - - override __.GetVertices () = - core.Vertices - - override __.ExistsVertex vid = - match core.TryFindVertexBy (fun v -> v.GetID () = vid) with - | Some _ -> true - | None -> false - - override __.FindVertexByID vid = - core.FindVertexBy (fun v -> v.GetID () = vid) - - override __.TryFindVertexByID vid = - core.TryFindVertexBy (fun v -> v.GetID () = vid) - |> Option.bind (fun v -> v |> Some) - - override __.FindVertexByData data = - core.FindVertexBy (fun v -> - if v.IsDummy () then false else v.VData = data) - - override __.TryFindVertexByData data = - core.TryFindVertexBy (fun v -> - if v.IsDummy () then false else v.VData = data) - |> Option.bind (fun v -> v |> Some) - - override __.FindVertexBy fn = - core.FindVertexBy fn - - override __.TryFindVertexBy fn = - core.TryFindVertexBy fn |> Option.bind (fun v -> v |> Some) - - override __.AddEdge srcid dstid e = - core.AddEdge __ srcid dstid e - - override __.RemoveEdge srcid dstid = - core.RemoveEdge __ srcid dstid - - override __.FindEdgeData src dst = - core.FindEdge src dst - - override __.TryFindEdgeData src dst = - core.TryFindEdge src dst - - override __.FoldVertex fn acc = - core.FoldVertex fn acc - - override __.IterVertex fn = - core.IterVertex fn - - override __.FoldEdge fn acc = - core.FoldEdge fn acc - - override __.IterEdge fn = - core.IterEdge fn - - override __.Clone () = - core.InitGraph (Some core) - - override __.SubGraph vs = - let g = core.InitGraph None - (* Add vertices to new graph *) - let g = - vs |> Set.fold (fun (g: DiGraph<'D, 'E>) (v: Vertex<'D>) -> - g.AddVertex v.VData |> snd) g - (* Collect edges both ends are in vids *) - let es = - [] |> __.FoldEdge (fun acc src dst e -> - if Set.contains src vs && Set.contains dst vs then - (src, dst, e) :: acc - else acc) - (* Add edges to new graph *) - List.fold (fun g (src: Vertex<_>, dst: Vertex<_>, e) -> - let src = g.FindVertexByID <| src.GetID () - let dst = g.FindVertexByID <| dst.GetID () - g.AddEdge src dst e) g es - - override __.ToDOTStr name vToStrFn _eToStrFn = - let inline strAppend (s: string) (sb: System.Text.StringBuilder) = - sb.Append(s) - let folder sb src dst _edata = - strAppend (vToStrFn src) sb - |> strAppend " -> " - |> strAppend (vToStrFn dst) - |> strAppend " [label=\"" - |> strAppend "\"];\n" - let sb = System.Text.StringBuilder () - let sb = strAppend "digraph " sb |> strAppend name |> strAppend " {\n" - let sb = __.FoldEdge folder sb - sb.Append("}\n").ToString() - - /// A list of unreachable nodes. We always add nodes into this list first, and - /// then later remove it from the list when adding edges. - member __.Unreachables = core.Unreachables - - /// A list of exit nodes, which do not have any successors. - member __.Exits = core.Exits - - member __.GetPreds vid = core.GetPreds vid - - member __.GetSuccs vid = core.GetSuccs vid - - member __.AddDummyVertex () = - let v, g = core.AddDummyVertex __ - v, g - - member __.AddDummyEdge srcid dstid = - core.AddDummyEdge __ srcid dstid - - /// Return a new transposed (i.e., reversed) graph. - member __.Reverse () = - core.InitGraph None - |> __.FoldVertex (fun g v -> - if v.IsDummy () then g.AddDummyVertex () |> snd - else g.AddVertex v.VData |> snd) - |> __.FoldEdge (fun g src dst e -> - let src = g.FindVertexByID <| src.GetID () - let dst = g.FindVertexByID <| dst.GetID () - g.AddEdge dst src e) - - [] - static member isEmpty (g: DiGraph<'D, 'E>) = - g.IsEmpty () - - [] - static member getSize (g: DiGraph<'D, 'E>) = - g.GetSize () - - [] - static member addDummyVertex (g: DiGraph<'D, 'E>) = - g.AddDummyVertex () - - [] - static member addVertex (g: DiGraph<'D, 'E>) data = - g.AddVertex data - - [] - static member removeVertex (g: DiGraph<'D, 'E>) (v: Vertex<'D>)= - g.RemoveVertex v - - [] - static member getPreds (g: DiGraph<'D, 'E>) (v: Vertex<'D>) = - g.GetPreds v - - [] - static member getSuccs (g: DiGraph<'D, 'E>) (v: Vertex<'D>) = - g.GetSuccs v - - [] - static member getUnreachables (g: DiGraph<'D, 'E>) = - g.Unreachables - - [] - static member getExits (g: DiGraph<'D, 'E>) = - g.Exits - - [] - static member getVertices (g: DiGraph<'D, 'E>) = - g.GetVertices () - - [] - static member existsVertex (g: DiGraph<'D, 'E>) vid = - g.ExistsVertex vid - - [] - static member findVertexByID (g: DiGraph<'D, 'E>) vid = - g.FindVertexByID vid - - [] - static member tryFindVertexByID (g: DiGraph<'D, 'E>) vid = - g.TryFindVertexByID vid - - [] - static member findVertexByData (g: DiGraph<'D, 'E>) data = - g.FindVertexByData data - - [] - static member tryFindVertexByData (g: DiGraph<'D, 'E>) data = - g.TryFindVertexByData data - - [] - static member findVertexBy (g: DiGraph<'D, 'E>) fn = - g.FindVertexBy fn - - [] - static member tryFindVertexBy (g: DiGraph<'D, 'E>) fn = - g.TryFindVertexBy fn - - [] - static member addDummyEdge (g: DiGraph<'D, 'E>) src dst = - g.AddDummyEdge src dst - - [] - static member addEdge (g: DiGraph<'D, 'E>) src dst e = - g.AddEdge src dst e - - [] - static member removeEdge (g: DiGraph<'D, 'E>) src dst = - g.RemoveEdge src dst - - [] - static member findEdgeData (g: DiGraph<'D, 'E>) src dst = - g.FindEdgeData src dst - - [] - static member tryFindEdgeData (g: DiGraph<'D, 'E>) src dst = - g.TryFindEdgeData src dst - - [] - static member foldVertex (g: DiGraph<'D, 'E>) fn acc = - g.FoldVertex fn acc - - [] - static member iterVertex (g: DiGraph<'D, 'E>) fn = - g.IterVertex fn - - [] - static member foldEdge (g: DiGraph<'D, 'E>) fn acc = - g.FoldEdge fn acc - - [] - static member iterEdge (g: DiGraph<'D, 'E>) fn = - g.IterEdge fn - - [] - static member clone (g: DiGraph<'D, 'E>) = - g.Clone () - - [] - static member reverse (g: DiGraph<'D, 'E>) = - g.Reverse () - - [] - static member subGraph (g: DiGraph<'D, 'E>) vs = - g.SubGraph vs - - [] - static member toDOTStr (g: DiGraph<'D, 'E>) name vToStrfn eToStrFn = - g.ToDOTStr name vToStrfn eToStrFn - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/MiddleEnd/BinGraph/DiGraph.fsi b/src/MiddleEnd/BinGraph/DiGraph.fsi deleted file mode 100644 index cf53636d..00000000 --- a/src/MiddleEnd/BinGraph/DiGraph.fsi +++ /dev/null @@ -1,217 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -/// Directedg graph inehrited from Graph. This type is mostly used by primary -/// graph algorithms, such as the dominator algorithm. We only expose static -/// members here to make code consistent for both persistent and imperative -/// graphs. -[] -type DiGraph<'D, 'E when 'D :> VertexData and 'D : equality> = - inherit Graph<'D, 'E, DiGraph<'D, 'E>> - - new: GraphCore<'D, 'E, DiGraph<'D, 'E>> -> DiGraph<'D, 'E> - override private ImplementationType: GraphImplementationType - override private IsEmpty: unit -> bool - override private GetSize: unit -> int - override private AddVertex: 'D -> Vertex<'D> * DiGraph<'D, 'E> - override private RemoveVertex: Vertex<'D> -> DiGraph<'D, 'E> - override private GetVertices: unit -> Set> - override private ExistsVertex: VertexID -> bool - override private FindVertexByID: VertexID -> Vertex<'D> - override private TryFindVertexByID: VertexID -> Vertex<'D> option - override private FindVertexByData: 'D -> Vertex<'D> - override private TryFindVertexByData: 'D -> Vertex<'D> option - override private FindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> - override private TryFindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> option - override private AddEdge: Vertex<'D> -> Vertex<'D> -> 'E -> DiGraph<'D, 'E> - override private RemoveEdge: Vertex<'D> -> Vertex<'D> -> DiGraph<'D, 'E> - override private FindEdgeData: Vertex<'D> -> Vertex<'D> -> 'E - override private TryFindEdgeData: Vertex<'D> -> Vertex<'D> -> 'E option - override private FoldVertex: ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - override private IterVertex: (Vertex<'D> -> unit) -> unit - override private FoldEdge: - ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - override private IterEdge: (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - override private Clone: unit -> DiGraph<'D, 'E> - override private SubGraph: Set> -> DiGraph<'D, 'E> - override private ToDOTStr: - string -> (Vertex<'D> -> string) -> (Edge<'E> -> string) -> string - - /// Check if the graph is empty. - [] - static member isEmpty: DiGraph<'D, 'E> -> bool - - /// Get the number of vertices of the graph. - [] - static member getSize: DiGraph<'D, 'E> -> int - - /// Add a dummy vertex to the graph. Dummy nodes are necessary when we run - /// some graph algorithms, and such nodes should be removed appropriately - /// before we return the final results. - [] - static member addDummyVertex: - DiGraph<'D, 'E> -> Vertex<'D> * DiGraph<'D, 'E> - - /// Add a vertex to the graph. - [] - static member addVertex: - DiGraph<'D, 'E> -> 'D -> Vertex<'D> * DiGraph<'D, 'E> - - /// Remove a vertex from the graph. - [] - static member removeVertex: - DiGraph<'D, 'E> -> Vertex<'D> -> DiGraph<'D, 'E> - - /// Get the predecessors of the given vertex in the graph. - [] - static member getPreds: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - - /// Get the successors of the given vertex in the graph. - [] - static member getSuccs: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - - /// Get unreachable nodes from the graph. - [] - static member getUnreachables: DiGraph<'D, 'E> -> Vertex<'D> list - - /// Get leaf (exit) nodes from the graph. - [] - static member getExits: DiGraph<'D, 'E> -> Vertex<'D> list - - /// Get the whole set of vertices from the graph. - [] - static member getVertices: DiGraph<'D, 'E> -> Set> - - /// Check if the given vertex exists in the graph. - [] - static member existsVertex: DiGraph<'D, 'E> -> VertexID -> bool - - /// Find vertex by VertexID. This function raises an exception when the given - /// ID does not exist in the graph. - [] - static member findVertexByID: - DiGraph<'D, 'E> -> VertexID -> Vertex<'D> - - /// Try to find vertex by VertexID. - [] - static member tryFindVertexByID: - DiGraph<'D, 'E> -> VertexID -> Vertex<'D> option - - /// Find vertex by given data. This function raises an exception when there is - /// no matching vertex in the graph. - [] - static member findVertexByData: - DiGraph<'D, 'E> -> 'D -> Vertex<'D> - - /// Try to find vertex by given data. - [] - static member tryFindVertexByData: - DiGraph<'D, 'E> -> 'D -> Vertex<'D> option - - /// Find vertex by the given predicate. This function raises an exception when - /// there is no matching vertex. - [] - static member findVertexBy: - DiGraph<'D, 'E> -> (Vertex<'D> -> bool) -> Vertex<'D> - - /// Try to find vertex by given data. - [] - static member tryFindVertexBy: - DiGraph<'D, 'E> -> (Vertex<'D> -> bool) -> Vertex<'D> option - - /// Add an edge to the graph without attaching data to it. - [] - static member addDummyEdge: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> DiGraph<'D, 'E> - - /// Add an edge to the graph. - [] - static member addEdge: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> 'E -> DiGraph<'D, 'E> - - /// Remove an edge from the graph. - [] - static member removeEdge: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> DiGraph<'D, 'E> - - /// Find an edge and return the data attached to it. This function raises an - /// exception when there is no matching edge. - [] - static member findEdgeData: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> 'E - - /// Try to find an edge and return the data attached to it. - [] - static member tryFindEdgeData: - DiGraph<'D, 'E> -> Vertex<'D> -> Vertex<'D> -> 'E option - - /// Fold vertices in the graph. - [] - static member foldVertex: - DiGraph<'D, 'E> -> ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - - /// Iterate vertices in the graph. - [] - static member iterVertex: - DiGraph<'D, 'E> -> (Vertex<'D> -> unit) -> unit - - /// Fold edges in the graph. - [] - static member foldEdge: - DiGraph<'D, 'E> -> ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - - /// Iterate edges in the graph. - [] - static member iterEdge: - DiGraph<'D, 'E> -> (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - - /// Clone a graph. For imperative graphs, this function involves deep copying. - [] - static member clone: - DiGraph<'D, 'E> -> DiGraph<'D, 'E> - - /// Create a reverse graph. - [] - static member reverse: - DiGraph<'D, 'E> -> DiGraph<'D, 'E> - - /// Return a subgraph of the given vertices. - [] - static member subGraph: - DiGraph<'D, 'E> -> Set> -> DiGraph<'D, 'E> - - /// Return a DOT-formatted string from the graph. - [] - static member toDOTStr: - DiGraph<'D, 'E> - -> string - -> (Vertex<'D> -> string) - -> (Edge<'E> -> string) - -> string - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/MiddleEnd/BinGraph/Dominator.fs b/src/MiddleEnd/BinGraph/Dominator.fs deleted file mode 100644 index 39b9a2d6..00000000 --- a/src/MiddleEnd/BinGraph/Dominator.fs +++ /dev/null @@ -1,336 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.BinGraph.Dominator - -open B2R2.Utils -open System.Collections.Generic - -type DomInfo<'D when 'D :> VertexData> = { - /// Vertex ID -> DFNum - DFNumMap: Dictionary - /// DFNum -> Vertex - Vertex: Vertex<'D> [] - /// DFNum -> DFNum in the ancestor chain s.t. DFNum of its Semi is minimal. - Label: int [] - /// DFNum -> DFNum of the parent node (zero if not exists). - Parent: int [] - /// DFNum -> DFNum of the child node (zero if not exists). - Child: int [] - /// DFNum -> DFNum of an ancestor. - Ancestor: int [] - /// DFNum -> DFNum of a semidominator. - Semi: int [] - /// DFNum -> set of DFNums (vertices that share the same sdom). - Bucket: Set [] - /// DFNum -> Size - Size: int [] - /// DFNum -> DFNum of an immediate dominator. - IDom: int [] - /// Length of the arrays. - MaxLength: int -} - -/// Storing DomInfo of a graph. We use this to repeatedly compute doms/pdoms of -/// the same graph. -type DominatorContext<'D, 'E when 'D :> VertexData and 'D : equality> = { - ForwardGraph: DiGraph<'D, 'E> - ForwardRoot: Vertex<'D> - ForwardDomInfo: DomInfo<'D> - BackwardGraph: DiGraph<'D, 'E> - BackwardRoot: Vertex<'D> - BackwardDomInfo: DomInfo<'D> -} - -let initDomInfo g = - (* To reserve a room for entry (dummy) node. *) - let len = DiGraph.getSize g + 1 - { DFNumMap = Dictionary () - Vertex = Array.zeroCreate len - Label = Array.create len 0 - Parent = Array.create len 0 - Child = Array.create len 0 - Ancestor = Array.create len 0 - Semi = Array.create len 0 - Bucket = Array.create len Set.empty - Size = Array.create len 1 - IDom = Array.create len 0 - MaxLength = len } - -let inline dfnum (info: DomInfo<'D>) (v: Vertex<_>) = - info.DFNumMap[v.GetID ()] - -let rec assignDFNum g (info: DomInfo<'D>) n = function - | (p, v : Vertex<_>) :: stack - when not <| info.DFNumMap.ContainsKey (v.GetID ()) -> - info.DFNumMap.Add (v.GetID (), n) - info.Semi[n] <- n - info.Vertex[n] <- v - info.Label[n] <- n - info.Parent[n] <- p - DiGraph.getSuccs g v - |> List.fold (fun acc s -> (n, s) :: acc) stack - |> assignDFNum g info (n+1) - | _ :: stack -> assignDFNum g info n stack - | [] -> n - 1 - -let rec compress info v = - let a = info.Ancestor[v] - if info.Ancestor[a] <> 0 then - compress info a - if info.Semi[info.Label[a]] < info.Semi[info.Label[v]] then - info.Label[v] <- info.Label[a] - else () - info.Ancestor[v] <- info.Ancestor[a] - -let eval info v = - if info.Ancestor[v] = 0 then info.Label[v] - else - compress info v - if info.Semi[info.Label[info.Ancestor[v]]] >= info.Semi[info.Label[v]] - then info.Label[v] - else info.Label[info.Ancestor[v]] - -/// Compute semidominator of v. -let rec computeSemiDom info v = function - | pred :: preds -> - let u = eval info pred - if info.Semi[u] < info.Semi[v] then info.Semi[v] <- info.Semi[u] - computeSemiDom info v preds - | [] -> () - -let link info v w = - let mutable s = w - while info.Semi[info.Label[w]] < info.Semi[info.Label[info.Child[s]]] do - if info.Size[s] + info.Size[info.Child[info.Child[s]]] - >= 2 * info.Size[info.Child[s]] - then info.Ancestor[info.Child[s]] <- s - info.Child[s] <- info.Child[info.Child[s]] - else info.Size[info.Child[s]] <- info.Size[s] - info.Ancestor[s] <- info.Child[s] - s <- info.Ancestor[s] - done - info.Label[s] <- info.Label[w] - info.Size[v] <- info.Size[v] + info.Size[w] - if info.Size[v] < 2 * info.Size[w] then - let t = s - s <- info.Child[v] - info.Child[v] <- t - while s <> 0 do - info.Ancestor[s] <- v - s <- info.Child[s] - done - -let computeDom info p = - Set.iter (fun v -> - let u = eval info v - if info.Semi[u] < info.Semi[v] then info.IDom[v] <- u - else info.IDom[v] <- p) info.Bucket[p] - info.Bucket[p] <- Set.empty - -let rec computeDomOrDelay info parent = - if info.Bucket[parent].IsEmpty then () - else computeDom info parent - -let initDominator g root = - let info = initDomInfo g - let dummyEntry, g = DummyEntry.Connect g root - let n = assignDFNum g info 0 [(0, dummyEntry)] - for i = n downto 1 do - let v = info.Vertex[i] - let p = info.Parent[i] - DiGraph.getPreds g v |> List.map (dfnum info) |> computeSemiDom info i - info.Bucket[info.Semi[i]] <- Set.add i info.Bucket[info.Semi[i]] - link info p i (* Link the parent (p) to the forest. *) - computeDomOrDelay info p - done - for i = 1 to n do - if info.IDom[i] <> info.Semi[i] then - info.IDom[i] <- info.IDom[info.IDom[i]] - else () - done - DiGraph.removeVertex g dummyEntry |> ignore - info - -let updateReachMap g exits reachMap = - let rec loop reachMap = function - | [] -> reachMap - | (v: Vertex<_>) :: vs -> - let reachMap = Map.add (v.GetID ()) true reachMap - let vs = - DiGraph.getSuccs g v - |> List.fold (fun acc (w: Vertex<_>) -> - if Map.find (w.GetID ()) reachMap then acc else w :: acc) vs - loop reachMap vs - List.filter (fun (v: Vertex<_>) -> - not (Map.find (v.GetID ()) reachMap)) exits - |> loop reachMap - -let rec calculateExits (fg: DiGraph<_, _>) bg reachMap exits = - if Map.forall (fun _ b -> b) reachMap then exits - else - let reachMap = updateReachMap bg exits reachMap - let exits = - fg.FoldVertex (fun acc (v: Vertex<_>) -> - let isExit = DiGraph.getSuccs fg v |> List.length = 0 - if isExit && not <| Map.find (v.GetID ()) reachMap then - DiGraph.findVertexByID bg (v.GetID ()) :: acc - else acc) exits - calculateExits fg bg reachMap exits - -let preparePostDomAnalysis fg root (bg: DiGraph<_, _>) = - let _, orderMap = - Traversal.foldTopologically fg [root] (fun (cnt, map) v -> - cnt + 1, Map.add v cnt map) (0, Map.empty) - let fg, backEdges = - fg.FoldEdge (fun (fg, acc) (src: Vertex<_>) (dst: Vertex<_>) edge -> - if src.GetID () = dst.GetID () then - DiGraph.removeEdge fg src dst, (src, dst, edge) :: acc - else fg, acc) (fg, []) - let fg, backEdges = - fg.FoldEdge (fun (fg, acc) (src: Vertex<_>) (dst: Vertex<_>) edge -> - if Map.find src orderMap > Map.find dst orderMap then - DiGraph.removeEdge fg src dst, (src, dst, edge) :: acc - else fg, acc) (fg, backEdges) - let reachMap = - bg.FoldVertex (fun acc (v: Vertex<_>) -> - Map.add (v.GetID ()) false acc) Map.empty - let exits = - DiGraph.getUnreachables bg |> Seq.toList |> calculateExits fg bg reachMap - (* Restore backedges. This is needed for imperative graphs. *) - let _ = - backEdges - |> List.fold (fun fg (src, dst, e) -> DiGraph.addEdge fg src dst e) fg - let dummy, bg = DiGraph.addDummyVertex bg - let bg = exits |> List.fold (fun bg v -> DiGraph.addDummyEdge bg dummy v) bg - bg, dummy - -let initDominatorContext g root = - let forward = initDominator g root - let g', root' = DiGraph.reverse g |> preparePostDomAnalysis g root - let backward = initDominator g' root' - { ForwardGraph = g - ForwardRoot = root - ForwardDomInfo = forward - BackwardGraph = g' - BackwardRoot = root' - BackwardDomInfo = backward } - -let checkVertexInGraph g (v: Vertex<_>) = - let v' = DiGraph.findVertexByData g v.VData - if v === v' then () - else raise VertexNotFoundException - -let private idomAux info v = - let id = info.IDom[dfnum info v] - if id >= 1 then Some info.Vertex[id] else None - -let idom ctxt v = - let g = ctxt.ForwardGraph - checkVertexInGraph g v - idomAux ctxt.ForwardDomInfo v - -let ipdom ctxt (v: Vertex<_>) = - let g' = ctxt.BackwardGraph - let v = DiGraph.findVertexByData g' v.VData - idomAux ctxt.BackwardDomInfo v - -let rec domsAux acc v info = - let id = info.IDom[dfnum info v] - if id > 0 then domsAux (info.Vertex[id] :: acc) info.Vertex[id] info - else List.rev acc - -let doms ctxt v = - let g = ctxt.ForwardGraph - checkVertexInGraph g v - domsAux [] v ctxt.ForwardDomInfo - -let pdoms ctxt v = - domsAux [] v ctxt.BackwardDomInfo - -let computeDomTree g info = - let domTree = Array.create info.MaxLength [] - DiGraph.iterVertex g (fun v -> - let idom = info.IDom[dfnum info v] - domTree[idom] <- v :: domTree[idom]) - domTree - -let rec computeFrontierLocal s ctxt (parent: Vertex<_>) = function - | succ :: rest -> - let succID = dfnum ctxt succ - let d = ctxt.Vertex[ctxt.IDom[succID]] - let s = if d.GetID () = parent.GetID () then s else Set.add succID s - computeFrontierLocal s ctxt parent rest - | [] -> s - -let rec computeDF domTree (frontiers: Vertex<_> list []) g ctxt r = - let mutable s = Set.empty - for succ in DiGraph.getSuccs g r do - let succID = dfnum ctxt succ - let domID = ctxt.IDom[succID] - let d = ctxt.Vertex[ctxt.IDom[succID]] - if domID <> 0 && d.GetID () <> r.GetID () then s <- Set.add succID s - done - for child in (domTree: Vertex<_> list [])[dfnum ctxt r] do - computeDF domTree frontiers g ctxt child - for node in frontiers[dfnum ctxt child] do - let doms = domsAux [] node ctxt - let dominate = doms |> List.exists (fun d -> d.GetID () = r.GetID ()) - if not dominate then s <- Set.add (dfnum ctxt node) s - done - done - frontiers[dfnum ctxt r] <- Set.fold (fun df n -> ctxt.Vertex[n] :: df) [] s - -let frontier ctxt v = - let g = ctxt.ForwardGraph - checkVertexInGraph g v - let root = ctxt.ForwardRoot - let ctxt = ctxt.ForwardDomInfo - let frontiers = Array.create ctxt.MaxLength [] - let domTree = computeDomTree g ctxt - computeDF domTree frontiers g ctxt root - frontiers[dfnum ctxt v] - -let frontiers ctxt = - let g = ctxt.ForwardGraph - let root = ctxt.ForwardRoot - let ctxt = ctxt.ForwardDomInfo - let frontiers = Array.create ctxt.MaxLength [] - let domTree = computeDomTree g ctxt - computeDF domTree frontiers g ctxt root - frontiers - -let dominatorTree ctxt = - let g = ctxt.ForwardGraph - let info = ctxt.ForwardDomInfo - let tree = computeDomTree g info - let tree = Array.sub tree 1 (Array.length tree - 1) // Remove a dummy node - let root = info.Vertex[1] - let tree = - Array.mapi (fun dfNum vs -> dfNum, vs) tree - |> Array.fold (fun tree (dfNum, vs) -> - Map.add info.Vertex[dfNum + 1] vs tree) Map.empty - tree, root - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/MiddleEnd/BinGraph/Dominator.fsi b/src/MiddleEnd/BinGraph/Dominator.fsi deleted file mode 100644 index 64987454..00000000 --- a/src/MiddleEnd/BinGraph/Dominator.fsi +++ /dev/null @@ -1,83 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.BinGraph.Dominator - -open System.Collections.Generic - -type DomInfo<'D when 'D :> VertexData> = { - /// Vertex ID -> DFNum - DFNumMap: Dictionary - /// DFNum -> Vertex - Vertex: Vertex<'D> [] - /// DFNum -> DFNum in the ancestor chain s.t. DFNum of its Semi is minimal. - Label: int [] - /// DFNum -> DFNum of the parent node (zero if not exists). - Parent: int [] - /// DFNum -> DFNum of the child node (zero if not exists). - Child: int [] - /// DFNum -> DFNum of an ancestor. - Ancestor: int [] - /// DFNum -> DFNum of a semidominator. - Semi: int [] - /// DFNum -> set of DFNums (vertices that share the same sdom). - Bucket: Set [] - /// DFNum -> Size - Size: int [] - /// DFNum -> DFNum of an immediate dominator. - IDom: int [] - /// Length of the arrays. - MaxLength: int -} - -/// Storing DomInfo of a graph. We use this to repeatedly compute doms/pdoms of -/// the same graph. -type DominatorContext<'D, 'E when 'D :> VertexData and 'D : equality> = { - ForwardGraph: DiGraph<'D, 'E> - ForwardRoot: Vertex<'D> - ForwardDomInfo: DomInfo<'D> - BackwardGraph: DiGraph<'D, 'E> - BackwardRoot: Vertex<'D> - BackwardDomInfo: DomInfo<'D> -} - -val initDominatorContext: - DiGraph<'D, 'E> -> Vertex<'D> -> DominatorContext<'D, 'E> - -val idom: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> option - -val ipdom: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> option - -val doms: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - -val pdoms: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - -val frontier: DominatorContext<'D, 'E> -> Vertex<'D> -> Vertex<'D> list - -val frontiers: DominatorContext<'D, 'E> -> Vertex<'D> list [] - -val dominatorTree: - DominatorContext<'D, 'E> -> Map, Vertex<'D> list> * Vertex<'D> - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/MiddleEnd/BinGraph/DummyVertex.fs b/src/MiddleEnd/BinGraph/DummyVertex.fs deleted file mode 100644 index a51c34af..00000000 --- a/src/MiddleEnd/BinGraph/DummyVertex.fs +++ /dev/null @@ -1,36 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -type DummyEntry = - /// Temporarily connect entry dummy node with the given root node. We do not - /// touch the Graph, but simply connect two vertices temporarily for the - /// convenience of analysis. - static member Connect g (root: Vertex<_>) = - if root.IsDummy () then root, g - else - let dummyEntry, g = DiGraph.addDummyVertex g - let g = DiGraph.addDummyEdge g dummyEntry root - dummyEntry, g diff --git a/src/MiddleEnd/BinGraph/Graph.fs b/src/MiddleEnd/BinGraph/Graph.fs deleted file mode 100644 index 71390624..00000000 --- a/src/MiddleEnd/BinGraph/Graph.fs +++ /dev/null @@ -1,114 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -/// Either persistent or imperative graph. -type GraphImplementationType = - | PersistentGraph - | ImperativeGraph - -/// The top-level graph data type. This one can be both directed or undirected. -[] -type Graph<'D, 'E, 'G - when 'D :> VertexData - and 'G :> Graph<'D, 'E, 'G>> () = - - /// Graph implementation type. - abstract ImplementationType: GraphImplementationType - - /// Is this empty? A graph is empty when there is no vertex in the graph. - abstract IsEmpty: unit -> bool - - /// Number of vertices. - abstract GetSize: unit -> int - - /// Add a vertex into the graph, and return a reference to the added vertex. - abstract AddVertex: 'D -> Vertex<'D> * 'G - - /// Remove the given vertex from the graph. - abstract RemoveVertex: Vertex<'D> -> 'G - - /// Get a set of all vertices in the graph. - abstract GetVertices: unit -> Set> - - /// Check the existence of the given vertex from the graph. - abstract ExistsVertex: VertexID -> bool - - /// Find a vertex by its VertexID. This function raises an exception when - /// there is no such a vertex. - abstract FindVertexByID: VertexID -> Vertex<'D> - - /// Find a vertex by its VertexID. This function returns an Option type. - abstract TryFindVertexByID: VertexID -> Vertex<'D> option - - /// Find a vertex that has the given VertexData from the graph. It will raise - /// an exception if such a vertex does not exist. Note that this function can - /// be used only when each vertex always has unique VertexData. - abstract FindVertexByData: 'D -> Vertex<'D> - - /// Find a vertex that has the given VertexData from the graph. This function - /// does not raise an exception unlike FindVertexByData. - abstract TryFindVertexByData: 'D -> Vertex<'D> option - - /// Find a vertex by the given function. This function returns the first - /// element, in which the function returns true. When there is no such an - /// element, the function raises an exception. - abstract FindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> - - /// Find a vertex by the given function without raising an exception. - abstract TryFindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> option - - /// Add an edge from src to dst. - abstract AddEdge: src: Vertex<'D> -> dst: Vertex<'D> -> 'E -> 'G - - /// Remove the edge that spans from src to dst. - abstract RemoveEdge: src: Vertex<'D> -> dst: Vertex<'D> -> 'G - - /// Find the data of the edge that spans from src to dst. - abstract FindEdgeData: src: Vertex<'D> -> dst: Vertex<'D> -> 'E - - abstract TryFindEdgeData: src: Vertex<'D> -> dst: Vertex<'D> -> 'E option - - /// Fold every vertex (the order can be arbitrary). - abstract FoldVertex: ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - - /// Iterate every vertex (the order can be arbitrary). - abstract IterVertex: (Vertex<'D> -> unit) -> unit - - /// Fold every edge in the graph (the order can be arbitrary). - abstract FoldEdge: ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - - /// Fold every edge in the graph (the order can be arbitrary). - abstract IterEdge: (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - - /// Clone the graph and create a new one. - abstract Clone: unit -> 'G - - /// Return a subgraph that contains only the set of vertices. - abstract SubGraph: Set> -> 'G - - /// Return the DOT-representation of this graph. - abstract ToDOTStr: - string -> (Vertex<'D> -> string) -> (Edge<'E> -> string) -> string diff --git a/src/MiddleEnd/BinGraph/GraphCore.fs b/src/MiddleEnd/BinGraph/GraphCore.fs deleted file mode 100644 index 9b278b74..00000000 --- a/src/MiddleEnd/BinGraph/GraphCore.fs +++ /dev/null @@ -1,81 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -/// GraphCore is an internal representation for the core graph operations, and -/// this should not be directly accessed by the user. -[] -type GraphCore<'D, 'E, 'G - when 'D :> VertexData and 'G :> Graph<'D, 'E, 'G>> internal () = - - abstract ImplementationType: GraphImplementationType - - abstract InitGraph: GraphCore<'D, 'E, 'G> option -> 'G - - abstract Vertices: Set> - - abstract Unreachables: Vertex<'D> list - - abstract Exits: Vertex<'D> list - - abstract GetSize: unit -> int - - abstract AddDummyVertex: 'G -> Vertex<'D> * 'G - - abstract AddVertex: 'G -> 'D -> Vertex<'D> * 'G - - abstract GetVertex: VertexID -> Vertex<'D> - - abstract ContainsVertex: VertexID -> bool - - abstract RemoveVertex: 'G -> Vertex<'D> -> 'G - - abstract FoldVertex: ('a -> Vertex<'D> -> 'a) -> 'a -> 'a - - abstract IterVertex: (Vertex<'D> -> unit) -> unit - - abstract FindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> - - abstract TryFindVertexBy: (Vertex<'D> -> bool) -> Vertex<'D> option - - abstract GetPreds: Vertex<'D> -> Vertex<'D> list - - abstract GetSuccs: Vertex<'D> -> Vertex<'D> list - - abstract AddDummyEdge: 'G -> Vertex<'D> -> Vertex<'D> -> 'G - - abstract AddEdge: 'G -> Vertex<'D> -> Vertex<'D> -> 'E -> 'G - - abstract RemoveEdge: 'G -> Vertex<'D> -> Vertex<'D> -> 'G - - abstract FoldEdge: ('a -> Vertex<'D> -> Vertex<'D> -> 'E -> 'a) -> 'a -> 'a - - abstract IterEdge: (Vertex<'D> -> Vertex<'D> -> 'E -> unit) -> unit - - abstract FindEdge: Vertex<'D> -> Vertex<'D> -> 'E - - abstract TryFindEdge: Vertex<'D> -> Vertex<'D> -> 'E option - - abstract Clone: unit -> GraphCore<'D, 'E, 'G> diff --git a/src/MiddleEnd/BinGraph/Imperative.fs b/src/MiddleEnd/BinGraph/Imperative.fs deleted file mode 100644 index 39242f5d..00000000 --- a/src/MiddleEnd/BinGraph/Imperative.fs +++ /dev/null @@ -1,352 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -open B2R2 -open System.Collections.Generic - -/// Imperative vertex. -type ImpVertex<'D when 'D :> VertexData> (?v: 'D) = - inherit Vertex<'D> (v) - - let mutable preds = [] - let mutable succs = [] - - /// List of predecessors. - override __.Preds with get () = preds and set v = preds <- v - - /// List of successors. - override __.Succs with get () = succs and set v = succs <- v - - static member Init () : Vertex<'D> = upcast (ImpVertex<'D> ()) - - static member Init data : Vertex<'D> = upcast (ImpVertex<'D> (data)) - -/// Imperative GraphCore for directed graph (DiGraph). -type ImperativeCore<'D, 'E when 'D :> VertexData and 'D: equality> - (init, edgeData, ?vertices, ?edges, ?unreachables, ?exits) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices (HashSet ()) - let edges = defaultArg edges (Dictionary ()) - let unreachables = defaultArg unreachables (HashSet ()) - let exits = defaultArg exits (HashSet ()) - - member private __.CheckVertexExistence v = - if not <| vertices.Contains v then raise VertexNotFoundException - - override __.ImplementationType = ImperativeGraph - - override __.InitGraph core = - match core with - | Some core -> init <| core.Clone () - | None -> init <| ImperativeCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Seq.fold (fun acc v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - unreachables |> Seq.fold (fun acc v -> v :: acc) [] - - override __.Exits with get () = - exits |> Seq.fold (fun acc v -> v :: acc) [] - - override __.GetSize () = vertices.Count - - member private __.AddVertexToCore v = - vertices.Add v |> ignore - unreachables.Add v |> ignore - exits.Add v |> ignore - - override __.AddDummyVertex g = - let v = ImpVertex.Init () - __.AddVertexToCore v - v, g - - override __.AddVertex g data = - let v = ImpVertex.Init data - __.AddVertexToCore v - v, g - - override __.GetVertex vid = - match Seq.tryFind (fun (v: Vertex<_>) -> v.GetID () = vid) vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - override __.ContainsVertex vid = - vertices |> Seq.exists (fun (v: Vertex<_>) -> v.GetID () = vid) - - override __.RemoveVertex g v = - __.CheckVertexExistence v - v.Preds - |> List.iter (fun p -> __.RemoveEdge g p v |> ignore) - v.Succs - |> List.iter (fun s -> __.RemoveEdge g v s |> ignore) - vertices.Remove v |> ignore - unreachables.Remove v |> ignore - exits.Remove v |> ignore - g - - override __.FoldVertex fn acc = - vertices |> Seq.fold fn acc - - override __.IterVertex fn = - vertices |> Seq.iter fn - - override __.FindVertexBy fn = - vertices |> Seq.find fn - - override __.TryFindVertexBy fn = - vertices |> Seq.tryFind fn - - override __.GetPreds v = - __.CheckVertexExistence v - v.Preds - - override __.GetSuccs v = - __.CheckVertexExistence v - v.Succs - - member private __.AddEdgeToCore (src: Vertex<'D>) (dst: Vertex<'D>) e = - __.CheckVertexExistence src - __.CheckVertexExistence dst - let srcid = src.GetID () - let dstid = dst.GetID () - if edges.ContainsKey (srcid, dstid) then () - else - edges[(srcid, dstid)] <- (src, dst, e) - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - unreachables.Remove dst |> ignore - exits.Remove src |> ignore - - override __.AddDummyEdge g src dst = - __.AddEdgeToCore src dst edgeData - g - - override __.AddEdge g src dst e = - __.AddEdgeToCore src dst e - g - - override __.RemoveEdge g src dst = - __.CheckVertexExistence src - __.CheckVertexExistence dst - let srcid = src.GetID () - let dstid = dst.GetID () - src.Succs <- List.filter (fun s -> s.GetID () <> dstid) src.Succs - dst.Preds <- List.filter (fun p -> p.GetID () <> srcid) dst.Preds - if List.isEmpty dst.Preds then unreachables.Add dst |> ignore - if List.isEmpty src.Succs then exits.Add src |> ignore - edges.Remove ((srcid, dstid)) |> ignore - g - - override __.FoldEdge fn acc = - edges.Values - |> Seq.fold (fun acc (src, dst, e) -> fn acc src dst e) acc - - override __.IterEdge fn = - edges.Values - |> Seq.iter (fun (src, dst, e) -> fn src dst e) - - override __.FindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges[(src.GetID (), dst.GetID ())] - e - else raise EdgeNotFoundException - - override __.TryFindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges[(src.GetID (), dst.GetID ())] - Some e - else None - - override __.Clone () = - let g = __.InitGraph None - let core = ImperativeCore (init, edgeData) :> GraphCore<_, _, _> - __.IterVertex (fun v -> core.AddVertex g v.VData |> ignore) - __.IterEdge (fun src dst e -> - let src = core.GetVertex <| src.GetID () - let dst = core.GetVertex <| dst.GetID () - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - core.AddEdge g src dst e |> ignore) - core - -/// Imperative GraphCore for directed graph (DiGraph) that uses AddrRange as key -/// for each vertex, which is useful for managing CFGs of a binary. -type ImperativeRangedCore<'D, 'E when 'D :> RangedVertexData and 'D: equality> - (init, edgeData, ?vertices, ?rangemap, ?edges, ?unreachables, ?exits) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices (HashSet ()) - let mutable rangemap = defaultArg rangemap IntervalMap.empty - let edges = defaultArg edges (Dictionary ()) - let unreachables = defaultArg unreachables (HashSet ()) - let exits = defaultArg exits (HashSet ()) - - member private __.CheckVertexExistence v = - if not <| vertices.Contains v then raise VertexNotFoundException - - override __.ImplementationType = ImperativeGraph - - override __.InitGraph core = - match core with - | Some core -> init <| core.Clone () - | None -> init <| ImperativeRangedCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Seq.fold (fun acc v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - unreachables |> Seq.fold (fun acc v -> v :: acc) [] - - override __.Exits with get () = - exits |> Seq.fold (fun acc v -> v :: acc) [] - - override __.GetSize () = vertices.Count - - member private __.AddVertexToCore v = - vertices.Add v |> ignore - unreachables.Add v |> ignore - exits.Add v |> ignore - - override __.AddDummyVertex g = - let v = ImpVertex.Init () - __.AddVertexToCore v - v, g - - override __.AddVertex g data = - let v = ImpVertex.Init data - __.AddVertexToCore v - rangemap <- IntervalMap.add v.VData.AddrRange v rangemap - v, g - - override __.GetVertex vid = - match Seq.tryFind (fun (v: Vertex<_>) -> v.GetID () = vid) vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - override __.ContainsVertex vid = - vertices |> Seq.exists (fun (v: Vertex<_>) -> v.GetID () = vid) - - override __.RemoveVertex g v = - __.CheckVertexExistence v - v.Preds - |> List.iter (fun p -> __.RemoveEdge g p v |> ignore) - v.Succs - |> List.iter (fun s -> __.RemoveEdge g v s |> ignore) - vertices.Remove v |> ignore - if v.IsDummy () |> not then - rangemap <- IntervalMap.remove v.VData.AddrRange rangemap - unreachables.Remove v |> ignore - exits.Remove v |> ignore - g - - override __.FoldVertex fn acc = - vertices |> Seq.fold fn acc - - override __.IterVertex fn = - vertices |> Seq.iter fn - - override __.FindVertexBy fn = - vertices |> Seq.find fn - - override __.TryFindVertexBy fn = - vertices |> Seq.tryFind fn - - override __.GetPreds v = - __.CheckVertexExistence v - v.Preds - - override __.GetSuccs v = - __.CheckVertexExistence v - v.Succs - - member private __.AddEdgeToCore (src: Vertex<'D>) (dst: Vertex<'D>) e = - __.CheckVertexExistence src - __.CheckVertexExistence dst - if not <| vertices.Contains src then failwith "No" - if not <| vertices.Contains dst then failwith "No" - let srcid = src.GetID () - let dstid = dst.GetID () - if edges.ContainsKey (srcid, dstid) then () - else - edges[(src.GetID (), dst.GetID ())] <- (src, dst, e) - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - unreachables.Remove dst |> ignore - exits.Remove src |> ignore - - override __.AddDummyEdge g src dst = - __.AddEdgeToCore src dst edgeData - g - - override __.AddEdge g src dst e = - __.AddEdgeToCore src dst e - g - - override __.RemoveEdge g src dst = - __.CheckVertexExistence src - __.CheckVertexExistence dst - let srcid = src.GetID () - let dstid = dst.GetID () - src.Succs <- List.filter (fun s -> s.GetID () <> dstid) src.Succs - dst.Preds <- List.filter (fun p -> p.GetID () <> srcid) dst.Preds - if List.isEmpty dst.Preds then unreachables.Add dst |> ignore - if List.isEmpty src.Succs then exits.Add src |> ignore - edges.Remove ((srcid, dstid)) |> ignore - g - - override __.FoldEdge fn acc = - edges.Values - |> Seq.fold (fun acc (src, dst, e) -> fn acc src dst e) acc - - override __.IterEdge fn = - edges.Values - |> Seq.iter (fun (src, dst, e) -> fn src dst e) - - override __.FindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges[(src.GetID (), dst.GetID ())] - e - else raise EdgeNotFoundException - - override __.TryFindEdge src dst = - if edges.ContainsKey (src.GetID (), dst.GetID ()) then - let _, _, e = edges[(src.GetID (), dst.GetID ())] - Some e - else None - - override __.Clone () = - let g = __.InitGraph None - let core = ImperativeRangedCore (init, edgeData) :> GraphCore<_, _, _> - __.IterVertex (fun v -> core.AddVertex g v.VData |> ignore) - __.IterEdge (fun src dst e -> - let src = core.GetVertex <| src.GetID () - let dst = core.GetVertex <| dst.GetID () - src.Succs <- dst :: src.Succs - dst.Preds <- src :: dst.Preds - core.AddEdge g src dst e |> ignore) - core diff --git a/src/MiddleEnd/BinGraph/Loop.fs b/src/MiddleEnd/BinGraph/Loop.fs deleted file mode 100644 index feb9f056..00000000 --- a/src/MiddleEnd/BinGraph/Loop.fs +++ /dev/null @@ -1,56 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.BinGraph.Loop - -open B2R2.Utils -open System.Collections.Generic - -let private getBackEdges g root = - let ctx = Dominator.initDominatorContext g root - let doms = - [] - |> DiGraph.foldVertex g (fun acc v -> - (v, Dominator.doms ctx v) :: acc) - |> Map.ofList - [] - |> DiGraph.foldEdge g (fun acc s d e -> - match doms[s] with - | l when l |> List.exists (fun v -> v = d) -> (s, d) :: acc - | _ -> acc) - -let private findIn g v = DiGraph<_, _>.findVertexByID g (Vertex<_>.GetID v) - -let getNaturalLoops g root = - let rev = DiGraph.reverse g - getBackEdges g root - |> List.fold (fun acc (s, d) -> - let s = findIn rev s - let d = findIn rev d - let vertices = - [ d ] - |> Traversal.foldPreorderExcept rev [ s ] [ d ] (fun acc v -> - (findIn g v) :: acc) - |> HashSet - vertices :: acc) [] diff --git a/src/MiddleEnd/BinGraph/Persistent.fs b/src/MiddleEnd/BinGraph/Persistent.fs deleted file mode 100644 index 953141ca..00000000 --- a/src/MiddleEnd/BinGraph/Persistent.fs +++ /dev/null @@ -1,357 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -open B2R2 - -/// Persistent vertex. -type PerVertex<'D when 'D :> VertexData> (?v: 'D) = - inherit Vertex<'D> (v) - - override __.Preds - with get () = Utils.impossible () and set _ = Utils.impossible () - - override __.Succs - with get () = Utils.impossible () and set _ = Utils.impossible () - - static member Init () : Vertex<'D> = upcast (PerVertex<'D> ()) - - static member Init data : Vertex<'D> = upcast (PerVertex<'D> (data)) - -/// Persistent GraphCore for directed graph (DiGraph). -type PersistentCore<'D, 'E when 'D :> VertexData and 'D: equality> - (init, edgeData, ?vertices, ?preds, ?succs) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices Map.empty - let preds: Map * Vertex<'D> * 'E) list> = - defaultArg preds Map.empty - let succs: Map * Vertex<'D> * 'E) list> = - defaultArg succs Map.empty - - override __.ImplementationType = PersistentGraph - - override __.InitGraph core = - match core with - | Some core -> init core - | None -> init <| PersistentCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Map.fold (fun acc _ v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - preds - |> Map.fold (fun acc vid ps -> - if List.isEmpty ps then (Map.find vid vertices) :: acc - else acc) [] - - override __.Exits with get () = - succs - |> Map.fold (fun acc vid ss -> - if List.isEmpty ss then (Map.find vid vertices) :: acc - else acc) [] - - override __.GetSize () = Map.count vertices - - member private __.InitGraphWithNewVertex (v: Vertex<'D>) = - let vid = v.GetID () - let vertices = Map.add vid v vertices - let preds = Map.add vid [] preds - let succs = Map.add vid [] succs - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyVertex _g = - let v = PerVertex.Init () - v, __.InitGraphWithNewVertex v - - override __.AddVertex _g data = - let v = PerVertex.Init data - v, __.InitGraphWithNewVertex v - - override __.GetVertex vid = - match Map.tryFind vid vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - member inline private __.RemoveEdgeFromMap map srcId dstId = - let isChild (_, child: Vertex<_>, _) = child.GetID () <> dstId - map - |> Map.map (fun id ss -> - if srcId = id then List.filter isChild ss else ss) - - override __.RemoveVertex _g v = - let vid = v.GetID () - let succs = - Map.find vid preds - |> List.fold (fun succs (_, p, _) -> - __.RemoveEdgeFromMap succs (p.GetID ()) vid) succs - let preds = - Map.find vid succs - |> List.fold (fun preds (_, s, _) -> - __.RemoveEdgeFromMap preds (s.GetID ()) vid) preds - let vertices = Map.remove vid vertices - let preds = Map.remove vid preds - let succs = Map.remove vid succs - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.ContainsVertex vid = - vertices |> Map.containsKey vid - - override __.FoldVertex fn acc = - vertices |> Map.fold (fun acc _ v -> fn acc v) acc - - override __.IterVertex fn = - vertices |> Map.iter (fun _ v -> fn v) - - override __.FindVertexBy fn = - vertices |> Map.pick (fun _ v -> if fn v then Some v else None) - - override __.TryFindVertexBy fn = - vertices |> Map.tryPick (fun _ v -> if fn v then Some v else None) - - override __.GetPreds v = - Map.find (v.GetID ()) preds |> List.map Utils.tripleSnd - - override __.GetSuccs v = - Map.find (v.GetID ()) succs |> List.map Utils.tripleSnd - - member private __.InitGraphWithNewEdge (src: Vertex<'D>) (dst: Vertex<'D>) e = - let srcid = src.GetID () - let dstid = dst.GetID () - let existsEdge (src', dst', _) = src = src' && dst = dst' - match Map.tryFind srcid succs with - | Some ss when List.exists existsEdge ss -> __.InitGraph (Some (upcast __)) - | _ -> - let preds = Map.add dstid ((dst, src, e) :: Map.find dstid preds) preds - let succs = Map.add srcid ((src, dst, e) :: Map.find srcid succs) succs - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyEdge _g src dst = - __.InitGraphWithNewEdge src dst edgeData - - override __.AddEdge _g src dst e = - __.InitGraphWithNewEdge src dst e - - override __.RemoveEdge _g src dst = - let srcid = src.GetID () - let dstid = dst.GetID () - let preds = __.RemoveEdgeFromMap preds dstid srcid - let succs = __.RemoveEdgeFromMap succs srcid dstid - let core = PersistentCore (init, edgeData, vertices, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.FoldEdge fn acc = - let folder acc (s, d, e) = fn acc s d e - succs - |> Map.fold (fun acc _ lst -> - lst |> List.fold folder acc) acc - - override __.IterEdge fn = - let iterator (s, d, e) = fn s d e - succs - |> Map.iter (fun _ lst -> lst |> List.iter iterator) - - override __.FindEdge src dst = - let dstID = dst.GetID () - Map.find (src.GetID ()) succs - |> List.find (fun (_, v, _) -> v.GetID () = dstID) - |> Utils.tripleThd - - override __.TryFindEdge src dst = - Map.tryFind (src.GetID ()) succs - |> Option.bind (fun lst -> - let dstID = dst.GetID () - lst |> List.tryFind (fun (_, v, _) -> v.GetID () = dstID)) - |> function - | Some (_, _, e) -> Some e - | None -> None - - override __.Clone () = - __ :> GraphCore<'D, 'E, DiGraph<'D, 'E>> - -/// Persistent GraphCore for directed graph (DiGraph) that uses AddrRange as a -/// key for each vertex. This is useful for handling CFGs of a binary. -type PersistentRangedCore<'D, 'E when 'D :> RangedVertexData and 'D: equality> - (init, edgeData, ?vertices, ?rangemap, ?edges, ?preds, ?succs) = - inherit GraphCore<'D, 'E, DiGraph<'D, 'E>> () - - let vertices = defaultArg vertices Map.empty - let rangemap = defaultArg rangemap IntervalMap.empty - let edges = defaultArg edges Map.empty - let preds: Map list> = defaultArg preds Map.empty - let succs: Map list> = defaultArg succs Map.empty - - override __.ImplementationType = PersistentGraph - - override __.InitGraph core = - match core with - | Some core -> init core - | None -> init <| PersistentRangedCore (init, edgeData) - - override __.Vertices with get () = - vertices |> Map.fold (fun acc _ v -> Set.add v acc) Set.empty - - override __.Unreachables with get () = - preds - |> Map.fold (fun acc vid ps -> - if List.isEmpty ps then (Map.find vid vertices) :: acc - else acc) [] - - override __.Exits with get () = - succs - |> Map.fold (fun acc vid ss -> - if List.isEmpty ss then (Map.find vid vertices) :: acc - else acc) [] - - override __.GetSize () = Map.count vertices - - member private __.InitGraphWithNewVertex (v: Vertex<'D>) = - let vid = v.GetID () - let vertices = Map.add vid v vertices - let rangemap = - if v.IsDummy () then rangemap - else IntervalMap.add v.VData.AddrRange v rangemap - let preds = Map.add vid [] preds - let succs = Map.add vid [] succs - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyVertex _g = - let v = PerVertex.Init () - v, __.InitGraphWithNewVertex v - - override __.AddVertex _g data = - let v = PerVertex.Init data - v, __.InitGraphWithNewVertex v - - override __.GetVertex vid = - match Map.tryFind vid vertices with - | Some v -> v - | None -> raise VertexNotFoundException - - member inline private __.RemoveEdgeFromMap map srcId dstId = - map - |> Map.map (fun id ss -> - if srcId = id then - List.filter (fun (child: Vertex<_>) -> child.GetID () <> dstId) ss - else ss) - - override __.RemoveVertex _g v = - let vid = v.GetID () - let edges, succs = - Map.find vid preds - |> List.fold (fun (edges, succs) p -> - let p = p.GetID () - Map.remove (p, vid) edges, - __.RemoveEdgeFromMap succs p vid) (edges, succs) - let edges, preds = - Map.find vid succs - |> List.fold (fun (edges, preds) s -> - let s = s.GetID () - Map.remove (vid, s) edges, - __.RemoveEdgeFromMap preds s vid) (edges, preds) - let vertices = Map.remove vid vertices - let rangemap = - if v.IsDummy () then rangemap - else IntervalMap.remove v.VData.AddrRange rangemap - let preds = Map.remove vid preds - let succs = Map.remove vid succs - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.ContainsVertex vid = - vertices |> Map.containsKey vid - - override __.FoldVertex fn acc = - vertices |> Map.fold (fun acc _ v -> fn acc v) acc - - override __.IterVertex fn = - vertices |> Map.iter (fun _ v -> fn v) - - override __.FindVertexBy fn = - vertices |> Map.pick (fun _ v -> if fn v then Some v else None) - - override __.TryFindVertexBy fn = - vertices |> Map.tryPick (fun _ v -> if fn v then Some v else None) - - override __.GetPreds v = - Map.find (v.GetID ()) preds - - override __.GetSuccs v = - Map.find (v.GetID ()) succs - - member private __.InitGraphWithNewEdge (src: Vertex<'D>) (dst: Vertex<'D>) e = - let srcid = src.GetID () - let dstid = dst.GetID () - if Map.containsKey (srcid, dstid) edges then __.InitGraph (Some (upcast __)) - else - let edges = Map.add (srcid, dstid) (src, dst, e) edges - let preds = Map.add dstid (src :: Map.find dstid preds) preds - let succs = Map.add srcid (dst :: Map.find srcid succs) succs - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.AddDummyEdge _g src dst = - __.InitGraphWithNewEdge src dst edgeData - - override __.AddEdge _g src dst e = - __.InitGraphWithNewEdge src dst e - - override __.RemoveEdge _g src dst = - let srcid = src.GetID () - let dstid = dst.GetID () - let preds = __.RemoveEdgeFromMap preds dstid srcid - let succs = __.RemoveEdgeFromMap succs srcid dstid - let edges = Map.remove (srcid, dstid) edges - let core = PersistentRangedCore (init, edgeData, - vertices, rangemap, edges, preds, succs) - __.InitGraph (Some (upcast core)) - - override __.FoldEdge fn acc = - edges - |> Map.fold (fun acc _ (src, dst, e) -> fn acc src dst e) acc - - override __.IterEdge fn = - edges - |> Map.iter (fun _ (src, dst, e) -> fn src dst e) - - override __.FindEdge src dst = - match Map.tryFind (src.GetID (), dst.GetID ()) edges with - | Some (_, _, e) -> e - | None -> raise EdgeNotFoundException - - override __.TryFindEdge src dst = - match Map.tryFind (src.GetID (), dst.GetID ()) edges with - | Some (_, _, e) -> Some e - | None -> None - - override __.Clone () = - __ :> GraphCore<'D, 'E, DiGraph<'D, 'E>> diff --git a/src/MiddleEnd/BinGraph/RangedDiGraph.fs b/src/MiddleEnd/BinGraph/RangedDiGraph.fs deleted file mode 100644 index 15d7563a..00000000 --- a/src/MiddleEnd/BinGraph/RangedDiGraph.fs +++ /dev/null @@ -1,49 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -type RangedDiGraph<'D, 'E - when 'D :> RangedVertexData and 'D : equality> (core) = - inherit DiGraph<'D, 'E> (core: GraphCore<'D, 'E, DiGraph<'D, 'E>>) - - member __.FindVertexByRange range = - core.FindVertexBy (fun (v: Vertex<'D>) -> v.VData.AddrRange = range) - -[] -module RangedDiGraph = - let private initializer core = RangedDiGraph<'D, 'E> (core) :> DiGraph<'D, 'E> - - let private initImperative edgeData = - let core = ImperativeRangedCore<'D, 'E> (initializer, edgeData) - RangedDiGraph<'D, 'E> (core) :> DiGraph<'D, 'E> - - let private initPersistent edgeData = - let core = PersistentRangedCore<'D, 'E> (initializer, edgeData) - RangedDiGraph<'D, 'E> (core) :> DiGraph<'D, 'E> - - /// Initialize RangedDiGraph based on the implementation type. - let init edgeData = function - | ImperativeGraph -> initImperative edgeData - | PersistentGraph -> initPersistent edgeData diff --git a/src/MiddleEnd/BinGraph/SCC.fs b/src/MiddleEnd/BinGraph/SCC.fs deleted file mode 100644 index 6ef9a6ae..00000000 --- a/src/MiddleEnd/BinGraph/SCC.fs +++ /dev/null @@ -1,130 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.BinGraph.SCC - -open System.Collections.Generic - -type SCC<'D when 'D :> VertexData> = Set> - -type SCCInfo<'D when 'D :> VertexData> = { - /// Vertex ID -> DFNum - DFNumMap: Dictionary - /// DFNum -> Vertex - Vertex: Vertex<'D> [] - /// DFNum -> LowLink - LowLink: int [] -} - -type CondensationBlock<'D when 'D :> VertexData> (scc: SCC<'D>) = - inherit VertexData(VertexData.genID ()) - - member __.SCC = scc - -type CondensationGraph<'D when 'D :> VertexData> = - DiGraph, unit> - -let initSCCInfo g = - let len = DiGraph.getSize g + 1 - { DFNumMap = Dictionary() - Vertex = Array.zeroCreate len - LowLink = Array.zeroCreate len } - -let inline dfnum ctxt (v: Vertex<_>) = - ctxt.DFNumMap[v.GetID ()] - -let inline lowlink ctxt v = - ctxt.LowLink[dfnum ctxt v] - -let rec assignSCC ctxt vNum stack scc = - if List.length stack <> 0 then - let wNum = List.head stack - if wNum >= vNum then - let stack = List.tail stack - let w = ctxt.Vertex[wNum] - let scc = Set.add w scc - assignSCC ctxt vNum stack scc - else stack, scc - else stack, scc - -let createSCC ctxt v stack sccs = - let vNum = dfnum ctxt v - if lowlink ctxt v = vNum then - let stack, scc = assignSCC ctxt vNum stack Set.empty - stack, scc :: sccs - else stack, sccs - -let inline min x y = if x < y then x else y - -/// R.Tarjan. Depth-first search and linear graph algorithms -let rec computeSCC g ctxt (v: Vertex<_>) n stack sccs = - ctxt.DFNumMap[v.GetID ()] <- n - ctxt.LowLink[n] <- n - ctxt.Vertex[n] <- v - let n, stack, sccs = - DiGraph.getSuccs g v - |> List.fold (computeLowLink g ctxt v) (n + 1, n :: stack, sccs) - let stack, sccs = createSCC ctxt v stack sccs - n, stack, sccs - -and computeLowLink g ctxt v (n, stack, sccs) (w: Vertex<_>) = - let vNum = dfnum ctxt v - let vLink = lowlink ctxt v - if ctxt.DFNumMap.ContainsKey <| w.GetID () then - let wNum = dfnum ctxt w - if List.contains wNum stack then ctxt.LowLink[vNum] <- min vLink wNum - n, stack, sccs - else - let n, stack, sccs = computeSCC g ctxt w n stack sccs - let wLink = lowlink ctxt w - ctxt.LowLink[vNum] <- min vLink wLink - n, stack, sccs - -let compute g root = - let ctxt = initSCCInfo g - DiGraph.getUnreachables g - |> Seq.fold (fun acc v -> Set.add v acc) Set.empty - |> Set.add root - |> Set.fold (fun (n, acc) root -> - let n, _, sccs = computeSCC g ctxt root n [] [] - let acc = sccs |> List.fold (fun acc scc -> Set.add scc acc) acc - n, acc) (1, Set.empty) - |> snd - -let condensation graphInit g root = - let sccs = compute g root - let cGraph = graphInit () - let vMap, cGraph = - sccs - |> Set.fold (fun (acc, cGraph) scc -> - let v, cGraph = DiGraph.addVertex cGraph <| CondensationBlock (scc) - let acc = Set.fold (fun acc w -> Map.add w v acc) acc scc - acc, cGraph) (Map.empty, cGraph) - Set.empty - |> DiGraph.foldEdge g (fun acc src dst _ -> - let src = Map.find src vMap - let dst = Map.find dst vMap - Set.add (src, dst) acc) - |> Set.fold (fun condensation (src, dst) -> - DiGraph.addEdge condensation src dst ()) cGraph diff --git a/src/MiddleEnd/BinGraph/Traversal.fs b/src/MiddleEnd/BinGraph/Traversal.fs deleted file mode 100644 index 29c290c8..00000000 --- a/src/MiddleEnd/BinGraph/Traversal.fs +++ /dev/null @@ -1,126 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.BinGraph.Traversal - -open System.Collections.Generic - -let inline private prependSuccessors g lst v = - DiGraph.getSuccs g v |> List.fold (fun lst s -> s :: lst) lst - -let rec private foldPreorderLoop visited g fn acc = function - | [] -> acc - | v: Vertex<_> :: tovisit when v.GetID () |> (visited: HashSet<_>).Contains -> - foldPreorderLoop visited g fn acc tovisit - | v :: tovisit -> - v.GetID () |> visited.Add |> ignore - foldPreorderLoop visited g fn (fn acc v) (prependSuccessors g tovisit v) - -let rec private foldPostorderLoop visited g fn acc vstack = function - | [] -> acc - | v: Vertex<_> :: tovisit when v.GetID () |> (visited: HashSet<_>).Contains -> - foldPostorderLoop visited g fn acc vstack tovisit - | v :: tovisit -> - v.GetID () |> visited.Add |> ignore - let struct (acc, vstack) = consume visited g fn acc (v :: vstack) - foldPostorderLoop visited g fn acc vstack (prependSuccessors g tovisit v) - -and consume visited g fn acc = function - | [] -> struct (acc, []) - | v :: rest -> - let allSuccsVisited = - DiGraph.getSuccs g v - |> List.forall (fun s -> s.GetID () |> visited.Contains) - if allSuccsVisited then consume visited g fn (fn acc v) rest - else struct (acc, v :: rest) - -/// Fold vertices of the graph in a depth-first manner with the preorder -/// traversal. -let foldPreorder g roots fn acc = - let visited = new HashSet () - foldPreorderLoop visited g fn acc roots - -/// Fold vertices, except them in the second list, of the graph in a -/// depth-first manner with the preorder traversal. -let foldPreorderExcept g roots excepts fn acc = - let visited = - excepts - |> List.map (fun v -> Vertex<_>.GetID v) - |> HashSet - foldPreorderLoop visited g fn acc roots - -/// Iterate vertices of the graph in a depth-first manner with the preorder -/// traversal. -let iterPreorder g roots fn = - foldPreorder g roots (fun () v -> fn v) () - -/// Iterate vertices, except them in the second list, of the graph in a -/// depth-first manner with the preorder traversal. -let iterPreorderExcept g roots excepts fn = - foldPreorderExcept g roots excepts (fun () v -> fn v) () - -/// Fold vertices of the graph in a depth-first manner with the postorder -/// traversal. The traversal starts from each vertex in roots. -let foldPostorder g roots fn acc = - let visited = new HashSet () - foldPostorderLoop visited g fn acc [] roots - -/// Iterate vertices of the graph in a depth-first manner with the postorder -/// traversal. The traversal starts from each vertex in roots. -let iterPostorder g roots fn = - foldPostorder g roots (fun () v -> fn v) () - -/// Fold vertices of the graph in a depth-first manner with the reverse -/// postorder traversal. The traversal starts from each vertex in roots. -let foldRevPostorder g roots fn acc = - foldPostorder g roots (fun acc v -> v :: acc) [] - |> List.fold fn acc - -/// Iterate vertices of the graph in a depth-first manner with the reverse -/// postorder traversal. The traversal starts from each vertex in roots. -let iterRevPostorder g roots fn = - foldPostorder g roots (fun acc v -> v :: acc) [] - |> List.iter fn - -/// Topologically fold every vertex of the given graph. For every unreachable -/// nodes, we accumulate vertices reachable from the node in a postorder -/// fashion. The accumulated list becomes the reverse postordered vertices, -/// which is essentially the same as a topologically sorted list of vertices. -/// We then simply fold the accumulated list. The second parameter (root) is for -/// providing root vertices in case there is no unreachable node, e.g., when -/// there is a loop to the root node. -let foldTopologically g roots fn acc = - let visited = new HashSet () - let roots = - DiGraph.getUnreachables g - |> Set.ofSeq - |> List.foldBack Set.add roots - |> Set.toList - |> foldPostorderLoop visited g (fun acc v -> v :: acc) [] [] - (* Consider unreachable loop components. For those vertices, the order is - random *) - DiGraph.getVertices g - |> Set.toList - |> foldPostorderLoop visited g (fun acc v -> v :: acc) roots [] - |> List.fold fn acc diff --git a/src/MiddleEnd/BinGraph/Vertices.fs b/src/MiddleEnd/BinGraph/Vertices.fs deleted file mode 100644 index eb67733b..00000000 --- a/src/MiddleEnd/BinGraph/Vertices.fs +++ /dev/null @@ -1,111 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.BinGraph - -open B2R2 - -/// Missing vertex. -exception VertexNotFoundException - -/// Multiple vertices found when looking for a vertex containing certain data -exception MultipleVerticesFoundException - -/// Trying to access dummy node's data -exception DummyDataAccessException - -/// A unique ID for a vertex. -type VertexID = int - -/// A data type for vertex. A VertexData should have an ID. -[] -type VertexData (id) = - member __.ID: VertexID = id - -module VertexData = - let private freshID = ref 0 - - let genID () = System.Threading.Interlocked.Increment (freshID) - -type RangedVertexData (range: AddrRange) = - inherit VertexData(VertexData.genID ()) - member __.AddrRange = range - -/// A vertex of a graph. The vertex data (v) is optional, and if it is None, we -/// will consider the vertex as a dummy node. Dummy nodes are useful for -/// representing entry/exit node in a CFG. -[] -type Vertex<'V when 'V :> VertexData> (v: 'V option) = - let myid = - match v with - | Some v -> v.ID - | None -> 0 - - /// Create a dummy vertex. - new () = Vertex (None) - /// Create a regular vertex. - new (v: 'V) = Vertex (Some v) - - abstract Preds : Vertex<'V> list with get, set - abstract Succs : Vertex<'V> list with get, set - - /// Data attached to the vertex. - member __.VData = - match v with - | Some v -> v - | None -> raise DummyDataAccessException - - /// Check whether vertex is a dummy node. - member __.IsDummy () = Option.isNone v - - /// Each vertex has a unique ID attached to it. We sometimes need to access ID - /// of dummy vertex for example calculating dominators. - member __.GetID () = myid - - /// Return the ID of the given vertex. - static member GetID (v: Vertex<#VertexData>) = v.GetID () - - // Each vertex has a unique ID, so ID can be used to check equality. - override __.Equals obj = - match obj with - | :? Vertex<'V> as obj -> __.GetID () = obj.GetID () - | _ -> false - - override __.GetHashCode () = __.GetID () - - override __.ToString () = - match v with - | Some v -> sprintf "Vertex<%s>" <| v.ToString () - | None -> "DummyVertex" - - // Each vertex has a unique ID, so ID can be used for comparison. - interface System.IComparable with - member __.CompareTo obj = - match obj with - | :? Vertex<'V> as v -> compare (__.GetID ()) (v.GetID ()) - | _ -> failwith "Invalid comparison" - -type V<'V when 'V :> VertexData> = Vertex<'V> - -// vim: set tw=80 sts=2 sw=2: diff --git a/src/MiddleEnd/ConcEval/B2R2.MiddleEnd.ConcEval.fsproj b/src/MiddleEnd/ConcEval/B2R2.MiddleEnd.ConcEval.fsproj deleted file mode 100644 index 0a5f11ef..00000000 --- a/src/MiddleEnd/ConcEval/B2R2.MiddleEnd.ConcEval.fsproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - LICENSE.md - b2r2-240x240.png - README.md - B2R2 concrete evaluation engine. - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/ConcEval/EvalState.fs b/src/MiddleEnd/ConcEval/EvalState.fs deleted file mode 100644 index 0209f1a4..00000000 --- a/src/MiddleEnd/ConcEval/EvalState.fs +++ /dev/null @@ -1,282 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ConcEval - -open System.Runtime.InteropServices -open B2R2 -open B2R2.BinIR - -type PerInstrHandler = - delegate of EvalState -> EvalState - -and LoadEventHandler = - delegate of Addr * Addr * BitVector -> unit - -and LoadFailureEventHandler = - delegate of Addr * Addr * RegType * ErrorCase -> Result - -and StoreEventHandler = - delegate of Addr * Addr * BitVector -> unit - -and PutEventHandler = - delegate of Addr * BitVector -> unit - -and SideEffectEventHandler = - delegate of SideEffect * EvalState -> unit - -and StmtEvalEventHandler = - delegate of LowUIR.Stmt -> unit - -/// The main evaluation state that will be updated by evaluating every statement -/// encountered during the course of execution. This can be considered as a -/// single-threaded CPU context. -and EvalState (regs, temps, lbls, mem, ignoreUndef) = - let mutable pc = 0UL - let mutable stmtIdx = 0 - let mutable mode = ArchOperationMode.NoMode - let mutable currentInsLen = 0u - let mutable isInstrTerminated = false - let mutable needToEvaluateIEMark = false - let mutable perInstrHdl = PerInstrHandler id - let mutable loadEventHdl = LoadEventHandler (fun _ _ _ -> ()) - let mutable loadFailureHdl = LoadFailureEventHandler (fun _ _ _ e -> Error e) - let mutable storeEventHdl = StoreEventHandler (fun _ _ _ -> ()) - let mutable putEventHdl = PutEventHandler (fun _ _ -> ()) - let mutable sideEffectHdl = SideEffectEventHandler (fun _ _ -> ()) - let mutable stmtEvalHdl = StmtEvalEventHandler (fun _ -> ()) - - /// This constructor will simply create a fresh new EvalState. - new () = - EvalState (Variables (Variables.maxNumVars), - Variables (Variables.maxNumTemporaries), - Labels (), - NonsharableMemory () :> Memory, - false) - - /// This constructor will simply create a fresh new EvalState with the given - /// memory. - new (mem) = - EvalState (Variables (Variables.maxNumVars), - Variables (Variables.maxNumTemporaries), - Labels (), - mem, - false) - - /// This constructor will simply create a fresh new EvalState. Depending on - /// the `ignoreUndef` parameter, the evaluator using this EvalState will - /// silently ignore Undef values. Such a feature is only useful for some - /// static analyses. - new (ignoreUndef) = - EvalState (Variables (Variables.maxNumVars), - Variables (Variables.maxNumTemporaries), - Labels (), - NonsharableMemory () :> Memory, - ignoreUndef) - - /// Current PC. - member __.PC with get() = pc and set(addr) = pc <- addr - - /// The current index of the statement to evaluate within the scope of a - /// machine instruction. This index behaves like a PC for statements of an - /// instruction. - member __.StmtIdx with get() = stmtIdx and set(i) = stmtIdx <- i - - /// Architecture mode. - member __.Mode with get() = mode and set(m) = mode <- m - - /// Current instruction length. - member __.CurrentInsLen - with get() = currentInsLen and set(l) = currentInsLen <- l - - /// Named register values. - member __.Registers with get() = regs - - /// Temporary variable values. - member __.Temporaries with get() = temps - - /// Memory. - member __.Memory with get() = mem - - /// Store labels and their corresponding statement indices. - member __.Labels with get() = lbls - - /// Indicate whether to terminate the current instruction or not. This flag is - /// set to true when we encounter an inter-jump statement or SideEffect, so - /// that we can ignore the rest of the statements. - member __.IsInstrTerminated - with get() = isInstrTerminated and set(f) = isInstrTerminated <- f - - /// Indicate whether to evaluate IEMark while ignoring the other instructions. - /// This means, the evaluation of the instruction is over, but we need to - /// advance the PC to the next instruction using IEMark. Thus, this flag is - /// only meaningful when `IsInstrTerminated` is true. - member __.NeedToEvaluateIEMark - with get() = needToEvaluateIEMark and set(f) = needToEvaluateIEMark <- f - - /// Whether to ignore statements that cannot be evaluated due to undef values. - /// This is particularly useful to quickly check some constants. - member __.IgnoreUndef with get() = ignoreUndef - - /// Update the current statement index to be the next (current + 1) statement. - member inline __.NextStmt () = - __.StmtIdx <- __.StmtIdx + 1 - - /// Stop evaluating further statements of the current instruction, and move on - /// the next instruction. - member __.AbortInstr ([] - needToUpdatePC: bool) = - isInstrTerminated <- true - needToEvaluateIEMark <- needToUpdatePC - __.NextStmt () - - /// Get the value of the given temporary variable. - member inline __.TryGetTmp n = - match __.Temporaries.TryGet (n) with - | Ok v -> Def v - | Error _ -> Undef - - /// Get the value of the given temporary variable. - member inline __.GetTmp n = - __.Temporaries.Get (n) - - /// Set the value for the given temporary variable. - member inline __.SetTmp n v = - __.Temporaries.Set n v - - /// Unset the given temporary variable. - member inline __.UnsetTmp n = - __.Temporaries.Unset n - - /// Get the value of the given register. - member inline __.TryGetReg (r: RegisterID) = - match __.Registers.TryGet (int r) with - | Ok v -> Def v - | Error _ -> Undef - - /// Get the value of the given register. - member inline __.GetReg (r: RegisterID) = - __.Registers.Get (int r) - - /// Set the value for the given register. - member inline __.SetReg (r: RegisterID) v = - __.Registers.Set (int r) v - - /// Unset the given register. - member inline __.UnsetReg (r: RegisterID) = - __.Registers.Unset (int r) - - /// Advance PC by `amount`. - member inline __.AdvancePC (amount: uint32) = - __.PC <- __.PC + uint64 amount - - /// Initialize the current context by updating register values. - member __.InitializeContext pc regs = - __.PC <- pc - regs |> List.iter (fun (r, v) -> __.SetReg r v) - - /// Go to the statement of the given label. - member inline __.GoToLabel lbl = - __.StmtIdx <- __.Labels.Index lbl - - /// Get ready for evaluating a new instruction. - member inline __.PrepareInstrEval stmts = - __.IsInstrTerminated <- false - __.NeedToEvaluateIEMark <- false - __.Labels.Update stmts - __.StmtIdx <- 0 - - /// Per-instruction handler. - member __.PerInstrHandler - with get() = perInstrHdl and set(f) = perInstrHdl <- f - - /// Memory load event handler. - member __.LoadEventHandler - with get() = loadEventHdl and set(f) = loadEventHdl <- f - - /// Memory load failure (access violation) event handler. - member __.LoadFailureEventHandler - with get() = loadFailureHdl and set(f) = loadFailureHdl <- f - - /// Memory store event handler. - member __.StoreEventHandler - with get() = storeEventHdl and set(f) = storeEventHdl <- f - - /// Put event handler. The first parameter is PC, and the second is the value - /// that is put to the destination. - member __.PutEventHandler - with get() = putEventHdl and set(f) = putEventHdl <- f - - /// Side-effect event handler. - member __.SideEffectEventHandler - with get() = sideEffectHdl and set(f) = sideEffectHdl <- f - - /// Statement evaluation event handler. - member __.StmtEvalEventHandler - with get() = stmtEvalHdl and set(f) = stmtEvalHdl <- f - - member internal __.OnInstr st = - __.PerInstrHandler.Invoke st - - member internal __.OnLoad pc addr v = - __.LoadEventHandler.Invoke (pc, addr, v) - - member internal __.OnLoadFailure pc addr rt e = - __.LoadFailureEventHandler.Invoke (pc, addr, rt, e) - - member internal __.OnStore pc addr v = - __.StoreEventHandler.Invoke (pc, addr, v) - - member internal __.OnPut pc v = - __.PutEventHandler.Invoke (pc, v) - - member internal __.OnSideEffect eff st = - __.SideEffectEventHandler.Invoke (eff, st) - - member internal __.OnStmtEval stmt = - __.StmtEvalEventHandler.Invoke (stmt) - - /// Make a copy of this EvalState with a given new Memory. - member __.Clone (newMem) = - EvalState (regs.Clone (), - temps.Clone (), - lbls.Clone (), - newMem, - ignoreUndef, - PC=pc, - StmtIdx=stmtIdx, - Mode=mode, - CurrentInsLen=currentInsLen, - IsInstrTerminated=isInstrTerminated, - NeedToEvaluateIEMark=needToEvaluateIEMark, - PerInstrHandler=perInstrHdl, - LoadEventHandler=loadEventHdl, - LoadFailureEventHandler=loadFailureHdl, - StoreEventHandler=storeEventHdl, - PutEventHandler=putEventHdl, - SideEffectEventHandler=sideEffectHdl, - StmtEvalEventHandler=stmtEvalHdl) - - /// Make a copy of this EvalState. - member __.Clone () = __.Clone (mem) diff --git a/src/MiddleEnd/ConcEval/Evaluator.fs b/src/MiddleEnd/ConcEval/Evaluator.fs deleted file mode 100644 index 2f99b225..00000000 --- a/src/MiddleEnd/ConcEval/Evaluator.fs +++ /dev/null @@ -1,218 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// ConcEval.Evaluator is a concrete evaluation module for LowUIR. -module B2R2.MiddleEnd.ConcEval.Evaluator - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.MiddleEnd.ConcEval.EvalUtils - -let rec evalConcrete (st: EvalState) e = - match e.E with - | Num n -> n - | Var (_, n, _, _) -> st.GetReg n - | PCVar (t, _) -> BitVector.ofUInt64 st.PC t - | TempVar (_, n) -> st.GetTmp n - | UnOp (t, e, _) -> evalUnOp st e t - | BinOp (t, _, e1, e2, _) -> evalBinOp st e1 e2 t - | RelOp (t, e1, e2, _) -> evalRelOp st e1 e2 t - | Load (endian, t, addr, _) -> evalLoad st endian t addr - | Ite (cond, e1, e2, _) -> - let cond = evalConcrete st cond - if cond = tr then evalConcrete st e1 else evalConcrete st e2 - | Cast (kind, t, e, _) -> evalCast st t e kind - | Extract (e, t, p, _) -> BitVector.extract (evalConcrete st e) t p - | Undefined (_) -> raise UndefExpException - | _ -> raise InvalidExprException - -and private evalLoad st endian t addr = - let addr = evalConcrete st addr |> BitVector.toUInt64 - match st.Memory.Read addr endian t with - | Ok v -> - st.OnLoad st.PC addr v - v - | Error e -> - match st.OnLoadFailure st.PC addr t e with - | Ok v -> v - | Error _ -> raise (InvalidMemException addr) - -and private evalCast st t e = function - | CastKind.SignExt -> BitVector.sext (evalConcrete st e) t - | CastKind.ZeroExt -> BitVector.zext (evalConcrete st e) t - | CastKind.FloatCast -> BitVector.fcast (evalConcrete st e) t - | CastKind.IntToFloat -> BitVector.itof (evalConcrete st e) t - | CastKind.FtoICeil -> BitVector.ftoiceil (evalConcrete st e) t - | CastKind.FtoIFloor -> BitVector.ftoifloor (evalConcrete st e) t - | CastKind.FtoIRound -> BitVector.ftoiround (evalConcrete st e) t - | CastKind.FtoITrunc -> BitVector.ftoitrunc (evalConcrete st e) t - | _ -> raise IllegalASTTypeException - -and private evalUnOp st e typ = - let v = evalConcrete st e - match typ with - | UnOpType.NEG -> BitVector.neg v - | UnOpType.NOT -> BitVector.bnot v - | UnOpType.FSQRT -> BitVector.fsqrt v - | UnOpType.FCOS -> BitVector.fcos v - | UnOpType.FSIN -> BitVector.fsin v - | UnOpType.FTAN -> BitVector.ftan v - | UnOpType.FATAN -> BitVector.fatan v - | _ -> raise IllegalASTTypeException - -and private evalBinOp st e1 e2 typ = - let e1 = evalConcrete st e1 - let e2 = evalConcrete st e2 - match typ with - | BinOpType.ADD -> BitVector.add e1 e2 - | BinOpType.SUB -> BitVector.sub e1 e2 - | BinOpType.MUL -> BitVector.mul e1 e2 - | BinOpType.DIV -> BitVector.div e1 e2 - | BinOpType.SDIV -> BitVector.sdiv e1 e2 - | BinOpType.MOD -> BitVector.modulo e1 e2 - | BinOpType.SMOD -> BitVector.smodulo e1 e2 - | BinOpType.SHL -> BitVector.shl e1 e2 - | BinOpType.SAR -> BitVector.sar e1 e2 - | BinOpType.SHR -> BitVector.shr e1 e2 - | BinOpType.AND -> BitVector.band e1 e2 - | BinOpType.OR -> BitVector.bor e1 e2 - | BinOpType.XOR -> BitVector.bxor e1 e2 - | BinOpType.CONCAT -> BitVector.concat e1 e2 - | BinOpType.FADD -> BitVector.fadd e1 e2 - | BinOpType.FSUB -> BitVector.fsub e1 e2 - | BinOpType.FMUL -> BitVector.fmul e1 e2 - | BinOpType.FDIV -> BitVector.fdiv e1 e2 - | BinOpType.FPOW -> BitVector.fpow e1 e2 - | BinOpType.FLOG -> BitVector.flog e1 e2 - | _ -> raise IllegalASTTypeException - -and private evalRelOp st e1 e2 typ = - let e1 = evalConcrete st e1 - let e2 = evalConcrete st e2 - match typ with - | RelOpType.EQ -> BitVector.eq e1 e2 - | RelOpType.NEQ -> BitVector.neq e1 e2 - | RelOpType.GT -> BitVector.gt e1 e2 - | RelOpType.GE -> BitVector.ge e1 e2 - | RelOpType.SGT -> BitVector.sgt e1 e2 - | RelOpType.SGE -> BitVector.sge e1 e2 - | RelOpType.LT -> BitVector.lt e1 e2 - | RelOpType.LE -> BitVector.le e1 e2 - | RelOpType.SLT -> BitVector.slt e1 e2 - | RelOpType.SLE -> BitVector.sle e1 e2 - | RelOpType.FLT -> BitVector.flt e1 e2 - | RelOpType.FLE -> BitVector.fle e1 e2 - | RelOpType.FGT -> BitVector.fgt e1 e2 - | RelOpType.FGE -> BitVector.fge e1 e2 - | _ -> raise IllegalASTTypeException - -let private evalPCUpdate st rhs = - let v = evalConcrete st rhs - st.OnPut st.PC v - st.PC <- BitVector.toUInt64 v - -let evalUndef (st: EvalState) lhs = - match lhs.E with - | Var (_, n, _, _) -> st.UnsetReg n - | TempVar (_, n) -> st.UnsetTmp n - | _ -> raise InvalidExprException - -let private evalPut st lhs rhs = - try - let v = evalConcrete st rhs - st.OnPut st.PC v - match lhs.E with - | Var (_, n, _, _) -> st.SetReg n v - | TempVar (_, n) -> st.SetTmp n v - | PCVar (_) -> st.PC <- BitVector.toUInt64 v - | _ -> raise InvalidExprException - with - | UndefExpException - | :? System.Collections.Generic.KeyNotFoundException -> -#if EMULATION - () -#else - evalUndef st lhs -#endif - -let private evalStore st endian addr v = - let addr = evalConcrete st addr |> BitVector.toUInt64 - let v = evalConcrete st v - st.OnStore st.PC addr v - st.Memory.Write addr v endian - -let private evalJmp (st: EvalState) target = - match target.E with - | Name n -> st.GoToLabel n - | _ -> raise InvalidExprException - -let private evalCJmp st cond t f = - let cond = evalConcrete st cond - if cond = tr then evalJmp st t else evalJmp st f - -let private evalIntCJmp st cond t f = - let cond = evalConcrete st cond - evalPCUpdate st (if cond = tr then t else f) - -let evalStmt (st: EvalState) s = - match s.S with - | ISMark (len) -> st.CurrentInsLen <- len; st.NextStmt () - | IEMark (len) -> st.AdvancePC len; st.AbortInstr () - | LMark _ -> st.NextStmt () - | Put (lhs, { E = Undefined (_) }) -> evalUndef st lhs |> st.NextStmt - | Put (lhs, rhs) -> evalPut st lhs rhs |> st.NextStmt - | Store (e, addr, v) -> evalStore st e addr v |> st.NextStmt - | Jmp target -> evalJmp st target - | CJmp (cond, t, f) -> evalCJmp st cond t f - | InterJmp (target, _) -> evalPCUpdate st target |> st.AbortInstr - | InterCJmp (c, t, f) -> evalIntCJmp st c t f |> st.AbortInstr - | SideEffect eff -> st.OnSideEffect eff st - -let internal tryEvaluate stmt st = - try evalStmt st stmt with - | UndefExpException - | InvalidMemException _ -> - if st.IgnoreUndef then st.NextStmt () - else raise UndefExpException - -/// Evaluate a sequence of statements, assuming that the statements are lifted -/// from a single instruction. -let rec evalStmts stmts (st: EvalState) = - let idx = st.StmtIdx - let numStmts = Array.length stmts - let st = if idx = 0 then st.OnInstr st else st - if numStmts > idx then - if st.IsInstrTerminated then - if st.NeedToEvaluateIEMark then - let stmt = stmts[numStmts - 1] - st.OnStmtEval stmt - tryEvaluate stmt st - else () - else - let stmt = stmts[idx] - st.OnStmtEval stmt - tryEvaluate stmt st - evalStmts stmts st - else () diff --git a/src/MiddleEnd/ConcEval/Memory.fs b/src/MiddleEnd/ConcEval/Memory.fs deleted file mode 100644 index 34d59fe0..00000000 --- a/src/MiddleEnd/ConcEval/Memory.fs +++ /dev/null @@ -1,108 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ConcEval - -open System.Collections.Generic -open System.Collections.Concurrent -open B2R2 - -[] -type Memory () = - - /// Read a byte from the memory. - abstract member ByteRead: Addr -> Result - - /// Write a byte from the memory. - abstract member ByteWrite: Addr * byte -> unit - - /// Clear up the memory contents; make the whole memory empty. - abstract member Clear: unit -> unit - - member private __.ReadLE acc addr i = - if i <= 0UL then Ok acc - else - match __.ByteRead (addr + i - 1UL) with - | Ok b -> __.ReadLE (b :: acc) addr (i - 1UL) - | Error e -> Error e - - member private __.ReadBE acc len addr i = - if i >= len then Ok acc - else - match __.ByteRead (addr + i) with - | Ok b -> __.ReadBE (b :: acc) len addr (i + 1UL) - | Error e -> Error e - - /// Read a bitvector value from the memory. - member __.Read addr endian typ = - let len = RegType.toByteWidth typ |> uint64 - match endian with - | Endian.Little -> __.ReadLE [] addr len - | _ -> __.ReadBE [] len addr 0UL - |> function - | Ok lst -> Array.ofList lst |> BitVector.ofArr |> Ok - | Error e -> Error e - - /// Write a bitvector value to the memory. - member __.Write addr v endian = - let len = BitVector.getType v |> RegType.toByteWidth |> int - let v = BitVector.getValue v - if endian = Endian.Big then - for i = 1 to len do - let offset = i - 1 - let b = (v >>> (offset * 8)) &&& 255I |> byte - __.ByteWrite (addr + uint64 (len - i), b) - else - for i = 1 to len do - let offset = i - 1 - let b = (v >>> (offset * 8)) &&& 255I |> byte - __.ByteWrite (addr + uint64 offset, b) - -/// Non-sharable memory. -type NonsharableMemory () = - inherit Memory () - - let mem = Dictionary () - - override __.ByteRead (addr) = - if mem.ContainsKey addr then Ok mem[addr] - else Error ErrorCase.InvalidMemoryRead - - override __.ByteWrite (addr, b) = mem[addr] <- b - - override __.Clear () = mem.Clear () - -/// Thread-safe (sharable) memory. -type SharableMemory () = - inherit Memory () - - let mem = ConcurrentDictionary () - - override __.ByteRead (addr) = - if mem.ContainsKey addr then Ok mem[addr] - else Error ErrorCase.InvalidMemoryRead - - override __.ByteWrite (addr, b) = mem[addr] <- b - - override __.Clear () = mem.Clear () diff --git a/src/MiddleEnd/ConcEval/README.md b/src/MiddleEnd/ConcEval/README.md deleted file mode 100644 index 61c00be6..00000000 --- a/src/MiddleEnd/ConcEval/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# B2R2.MiddleEnd.ConcEval - -### B2R2? - -B2R2 is a binary analysis and reversing framework written purely in F#. Since it -does not rely on any native (unmanaged) code, it is readily usable in any -platform or OS that .NET runs on. - -### B2R2.MiddleEnd.ConcEval Package? - -`B2R2.MiddleEnd.ConcEval` contains helper classes and functions that enable -concrete execution on B2R2's LowUIR statements. diff --git a/src/MiddleEnd/ConcEval/SafeEvaluator.fs b/src/MiddleEnd/ConcEval/SafeEvaluator.fs deleted file mode 100644 index dffcbc86..00000000 --- a/src/MiddleEnd/ConcEval/SafeEvaluator.fs +++ /dev/null @@ -1,262 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -/// ConcEval.SafeEvaluator is a safe concrete evaluation module for LowUIR. -/// Unlike ConcEval.Evaluator, it does not raise exceptions, but it is slower -/// than ConcEval.Evaluator. -module B2R2.MiddleEnd.ConcEval.SafeEvaluator - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.MiddleEnd.ConcEval.EvalUtils - -let private map1 fn p1 = function - | Ok (Def bv) -> Def (fn bv p1) |> Ok - | _ -> Error ErrorCase.InvalidExprEvaluation - -let private map2 fn p1 p2 = function - | Ok (Def bv) -> Def (fn bv p1 p2) |> Ok - | _ -> Error ErrorCase.InvalidExprEvaluation - -let private unwrap = function - | Ok (Def bv) -> Ok bv - | _ -> Error ErrorCase.InvalidExprEvaluation - -let rec evalConcrete (st: EvalState) e = - match e.E with - | Num n -> Def n |> Ok - | Var (_, n, _, _) -> st.TryGetReg n |> Ok - | PCVar (t, _) -> BitVector.ofUInt64 st.PC t |> Def |> Ok - | TempVar (_, n) -> st.TryGetTmp n |> Ok - | UnOp (t, e, _) -> evalUnOp st e t - | BinOp (t, _, e1, e2, _) -> evalBinOp st e1 e2 t - | RelOp (t, e1, e2, _) -> evalRelOp st e1 e2 t - | Load (endian, t, addr, _) -> evalLoad st endian t addr - | Ite (cond, e1, e2, _) -> evalIte st cond e1 e2 - | Cast (kind, t, e, _) -> evalCast st t e kind - | Extract (e, t, p, _) -> evalConcrete st e |> map2 BitVector.extract t p - | Undefined (_) -> Ok Undef - | _ -> Error ErrorCase.InvalidExprEvaluation - -and private evalLoad st endian t addr = - match evalConcrete st addr |> unwrap |> Result.map BitVector.toUInt64 with - | Ok addr -> - match st.Memory.Read addr endian t with - | Ok v -> - st.OnLoad st.PC addr v - Ok (Def v) - | Error e -> - st.OnLoadFailure st.PC addr t e - |> Result.map Def - | Error e -> Error e - -and private evalIte st cond e1 e2 = - match evalConcrete st cond |> unwrap with - | Ok cond -> - if cond = tr then evalConcrete st e1 else evalConcrete st e2 - | Error e -> Error e - -and private evalBinOpConc st e1 e2 fn = - let e1 = evalConcrete st e1 |> unwrap - let e2 = evalConcrete st e2 |> unwrap - match e1, e2 with - | Ok e1, Ok e2 -> fn e1 e2 |> Def |> Ok - | Error e, _ | _, Error e -> Error e - -and private evalUnOpConc st e fn = - evalConcrete st e |> unwrap |> Result.map (fn >> Def) - -and private evalCast st t e = function - | CastKind.SignExt -> evalConcrete st e |> map1 BitVector.sext t - | CastKind.ZeroExt -> evalConcrete st e |> map1 BitVector.zext t - | CastKind.FloatCast -> evalConcrete st e |> map1 BitVector.fcast t - | CastKind.IntToFloat -> evalConcrete st e |> map1 BitVector.itof t - | CastKind.FtoICeil -> evalConcrete st e |> map1 BitVector.ftoiceil t - | CastKind.FtoIFloor -> evalConcrete st e |> map1 BitVector.ftoifloor t - | CastKind.FtoIRound -> evalConcrete st e |> map1 BitVector.ftoiround t - | CastKind.FtoITrunc -> evalConcrete st e |> map1 BitVector.ftoitrunc t - | _ -> raise IllegalASTTypeException - -and private evalUnOp st e = function - | UnOpType.NEG -> evalUnOpConc st e BitVector.neg - | UnOpType.NOT -> evalUnOpConc st e BitVector.bnot - | UnOpType.FSQRT -> evalUnOpConc st e BitVector.fsqrt - | UnOpType.FCOS -> evalUnOpConc st e BitVector.fcos - | UnOpType.FSIN -> evalUnOpConc st e BitVector.fsin - | UnOpType.FTAN -> evalUnOpConc st e BitVector.ftan - | UnOpType.FATAN -> evalUnOpConc st e BitVector.fatan - | _ -> raise IllegalASTTypeException - -and private evalBinOp st e1 e2 = function - | BinOpType.ADD -> evalBinOpConc st e1 e2 BitVector.add - | BinOpType.SUB -> evalBinOpConc st e1 e2 BitVector.sub - | BinOpType.MUL -> evalBinOpConc st e1 e2 BitVector.mul - | BinOpType.DIV -> evalBinOpConc st e1 e2 BitVector.div - | BinOpType.SDIV -> evalBinOpConc st e1 e2 BitVector.sdiv - | BinOpType.MOD -> evalBinOpConc st e1 e2 BitVector.modulo - | BinOpType.SMOD -> evalBinOpConc st e1 e2 BitVector.smodulo - | BinOpType.SHL -> evalBinOpConc st e1 e2 BitVector.shl - | BinOpType.SAR -> evalBinOpConc st e1 e2 BitVector.sar - | BinOpType.SHR -> evalBinOpConc st e1 e2 BitVector.shr - | BinOpType.AND -> evalBinOpConc st e1 e2 BitVector.band - | BinOpType.OR -> evalBinOpConc st e1 e2 BitVector.bor - | BinOpType.XOR -> evalBinOpConc st e1 e2 BitVector.bxor - | BinOpType.CONCAT -> evalBinOpConc st e1 e2 BitVector.concat - | BinOpType.FADD -> evalBinOpConc st e1 e2 BitVector.fadd - | BinOpType.FSUB -> evalBinOpConc st e1 e2 BitVector.fsub - | BinOpType.FMUL -> evalBinOpConc st e1 e2 BitVector.fmul - | BinOpType.FDIV -> evalBinOpConc st e1 e2 BitVector.fdiv - | BinOpType.FPOW -> evalBinOpConc st e1 e2 BitVector.fpow - | BinOpType.FLOG -> evalBinOpConc st e1 e2 BitVector.flog - | _ -> raise IllegalASTTypeException - -and private evalRelOp st e1 e2 = function - | RelOpType.EQ -> evalBinOpConc st e1 e2 BitVector.eq - | RelOpType.NEQ -> evalBinOpConc st e1 e2 BitVector.neq - | RelOpType.GT -> evalBinOpConc st e1 e2 BitVector.gt - | RelOpType.GE -> evalBinOpConc st e1 e2 BitVector.ge - | RelOpType.SGT -> evalBinOpConc st e1 e2 BitVector.sgt - | RelOpType.SGE -> evalBinOpConc st e1 e2 BitVector.sge - | RelOpType.LT -> evalBinOpConc st e1 e2 BitVector.lt - | RelOpType.LE -> evalBinOpConc st e1 e2 BitVector.le - | RelOpType.SLT -> evalBinOpConc st e1 e2 BitVector.slt - | RelOpType.SLE -> evalBinOpConc st e1 e2 BitVector.sle - | RelOpType.FLT -> evalBinOpConc st e1 e2 BitVector.flt - | RelOpType.FLE -> evalBinOpConc st e1 e2 BitVector.fle - | RelOpType.FGT -> evalBinOpConc st e1 e2 BitVector.fgt - | RelOpType.FGE -> evalBinOpConc st e1 e2 BitVector.fge - | _ -> raise IllegalASTTypeException - -let private markUndefAfterFailure (st: EvalState) lhs = - match lhs with - | Var (_, n, _, _) -> st.UnsetReg n - | TempVar (_, n) -> st.UnsetTmp n - | _ -> () - -let private evalPCUpdate st rhs = - match evalConcrete st rhs with - | (Ok (Def v)) -> - st.OnPut st.PC v - st.PC <- BitVector.toUInt64 v - Ok () - | _ -> Error ErrorCase.InvalidExprEvaluation - -let private evalPut st lhs rhs = - match evalConcrete st rhs with - | Ok (Def v) -> - st.OnPut st.PC v - match lhs.E with - | Var (_, n, _, _) -> st.SetReg n v |> Ok - | TempVar (_, n) -> st.SetTmp n v |> Ok - | PCVar (_) -> st.PC <- BitVector.toUInt64 v; Ok () - | _ -> Error ErrorCase.InvalidExprEvaluation - | _ -> - markUndefAfterFailure st lhs.E - Error ErrorCase.InvalidExprEvaluation - -let private evalStore st endian addr v = - let addr = evalConcrete st addr |> unwrap |> Result.map BitVector.toUInt64 - let v = evalConcrete st v |> unwrap - match addr, v with - | Ok addr, Ok v -> - st.OnStore st.PC addr v - st.Memory.Write addr v endian - Ok () - | Error e, _ | _, Error e -> Error e - -let private evalJmp (st: EvalState) target = - match target.E with - | Name n -> st.GoToLabel n |> Ok - | _ -> Error ErrorCase.InvalidExprEvaluation - -let private evalCJmp st cond t f = - match evalConcrete st cond |> unwrap with - | Ok cond -> - if cond = tr then evalJmp st t else evalJmp st f - | Error e -> Error e - -let private evalIntCJmp st cond t f = - match evalConcrete st cond |> unwrap with - | Ok cond -> evalPCUpdate st (if cond = tr then t else f) - | Error e -> Error e - -/// Evaluate an IR statement. -let evalStmt (st: EvalState) = function - | ISMark (len) -> st.CurrentInsLen <- len; st.NextStmt () |> Ok - | IEMark (len) -> st.AdvancePC len; st.AbortInstr () |> Ok - | LMark _ -> st.NextStmt () |> Ok - | Put (lhs, rhs) -> evalPut st lhs rhs |> Result.map st.NextStmt - | Store (e, addr, v) -> evalStore st e addr v |> Result.map st.NextStmt - | Jmp target -> evalJmp st target - | CJmp (cond, t, f) -> evalCJmp st cond t f - | InterJmp (target, _) -> evalPCUpdate st target |> Result.map st.AbortInstr - | InterCJmp (c, t, f) -> evalIntCJmp st c t f |> Result.map st.AbortInstr - | SideEffect eff -> st.OnSideEffect eff st |> ignore |> Ok - -let internal tryEvaluate stmt st = - match evalStmt st stmt.S with - | Ok () -> Ok st - | Error e -> - if st.IgnoreUndef then st.NextStmt (); Ok st - else Error e - -/// Evaluate a sequence of statements, which is lifted from a single -/// instruction. -let rec internal evalStmts stmts result = - match result with - | Ok (st: EvalState) -> - let idx = st.StmtIdx - let numStmts = Array.length stmts - let st = if idx = 0 then st.OnInstr st else st - if numStmts > idx then - if st.IsInstrTerminated then - if st.NeedToEvaluateIEMark then tryEvaluate stmts[numStmts - 1] st - else Ok st - else - let stmt = stmts[idx] - st.OnStmtEval stmt - evalStmts stmts (tryEvaluate stmt st) - else Ok st - | Error _ -> result - -let rec private evalBlockLoop idx (blk: Stmt [][]) result = - match result with - | Ok (st: EvalState) -> - if idx < blk.Length then - let stmts = blk[idx] - st.PrepareInstrEval stmts - evalStmts stmts (Ok st) - |> evalBlockLoop (idx + 1) blk - else result - | Error e -> Error e - -/// Evaluate a series of statement arrays, assuming that each array is obtained -/// from a single machine instruction. -let evalBlock (st: EvalState) pc blk = - st.PC <- pc - evalBlockLoop 0 blk (Ok st) - |> function - | Ok st -> Ok st - | Error e -> Error e diff --git a/src/MiddleEnd/ConcEval/Variables.fs b/src/MiddleEnd/ConcEval/Variables.fs deleted file mode 100644 index b8d30655..00000000 --- a/src/MiddleEnd/ConcEval/Variables.fs +++ /dev/null @@ -1,59 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ConcEval - -open B2R2 - -type Variables (vars) = - let vars: BitVector[] = vars - - new (cnt: int) = Variables (Array.zeroCreate cnt) - - member __.TryGet k = - let v = vars[k] - if isNull v then Error ErrorCase.InvalidRegister - else Ok v - - member __.Get k = vars[k] - - member __.Set k v = vars[k] <- v - - member __.Unset k = vars[k] <- null - - member __.Count () = vars.Length - - member __.ToArray () = vars |> Array.mapi (fun i v -> i, v) - - member __.Clone () = - Variables (Array.copy vars) - -module Variables = - /// This is the maximum number of temporary variables per instruction. 64 is - /// just a conservative number. - let [] maxNumTemporaries = 64 - - /// This is the maxinum number of register variables that an ISA can have. - /// This is a conservative number. - let [] maxNumVars = 1024 diff --git a/src/MiddleEnd/ControlFlowAnalysis/B2R2.MiddleEnd.ControlFlowAnalysis.fsproj b/src/MiddleEnd/ControlFlowAnalysis/B2R2.MiddleEnd.ControlFlowAnalysis.fsproj deleted file mode 100644 index 90625b3a..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/B2R2.MiddleEnd.ControlFlowAnalysis.fsproj +++ /dev/null @@ -1,58 +0,0 @@ - - - - LICENSE.md - b2r2-240x240.png - README.md - B2R2 CFG recovery engine. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/ControlFlowAnalysis/BBLManager.fs b/src/MiddleEnd/ControlFlowAnalysis/BBLManager.fs deleted file mode 100644 index 0762c8a5..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/BBLManager.fs +++ /dev/null @@ -1,455 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.LowUIR -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph - -/// Temporary information obtained by parsing a block (bbl) of instructions, -/// such as IR-level leaders and auxiliary information about an -/// instruction-level basic block. This information is necessary to construct a -/// (IR-level) CFG. Normally, a single instruction-level bbl represents a single -/// IR-level basic block, but if there exist intra-instruction control flows, it -/// can have multiple intra blocks. -type TempInfo = { - /// Helper for translating symbol to program point. - LabelPPoints: Map - /// All leaders in this block. - Leaders: Set - /// Intra-Instruction edges in this block. - IntraEdges: (ProgramPoint * ProgramPoint * CFGEdgeKind) list - /// Inter-Instruction edges related to this block. - InterEdges: (ProgramPoint * ProgramPoint * CFGEdgeKind) list - /// Flag indicating that IEMark statement follows a terminatinig statment, - /// such as SideEffect. Although our IR optimizer will remove such IEMarks in - /// most cases, there is one exception, though. If there is a SideEffect - /// statement immediately followed by an IEMark, our optmizer will not remove - /// the IEMark because we cannot assume that the SideEffect statement will - /// advance the PC. In fact, the SideEffect statement does not necessarily - /// know the size of the corresponding machine instruction. Thus, it is not - /// natural to remove such IEMarks. - HasExplicitTerminator: bool - /// Next events to consume. Since BBLManager parses only a single BBL, other - /// events need to be consumed later. - NextEvents: CFGEvents -} -with - static member Init initialLeader evts = - { LabelPPoints = Map.empty - Leaders = Set.singleton initialLeader - IntraEdges = [] - InterEdges = [] - HasExplicitTerminator = false - NextEvents = evts } - - /// Find label symbol at the given program point (myPp). - static member FindLabelSymbol tmpInfo myPp = - Map.findKey (fun _ labelPp -> labelPp = myPp) tmpInfo.LabelPPoints - |> snd - -/// Since Symbol is only unique within an instruction, it is necessary to tag it -/// with the instruction address that holds the symbol. -and LabelIdentifier = Addr * Symbol - -/// Represents an instruction-level basic block. -type BBLInfo = { - /// The range (start addr, end addr) of the basic block. - BlkRange: AddrRange - /// Instruction addresses in the basic block. - InstrAddrs: Set - /// IR-level leaders (program points) within the bbl. - IRLeaders: Set - /// Function Entry - FunctionEntry: Addr -} - -module BBLInfo = - /// Return the bitmask for the given BinHandle to correctly compute jump - /// target addresses. - let computeJumpTargetMask (hdl: BinHandle) = - let rt = hdl.ISA.WordSize |> WordSize.toRegType - (* It is reasonable enough to assume that jump target addresses will never - overflow when rt is greater than 64. *) - if rt > 64 then 0xFFFFFFFFFFFFFFFFUL - else BitVector.unsignedMax rt |> BitVector.toUInt64 - - let private maskingAddr hdl addr = - let mask = computeJumpTargetMask hdl - addr &&& mask - - let private addLabel addr idx symb tmp = - let leader = ProgramPoint (addr, idx) - let labels = Map.add (addr, symb) leader tmp.LabelPPoints - let leaders = Set.add leader tmp.Leaders - { tmp with LabelPPoints = labels; Leaders = leaders } - - let private addAddrLeader addr tmp = - { tmp with Leaders = Set.add (ProgramPoint (addr, 0)) tmp.Leaders } - - let inline private updateNextEvents tmp evts = - { tmp with NextEvents = evts } - - /// Since there is an explicit edge to another bbl, we should add events to - /// parse those new edges. - let private addExplicitBranchEvents fm addr fn target e tmp = - (* Do nothing when there is a recursion *) - if (fm: FunctionMaintainer).Contains (addr=target) then - CFGEvents.addTailCallEvt fn addr target tmp.NextEvents - |> updateNextEvents tmp - else - let lastLeader = Set.maxElement tmp.Leaders - CFGEvents.addEdgeEvt fn lastLeader target e tmp.NextEvents - |> updateNextEvents tmp - - let private collectAux hdl fm addr fn idx tmp stmt isLast = - match stmt.S with - | LMark symb -> addLabel addr idx symb tmp - (* This is the case of "JMP PC". This means, the instruction iterates - itself. Therefore, the current instruction needs to be considered as a - new leader. *) - | InterJmp ({ E = PCVar _ }, InterJmpKind.Base) -> - addAddrLeader addr tmp - | InterJmp ({ E = BinOp (BinOpType.ADD, _, { E = PCVar (_) }, - { E = Num bv }, _) }, - InterJmpKind.Base) -> - let target = (addr + BitVector.toUInt64 bv) |> maskingAddr hdl - (* If the ijmp statement is the last one of the corresponding basic block, - then we know it is used to jump to another bbl. If otherwise, the ijmp - statement should branch to the current instruction. In such a case, we - simply consider the target address as a new (intra-bbl) leader. *) - if isLast then addExplicitBranchEvents fm addr fn target InterJmpEdge tmp - else addAddrLeader target tmp - (* InterCJmp targets are leaders if they are not belonging to last - instruction of a basic block, i.e. intra-instruction level branch *) - | InterCJmp (_, { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num tBv }, _) }, - { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num fBv }, _) }) -> - let tTarget = (addr + BitVector.toUInt64 tBv) |> maskingAddr hdl - let fTarget = (addr + BitVector.toUInt64 fBv) |> maskingAddr hdl - if isLast then - addExplicitBranchEvents fm addr fn tTarget InterCJmpTrueEdge tmp - |> addExplicitBranchEvents fm addr fn fTarget InterCJmpFalseEdge - else addAddrLeader tTarget tmp |> addAddrLeader fTarget - | InterCJmp (_, { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num tBv }, _) }, - _) -> - let tTarget = (addr + BitVector.toUInt64 tBv) |> maskingAddr hdl - if isLast then - addExplicitBranchEvents fm addr fn tTarget InterCJmpTrueEdge tmp - else addAddrLeader tTarget tmp - | InterCJmp (_, _, - { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num fBv }, _) }) -> - let fTarget = (addr + BitVector.toUInt64 fBv) |> maskingAddr hdl - if isLast then - addExplicitBranchEvents fm addr fn fTarget InterCJmpFalseEdge tmp - else addAddrLeader fTarget tmp - | _ -> tmp - - let rec private collectLeaders hdl fm addr fn idx isLastIns stmts tmp = - if idx >= (stmts: Stmt []).Length then tmp - else - let isLastStmt = isLastIns && idx = stmts.Length - 1 - let tmp = - collectAux hdl fm addr fn idx tmp stmts[idx] isLastStmt - collectLeaders hdl fm addr fn (idx + 1) isLastIns stmts tmp - - let rec private prepareLeaders hdl fm instrs fn tmp = - match instrs with - | (insInfo: InstructionInfo) :: tl -> - let isLastIns = List.isEmpty tl - let addr = insInfo.Instruction.Address - let stmts = insInfo.Stmts - prepareLeaders hdl fm tl fn - (collectLeaders hdl fm addr fn 0 isLastIns stmts tmp) - | [] -> tmp - - let private addIntraEdge src insAddr symb edge tmp = - let dst = Map.find (insAddr, symb) tmp.LabelPPoints - let intraEdges = (src, dst, edge) :: tmp.IntraEdges - { tmp with IntraEdges = intraEdges } - - let private addInterEdge src dstAddr edge tmp = - let dst = ProgramPoint (dstAddr, 0) - { tmp with InterEdges = (src, dst, edge) :: tmp.InterEdges } - - let private addExceptionEdgeEvents callSite excTbl fn entry caller tmp = - match (excTbl: ExceptionTable).TryFindExceptionTarget entry callSite with - | Some target -> - tmp.NextEvents - |> CFGEvents.addEdgeEvt fn caller target ExceptionFallThroughEdge - | None -> tmp.NextEvents - - let private addCallEdgeEvents callSite excTbl fn caller target ftAddr tmp = - let entry = (fn: RegularFunction).Entry - if target = ftAddr then (* Clang often produces PC-getter like this. *) - CFGEvents.addRetEvt fn target ftAddr callSite tmp.NextEvents - |> CFGEvents.addEdgeEvt fn caller ftAddr CallFallThroughEdge - |> CFGEvents.addCallEvt fn callSite target true - |> updateNextEvents tmp - else - addExceptionEdgeEvents callSite excTbl fn entry caller tmp - |> CFGEvents.addCallEvt fn callSite target false - |> updateNextEvents tmp - - let private addIndirectCallEvents callSite excTbl fn caller tmp = - let entry = (fn: RegularFunction).Entry - addExceptionEdgeEvents callSite excTbl fn entry caller tmp - |> CFGEvents.addIndCallEvt fn callSite - |> updateNextEvents tmp - - /// Add intra-instruction edges. - let private addEdgesAux hdl fm excTbl fn addr idx leader tmp insInfo isLast = - let stmt = insInfo.Stmts[idx] - match stmt.S with - | LMark _ -> ProgramPoint (addr, idx), tmp - | Jmp { E = Name symb } -> - leader, addIntraEdge leader addr symb IntraJmpEdge tmp - | CJmp (_, { E = Name tSymb }, { E = Name fSymb }) -> - let tmp = - addIntraEdge leader addr tSymb IntraCJmpTrueEdge tmp - |> addIntraEdge leader addr fSymb IntraCJmpFalseEdge - leader, tmp - | CJmp (_, { E = Name tSymb }, { E = Undefined _ }) -> - leader, addIntraEdge leader addr tSymb IntraCJmpTrueEdge tmp - | CJmp (_, { E = Undefined _ }, { E = Name fSymb }) -> - leader, addIntraEdge leader addr fSymb IntraCJmpFalseEdge tmp - | InterJmp ({ E = PCVar _ }, InterJmpKind.Base) -> - leader, addInterEdge leader addr InterJmpEdge tmp - (* InterJmp target is an inter-block edge only if the statement is placed - at the end of block *) - | InterJmp ({ E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num bv }, _) }, - InterJmpKind.Base) -> - let target = (addr + BitVector.toUInt64 bv) |> maskingAddr hdl - if isLast then leader, tmp - else leader, addInterEdge leader target InterJmpEdge tmp - | InterJmp ({ E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num bv }, _) }, - InterJmpKind.IsCall) -> - let target = (addr + BitVector.toUInt64 bv) |> maskingAddr hdl - let ftAddr = addr + uint64 insInfo.Instruction.Length - let tmp = addCallEdgeEvents addr excTbl fn leader target ftAddr tmp - if isLast then leader, tmp - else leader, addInterEdge leader target InterJmpEdge tmp - | InterJmp ({ E = Var _ }, InterJmpKind.Base) - | InterJmp ({ E = Load _ }, InterJmpKind.Base) -> - (fn: RegularFunction).RegisterNewIndJump addr - leader, tmp - (* Indirect calls. *) - | InterJmp (_, InterJmpKind.IsCall) -> - leader, addIndirectCallEvents addr excTbl fn leader tmp - (* InterCJmp targets are inter-block edges only if the statement is placed - at the end of block *) - | InterCJmp (_, { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num tBv }, _) }, - { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num fBv }, _) }) -> - let tTarget = (addr + BitVector.toUInt64 tBv) |> maskingAddr hdl - let fTarget = (addr + BitVector.toUInt64 fBv) |> maskingAddr hdl - if isLast then leader, tmp - else - let tmp = - addInterEdge leader tTarget InterCJmpTrueEdge tmp - |> addInterEdge leader fTarget InterCJmpFalseEdge - leader, tmp - | InterCJmp (_, { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num tBv }, _) }, - _) -> - let tTarget = (addr + BitVector.toUInt64 tBv) |> maskingAddr hdl - if isLast then leader, tmp - else leader, addInterEdge leader tTarget InterCJmpTrueEdge tmp - | InterCJmp (_, _, - { E = BinOp (BinOpType.ADD, _, { E = PCVar _ }, - { E = Num fBv }, _) }) -> - let fTarget = (addr + BitVector.toUInt64 fBv) |> maskingAddr hdl - if isLast then leader, tmp - else leader, addInterEdge leader fTarget InterCJmpFalseEdge tmp - | InterJmp (_, InterJmpKind.IsRet) -> leader, tmp - (* SideEffects *) - | SideEffect SysCall -> - fn.AddSysCallSite addr - leader, { tmp with HasExplicitTerminator = true } - | SideEffect _ when insInfo.Instruction.IsExit () -> - leader, { tmp with HasExplicitTerminator = true } - (* For EVM. *) - | InterJmp ({ E = TempVar (_, _) }, _) - | InterCJmp (_, { E = TempVar (_, _) }, { E = Num _ }) -> - (fn: RegularFunction).RegisterNewIndJump addr - leader, tmp - | _ -> (* Fall-through cases. *) - (* Inter-instruction fall-through. *) - if isLast then - let ftAddr = addr + uint64 insInfo.Instruction.Length - let tmp = - if (fm: FunctionMaintainer).Contains ftAddr - || tmp.HasExplicitTerminator - then tmp - else - tmp.NextEvents - |> CFGEvents.addEdgeEvt fn leader ftAddr FallThroughEdge - |> updateNextEvents tmp - leader, tmp - else - let nextPp = ProgramPoint (addr, idx + 1) - (* Intra-instruction fall-through. *) - if Set.contains nextPp tmp.Leaders then - let symb = TempInfo.FindLabelSymbol tmp nextPp - leader, addIntraEdge leader addr symb FallThroughEdge tmp - else leader, tmp - - let rec private addEdges hdl fm excTbl fn addr idx isLastIns ins leader t = - let len = ins.Stmts.Length - if idx >= len then t - else - let isLastStmt = isLastIns && idx = (len - 1) - let leader, tmp = - addEdgesAux hdl fm excTbl fn addr idx leader t ins isLastStmt - addEdges hdl fm excTbl fn addr (idx + 1) isLastIns ins leader tmp - - let private isKnownEdge (src1: ProgramPoint) (dst1: ProgramPoint) tmp = - tmp.InterEdges - |> List.exists (fun (src2: ProgramPoint, dst2: ProgramPoint, _) -> - src2.Address = src1.Address && dst2.Address = dst1.Address) - - let private addFallThrough src dst tmp = - if Set.contains dst tmp.Leaders - && not (isKnownEdge src dst tmp) then - { tmp with InterEdges = (src, dst, FallThroughEdge) :: tmp.InterEdges } - else tmp - - let rec private includeEdges hdl fm excTbl leader instrs fn tmp = - match instrs with - | (insInfo: InstructionInfo) :: ((nextInsInfo :: _) as tl) -> - let addr = insInfo.Instruction.Address - let pp = ProgramPoint (addr, 0) - let nextPp = ProgramPoint (nextInsInfo.Instruction.Address, 0) - let leader = if Set.contains pp tmp.Leaders then pp else leader - let tmp = addEdges hdl fm excTbl fn addr 0 false insInfo leader tmp - let tmp = addFallThrough leader nextPp tmp - includeEdges hdl fm excTbl leader tl fn tmp - | insInfo :: [] -> - let addr = insInfo.Instruction.Address - let pp = ProgramPoint (addr, 0) - let leader = if Set.contains pp tmp.Leaders then pp else leader - addEdges hdl fm excTbl fn addr 0 true insInfo leader tmp - | [] -> tmp - - /// Sequentially scan instructions at an IR-level, and find both intra-block - /// and inter-block edges. - let private scanBlock hdl fm excTbl instrs fn startAddr evts = - let leader = ProgramPoint (startAddr, 0) - let tmp = TempInfo.Init leader evts - prepareLeaders hdl fm instrs fn tmp - |> includeEdges hdl fm excTbl leader instrs fn - - let rec private findInsInfo (ppoint: ProgramPoint) instrs = - match instrs with - | (info: InstructionInfo) :: tl -> - if info.Instruction.Address = ppoint.Address then - struct (info, instrs) - else findInsInfo ppoint tl - | [] -> Utils.impossible () - - /// Extract ir-bbl part of InstructionInfo from a single instruction from - /// given ppoint. - let private extractInsInfo i (ppoint: ProgramPoint) nextLeader = - (* If addresses are different, we take everything from ppoint *) - if ppoint.Address <> (nextLeader: ProgramPoint).Address then - let nextInsAddr = i.Instruction.Address + uint64 i.Instruction.Length - let nextPoint = ProgramPoint (nextInsAddr, 0) - if ppoint.Position > 0 then - let delta = i.Stmts.Length - ppoint.Position - let i' = { i with Stmts = Array.sub i.Stmts ppoint.Position delta } - i', nextPoint - else i, nextPoint - else (* Intra-instruction case. *) - let delta = nextLeader.Position - ppoint.Position - let i' = { i with Stmts = Array.sub i.Stmts ppoint.Position delta } - i', nextLeader - - /// This function returns an array of InstructionInfo for ir-level bbl - let rec private gatherInsInfos acc instrs ppoint nextLeader = - if ppoint < nextLeader then - let struct (info, instrs) = findInsInfo ppoint instrs - let info, nextPoint = extractInsInfo info ppoint nextLeader - let acc = info :: acc - if nextPoint = nextLeader then List.rev acc |> List.toArray - else gatherInsInfos acc instrs nextPoint nextLeader - elif ppoint = nextLeader then List.rev acc |> List.toArray - (* Next point is beyond the next leader's point. This is possible when two - control flows divide an instruction into two parts. This typically - happens in obfuscated code. *) - else Utils.futureFeature () - - let private createIRBBL fn instrs nextAddr leaders idx leader = - let nextLeader = - if idx < (leaders: ProgramPoint []).Length - 1 then leaders[idx + 1] - else ProgramPoint (nextAddr, 0) - let instrs = gatherInsInfos [] instrs leader nextLeader - if Array.isEmpty instrs then () - else (fn: RegularFunction).AddVertex (instrs, leader) |> ignore - - let private resetFunctionBoundary (fn: RegularFunction) endAddr = - if endAddr > fn.MaxAddr then fn.SetBoundary fn.MinAddr endAddr - else () - - let private markNoReturn (fn: RegularFunction) instrs = - let insInfo: InstructionInfo = instrs |> List.last - if insInfo.Instruction.IsRET () then fn.NoReturnProperty <- NotNoRet - else () - - let private buildVertices instrs nextAddr fn tmp = - let leaders = Set.toArray tmp.Leaders - leaders - |> Array.iteri (createIRBBL fn instrs nextAddr leaders) - resetFunctionBoundary fn (nextAddr - 1UL) - markNoReturn fn instrs - - let private buildEdges (fn: RegularFunction) tmp = - tmp.IntraEdges |> List.iter fn.AddEdge - tmp.InterEdges |> List.iter fn.AddEdge - - let parse hdl instrs sAddr nextAddr fn fnMaintainer excTbl evts = - let tmp = scanBlock hdl fnMaintainer excTbl instrs fn sAddr evts - buildVertices instrs nextAddr fn tmp - buildEdges fn tmp - struct ( - { BlkRange = AddrRange (sAddr, nextAddr - 1UL) - InstrAddrs = - instrs |> List.map (fun i -> i.Instruction.Address) |> Set.ofList - IRLeaders = tmp.Leaders - FunctionEntry = fn.Entry }, tmp.NextEvents - ) - - let init blkRange blkAddrs irLeaders funcEntry = - { BlkRange = blkRange - InstrAddrs = blkAddrs |> Set.ofList - IRLeaders = irLeaders - FunctionEntry = funcEntry } diff --git a/src/MiddleEnd/ControlFlowAnalysis/CFGBuilder.fs b/src/MiddleEnd/ControlFlowAnalysis/CFGBuilder.fs deleted file mode 100644 index a16c60c5..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/CFGBuilder.fs +++ /dev/null @@ -1,585 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd.BinFile.ELF -open B2R2.FrontEnd.BinInterface -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinLifter.Intel -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph - -/// Information about a fall-through block to resolve next. -type FallThroughInfo = - | FTCall of caller: ProgramPoint - * callSite: Addr - * callee: Addr - * ftAddr: Addr - | FTNonCall of srcPp: ProgramPoint * ftAddr: Addr - -[] -module private CFGBuilder = - /// In this function, we only consider a single instruction-level basic block. - /// We parse its corresponding IR-level basic blocks as well as - /// intra-instruction edges. But we don't add inter-instruction CFG edges. - /// Instead, this function returns a list of CFGEvents to perform in the next - /// iteration. - let buildBBL hdl codeMgr func mode leaderAddr evts = - match (codeMgr: CodeManager).ParseBBL hdl mode leaderAddr func evts with - | Ok evts -> Ok evts - | Error ErrorCase.ParsingFailure -> Error ErrorParsing - | Error _ -> Utils.impossible () - - let buildFunction hdl (codeMgr: CodeManager) _dataMgr entry mode evts = - match codeMgr.TryGetBBL entry with - | Some bbl when bbl.FunctionEntry <> entry -> (* Need to split *) - codeMgr.HistoryManager.Record <| CreatedFunction entry - if bbl.BlkRange.Min <> entry then - let _, evts = codeMgr.SplitBlock bbl entry evts - let _, evts = codeMgr.PromoteBBL hdl entry bbl evts - Ok evts - else - let _, evts = codeMgr.PromoteBBL hdl entry bbl evts - Ok evts - | _ -> - let func = - match codeMgr.FunctionMaintainer.TryFindRegular entry with - | Some func -> func - | None -> codeMgr.FunctionMaintainer.GetOrAddFunction (hdl, entry) - if func.HasVertex (ProgramPoint (entry, 0)) then Ok evts - else buildBBL hdl codeMgr func mode entry evts (* Build new block *) - - let inline isIntrudingBlk (codeMgr: CodeManager) addr = - match codeMgr.TryGetBBL addr with - | Some bbl -> addr <> bbl.BlkRange.Min - | None -> false - - let splitAndConnectEdge hdl (codeMgr: CodeManager) fn src dst edge evts = - let bbl = codeMgr.GetBBL dst - if bbl.FunctionEntry <> (fn: RegularFunction).Entry then - (* There is an edge from a function to another function, and the edge is - intruding an existing bbl, too. In this case, the destination address - becomes a new function. This happens when there is an edge to the - middle of a ".cold" snippet. *) - let _, evts = codeMgr.SplitBlock bbl dst evts - let _, evts = codeMgr.PromoteBBL hdl dst bbl evts - Ok evts - else - match codeMgr.SplitBlock bbl dst evts with - | Some front, evts -> - (* When a bbl is self-dividing itself, then the dst block should have a - self-loop. For example, if a BBL has three instructions (a, b, c) and - if c has a branch to b, then we split the block into (a) and (b, c), - and the second block will have a self-loop. *) - let src = if src = front then ProgramPoint (dst, 0) else src - fn.AddEdge (src, ProgramPoint (dst, 0), edge) - Ok evts - | _, evts -> - fn.AddEdge (src, ProgramPoint (dst, 0), edge) - Ok evts - - let getCallee hdl (codeMgr: CodeManager) callee evts = - match codeMgr.FunctionMaintainer.TryFind (addr=callee) with - | Some calleeFunc -> calleeFunc, evts - | None -> - let calleeFunc = codeMgr.FunctionMaintainer.GetOrAddFunction (hdl, callee) - let evts = CFGEvents.addFuncEvt callee ArchOperationMode.NoMode evts - calleeFunc :> Function, evts - - /// If there is a tail-call from my function to a callee, and the callee is a - /// returning function, then we know that my function should *not* no return. - let markAsReturning (myfn: RegularFunction) isTailCall (calleeFn: Function) = - if isTailCall - && (calleeFn.NoReturnProperty = NotNoRet - || calleeFn.NoReturnProperty = NotNoRetConfirmed) - then myfn.NoReturnProperty <- NotNoRet - else () - - let tryGetRelocatableFunction (codeMgr: CodeManager) dataMgr relocSite = - let sym = (dataMgr: DataManager).RelocatableFuncs[relocSite] - let funcName = sym.SymName - match codeMgr.FunctionMaintainer.TryFind funcName with - | Some calleeFn -> Some calleeFn.Entry - | _ -> None - - let buildCall hdl codeMgr dataMgr fn callSite callee isTailCall isNoFn evts = - let callerBBL = (codeMgr: CodeManager).GetBBL callSite - let callerPp = Set.maxElement callerBBL.IRLeaders - let relocFuncs = (dataMgr: DataManager).RelocatableFuncs - let relocSite = callSite + 1UL - let callee = - if relocFuncs.ContainsKey relocSite then - tryGetRelocatableFunction codeMgr dataMgr relocSite - else Some callee - match callee with - | Some 0UL -> Ok evts (* Ignore the callee for "call 0" cases. *) - | Some callee -> - (fn: RegularFunction).AddEdge (callerPp, callSite, callee, - isTailCall, isNoFn) - if not isNoFn then - let calleeFn, evts = getCallee hdl codeMgr callee evts - markAsReturning fn isTailCall calleeFn - Ok evts - else Ok evts - | _ -> - let callerV = fn.FindVertex callerPp - let last = callerV.VData.LastInstruction - let ftAddr = last.Address + uint64 last.Length - evts - |> CFGEvents.addEdgeEvt fn callerPp ftAddr CallFallThroughEdge - |> Ok - - let buildIndCall (codeMgr: CodeManager) fn callSite evts = - let callerPp = Set.maxElement (codeMgr.GetBBL callSite).IRLeaders - (fn: RegularFunction).AddEdge (callerPp, callSite) - Ok evts - - let buildTailCall hdl codeMgr dataMgr fn caller callee evts = - buildCall hdl codeMgr dataMgr fn caller callee true false evts - - let makeCalleeNoReturn (codeMgr: CodeManager) fn callee callSite = - let callee = codeMgr.FunctionMaintainer.Find (addr=callee) - let callBlk = codeMgr.GetBBL callSite -#if CFGDEBUG - dbglog "CFGBuilder" - "Ret edge connects to an existing func, %x must be noret" callee.Entry -#endif - let srcPp = ProgramPoint (callBlk.BlkRange.Min, 0) - let src = (fn: RegularFunction).FindVertex srcPp - DiGraph.getSuccs fn.IRCFG src - |> List.iter (fun dst -> - (* Do not remove fake block *) - if not <| dst.VData.IsFakeBlock () then fn.RemoveEdge (src, dst)) - callee.NoReturnProperty <- NoRet - - let buildRet codeMgr (fn: RegularFunction) callee ftAddr callSite evts = - let fallBlk = (codeMgr: CodeManager).GetBBL ftAddr - if fallBlk.FunctionEntry = fn.Entry then - fn.AddEdge (callSite=callSite, callee=callee, ftAddr=ftAddr) - Ok evts - else - makeCalleeNoReturn codeMgr fn callee callSite - Ok evts - - let createJumpAfterLockChunk (codeMgr: CodeManager) chunkStartAddr addrs = - let last = List.rev addrs |> List.head - let lastIns = codeMgr.GetInstruction last - let size = last + uint64 lastIns.Instruction.Length - chunkStartAddr - let wordSize = lastIns.Instruction.WordSize - let stmts = lastIns.Stmts - InlinedAssembly.Init chunkStartAddr (uint32 size) wordSize stmts - - /// Build a regular edge, which is any edge that is not a call, an indirect - /// call, nor a ret edge. - let buildRegularEdge hdl (codeMgr: CodeManager) dataMgr fn src dst edge evts = - let mode = ArchOperationMode.NoMode (* XXX: put mode in the event. *) - if not <| hdl.FileInfo.IsExecutableAddr (fn: RegularFunction).Entry then - Error ErrorConnectingEdge (* Invalid bbl encountered. *) - elif codeMgr.HasBBL dst then - let dstPp = ProgramPoint (dst, 0) - let dstBlk = codeMgr.GetBBL dst - if fn.HasVertex dstPp then - fn.AddEdge (src, ProgramPoint (dst, 0), edge) - Ok evts - elif edge = CallFallThroughEdge && dstBlk.FunctionEntry = dst then - Ok evts (* Undetected no-return case, so we do not add fall-through. *) - else (* Tail-call. *) - buildFunction hdl codeMgr dataMgr dst mode evts - |> Result.bind (buildCall hdl codeMgr dataMgr fn src.Address dst true false) - elif isIntrudingBlk codeMgr dst then - splitAndConnectEdge hdl codeMgr fn src dst edge evts - elif not (codeMgr.HasInstruction dst) (* Jump to the middle of an instr *) - && fn.IsAddressCovered dst then - match InlinedAssemblyPattern.checkInlinedAssemblyPattern hdl dst with - | NotInlinedAssembly -> Error ErrorConnectingEdge - | JumpAfterLock addrs -> - let patternStart = List.head addrs - let chunk = createJumpAfterLockChunk codeMgr patternStart addrs - codeMgr.ReplaceInlinedAssemblyChunk addrs chunk evts |> Ok - elif dst = 0UL then Ok evts (* "jmp 0" case (as in "call 0"). *) - else - match buildBBL hdl codeMgr fn mode dst evts with - | Ok evts -> fn.AddEdge (src, ProgramPoint (dst, 0), edge); Ok evts - | Error e -> Error e - - let checkIfIndCallAnalysisRequired (fn: RegularFunction) exitNodes = - exitNodes - |> List.exists (fun (v: Vertex) -> - v.VData.IsFakeBlock () - && fn.IsUnresolvedIndirectCall v.VData.FakeBlockInfo.CallSite) - - /// Does the vertex (v) end with a regular (returning) syscall? - let inline isReturningSyscall hdl (noret: NoReturnFunctionIdentification) v = - match (v: Vertex).VData.SyscallTail with - | UnknownSyscallTail -> - if noret.IsNoRetSyscallBlk hdl v then - v.VData.SyscallTail <- ExitSyscallTail; false - else - v.VData.SyscallTail <- RegularSyscallTail; true - | RegularSyscallTail -> true - | _ -> false - - /// Obtain fall-through information from a fake block and add it to the - /// accumulator. The information includes a 4-tuple: (caller program point, - /// call instruction address, callee's address, fall-through address). - let accFTInfoFromFake (codeMgr: CodeManager) fn (v: IRVertex) infos = - let callSite = v.VData.FakeBlockInfo.CallSite - let callerPp = Set.maxElement (codeMgr.GetBBL callSite).IRLeaders - let calleeAddr = v.VData.PPoint.Address - let callerV = (fn: RegularFunction).FindVertex callerPp - let last = callerV.VData.LastInstruction - let ftAddr = last.Address + uint64 last.Length - FTCall (callerPp, callSite, calleeAddr, ftAddr) :: infos - - /// Check if a call instruction is indeed a system call. In particular, - /// call dword ptr [gs:0x10] is a system call in x86/x64 Linux environment. - /// We pattern-match the instruction. - let isIndirectSyscall hdl (fn: RegularFunction) (v: Vertex) = - match hdl.FileInfo.FileFormat, hdl.FileInfo.ISA.Arch with - | FileFormat.ELFBinary, Architecture.IntelX86 -> - let caller = DiGraph.getPreds fn.IRCFG v |> List.head - let callIns = caller.VData.LastInstruction :?> IntelInstruction - match callIns.Prefixes, callIns.Operands with - | Prefix.PrxGS, OneOperand (OprMem (None, None, Some 16L, _)) -> true - | _ -> false - | _ -> false - - /// Scan all exit nodes and obtain two things: (1) a list of addresses that - /// are a target of fall-through edges; and (2) a set of function addresses - /// which need to perform the no-ret analysis. We assume that the indirect - /// call recovery is performed on the given function (fn). - let scanCandidates hdl codeMgr noret fn exitNodes = - exitNodes - |> List.fold (fun (infos, toAnalyze) (v: Vertex) -> - if not (v.VData.IsFakeBlock ()) then - if isReturningSyscall hdl noret v then - let last = v.VData.LastInstruction - let ftAddr = last.Address + uint64 last.Length - FTNonCall (v.VData.PPoint, ftAddr) :: infos, toAnalyze - else infos, toAnalyze - elif isIndirectSyscall hdl fn v then - (* First mark it as resolved indirect call so that indirect call - analyzer will not analyze this again. *) - let callsite = v.VData.FakeBlockInfo.CallSite - fn.UpdateCallEdgeInfo (callsite, IndirectCallees Set.empty) - let caller = DiGraph.getPreds fn.IRCFG v |> List.head - if noret.IsNoRetSyscallBlk hdl caller then infos, toAnalyze - else accFTInfoFromFake codeMgr fn v infos, toAnalyze - else - let callSite = v.VData.FakeBlockInfo.CallSite - (fn: RegularFunction).CallTargets callSite - |> Set.fold (fun (infos, toAnalyze) calleeAddr -> - let callee = (codeMgr: CodeManager).FunctionMaintainer.Find calleeAddr - match callee.NoReturnProperty with - | NotNoRetConfirmed | NotNoRet -> - if v.VData.FakeBlockInfo.IsTailCall then infos, toAnalyze - else accFTInfoFromFake codeMgr fn v infos, toAnalyze - | ConditionalNoRet arg -> - let callerPp = Set.maxElement (codeMgr.GetBBL callSite).IRLeaders - let callerV = fn.FindVertex callerPp - if noret.HasNonZeroArg hdl callerV arg then infos, toAnalyze - elif v.VData.FakeBlockInfo.IsTailCall then infos, toAnalyze - else accFTInfoFromFake codeMgr fn v infos, toAnalyze - | UnknownNoRet -> - if callee.Entry = fn.Entry then (* Recursive *) infos, toAnalyze - else infos, Set.add calleeAddr toAnalyze - | _ -> infos, toAnalyze) (infos, toAnalyze) - ) ([], Set.empty) - - let addFallThroughEvts (hdl: BinHandle) codeMgr fn ftInfos evts = - let evts = - CFGEvents.addPerFuncAnalysisEvt (fn: RegularFunction).Entry evts - ftInfos - |> List.fold (fun evts ftInfo -> - match ftInfo with - | FTCall (caller, callSite, callee, ftAddr) -> - if not (hdl.FileInfo.IsExecutableAddr ftAddr) then - let calleeFn = (codeMgr: CodeManager).FunctionMaintainer.Find callee - calleeFn.NoReturnProperty <- NoRet - evts - else - evts - |> CFGEvents.addRetEvt fn callee ftAddr callSite - |> CFGEvents.addEdgeEvt fn caller ftAddr CallFallThroughEdge - | FTNonCall (srcPp, ftAddr) -> - evts |> CFGEvents.addEdgeEvt fn srcPp ftAddr FallThroughEdge - ) evts - - let updateCalleeInfo (codeMgr: CodeManager) (func: RegularFunction) = - DiGraph.iterVertex func.IRCFG (fun v -> - if v.VData.IsFakeBlock () && v.VData.PPoint.Address <> 0UL - && not v.VData.FakeBlockInfo.IsNoFunction then - let calleeFunc = codeMgr.FunctionMaintainer.Find v.VData.PPoint.Address - if calleeFunc.FunctionKind = FunctionKind.Regular then - let calleeFunc = calleeFunc :?> RegularFunction - v.VData.FakeBlockInfo <- - { v.VData.FakeBlockInfo with - UnwindingBytes = calleeFunc.AmountUnwinding - GetPCThunkInfo = calleeFunc.GetPCThunkInfo } - else - v.VData.FakeBlockInfo <- { v.VData.FakeBlockInfo with IsPLT = true } - else ()) - - let runIndirectCallRecovery hdl codeMgr dataMgr entry indcall fn evts = -#if CFGDEBUG - dbglog "CFGBuilder" "@%x Started indcall analysis" entry -#endif - updateCalleeInfo codeMgr fn - CFGEvents.addPerFuncAnalysisEvt fn.Entry evts - |> (indcall: PerFunctionAnalysis).Run hdl codeMgr dataMgr fn - - let runIndirectJmpRecovery hdl codeMgr dataMgr entry indjmp fn evts = -#if CFGDEBUG - dbglog "CFGBuilder" "@%x Started indjmp analysis" entry -#endif - updateCalleeInfo codeMgr fn - CFGEvents.addPerFuncAnalysisEvt fn.Entry evts - |> (indjmp: PerFunctionAnalysis).Run hdl codeMgr dataMgr fn - - let private hasPath src dst evts = - let map = evts.CalleeAnalysisEdges - let visited = HashSet () - let rec dfs addrs = - let addr = List.head addrs - if addr = dst then true, List.rev addrs - elif visited.Contains addr then false, addrs - else - visited.Add addr |> ignore - Map.tryFind addr map - |> Option.defaultValue Set.empty - |> Set.fold (fun (found, path) succ -> - if found then found, path - else dfs (succ :: addrs)) (false, addrs) - dfs [src] - - /// We consider mutually recursive functions to be "returning", i.e., "not no - /// ret". This is to make sure that our analysis to terminate. When there is a - /// function call chain a -> b -> c -> a -> ..., then we cannot decide the - /// no-ret property of each function because our analysis assumes that all the - /// callees of a function should be analyzed first. Thus, when we detect - /// mutual recursions, we simply consider the first function in the chain as - /// a returning function. - let makeMutuallyRecursiveFunctionsNotNoRet codeMgr myAddr toAnalyze evts = - toAnalyze - |> Set.iter (fun addr -> - match hasPath addr myAddr evts with - | true, path -> - let funcsInPath = - path |> List.map (fun a -> - (codeMgr: CodeManager).FunctionMaintainer.FindRegular (a)) - if funcsInPath - |> List.exists (fun f -> f.NoReturnProperty <> UnknownNoRet) - then () (* No need to worry about infinite loop. *) - else - funcsInPath - |> List.choose (fun f -> - if f.NoReturnProperty = UnknownNoRet then Some f else None) - |> List.sortByDescending (fun callee -> - let nextAddr = - codeMgr.FunctionMaintainer.FindNextFunctionAddr callee - nextAddr - callee.MaxAddr) - |> List.tryHead (* Take the one with the biggest gap *) - |> function - | Some callee -> -#if CFGDEBUG - dbglog "CFGBuilder" "Make %x as NotNoRet (%x -> %x)" - callee.Entry addr myAddr -#endif - callee.NoReturnProperty <- NotNoRet - | None -> () - | false, _ -> ()) - - /// Before we run the no-return analysis on this function (fn), we should - /// first analyze the other callees, and come back later. - let analyzeCalleesFirst codeMgr (fn: RegularFunction) toAnalyze evts = - makeMutuallyRecursiveFunctionsNotNoRet codeMgr fn.Entry toAnalyze evts - let evts = CFGEvents.addPerFuncAnalysisEvt fn.Entry evts - toAnalyze - |> Set.fold (fun evts entry -> - CFGEvents.addPerFuncAnalysisEvt entry evts - |> CFGEvents.addCalleeAnalysisEvt fn.Entry entry) evts - |> Ok - - let retrieveStackAdjustment (ins: Instruction) = - match ins.Immediate () with - | true, v -> int64 v - | false, _ -> 0L - - /// Assuming that "ret NN" instructions are used, compute how much stack - /// unwinding is happening for the given function. - /// - /// TODO: We can extend this analysis further to make it more precise. - let computeStackUnwindingAmount cfg = - DiGraph.getExits cfg - |> List.fold (fun acc (v: Vertex) -> - if Option.isSome acc || v.VData.IsFakeBlock () then acc - else - let ins = v.VData.LastInstruction - if ins.IsRET () then retrieveStackAdjustment ins |> Some - else acc) None - |> function - | None -> 0L - | Some n -> n - - /// Update extra function information as we have finished all the per-function - /// analyses. - let finalizeFunctionInfo (func: RegularFunction) = - let amountUnwinding = computeStackUnwindingAmount func.IRCFG - if amountUnwinding <> 0L then func.AmountUnwinding <- amountUnwinding - else () - - let runPerFuncAnalysis hdl codeMgr dataMgr entry noret indcall indjmp evts = - let fn = (codeMgr: CodeManager).FunctionMaintainer.FindRegular (addr=entry) - let exits = DiGraph.getExits (fn: RegularFunction).IRCFG - let ftInfos, toAnalyze = scanCandidates hdl codeMgr noret fn exits - if not (List.isEmpty ftInfos) then - addFallThroughEvts hdl codeMgr fn ftInfos evts |> Ok - elif not (fn.YetAnalyzedIndirectJumpAddrs |> Seq.isEmpty) then - runIndirectJmpRecovery hdl codeMgr dataMgr entry indjmp fn evts - elif checkIfIndCallAnalysisRequired fn exits then - runIndirectCallRecovery hdl codeMgr dataMgr entry indcall fn evts - elif Set.isEmpty toAnalyze |> not then - analyzeCalleesFirst codeMgr fn toAnalyze evts - else -#if CFGDEBUG - dbglog "CFGBuilder" "@%x Finalize with no-ret analysis" entry -#endif - (* We implement unwinding calculation for EVM in the other function - analyzeIndirectBranchPattern in IndirectJumpResolution. It's for - minimizing the overhead in calling CP, and we can get it back here when - incremental CP is implemented. *) - if hdl.ISA.Arch = Arch.EVM then () - else finalizeFunctionInfo fn - updateCalleeInfo codeMgr fn - noret.Run hdl codeMgr dataMgr fn evts - -/// This is the main class for building a CFG from a given binary. -type CFGBuilder (hdl, codeMgr: CodeManager, dataMgr: DataManager) as this = - let noret = NoReturnFunctionIdentification () - let indcall = IndirectCallResolution () - let indjmp = - match hdl.ISA.Arch with - | Arch.EVM -> EVMJmpResolution () :> PerFunctionAnalysis - | _ -> JmpTableResolution (this) :> PerFunctionAnalysis - -#if CFGDEBUG - let countEvts evts = - "(" + (List.length evts.BasicEvents).ToString () - + ", " - + (List.length evts.FunctionAnalysisAddrs).ToString () - + " left)" -#endif - - let rec update evts = - match evts with - | Ok ({ BasicEvents = CFGFunc (entry, mode) :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x %s %s" - entry (nameof CFGFunc) (countEvts evts) -#endif - let evts = { evts with BasicEvents = tl } - update (buildFunction hdl codeMgr dataMgr entry mode evts) - | Ok ({ BasicEvents = CFGEdge (fn, src, dst, edge) :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x %s (%x -> %x; %s) %s" - fn.Entry (nameof CFGEdge) src.Address dst (CFGEdgeKind.toString edge) - (countEvts evts) -#endif - let evts = { evts with BasicEvents = tl } - update (buildRegularEdge hdl codeMgr dataMgr fn src dst edge evts) - | Ok ({ BasicEvents = CFGCall (fn, csite, callee, noFn) :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x %s (%x -> %x) %s" - fn.Entry (nameof CFGCall) csite callee (countEvts evts) -#endif - let evts = { evts with BasicEvents = tl } - update (buildCall hdl codeMgr dataMgr fn csite callee false noFn evts) - | Ok ({ BasicEvents = CFGIndCall (fn, callSite) :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x %s (%x) %s" - fn.Entry (nameof CFGIndCall) callSite (countEvts evts) -#endif - let evts = { evts with BasicEvents = tl } - update (buildIndCall codeMgr fn callSite evts) - | Ok ({ BasicEvents = CFGRet (fn, callee, ft, callSite) :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x %s (%x -> %x) (%x -> %x) %s" - fn.Entry (nameof CFGRet) callSite ft callee ft (countEvts evts) -#endif - let evts = { evts with BasicEvents = tl } - update (buildRet codeMgr fn callee ft callSite evts) - | Ok ({ BasicEvents = CFGTailCall (fn, callSite, callee) :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x %s (%x -> %x) %s" - fn.Entry (nameof CFGTailCall) callSite callee (countEvts evts) -#endif - let evts = { evts with BasicEvents = tl } - update (buildTailCall hdl codeMgr dataMgr fn callSite callee evts) - | Ok ({ BasicEvents = [] - FunctionAnalysisAddrs = fnAddr :: tl } as evts) -> -#if CFGDEBUG - dbglog (nameof CFGBuilder) "@%x per-func-analysis %s" - fnAddr (countEvts evts) -#endif - let evts = { evts with FunctionAnalysisAddrs = tl } - update (runPerFuncAnalysis - hdl codeMgr dataMgr fnAddr noret indcall indjmp evts) - | Ok ({ BasicEvents = [] }) -> (* FunctionAnalysisAddrs is empty *) -#if CFGDEBUG - dbglog (nameof CFGBuilder) "Done %s" (nameof update) -#endif - codeMgr.FunctionMaintainer.UpdateCallerCrossReferences () |> Ok - | Error err -> Error err - - interface ICFGBuildable with - member __.Update evts = - update (Ok evts) - - /// Add new events to the event list (evts). - member private __.AddNewFunction evts (entry, mode) = - if codeMgr.FunctionMaintainer.Contains (addr=entry) then Ok evts - elif not <| hdl.FileInfo.IsExecutableAddr entry then Error ErrorParsing - else CFGEvents.addFuncEvt entry mode evts |> Ok - - /// This is the only function that is available to users, which takes in a - /// list of known function entry infos and recover the whole CFGs, thereby - /// updating both code manager and data manager. The return value is Error if - /// a fatal error is encountered. - member __.AddNewFunctions entries = -#if CFGDEBUG - dbglog (nameof CFGBuilder) "Start by adding %d function(s) for %s" - (List.length entries) (hdl.FileInfo.FilePath) -#endif - (* List.foldBack is used here to preserve the order of input entries *) - List.foldBack (fun elm evts -> - match evts with - | Ok evts -> __.AddNewFunction evts elm - | Error e -> Error e) entries (Ok CFGEvents.empty) - |> function - | Ok evts -> (__ :> ICFGBuildable).Update evts - | Error e -> Error e diff --git a/src/MiddleEnd/ControlFlowAnalysis/CFGError.fs b/src/MiddleEnd/ControlFlowAnalysis/CFGError.fs deleted file mode 100644 index f7611716..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/CFGError.fs +++ /dev/null @@ -1,52 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 - -/// Error occured from a CFG analysis. -type CFGError = - /// This error occurs while resolving an indirect branch. - | ErrorBranchRecovery of fnAddr: Addr - * brAddr: Addr - * rollbackFuncs: Set - /// Nested switch is found and we found the existence of a jump-table overlap - /// late. So we rollback. - | ErrorLateDetection - /// This error occurs while parsing an invalid basic block. - | ErrorParsing - /// This error occurs while connecting an invalid edge; src/dst node is - /// invalid, e.g., when an edge is intruding an instruction boundary. - | ErrorConnectingEdge - -[] -module CFGError = - let toString = function - | ErrorBranchRecovery (fnAddr, brAddr, _) -> - (nameof ErrorBranchRecovery) - + "(" + fnAddr.ToString("x") + "," + brAddr.ToString("x") + ")" - | ErrorLateDetection -> nameof ErrorLateDetection - | ErrorParsing -> nameof ErrorParsing - | ErrorConnectingEdge -> nameof ErrorConnectingEdge diff --git a/src/MiddleEnd/ControlFlowAnalysis/CFGEvents.fs b/src/MiddleEnd/ControlFlowAnalysis/CFGEvents.fs deleted file mode 100644 index 3211ebce..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/CFGEvents.fs +++ /dev/null @@ -1,151 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.MiddleEnd.ControlFlowGraph - -/// A basic event that triggers CFG modifications. -type BasicCFGEvent = - /// Add a new function. - | CFGFunc of entry: Addr * mode: ArchOperationMode - /// Add a new inter edge. Note intra edges are connected during bbl parsing. - | CFGEdge of fn: RegularFunction - * src: ProgramPoint * dst: Addr * edge: CFGEdgeKind - /// Add an inter-procedural fake block for the call instruction. - | CFGCall of fn: RegularFunction * callSite: Addr * callee: Addr * noFn: bool - /// Add a fake return edge for the call instruction. - | CFGRet of fn: RegularFunction * callee: Addr * ftAddr: Addr * callSite: Addr - /// Add a fake block for an indirect call instruction. - | CFGIndCall of fn: RegularFunction * callSite: Addr - /// Add a fake block for a tail-call. - | CFGTailCall of fn: RegularFunction * callSite: Addr * callee: Addr - -/// List of CFGEvents. We divide events into three groups: (1) basic events, (2) -/// callee-analysis events, and (3) per-function-analysis events. The basic -/// events are essential ones for building regular CFGs. The callee-analysis -/// events are to detect mutually recursive callee analysis events. The -/// function-analysis events are to perform per-function analysis in order to -/// recover high-level CFG information, such as no-return information, and -/// indirect branch targets. -type CFGEvents = { - /// List of basic CFG events (LIFO). - BasicEvents: BasicCFGEvent list - /// Callee analysis edges, where each edge shows dependency between two - /// functions. This maps a source node to a set of destination nodes. - CalleeAnalysisEdges: Map> - /// List of function addresses (FIFO) that needs to perform per-function - /// analyses. - FunctionAnalysisAddrs: Addr list -} - -[] -module CFGEvents = - let empty = - { BasicEvents = [] - CalleeAnalysisEdges = Map.empty - FunctionAnalysisAddrs = [] } - - let addFuncEvt entry mode evts = - { evts with - BasicEvents = CFGFunc (entry, mode) :: evts.BasicEvents - FunctionAnalysisAddrs = entry :: evts.FunctionAnalysisAddrs } - - let addEdgeEvt fn src dst edge evts = - { evts with - BasicEvents = CFGEdge (fn, src, dst, edge) :: evts.BasicEvents } - - let addCallEvt fn callSiteAddr callee noFn evts = - { evts with - BasicEvents = - CFGCall (fn, callSiteAddr, callee, noFn) :: evts.BasicEvents } - - let addRetEvt fn callee ftAddr callSiteAddr evts = - { evts with - BasicEvents = - CFGRet (fn, callee, ftAddr, callSiteAddr) :: evts.BasicEvents } - - let addIndCallEvt fn callSiteAddr evts = - { evts with - BasicEvents = CFGIndCall (fn, callSiteAddr) :: evts.BasicEvents } - - let addTailCallEvt fn callSiteAddr callee evts = - { evts with - BasicEvents = - CFGTailCall (fn, callSiteAddr, callee) :: evts.BasicEvents } - - let addPerFuncAnalysisEvt entry evts = - { evts with FunctionAnalysisAddrs = entry :: evts.FunctionAnalysisAddrs } - - let addCalleeAnalysisEvt src dst evts = - let s = - match Map.tryFind src evts.CalleeAnalysisEdges with - | Some set -> set - | None -> Set.empty - let dsts = Set.add dst s - { evts with - CalleeAnalysisEdges = Map.add src dsts evts.CalleeAnalysisEdges } - - let updateEvtsAfterBBLSplit oldPp newPp evts = - let basicEvents = - evts.BasicEvents - |> List.map (fun elm -> - match elm with - | CFGEdge (fn, src, dst, edge) when src = oldPp -> - CFGEdge (fn, newPp, dst, edge) - | elm -> elm) - { evts with BasicEvents = basicEvents } - - let updateEvtsAfterBBLMerge srcPp dstPp evts = - let basicEvents = - evts.BasicEvents - |> List.map (fun elm -> - match elm with - | CFGEdge (fn, src, dst, edge) when src = dstPp -> - CFGEdge (fn, srcPp, dst, edge) - | elm -> elm) - { evts with BasicEvents = basicEvents } - - let updateEvtsAfterFuncSplit (newFn: RegularFunction) evts = - let basicEvents = - evts.BasicEvents - |> List.map (fun elm -> - match elm with - | CFGEdge (_, src, dst, edge) when newFn.HasVertex src -> - CFGEdge (newFn, src, dst, edge) - | CFGCall (_, callSite, callee, noFn) - when newFn.Entry < callSite && newFn.MaxAddr > callSite -> - CFGCall (newFn, callSite, callee, noFn) - | CFGRet (_, callee, ftAddr, callSite) - when newFn.Entry < ftAddr && (newFn.MaxAddr + 1UL) >= ftAddr -> - CFGRet (newFn, callee, ftAddr, callSite) - | CFGIndCall (_, callSite) - when newFn.Entry < callSite && newFn.MaxAddr > callSite -> - CFGIndCall (newFn, callSite) - | CFGTailCall (_, callSite, callee) - when newFn.Entry < callSite && newFn.MaxAddr > callSite -> - CFGTailCall (newFn, callSite, callee) - | elm -> elm) - { evts with BasicEvents = basicEvents } diff --git a/src/MiddleEnd/ControlFlowAnalysis/CFGHelper.fs b/src/MiddleEnd/ControlFlowAnalysis/CFGHelper.fs deleted file mode 100644 index a7563122..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/CFGHelper.fs +++ /dev/null @@ -1,73 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -[] -module internal B2R2.MiddleEnd.ControlFlowAnalysis.CFGHelper - -open B2R2 -open B2R2.MiddleEnd.BinGraph - -#if CFGDEBUG -open System.IO - -[] -module internal Dbg = - let logger = - let path = Path.Combine (Directory.GetCurrentDirectory (), "cfg.log") - FileLogger (path) :> ILogger - - let inline dbglog (locationName: string) fmt = - let after str = logger.LogLine (locationName.PadRight 20 + "| " + str) - Printf.ksprintf after fmt -#endif - -/// Categorize neighboring edges of a given vertex (v) in the graph (g). This -/// function returns three different groups of edges: (1) incoming edges, (2) -/// outgoing edges, and (3) self-cycle edge. -let categorizeNeighboringEdges g v = - let incomings, cycle = - DiGraph.getPreds g v - |> List.fold (fun (incomings, cycle) p -> - let e = DiGraph.findEdgeData g p v - if p.GetID () = v.GetID () then incomings, Some e - else (p, e) :: incomings, cycle) ([], None) - let outgoings = - DiGraph.getSuccs g v - |> List.fold (fun outgoings s -> - let e = DiGraph.findEdgeData g v s - if s.GetID () = v.GetID () then outgoings - else (s, e) :: outgoings) [] - incomings, outgoings, cycle - -/// Get reachable vertices and edges from v in g. -let getReachables g v = - let reachables = - Set.empty |> Traversal.foldPostorder g [v] (fun acc v -> Set.add v acc) - let edges = (* Collect corresponding edges. *) - DiGraph.foldEdge g (fun acc src dst e -> - (* Collect only when both src and dst belong to vertices. *) - if Set.contains src reachables && Set.contains dst reachables then - Set.add (src, dst, e) acc - else acc) Set.empty - reachables, edges diff --git a/src/MiddleEnd/ControlFlowAnalysis/CodeManager.fs b/src/MiddleEnd/ControlFlowAnalysis/CodeManager.fs deleted file mode 100644 index 48f3ab52..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/CodeManager.fs +++ /dev/null @@ -1,271 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph - -/// CodeManager manages all the processed information about the binary code -/// including *parsed* instructions, their basic blocks, functions, as well as -/// exception handling routines. -type CodeManager (hdl) = - let insMap = Dictionary () - let bblMap = Dictionary () - let excTbl = ExceptionTable (hdl) - let history = HistoryManager () - let fnMaintainer = FunctionMaintainer.Init hdl history - - let newInstructionInfo hdl (ins: Instruction) bblAddr = - let stmts = BinHandle.LiftOptimizedInstr hdl ins - { Instruction = ins - Stmts = stmts - BBLAddr = bblAddr } - - let rec postProcessInstrs hdl leaderAddr acc instrs = - match instrs with - | (ins: Instruction) :: tl -> - let addr = ins.Address - let info = newInstructionInfo hdl ins leaderAddr - insMap[addr] <- info - postProcessInstrs hdl leaderAddr (info :: acc) tl - | [] -> acc - - /// This function *NEVER* returns an empty list. - let rec parseBBL hdl mode acc pc = - hdl.Parser.OperationMode <- mode - match BinHandle.TryParseInstr (hdl, addr=pc) with - | Ok ins -> - let nextAddr = pc + uint64 ins.Length - if ins.IsBBLEnd () || bblMap.ContainsKey nextAddr then - Ok <| struct (ins :: acc, ins) - else parseBBL hdl mode (ins :: acc) nextAddr - | Error _ -> Error pc - - /// Parse an instruction-level basic block starting from the given leader - /// address. Return new CFG events to handle. - member __.ParseBBL hdl mode leaderAddr func evts = - match parseBBL hdl mode [] leaderAddr with - | Ok (instrs, lastIns) -> - let ins = postProcessInstrs hdl leaderAddr [] instrs - let nextAddr = lastIns.Address + uint64 lastIns.Length - let struct (bbl, evts) = - BBLInfo.parse hdl ins leaderAddr nextAddr func fnMaintainer excTbl evts - bblMap[leaderAddr] <- bbl - Ok evts - | Error addr -> -#if DEBUG - printfn "Parsing error detected at %x" addr -#endif - Error ErrorCase.ParsingFailure - - /// Get the current instruction count. - member __.InstructionCount with get() = insMap.Count - - /// Check if the manager contains parsed InstructionInfo located at the given - /// address. - member __.HasInstruction addr = insMap.ContainsKey addr - - /// Access instruction at the given address. - member __.GetInstruction (addr: Addr) = insMap[addr] - - /// Fold every instruction stored in the CodeManager. - member __.FoldInstructions fn acc = - insMap |> Seq.fold fn acc - - /// Get the current basic block count. - member __.BBLCount with get() = bblMap.Count - - /// Check if the manager contains a basic block starting at the given address. - member __.HasBBL addr = bblMap.ContainsKey addr - - /// Find the corresponding BBL address from the given instruction address. - member __.GetBBL addr = bblMap[insMap[addr].BBLAddr] - - /// Try to find the corresponding BBL address from the given instruction - /// address. - member __.TryGetBBL addr = - match insMap.TryGetValue addr with - | true, ins -> - match bblMap.TryGetValue ins.BBLAddr with - | true, bbl -> Some bbl - | _ -> None - | _ -> None - - /// Add the given bbl information; update the instruction-to-bbl mapping - /// information. - member __.AddBBL blkRange irLeaders funcEntry insAddrs = - match insAddrs with - | leaderAddr :: _ -> - insAddrs - |> List.iter (fun addr -> - let ins = insMap[addr] - insMap[addr] <- { ins with BBLAddr = leaderAddr }) - bblMap[leaderAddr] <- BBLInfo.init blkRange insAddrs irLeaders funcEntry - | [] -> () - - /// Remove the given BBLInfo. - member __.RemoveBBL (bbl) = - bblMap.Remove bbl.BlkRange.Min |> ignore - - /// Remove the given BBL located at the bblAddr. - member __.RemoveBBL (bblAddr) = - if bblMap.ContainsKey bblAddr then __.RemoveBBL bblMap[bblAddr] - else () - - /// Fold every instruction stored in the CodeManager. - member __.FoldBBLs fn acc = - bblMap |> Seq.fold fn acc - - member private __.SplitBBLInfo (bbl: BBLInfo) splitAddr splitPp = - __.RemoveBBL (bbl) - let fstAddrs, sndAddrs = - Set.partition (fun insAddr -> insAddr < splitAddr) bbl.InstrAddrs - let fstAddrs = Set.toList fstAddrs - let sndAddrs = Set.toList sndAddrs - let fstLeaders, sndLeaders = - Set.add splitPp bbl.IRLeaders - |> Set.partition (fun pp -> pp < splitPp) - let oldRange = bbl.BlkRange - let fstRange = AddrRange (oldRange.Min, splitAddr - 1UL) - let sndRange = AddrRange (splitAddr, oldRange.Max) - let entry = bbl.FunctionEntry - __.AddBBL fstRange fstLeaders entry fstAddrs - __.AddBBL sndRange sndLeaders entry sndAddrs - - /// This is when a contiguous bbl (it is even contiguous at the IR-level) is - /// divided into two at the splitPoint. - member private __.SplitCFG fn prevBBL splitPoint evts = - let bblPoint = (* The program point of the dividing block. *) - prevBBL.IRLeaders - |> Set.partition (fun pp -> pp < splitPoint) - |> fst |> Set.maxElement - (fn: RegularFunction).SplitBBL (bblPoint, splitPoint) |> ignore - Some bblPoint, CFGEvents.updateEvtsAfterBBLSplit bblPoint splitPoint evts - - /// Split the given basic block into two at the given address (splitAddr), and - /// returns a pair of (the address of the front bbl after the cut-out, and new - /// events). The front bbl may not exist if the split point is at the address - /// of an existing bbl leader. - member __.SplitBlock bbl splitAddr evts = - let splitPp = ProgramPoint (splitAddr, 0) -#if CFGDEBUG - dbglog (nameof CodeManager) "Split BBL @ %x%s" - splitAddr (if Set.contains splitPp bbl.IRLeaders then " (& CFG)" else "") -#endif - let func = fnMaintainer.FindRegular bbl.FunctionEntry - __.SplitBBLInfo bbl splitAddr splitPp - if Set.contains splitPp bbl.IRLeaders then None, evts - else __.SplitCFG func bbl splitPp evts - - member private __.MergeBBLInfoAndReplaceInlinedAssembly addrs fstBBL sndBBL = - let restAddrs = List.tail addrs - __.RemoveBBL (bbl=fstBBL) - __.RemoveBBL (bbl=sndBBL) - let blkRange = AddrRange (fstBBL.BlkRange.Min, sndBBL.BlkRange.Max) - let leaders = - Set.union fstBBL.IRLeaders sndBBL.IRLeaders - |> Set.filter (fun leader -> not <| List.contains leader.Address restAddrs) - let addrs = - Set.union fstBBL.InstrAddrs sndBBL.InstrAddrs - |> Set.filter (fun addr -> not <| List.contains addr restAddrs) - |> Set.toList - let entry = fstBBL.FunctionEntry - __.AddBBL blkRange leaders entry addrs - - member __.ReplaceInlinedAssemblyChunk insAddrs (chunk: Instruction) evts = - let fstBBL = __.GetBBL chunk.Address - let sndBBL = __.GetBBL (fstBBL.BlkRange.Max + 1UL) - __.MergeBBLInfoAndReplaceInlinedAssembly insAddrs fstBBL sndBBL - let fn = fnMaintainer.FindRegular fstBBL.FunctionEntry - let srcPoint = fstBBL.IRLeaders.MaximumElement - let dstPoint = sndBBL.IRLeaders.MinimumElement - let dstLeaders = sndBBL.IRLeaders - fn.MergeVerticesWithInlinedAsmChunk (insAddrs, srcPoint, dstLeaders, chunk) - CFGEvents.updateEvtsAfterBBLMerge srcPoint dstPoint evts - - /// Update function entry information for the basic block located at the given - /// address. - member __.UpdateFunctionEntry bblAddr funcEntry = - match bblMap.TryGetValue bblAddr with - | true, bbl -> - let bbl = { bbl with FunctionEntry = funcEntry } - bblMap[bbl.BlkRange.Min] <- bbl - | _ -> () - - /// The BBL had been created as a non-function bbl; there was a jump edge to - /// this BBL. However, we later found that this block was a function and the - /// jump edge must be changed to a tail-call edge. So we turn the BBL into a - /// function. We call this process as BBL promotion. - member __.PromoteBBL hdl bblAddr (bbl: BBLInfo) evts = -#if CFGDEBUG - dbglog (nameof CodeManager) "Turn BBL @ %x into func" bblAddr -#endif - let entry = bbl.FunctionEntry - let prevFn = fnMaintainer.FindRegular entry - let vertices, fn = prevFn.SplitFunction (hdl, bblAddr) - vertices - |> Set.iter (fun v -> - let addr = v.VData.PPoint.Address - let bbl = __.GetBBL addr - __.UpdateFunctionEntry bbl.BlkRange.Min bblAddr) - fnMaintainer.AddFunction fn - fn, - CFGEvents.updateEvtsAfterFuncSplit fn evts - |> CFGEvents.addPerFuncAnalysisEvt entry - - /// Return the exception table. - member __.ExceptionTable with get() = excTbl - - /// Return the function maintainer. - member __.FunctionMaintainer with get() = fnMaintainer - - /// Return the history manager. - member __.HistoryManager with get() = history - - member private __.RemoveFunction fnAddr = - match fnMaintainer.TryFindRegular fnAddr with - | Some fn -> - fn.IterRegularVertexPps (fun pp -> __.RemoveBBL pp.Address) - fnMaintainer.RemoveFunction fnAddr - | None -> () (* Already removed. *) - - member private __.RollBackFact evts fact = -#if CFGDEBUG - dbglog (nameof CodeManager) "Rollback %s" (HistoricalFact.toString fact) -#endif - match fact with - | CreatedFunction (fnAddr) -> - __.RemoveFunction fnAddr - CFGEvents.addFuncEvt fnAddr ArchOperationMode.NoMode evts (* XXX *) - - member __.RollBack (evts, fnAddrs: Addr list) = - fnAddrs - |> List.fold (fun evts fnAddr -> - history.PeekFunctionHistory fnAddr - |> Array.fold __.RollBackFact evts - ) evts diff --git a/src/MiddleEnd/ControlFlowAnalysis/CoverageMaintainer.fs b/src/MiddleEnd/ControlFlowAnalysis/CoverageMaintainer.fs deleted file mode 100644 index d1cf6f3a..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/CoverageMaintainer.fs +++ /dev/null @@ -1,94 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 - -/// Maintain the address-level coverage information, and thereby, gap -/// information. -type CoverageMaintainer () = - let mutable coverage = IntervalSet.empty - - let rec combineRanges minAddr maxAddr = function - | (r: AddrRange) :: tl -> - combineRanges (min r.Min minAddr) (max r.Max maxAddr) tl - | [] -> AddrRange (minAddr, maxAddr) - - let rec computeGaps map myAddr = function - | (r1: AddrRange) :: tl -> - if r1.IsIncluding myAddr then computeGaps map (r1.Max + 1UL) tl - else -#if CFGDEBUG - dbglog (nameof CoverageMaintainer) - "Computed gap %x--%x" myAddr (r1.Min - 1UL) -#endif - computeGaps (Map.add myAddr (r1.Min - 1UL) map) (r1.Max + 1UL) tl - | _ -> map - - /// Add covered address range. - member __.AddCoverage range = - let overlaps = IntervalSet.findAll range coverage - let range = range :: overlaps |> combineRanges System.UInt64.MaxValue 0UL - coverage <- - overlaps |> List.fold (fun cov r -> IntervalSet.remove r cov) coverage - coverage <- IntervalSet.add range coverage - - /// Make the address range uncovered. - member __.RemoveCoverage (range: AddrRange) = - let rec removeLoop = function - | (r: AddrRange) :: tl -> - if r.Min >= range.Min && r.Max <= range.Max then - coverage <- IntervalSet.remove r coverage - elif range.Min > r.Min && range.Max < r.Max then - let left = AddrRange (r.Min, range.Min - 1UL) - let right = AddrRange (range.Max + 1UL, r.Max) - let c = IntervalSet.remove r coverage - coverage <- IntervalSet.add left c |> IntervalSet.add right - elif r.Min >= range.Min then - let r' = AddrRange (range.Max + 1UL, r.Max) - coverage <- IntervalSet.remove r coverage |> IntervalSet.add r' - else (* elif r.Max <= range.Max then *) - let r' = AddrRange (r.Min, range.Min - 1UL) - coverage <- IntervalSet.remove r coverage |> IntervalSet.add r' - removeLoop tl - | [] -> () - IntervalSet.findAll range coverage |> removeLoop - - /// Is the given address is within the range of parsed code? - member __.IsAddressCovered addr = - IntervalSet.tryFindByAddr addr coverage |> Option.isSome - - /// For a given address range (from sAddr to eAddr), return a map of gaps, - /// where each mapping maps from a gap start address to a gap end address. A - /// gap is a "uncovered chunk" in the binary code. - member __.ComputeGapAddrs sAddr eAddr = - let range = AddrRange (sAddr, eAddr) - match IntervalSet.findAll range coverage with - | [] -> (* Nothing covered; the whole range is a gap. *) - Map.add sAddr eAddr Map.empty - | [ overlap ] when range = overlap -> (* Given range is covering all. *) - Map.empty - | overlaps -> - overlaps |> List.sortBy (fun r -> r.Min) |> computeGaps Map.empty sAddr diff --git a/src/MiddleEnd/ControlFlowAnalysis/DataManager.fs b/src/MiddleEnd/ControlFlowAnalysis/DataManager.fs deleted file mode 100644 index 964ea35d..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/DataManager.fs +++ /dev/null @@ -1,63 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinFile.ELF -open B2R2.FrontEnd.BinInterface - -[] -module private DataManager = - let parseRelocatableFunctionSymbols reloc = - let dict = Dictionary () - let iter (KeyValue (addr, rel: RelocationEntry)) = - match rel.RelType with - | RelocationX86 RelocationX86.Reloc38632 - | RelocationX86 RelocationX86.Reloc386PC32 - | RelocationX64 RelocationX64.RelocX64PLT32 -> - match rel.RelSymbol with - | Some sym when sym.SymType = SymbolType.STTFunc -> - dict.Add (addr, sym) - | _ -> () - | _ -> () - reloc.RelocByAddr |> Seq.iter iter - dict - - let parseRelocatableFuncs (hdl: BinHandle) = - match hdl.FileInfo with - | :? ELFFileInfo as efi -> parseRelocatableFunctionSymbols efi.ELF.RelocInfo - | _ -> Dictionary () - -type DataManager (hdl) = - let jmpTables = JumpTableMaintainer () - let relocatableFuncs = parseRelocatableFuncs hdl - - /// Return the JumpTableMaintainer. - member __.JumpTables with get() = jmpTables - - /// Return a map from a relocatable offset to its corresponding symbol. This - /// map considers relocatable functions only. - member __.RelocatableFuncs with get() = relocatableFuncs \ No newline at end of file diff --git a/src/MiddleEnd/ControlFlowAnalysis/EVMJmpResolution.fs b/src/MiddleEnd/ControlFlowAnalysis/EVMJmpResolution.fs deleted file mode 100644 index 59c0968e..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/EVMJmpResolution.fs +++ /dev/null @@ -1,196 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.ControlFlowAnalysis.IRHelper -open B2R2.MiddleEnd.DataFlow - -[] -module private EVMJmpResolution = - - let tryGetStackPointerValue hdl srcV cpState = - match hdl.RegisterBay.StackPointer with - | Some sp -> - let t = hdl.RegisterBay.RegIDToRegType sp - let str = hdl.RegisterBay.RegIDToString sp - let k = RegVar (t, sp, str) - match SSACFG.findDef srcV k with - | Some (Def (_, e)) -> - match tryResolveExprToUInt64 cpState e with - | Some _ as v -> v - | None -> None - | _ -> None - | None -> None - - /// Get elements in the latest stack frame. The upper bound of SP should be - /// calculated in first. Note that we handle EVM's SP in the ascending-order. - let rec getStackVarExprsUntil v sp (ret: Dictionary) = - let offLB = - int (sp - Utils.InitialStackPointer) - let stmtInfos = (v: SSAVertex).VData.SSAStmtInfos - None - |> Array.foldBack (fun (_, stmt) _ -> - match stmt with - | Def ({ Kind = StackVar (_, off) as k }, e) when off >= offLB -> - if ret.ContainsKey k then () - else ret.Add (k, e) |> ignore - None - | _ -> None) stmtInfos |> ignore - match v.VData.ImmDominator with - | Some idom -> getStackVarExprsUntil idom sp ret - | None -> ret - - /// Check if the latest stack frame has the fall-through address (ftAddr). It - /// assumes that the last instruction is either a jump or a conditional jump. - let rec checkIfStackHasFtAddr hdl srcV cpState ftAddr isCJmp = - match tryGetStackPointerValue hdl srcV cpState with - | Some sp -> - let wordSize = uint64 <| RegType.toByteWidth 256 - (* Note that the addresses in the stack have already been popped out. *) - let spDiff = if isCJmp then wordSize * 2UL else wordSize - let sp = sp + spDiff - let stackVarExprMap = getStackVarExprsUntil srcV sp <| Dictionary () - stackVarExprMap.Values - |> Seq.exists (fun e -> - match tryResolveExprToUInt64 cpState e with - | Some v when v = ftAddr -> true - | _ -> false) - | None -> false - - let isCallPattern hdl srcV cpState addr ftAddr = - (* It is based on heuristics, and could be replaced by argument analysis. *) - if addr = ftAddr then false - else checkIfStackHasFtAddr hdl srcV cpState ftAddr false - - let classifyJmpExpr hdl srcV cpState = function - | Var ({ Kind = StackVar (_, _); Identifier = 0; }) -> - match tryGetStackPointerValue hdl srcV cpState with - (* Return back to a constant address stored on the stack. *) - | Some addr -> ReturnPattern addr - | _ -> UnknownPattern - | Num addr -> - match tryConvertBVToUInt64 addr with - | Some addr -> - let insInfos = srcV.VData.InsInfos - let lastInsInfo = Array.last insInfos - let lastInsAddr = lastInsInfo.Instruction.Address - let lastInsLength = uint64 lastInsInfo.Instruction.Length - let ftAddr = lastInsAddr + lastInsLength - if isCallPattern hdl srcV cpState addr ftAddr then - ConstCallPattern (addr, ftAddr) - else - ConstJmpPattern addr - | _ -> UnknownPattern - | _ -> UnknownPattern - -/// IndirectJumpResolution recovers jump targets of indirect jumps by inferring -/// their jump tables. It first identifies jump table bases with constant -/// propagation and recovers the entire table ranges by leveraging the -/// structural properties of the binary. -type EVMJmpResolution () = - inherit IndirectJumpResolution () - - let mutable isEvtAdded = false - - member private __.AddPerFuncEvt (fn: RegularFunction) evts = - if isEvtAdded then evts - else - isEvtAdded <- true - CFGEvents.addPerFuncAnalysisEvt fn.Entry evts - - member private __.AddEvtsForConstJmp fn src addr evts = - __.AddPerFuncEvt fn evts - |> CFGEvents.addEdgeEvt fn src addr InterJmpEdge - - member private __.AddEvtsForConstCJmp fn src tAddr fAddr evts = - __.AddPerFuncEvt fn evts - |> CFGEvents.addEdgeEvt fn src tAddr InterCJmpTrueEdge - |> CFGEvents.addEdgeEvt fn src fAddr InterCJmpFalseEdge - - member private __.AddEvtsForConstCall fn src insAddr calleeAddr ftAddr evts = - __.AddPerFuncEvt fn evts - |> CFGEvents.addEdgeEvt fn src ftAddr CallFallThroughEdge - |> CFGEvents.addCallEvt fn insAddr calleeAddr false - - member private __.FinalizeFunctionInfo (fn: RegularFunction) sp = - let spDiff = int64 <| Utils.InitialStackPointer - sp - let retAddrSize = int64 <| RegType.toByteWidth 256 - let amountUnwinding = - spDiff - retAddrSize - fn.AmountUnwinding <- amountUnwinding - fn.NoReturnProperty <- NotNoRet - - override __.Name = "EVMJmpResolution" - - override __.Classify hdl srcV cpState jmpType = - match jmpType with - | InterJmp jmpExpr -> - let symbExpr = resolveExpr cpState true jmpExpr -#if CFGDEBUG - dbglog "IndJmpRecovery" "Pattern indjmp: %s" (Pp.expToString symbExpr) -#endif - classifyJmpExpr hdl srcV cpState symbExpr - | InterCJmp (_, tJmpExpr, fJmpExpr) -> -#if CFGDEBUG - dbglog "IndJmpRecovery" "Pattern indcjmp(t): %s" (Pp.expToString tJmpExpr) - dbglog "IndJmpRecovery" "Pattern indcjmp(f): %s" (Pp.expToString fJmpExpr) -#endif - let tAddr = tryResolveExprToUInt64 cpState tJmpExpr - let fAddr = tryResolveExprToUInt64 cpState fJmpExpr - match tAddr, fAddr with - | Some tAddr, Some fAddr -> ConstCJmpPattern (tAddr, fAddr) - | _ -> UnknownPattern - | _ -> Utils.impossible () - - override __.MarkIndJmpAsTarget _ fn insAddr src evts pattern = - match pattern with - | ConstJmpPattern addr -> - (fn: RegularFunction).RemoveIndJump insAddr - let evts = __.AddEvtsForConstJmp fn src addr evts - Ok (false, evts) - | ConstCJmpPattern (tAddr, fAddr) -> - fn.RemoveIndJump insAddr - let evts = __.AddEvtsForConstCJmp fn src tAddr fAddr evts - Ok (false, evts) - | ConstCallPattern (calleeAddr, ftAddr) -> - fn.RemoveIndJump insAddr - let evts = - __.AddEvtsForConstCall fn src insAddr calleeAddr ftAddr evts - Ok (false, evts) - | ReturnPattern sp -> - fn.RemoveIndJump insAddr - __.FinalizeFunctionInfo fn sp - Ok (false, evts) - | _ -> - fn.MarkIndJumpAsUnknown insAddr - Ok (false, evts) - - override __.RecoverTarget _ _ _ _ evts = RecoverDone <| Ok evts - - override __.OnError _ _ _ evts _ = Ok evts diff --git a/src/MiddleEnd/ControlFlowAnalysis/EvalHelper.fs b/src/MiddleEnd/ControlFlowAnalysis/EvalHelper.fs deleted file mode 100644 index 9d10ad78..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/EvalHelper.fs +++ /dev/null @@ -1,103 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.ControlFlowAnalysis.EvalHelper - -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.ConcEval - -let private memoryReader hdl _pc addr typ _e = - let len = RegType.toByteWidth typ - let fileInfo = hdl.FileInfo - if addr < System.UInt64.MaxValue && fileInfo.IsValidAddr addr then - match BinHandle.TryReadBytes (hdl, addr, len) with - | Ok v -> Ok (BitVector.ofArr v) - | Error e -> Error e - else Error ErrorCase.InvalidMemoryRead - -let private stackAddr t = BitVector.ofInt32 0x1000000 t - -let private obtainStackDef hdl = - match hdl.RegisterBay.StackPointer with - | Some r -> Some (r, hdl.ISA.WordSize |> WordSize.toRegType |> stackAddr) - | None -> None - -let private obtainFramePointerDef hdl = - match hdl.RegisterBay.FramePointer with - | Some r -> Some (r, hdl.ISA.WordSize |> WordSize.toRegType |> BitVector.zero) - | None -> None - -let private initState hdl pc = - let st = EvalState (true) - st.LoadFailureEventHandler <- memoryReader hdl - [ obtainStackDef hdl; obtainFramePointerDef hdl ] - |> List.choose id - |> st.InitializeContext pc - st - -let evalBlock hdl (blk: Vertex) = - let pc = blk.VData.PPoint.Address - let st = initState hdl pc - st.SideEffectEventHandler <- fun _ st -> st.AbortInstr () - match blk.VData.IRStatements |> SafeEvaluator.evalBlock st pc with - | Ok st -> st - | Error _ -> Utils.impossible () - -let evalFunctionUntilStopFn hdl (fn: RegularFunction) stopFn = - let visited = HashSet () - let rec evalLoop (blk: Vertex) st stopFn = - let pp = blk.VData.PPoint - if visited.Contains pp then None - else - visited.Add pp |> ignore - let result = - blk.VData.IRStatements - |> SafeEvaluator.evalBlock st pp.Address - match result with - | Ok st' -> - if stopFn blk then Some st' - else - match fn.TryFindVertex (ProgramPoint (st'.PC, 0)) with - | Some v -> evalLoop v st' stopFn - | None -> None - | Error _ -> None - let pc = fn.Entry - let st = initState hdl pc - let root = fn.FindVertex (ProgramPoint (pc, 0)) - evalLoop root st stopFn - -let readReg (st: EvalState) regID = - match st.TryGetReg regID with - | Def v -> Some v - | Undef -> None - -let readMem (st: EvalState) addr endian size = - let addr = BitVector.toUInt64 addr - match st.Memory.Read addr endian size with - | Ok bs -> BitVector.toUInt64 bs |> Some - | Error _ -> None diff --git a/src/MiddleEnd/ControlFlowAnalysis/ExceptionTable.fs b/src/MiddleEnd/ControlFlowAnalysis/ExceptionTable.fs deleted file mode 100644 index 6f665e37..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/ExceptionTable.fs +++ /dev/null @@ -1,55 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinInterface - -/// ExceptionTable holds parsed exception information of a binary code (given by -/// the BinHandle). -type ExceptionTable (hdl) = - let tbl = Dictionary> () - do - hdl.FileInfo.ExceptionTable - |> ARMap.iter (fun funcRange funcTbl -> - let funcInfo = - funcTbl - |> ARMap.fold (fun funcTbl range target -> - if target = 0UL then funcTbl - else ARMap.add range target funcTbl) ARMap.empty - if ARMap.isEmpty funcInfo then () - else tbl[funcRange.Min] <- funcInfo) - - /// For the given function entry and an instruction address, find the landing - /// pad (exception target) of the instruction. - member __.TryFindExceptionTarget entry insAddr = - match tbl.TryGetValue entry with - | true, funcTbl -> ARMap.tryFindByAddr insAddr funcTbl - | _ -> None - - /// Fold every table entry. - member __.Fold fn acc = - tbl |> Seq.fold fn acc diff --git a/src/MiddleEnd/ControlFlowAnalysis/Function.fs b/src/MiddleEnd/ControlFlowAnalysis/Function.fs deleted file mode 100644 index e8c16008..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/Function.fs +++ /dev/null @@ -1,686 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open System.Runtime.InteropServices -open B2R2 -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph - -/// Function can be either external or regualr. -type FunctionKind = - /// Regular function. - | Regular = 0 - /// External function. - | External = 1 - -/// Callee's kind. -type CalleeKind = - /// Callee is a regular function. - | RegularCallee of Addr - /// Callee is a set of indirect call targets. This means potential callees - /// have been analyzed already. - | IndirectCallees of Set - /// Callee (call target) is unresolved yet. This eventually will become - /// IndirectCallees after indirect call analyses. - | UnresolvedIndirectCallees - /// There can be "call 0" to call an external function. This pattern is typically - /// observed by object files, but sometimes we do see this pattern in regular - /// executables, e.g., GNU libc. - | NullCallee - -/// NoReturnProperty of a function specifies whether the function will -/// eventually return or not. Some functions, e.g., exit, will never return in -/// any cases, and compilers often remove fall-through edges of callers of such -/// functions. -type NoReturnProperty = - /// This function will never return. For example, the "exit" function should - /// have this property. - | NoRet - /// Conditionally no-return; function does not return only if the n-th - /// argument (starting from one) specified is non-zero. - | ConditionalNoRet of int - /// Regular case: this is *not* no-return, and we have already performed - /// parameter analysis to examine the possibility of being conditional no-ret. - | NotNoRetConfirmed - /// Regular case: *not* no-return. - | NotNoRet - /// When we are not certain: we need further analyses. - | UnknownNoRet - -/// Indirect jump's kind. -type IndirectJumpKind = - /// We did not analyzed this indirect jump yet. - | YetAnalyzed - /// We found a corresponding jump table at Addr. - | JmpTbl of tAddr: Addr - /// We analyzed the given jump, and we could not determine its kind. - | UnknownIndJmp - -/// Function is a non-overlapping chunk of code in a binary. We do not allow -/// function overlaps. When there exist two functions sharing common basic -/// blocks, B2R2 will create a new function to represent the common blocks. -/// Function can also represent a function defined outside of the current -/// binary. Such functions are called ExternalFunction. -[] -type Function (entry, name) = - let fid = Addr.toFuncName entry - let callers = SortedSet () - let mutable noRetProp = UnknownNoRet - - /// Starting address of the function. - member __.Entry with get(): Addr = entry - - /// Function's unique ID. This field is used to distinguish between functions. - member __.FunctionID with get(): string = fid - - /// Function's symbolic name. - member __.FunctionName with get(): string = name - - /// Function's kind. Is this external or regular? - abstract FunctionKind: FunctionKind - - /// A set of functions which call this function. - member __.Callers with get() = callers - - /// Register a set of callers to this function. - member __.RegisterCallers (newCallers: Set) = - callers.UnionWith newCallers - - /// No-return property of this function. - member __.NoReturnProperty - with get() = noRetProp and set(b) = noRetProp <- b - -/// FakeEdge is a tuple of (Callsite address, Call target address). This is to -/// uniquely identify edges from a call instruction to a fake block. Note that -/// even though there are multiple calls to the same outer function, each of the -/// callsites should be connected to an independent fake block. That's the -/// reason why we use FakeEdge to distinguish them. -type FakeEdge = Addr * Addr - -module private RegularFunction = - /// This is a heuristic to discover __x86.get_pc_thunk- family functions. - /// We directly compare first 4 bytes of byte code. Because - /// __x86.get_pc_thunk- family only has 4 bytes for its function body and - /// their values are fixed. - let obtainGetPCThunkReg hdl (entry: Addr) = - match hdl.ISA.Arch with - | Arch.IntelX86 -> - match BinHandle.ReadUInt (hdl, entry, 4) with - | 0xc324048bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "EAX" - | 0xc3241c8bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "EBX" - | 0xc3240c8bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "ECX" - | 0xc324148bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "EDX" - | 0xc324348bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "ESI" - | 0xc3243c8bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "EDI" - | 0xc3242c8bUL -> YesGetPCThunk <| hdl.RegisterBay.RegIDFromString "EBP" - | _ -> NoGetPCThunk - | _ -> NoGetPCThunk - -/// Regular function is a function that has its own body in the target binary. -/// Therefore, regular functions have their own IR-level CFG. -type RegularFunction private (histMgr: HistoryManager, entry, name, thunkInfo) = - inherit Function (entry, name) - - let callEdges = SortedList () - let syscallSites = SortedSet () - let indirectJumps = Dictionary () - let regularVertices = Dictionary> () - let fakeVertices = Dictionary> () - let coverage = CoverageMaintainer () - let mutable callEdgeChanged = false - let mutable needRecalcSSA = true - let mutable ircfg = IRCFG.init PersistentGraph - let mutable ssacfg = SSACFG.init PersistentGraph - let mutable amountUnwinding = 0L - let mutable getPCThunkInfo = thunkInfo - let mutable minAddr = entry - let mutable maxAddr = entry - - /// Create a new RegularFunction. - new (histMgr, hdl, entry) = - let name = - match hdl.FileInfo.TryFindFunctionSymbolName entry with - | Error _ -> Addr.toFuncName entry - | Ok name -> name - let thunkInfo = RegularFunction.obtainGetPCThunkReg hdl entry - RegularFunction (histMgr, entry, name, thunkInfo) - - override __.FunctionKind with get() = FunctionKind.Regular - - /// A sequence of call edges (call site address, callee). That is, a CallEdge - /// represents a function call edge from the caller bbl to its callee(s). - member __.CallEdges with get() = - callEdges - |> Seq.map (fun (KeyValue (pp, callee)) -> pp, callee) - |> Seq.toArray - - /// Is the given indirect call unresolved? - member __.IsUnresolvedIndirectCall callSiteAddr = - match callEdges.TryGetValue callSiteAddr with - | true, UnresolvedIndirectCallees -> true - | _ -> false - - /// Returns the set of call target addresses. This function returns the - /// correct set regardless of their callee types; for indirect calls, it - /// returns a set of resolved target addresses, and for direct calls, it - /// returns a singleton target address set. - member __.CallTargets callSiteAddr = - match callEdges.TryGetValue callSiteAddr with - | true, IndirectCallees targets -> targets - | true, RegularCallee addr -> Set.singleton addr - | _ -> Set.empty - - /// Remove call edge information from this function. - member __.ClearCallEdges () = callEdges.Clear () - - /// Return only a sequence of unresolved indirect call edge info: a tuple of - /// (call site addr, fall-through addr). - member __.UnresolvedIndirectCallEdges with get() = - __.CallEdges - |> Array.choose (fun (callSiteAddr, callee) -> - match callee with - | UnresolvedIndirectCallees -> Some callSiteAddr - | _ -> None) - - /// A set of bbl entry points which have syscall at the end of each. - member __.SyscallSites with get() = syscallSites - - /// Add a syscall callsite. - member __.AddSysCallSite callSiteAddr = - syscallSites.Add callSiteAddr |> ignore - - /// Remove the syscall callsite. - member __.RemoveSysCallSite callSiteAddr = - syscallSites.Remove callSiteAddr |> ignore - - /// IR-level CFG of this function. - member __.IRCFG - with get() = ircfg - and private set(cfg) = ircfg <- cfg; needRecalcSSA <- true - - /// Check if the given vertex exists in this function. - member __.HasVertex (v) = regularVertices.ContainsKey v - - /// Find an IRCFG vertex at the given program point. - member __.FindVertex (pp) = regularVertices[pp] - - /// Try to find an IRCFG vertex at the given program point. - member __.TryFindVertex (pp) = - regularVertices.TryGetValue pp |> Utils.tupleToOpt - - /// Return the current number of regular vertices in this function's IRCFG. - member __.CountRegularVertices with get() = regularVertices.Count - - /// Fold each regular vertex in this function. - member __.FoldRegularVertices fn acc = regularVertices |> Seq.fold fn acc - - /// Iterate each regular vertex's program points. - member __.IterRegularVertexPps fn = - regularVertices.Keys |> Seq.iter fn - - /// Add a vertex of a parsed regular basic block to this function. - member __.AddVertex (blk: IRBasicBlock) = - let v, g = DiGraph.addVertex __.IRCFG blk - __.IRCFG <- g - regularVertices[blk.PPoint] <- v - coverage.AddCoverage blk.Range - v - - /// Add a parsed regular basic block (given as an array of instructions along - /// with its leader address) to this function. - member __.AddVertex (instrs, leader) = - let blk = IRBasicBlock.initRegular instrs leader - __.AddVertex blk - - /// Add/replace a regular edge to this function. - member __.AddEdge (srcPp, dstPp, edge) = - let src = regularVertices[srcPp] - let dst = regularVertices[dstPp] - __.IRCFG <- DiGraph.addEdge __.IRCFG src dst edge - - member private __.AddFakeVertex edgeKey bbl = - let v, g = DiGraph.addVertex __.IRCFG bbl - __.IRCFG <- g - fakeVertices[edgeKey] <- v - v - - /// Find a call fake block from callSite to callee. The third arg (isTailCall) - /// indicates whether this is a tail call. - member private __.GetOrAddFakeVertex (callSite, callee, isTailCall) = - let edgeKey = callSite, callee - match fakeVertices.TryGetValue (edgeKey) with - | true, v -> v - | _ -> - let bbl = (* When callee = 0UL, then it means an indirect call. *) - if callee = 0UL then IRBasicBlock.initIndirectCallBlock callSite - else IRBasicBlock.initCallBlock callee callSite isTailCall - __.AddFakeVertex edgeKey bbl - - /// Add/replace a direct call edge to this function. - member __.AddEdge (callerBlk, callSite, callee, isTailCall, isNoFn) = - let src = regularVertices[callerBlk] - let dst = __.GetOrAddFakeVertex (callSite, callee, isTailCall) - if not isNoFn then - callEdges[callSite] <- - if callee = 0UL then NullCallee else RegularCallee callee - callEdgeChanged <- true - else - dst.VData.FakeBlockInfo <- - { dst.VData.FakeBlockInfo with IsNoFunction = true } - __.IRCFG <- DiGraph.addEdge __.IRCFG src dst CallEdge - - /// Add/replace an indirect call edge to this function. - member __.AddEdge (callerBlk, callSite) = - let src = regularVertices[callerBlk] - let dst = __.GetOrAddFakeVertex (callSite, 0UL, false) - callEdges[callSite] <- UnresolvedIndirectCallees - callEdgeChanged <- true - __.IRCFG <- DiGraph.addEdge __.IRCFG src dst IndirectCallEdge - - /// Add/replace a ret edge to this function. - member __.AddEdge (callSite, callee, ftAddr) = - let src = __.GetOrAddFakeVertex (callSite, callee, false) - let dst = regularVertices[(ProgramPoint (ftAddr, 0))] - __.IRCFG <- DiGraph.addEdge __.IRCFG src dst RetEdge - - /// Update the call edge info. - member __.UpdateCallEdgeInfo (callSiteAddr, callee) = - callEdges[callSiteAddr] <- callee - callEdgeChanged <- true - - /// Remove the basic block at the given program point from this function. - member private __.RemoveVertex (v: Vertex) = - __.IRCFG <- DiGraph.removeVertex __.IRCFG v - if v.VData.IsFakeBlock () then - let callSite = v.VData.FakeBlockInfo.CallSite - let edgeKey = callSite, v.VData.PPoint.Address - fakeVertices.Remove (edgeKey) |> ignore - callEdges.Remove callSite |> ignore - else - regularVertices.Remove v.VData.PPoint |> ignore - coverage.RemoveCoverage v.VData.Range - - /// Remove the regular basic block at the given program point from this - /// function. - member __.RemoveVertex (pp: ProgramPoint) = - regularVertices[pp] |> __.RemoveVertex - - /// Remove the fake block from this function. - member __.RemoveFakeVertex ((callSite, _) as fakeEdgeKey) = - let v = fakeVertices[fakeEdgeKey] - __.IRCFG <- DiGraph.removeVertex __.IRCFG v - fakeVertices.Remove (fakeEdgeKey) |> ignore - callEdges.Remove callSite |> ignore - - /// Remove the given edge. - member __.RemoveEdge (src, dst) = - __.IRCFG <- DiGraph.removeEdge __.IRCFG src dst - - /// Remove the given edge. - member __.RemoveEdge (src, dst, _kind) = - __.IRCFG <- DiGraph.removeEdge __.IRCFG src dst - - static member AddEdgeByType (fn: RegularFunction) - (src: Vertex) - (dst: Vertex) e = - match e with - | CallEdge -> - let callSite = dst.VData.FakeBlockInfo.CallSite - let callee = dst.VData.PPoint.Address - let isTailCall = dst.VData.FakeBlockInfo.IsTailCall - let isNoFunc = dst.VData.FakeBlockInfo.IsNoFunction - fn.AddEdge (src.VData.PPoint, callSite, callee, isTailCall, isNoFunc) - | IndirectCallEdge -> - fn.AddEdge (src.VData.PPoint, dst.VData.FakeBlockInfo.CallSite) - | RetEdge -> - let callSite = src.VData.FakeBlockInfo.CallSite - let ftAddr = dst.VData.PPoint.Address - fn.AddEdge (callSite, src.VData.PPoint.Address, ftAddr) - | _ -> (* regular edges *) - fn.AddEdge (src.VData.PPoint, dst.VData.PPoint, e) - - /// Split the given IR-level vertex (v) at the given point (splitPoint), and - /// add the resulting vertices to the graph. - member private __.AddByDividingVertex v (splitPoint: ProgramPoint) = - let insInfos = (v: Vertex).VData.InsInfos - let srcInfos, dstInfos = - insInfos - |> Array.partition (fun insInfo -> - insInfo.Instruction.Address < splitPoint.Address) - let srcBlk = IRBasicBlock.initRegular srcInfos v.VData.PPoint - let dstBlk = IRBasicBlock.initRegular dstInfos splitPoint - let src = __.AddVertex srcBlk - let dst = __.AddVertex dstBlk - __.AddEdge (src.VData.PPoint, dst.VData.PPoint, FallThroughEdge) - struct (src, dst) - - /// Split the BBL at bblPoint into two at the splitPoint. This function - /// returns the second block located at the splitPoint. - member __.SplitBBL (bblPoint: ProgramPoint, splitPoint: ProgramPoint) = - assert (bblPoint < splitPoint) - let v = regularVertices[bblPoint] - let ins, outs, cycle = categorizeNeighboringEdges __.IRCFG v - ins |> List.iter (fun (p, kind) -> __.RemoveEdge (p, v, kind)) - outs |> List.iter (fun (s, kind) -> __.RemoveEdge (v, s, kind)) - cycle |> Option.iter (fun kind -> __.RemoveEdge (v, v, kind)) - __.RemoveVertex v - let struct (src, dst) = __.AddByDividingVertex v splitPoint - ins |> List.iter (fun (p, e) -> RegularFunction.AddEdgeByType __ p src e) - outs |> List.iter (fun (s, e) -> RegularFunction.AddEdgeByType __ dst s e) - cycle |> Option.iter (fun e -> RegularFunction.AddEdgeByType __ dst src e) - dst - - member private __.GetMergedVertex srcV dstV insAddrs chunk = - let src = (srcV: IRVertex).VData.InsInfos - let dst = (dstV: IRVertex).VData.InsInfos - let fstAddr = List.head insAddrs - let lastAddr = List.last insAddrs - let chunkIdx = - src |> Array.findIndex (fun i -> i.Instruction.Address >= fstAddr) - let backIdx = - dst |> Array.findIndexBack (fun i -> i.Instruction.Address <= lastAddr) - let front = src[0 .. chunkIdx - 1] - let back = dst[backIdx + 1 .. dst.Length - 1] - let lastInsInfo = dst[backIdx] - let chunkInfo = - [| { Instruction = chunk; - Stmts = lastInsInfo.Stmts; - BBLAddr = src[0].BBLAddr } |] - let insInfos = Array.concat [ front; chunkInfo; back ] - IRBasicBlock.initRegular insInfos srcV.VData.PPoint - |> __.AddVertex - - /// Merge two vertices connected with an inlined assembly chunk, where there - /// is a control-flow to the middle of an instruction. - member __.MergeVerticesWithInlinedAsmChunk (insAddrs, srcPp, dstLeaders, chunk) = - let minPp = Set.minElement (dstLeaders: Set) - let dstLeaders = - Set.filter (fun (leader: ProgramPoint) -> - leader.Address = minPp.Address) dstLeaders - let src = regularVertices[srcPp] - let ins, _, _ = categorizeNeighboringEdges __.IRCFG src - (* Here, we have an assumption that the inlined asm chunk should fall - through to the next instruction. If we want to handle inlined asm chunks - without the assumption, then we should FIX the below logic. *) - let lastLeader = Set.maxElement dstLeaders - let lastV = regularVertices[lastLeader] - let _, outs, _ = categorizeNeighboringEdges __.IRCFG lastV - regularVertices.Remove srcPp |> ignore - Set.iter (fun pp -> - let v = regularVertices[pp] - __.RemoveVertex v - regularVertices.Remove pp |> ignore) dstLeaders - __.RemoveVertex src - let v = __.GetMergedVertex src lastV insAddrs chunk - ins |> List.iter (fun (p, e) -> - (* When the incoming edge is from the merged vertex. This logic also - assumes the assumption described in the above. *) - if p.VData.PPoint = lastLeader then RegularFunction.AddEdgeByType __ v v e - else RegularFunction.AddEdgeByType __ p v e) - outs |> List.iter (fun (s, e) -> - (* When the outgoing edge is to the merged vertex. What we should be aware - of is when the successor is a fake-block. *) - if s.VData.PPoint = srcPp && not <| s.VData.IsFakeBlock () then - RegularFunction.AddEdgeByType __ v v e - else RegularFunction.AddEdgeByType __ v s e) - regularVertices[v.VData.PPoint] <- v - - member private __.AddCallEdge callSite callee = - callEdges[callSite] <- callee - - member private __.RemoveCallEdge callSite = - callEdges.Remove callSite |> ignore - - member private __.AddIndirectJump insAddr jmpKind = - indirectJumps[insAddr] <- jmpKind - - member private __.RemoveIndirectJump insAddr = - indirectJumps.Remove insAddr |> ignore - - member private __.MoveBlockInfo fn (v: Vertex) = - let lastAddr = v.VData.LastInstruction.Address - if v.VData.Range.Max > (fn: RegularFunction).MaxAddr then - fn.MaxAddr <- v.VData.Range.Max - else () - (* CallEdge *) - if callEdges.ContainsKey lastAddr then - let callee = callEdges[lastAddr] - __.RemoveCallEdge lastAddr - (fn: RegularFunction).AddCallEdge lastAddr callee - (* SysCall *) - elif syscallSites.Contains lastAddr then - __.RemoveSysCallSite lastAddr - fn.AddSysCallSite lastAddr - (* IndirectJump *) - elif indirectJumps.ContainsKey lastAddr then - let jmpKind = indirectJumps[lastAddr] - __.RemoveIndirectJump lastAddr - fn.AddIndirectJump lastAddr jmpKind - (* NoReturnProperty *) - elif v.VData.LastInstruction.IsRET () then - fn.NoReturnProperty <- NotNoRet - else () - - /// Split this function into two separate functions, one is this one, the - /// original function, and the other is a function starting from newEntry. - member __.SplitFunction (hdl, newEntry) = - let newFn = RegularFunction (histMgr, hdl, newEntry) - let entryBlk = regularVertices[ProgramPoint (newEntry, 0)] - (* Transplant CFG first *) - let reachableNodes, reachableEdges = getReachables __.IRCFG entryBlk - let callerBlk: IRVertex = - DiGraph.getPreds __.IRCFG entryBlk - |> List.filter (fun v -> not <| Set.contains v reachableNodes) - |> List.head - reachableNodes - |> Set.iter (fun v -> - if v.VData.IsFakeBlock () then - let edgeKey = v.VData.FakeBlockInfo.CallSite, v.VData.PPoint.Address - __.RemoveFakeVertex edgeKey - newFn.AddFakeVertex edgeKey v.VData |> ignore - else - __.RemoveVertex v - newFn.AddVertex v.VData |> ignore) - reachableEdges - |> Set.iter (fun (src, dst, e) -> - RegularFunction.AddEdgeByType newFn src dst e) - (* Replace newFn to FakeBlock *) - let callerPoint = callerBlk.VData.PPoint - let callSite = callerBlk.VData.LastInstruction.Address - __.AddEdge (callerPoint, callSite, newEntry, true, false) - (* Move necessary information *) - reachableNodes - |> Set.iter (fun v -> - if v.VData.IsFakeBlock () then () - else __.MoveBlockInfo newFn v) - let bbls = - reachableNodes - |> Set.filter (fun v -> not <| v.VData.IsFakeBlock ()) - (* Update max address *) - let maxAddr = - DiGraph.foldVertex __.IRCFG (fun addr v -> - if Set.contains v reachableNodes then addr - elif v.VData.IsFakeBlock () then addr - else max v.VData.Range.Max addr) 0UL - __.MaxAddr <- maxAddr - bbls, newFn - - /// This field indicates the amount of stack unwinding happening at the return - /// of this function. This value is 0 if caller cleans the stack (e.g., - /// cdecl). That is, this value is only meaning for calling conventions where - /// callee cleans up the stack, such as stdcall. - member __.AmountUnwinding - with get() = amountUnwinding and set(n) = amountUnwinding <- n - - /// This field is to remember a register ID that holds a PC value. When this - /// function is deemed as a special thunk (e.g., *_get_pc_thunk), the register - /// will hold a PC value after this function returns. - member __.GetPCThunkInfo - with get() = getPCThunkInfo and set(i) = getPCThunkInfo <- i - - /// Return a Dictionary that maps an indirect jump address to its jump kinds. - member __.IndirectJumps with get() = indirectJumps - - /// Return an array of yet-analyzed indirect jump addresses. - member __.YetAnalyzedIndirectJumpAddrs - with get() = - indirectJumps - |> Seq.choose (fun (KeyValue (indJumpAddr, kind)) -> - match kind with - | YetAnalyzed -> Some indJumpAddr - | _ -> None) - |> Seq.toList - - /// Retrieve the currently known jump table addresses. - member __.JumpTableAddrs - with get() = - indirectJumps - |> Seq.choose (fun (KeyValue (_, kind)) -> - match kind with - | JmpTbl (tAddr) -> Some tAddr - | _ -> None) - |> Seq.toList - - /// Retrieve the jump table address of a given indirect jump address. - member __.FindJumpTableAddr indJumpAddr = - match indirectJumps.TryGetValue indJumpAddr with - | true, JmpTbl addr -> addr - | _ -> Utils.impossible () - - /// Register a new indirect jump as YetAnalyzed. - member __.RegisterNewIndJump indJumpAddr = - __.AddIndirectJump indJumpAddr YetAnalyzed - - /// Remove an indirect jump. - member __.RemoveIndJump indJumpAddr = - __.RemoveIndirectJump indJumpAddr |> ignore - - /// Mark the given indirect jump as unknown. - member __.MarkIndJumpAsUnknown indJumpAddr = - __.AddIndirectJump indJumpAddr UnknownIndJmp - - /// Mark the given indirect jump as analyzed; we know the table address of it. - member __.MarkIndJumpAsJumpTbl indJumpAddr tAddr = - __.AddIndirectJump indJumpAddr (JmpTbl tAddr) - - /// The minimum address of this function's range. - member __.MinAddr with get() = minAddr and set(a) = minAddr <- a - - /// The maximum address of this function's range. - member __.MaxAddr with get() = maxAddr and set(a) = maxAddr <- a - - /// Set the boundary of this function; set both MinAddr and MaxAddr. - member __.SetBoundary minAddr maxAddr = - __.MinAddr <- minAddr - __.MaxAddr <- maxAddr - - /// Retrieve the SSA CFG of this function. - member __.GetSSACFG hdl = - if needRecalcSSA then - let root = - DiGraph.findVertexBy __.IRCFG (fun v -> - v.VData.PPoint.Address = __.Entry && not <| v.VData.IsFakeBlock ()) - let struct (ssa, root) = SSACFG.ofIRCFG hdl __.IRCFG root - let struct (ssa, root) = SSAPromotion.promote hdl ssa root - ssacfg <- ssa - needRecalcSSA <- false - ssa, root - else - let root = - DiGraph.findVertexBy ssacfg (fun v -> - v.VData.PPoint.Address = __.Entry && not <| v.VData.IsFakeBlock ()) - ssacfg, root - - member private __.AddXRef entry xrefs callee = - match Map.tryFind callee xrefs with - | Some callers -> Map.add callee (Set.add entry callers) xrefs - | None -> Map.add callee (Set.singleton entry) xrefs - - /// Accumulate cross references only if there is a change in the call edges. - member __.AccumulateXRefs xrefs = - if callEdgeChanged then - callEdgeChanged <- false - let entry = __.Entry - callEdges - |> Seq.fold (fun xrefs (KeyValue (_, callee)) -> - match callee with - | RegularCallee callee -> __.AddXRef entry xrefs callee - | IndirectCallees callees -> Set.fold (__.AddXRef entry) xrefs callees - | UnresolvedIndirectCallees | NullCallee -> xrefs) xrefs - else xrefs - - /// Return the sorted gaps' ranges. Each range is a mapping from a start - /// address to an end address (exclusive). - member __.GapAddresses - with get() = coverage.ComputeGapAddrs __.Entry __.MaxAddr - - /// Check if the function regards the given address as a valid instruction - /// address. - member __.IsAddressCovered addr = - coverage.IsAddressCovered addr - -/// External function is a function that is defined in another binary. Functions -/// in PLT is also considered as an external function, and we always link a PLT -/// entry with its corresponding GOT entry to consider such a pair as an -/// external function, where its entry is located at the GOT and its trampoline -/// is at the PLT. -type ExternalFunction private (entry, name, trampoline) = - inherit Function (entry, name) - - /// Known list of no-return function names. - static let knownNoReturnFuncs = - [| "__assert_fail" - "__stack_chk_fail" - "abort" - "_abort" - "exit" - "_exit" - "__longjmp_chk" - "__cxa_throw" - "_Unwind_Resume" - "_ZSt20__throw_length_errorPKc" - "_gfortran_stop_numeric" - "__libc_start_main" - "longjmp" |] - - override __.FunctionKind with get() = FunctionKind.External - - /// If there is a trampoline (e.g., PLT) for the external function, this - /// function returns the address of it. - member __.TrampolineAddr ([] addr: byref) = - match trampoline with - | 0UL -> false - | _ -> addr <- trampoline; true - - /// Create a new ExternalFunction. - static member Init entry name trampoline = - let noretProp = - if Array.contains name knownNoReturnFuncs then NoRet - elif name = "error" || name = "error_at_line" then ConditionalNoRet 1 - else NotNoRet - ExternalFunction (entry, name, trampoline, NoReturnProperty = noretProp) diff --git a/src/MiddleEnd/ControlFlowAnalysis/FunctionMaintainer.fs b/src/MiddleEnd/ControlFlowAnalysis/FunctionMaintainer.fs deleted file mode 100644 index e0e14fe2..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/FunctionMaintainer.fs +++ /dev/null @@ -1,162 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface - -[] -module private FunctionMaintainer = - /// These are some functions that sometimes get linked without the use of PLT. - let knownNoPLTFuncs = - [| "__libc_start_main"; "__gmon_start__" |] - -/// Maintains functions in the binary. -type FunctionMaintainer private (histMgr: HistoryManager) = - let addrMap = SortedList () - let regularMap = Dictionary () - let nameMap = Dictionary () - - /// The current number of functions. - member __.Count with get() = addrMap.Count - - /// Return the sequence of functions. - member __.Functions - with get () = addrMap |> Seq.map (fun (KeyValue (_, f)) -> f) - - /// Return the sequence of function entry addresses. - member __.Entries - with get () = addrMap |> Seq.map (fun (KeyValue (a, _)) -> a) - - /// Check if the given address belongs to a known function entry address. - member __.Contains (addr) = addrMap.ContainsKey addr - - /// Check if there is a function with the given name. - member __.Contains (name) = nameMap.ContainsKey name - - /// Try to obtain a function by the given function entry address. - member __.TryFind (addr) = addrMap.TryGetValue addr |> Utils.tupleToOpt - - /// Try to obtain a function by the given function name. - member __.TryFind (name) = - match nameMap.TryGetValue name with - | true, addr -> __.TryFind addr - | _ -> None - - /// Obtain a function by the given function entry address. - member __.Find (addr) = addrMap[addr] - - /// Obtain a function by the given function name. - member __.Find (name) = addrMap[nameMap[name]] - - /// Obtain a regular function by the given function entry address. - member __.TryFindRegular (addr) = - regularMap.TryGetValue addr |> Utils.tupleToOpt - - /// Obtain a regular function by the given function entry address. - member __.FindRegular (addr) = regularMap[addr] - - /// Returns an array of regualr functions. - member __.RegularFunctions with get () = regularMap.Values |> Seq.toArray - - /// Return the next function address relative to the given function (fn). - member __.FindNextFunctionAddr (fn: RegularFunction) = - match SortedList.findLeastUpperBoundKey (fn.Entry + 1UL) addrMap with - | Some ubAddr -> ubAddr - | None -> System.UInt64.MaxValue - - /// Remove the given function. - member __.RemoveFunction (addr) = - let fnName = addrMap[addr].FunctionName - regularMap.Remove addr |> ignore - addrMap.Remove addr |> ignore - nameMap.Remove fnName |> ignore - - /// Add an external function. This function should not be called outside. - member private __.AddFunction (func: ExternalFunction) = - nameMap[func.FunctionID] <- func.Entry - nameMap[func.FunctionName] <- func.Entry - addrMap[func.Entry] <- func - match func.TrampolineAddr () with - | true, addr -> addrMap[addr] <- func - | _ -> () - - /// Add a new regular function - member __.AddFunction (func: RegularFunction) = - let entry = func.Entry - nameMap[func.FunctionID] <- entry - nameMap[func.FunctionName] <- entry - addrMap[entry] <- func - regularMap[entry] <- func - - /// Get a regular function at the entry. If the entry does not contain any - /// function, create a new one and return it. - member __.GetOrAddFunction (hdl, entry) = - match regularMap.TryGetValue entry with - | true, f -> f - | false, _ -> - histMgr.Record <| CreatedFunction entry - let f = RegularFunction (histMgr, hdl, entry) - __.AddFunction f - f - - member private __.CollectXRefs () = - regularMap.Values - |> Seq.fold (fun xrefs func -> - func.AccumulateXRefs xrefs) Map.empty - - /// Update callers' cross references. - member __.UpdateCallerCrossReferences () = - __.CollectXRefs () - |> Map.iter (fun callee callers -> - addrMap[callee].RegisterCallers callers) - - static member private InitELFExterns hdl (fnMaintainer: FunctionMaintainer) = - let elf = (hdl.FileInfo :?> ELFFileInfo).ELF - elf.PLT - |> ARMap.iter (fun range symb -> - let func = ExternalFunction.Init symb.Addr symb.SymName range.Min - fnMaintainer.AddFunction func) - elf.RelocInfo.RelocByAddr.Values - |> Seq.iter (fun reloc -> - match reloc.RelSymbol with - | Some symb -> - let sec = elf.SecInfo.SecByNum[reloc.RelSecNumber] - if (sec.SecName = ".rela.dyn" || sec.SecName = ".rel.dyn") - && Array.contains symb.SymName knownNoPLTFuncs - then - let func = ExternalFunction.Init reloc.RelOffset symb.SymName 0UL - fnMaintainer.AddFunction func - else () - | None -> ()) - - static member Init hdl histMgr = - let fnMaintainer = FunctionMaintainer (histMgr) - match hdl.FileInfo.FileFormat with - | FileFormat.ELFBinary -> FunctionMaintainer.InitELFExterns hdl fnMaintainer - | _ -> () - fnMaintainer diff --git a/src/MiddleEnd/ControlFlowAnalysis/HistoryManager.fs b/src/MiddleEnd/ControlFlowAnalysis/HistoryManager.fs deleted file mode 100644 index 567df47e..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/HistoryManager.fs +++ /dev/null @@ -1,95 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 - -/// To support the rollback mechanism, we remember inter-function edges created -/// during the recovery of an indirect branch. If a vertex has been promoted due -/// to such an edge, and the edge has turned out to be invalid, then we should -/// be able to revert the promotion. -type HistoricalFact = - | CreatedFunction of func: Addr - -module private HistoricalFact = - let toString = function - | CreatedFunction (func) -> "CreatedFunction(" + func.ToString("x") + ")" - -/// Record and manage the CFG recovery history. -type HistoryManager () = - let functionStack = Stack () - let history = Dictionary> () - - /// Record the history of a certain function. - member __.StartRecordingFunctionHistory addr = - functionStack.Push (addr) - - /// Stop recording the history of a certain function. - member __.StopRecordingFunctionHistory addr = - let top = functionStack.Pop () - assert (addr = top) - - /// Check if the given function address exists in the function stack excluding - /// the stack top. - member __.HasFunctionLater addr = - if functionStack.Count = 0 then false - else Seq.tail functionStack |> Seq.exists (fun a -> addr = a) - - /// Record the historical fact. - member __.Record fact = - match functionStack.TryPeek () with - | true, funcAddr -> - match history.TryGetValue funcAddr with - | true, stack -> stack.Push fact - | false, _ -> - let stack = Stack() - stack.Push fact - history[funcAddr] <- stack - | false, _ -> () - - /// Peek the history of the current function. - member __.PeekFunctionHistory fnAddr = - let arr = - match history.TryGetValue fnAddr with - | true, stack -> - history[fnAddr] <- Stack () - stack |> Seq.toArray - | false, _ -> [||] - Array.append arr [| CreatedFunction (fnAddr) |] - -#if CFGDEBUG - /// Debug print the history. - member __.DebugPrint () = - match functionStack.TryPeek () with - | true, funcAddr -> - match history.TryGetValue funcAddr with - | true, stack -> - stack |> Seq.iter (fun fact -> - HistoricalFact.toString fact - |> dbglog (nameof HistoryManager) "%s") - | false, _ -> () - | false, _ -> () -#endif diff --git a/src/MiddleEnd/ControlFlowAnalysis/IPluggableAnalysis.fs b/src/MiddleEnd/ControlFlowAnalysis/IPluggableAnalysis.fs deleted file mode 100644 index af5ab101..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/IPluggableAnalysis.fs +++ /dev/null @@ -1,52 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowAnalysis - -/// Return types of pluggable analysis interface. -type PluggableAnalysisReturnType = - /// Analysis done ok. - | PluggableAnalysisOk - /// Analysis done with error. - | PluggableAnalysisError - /// Analysis done and a new BinHandle has been created. - | PluggableAnalysisNewBinary of BinHandle - -/// Pluggable analysis interface. Any CFG-related analysis implementing this -/// interface can be plugged in or unplugged from the BinEssence. -type IPluggableAnalysis = - - /// The name of the analysis (for debugging purpose). - abstract Name: string - - /// Run the analysis, which will return whether it needs further iteration. - abstract Run: - CFGBuilder - -> BinHandle - -> CodeManager - -> DataManager - -> PluggableAnalysisReturnType diff --git a/src/MiddleEnd/ControlFlowAnalysis/IRHelper.fs b/src/MiddleEnd/ControlFlowAnalysis/IRHelper.fs deleted file mode 100644 index 56ce75ad..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/IRHelper.fs +++ /dev/null @@ -1,182 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.ControlFlowAnalysis.IRHelper - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.MiddleEnd.DataFlow - -let private varToBV cpState var id = - let v = { var with Identifier = id } - match CPState.findReg cpState v with - | Const bv | Thunk bv | Pointer bv -> Some bv - | _ -> None - -let private expandPhi cpState var ids e = - let bvs = ids |> Array.toList |> List.map (fun id -> varToBV cpState var id) - match bvs[0] with - | Some hd -> - if bvs.Tail |> List.forall (function Some bv -> bv = hd | None -> false) - then Num hd - else e - | None -> e - -/// Recursively expand vars until we meet a Load expr. -let rec symbolicExpand cpState = function - | Num _ as e -> e - | Var v as e -> - match Map.tryFind v cpState.SSAEdges.Defs with - | Some (Def (_, e)) -> symbolicExpand cpState e - | Some (Phi (_, ids)) -> expandPhi cpState v ids e - | _ -> e - | Load _ as e -> e - | UnOp (_, _, Load _) as e -> e - | UnOp (op, rt, e) -> - let e = symbolicExpand cpState e - UnOp (op, rt, e) - | BinOp (_, _, Load _, _) - | BinOp (_, _, _, Load _) as e -> e - | BinOp (op, rt, e1, e2) -> - let e1 = symbolicExpand cpState e1 - let e2 = symbolicExpand cpState e2 - BinOp (op, rt, e1, e2) - | RelOp (_, _, Load _, _) - | RelOp (_, _, _, Load _) as e -> e - | RelOp (op, rt, e1, e2) -> - let e1 = symbolicExpand cpState e1 - let e2 = symbolicExpand cpState e2 - RelOp (op, rt, e1, e2) - | Ite (Load _, _, _, _) - | Ite (_, _, Load _, _) - | Ite (_, _, _, Load _) as e -> e - | Ite (e1, rt, e2, e3) -> - let e1 = symbolicExpand cpState e1 - let e2 = symbolicExpand cpState e2 - let e3 = symbolicExpand cpState e3 - Ite (e1, rt, e2, e3) - | Cast (_, _, Load _) as e -> e - | Cast (op, rt, e) -> - let e = symbolicExpand cpState e - Cast (op, rt, e) - | Extract (Load _, _, _) as e -> e - | Extract (e, rt, pos) -> - let e = symbolicExpand cpState e - Extract (e, rt, pos) - | e -> e - -let rec simplify = function - | Load (v, rt, e) -> Load (v, rt, simplify e) - | Store (v, rt, e1, e2) -> Store (v, rt, simplify e1, simplify e2) - | BinOp (BinOpType.ADD, rt, BinOp (BinOpType.ADD, _, Num v1, e), Num v2) - | BinOp (BinOpType.ADD, rt, BinOp (BinOpType.ADD, _, e, Num v1), Num v2) - | BinOp (BinOpType.ADD, rt, Num v1, BinOp (BinOpType.ADD, _, e, Num v2)) - | BinOp (BinOpType.ADD, rt, Num v1, BinOp (BinOpType.ADD, _, Num v2, e)) -> - BinOp (BinOpType.ADD, rt, e, Num (BitVector.add v1 v2)) - | BinOp (BinOpType.ADD, _, Num v1, Num v2) -> Num (BitVector.add v1 v2) - | BinOp (BinOpType.SUB, _, Num v1, Num v2) -> Num (BitVector.sub v1 v2) - | BinOp (BinOpType.MUL, _, Num v1, Num v2) -> Num (BitVector.mul v1 v2) - | BinOp (BinOpType.DIV, _, Num v1, Num v2) -> Num (BitVector.div v1 v2) - | BinOp (BinOpType.AND, _, Num v1, Num v2) -> Num (BitVector.band v1 v2) - | BinOp (BinOpType.OR, _, Num v1, Num v2) -> Num (BitVector.bor v1 v2) - | BinOp (op, rt, e1, e2) -> BinOp (op, rt, simplify e1, simplify e2) - | UnOp (op, rt, e) -> UnOp (op, rt, simplify e) - | RelOp (op, rt, e1, e2) -> RelOp (op, rt, simplify e1, simplify e2) - | Ite (c, rt, e1, e2) -> Ite (simplify c, rt, simplify e1, simplify e2) - | Cast (k, rt, e) -> Cast (k, rt, simplify e) - | Extract (Cast (CastKind.ZeroExt, _, e), rt, 0) when AST.typeOf e = rt -> e - | Extract (Cast (CastKind.SignExt, _, e), rt, 0) when AST.typeOf e = rt -> e - | Extract (e, rt, pos) -> Extract (simplify e, rt, pos) - | expr -> expr - -let rec foldWithConstant cpState = function - | Var v as e -> - match CPState.findReg cpState v with - | Const bv | Thunk bv | Pointer bv -> Num bv - | _ -> - match Map.tryFind v cpState.SSAEdges.Defs with - | Some (Def (_, e)) -> foldWithConstant cpState e - | _ -> e - | Load (m, rt, addr) as e -> - match foldWithConstant cpState addr with - | Num addr -> - let addr = BitVector.toUInt64 addr - match CPState.tryFindMem cpState m rt addr with - | Some (Const bv) | Some (Thunk bv) | Some (Pointer bv) -> Num bv - | _ -> e - | _ -> e - | UnOp (op, rt, e) -> UnOp (op, rt, foldWithConstant cpState e) - | BinOp (op, rt, e1, e2) -> - let e1 = foldWithConstant cpState e1 - let e2 = foldWithConstant cpState e2 - BinOp (op, rt, e1, e2) |> simplify - | RelOp (op, rt, e1, e2) -> - let e1 = foldWithConstant cpState e1 - let e2 = foldWithConstant cpState e2 - RelOp (op, rt, e1, e2) - | Ite (e1, rt, e2, e3) -> - let e1 = foldWithConstant cpState e1 - let e2 = foldWithConstant cpState e2 - let e3 = foldWithConstant cpState e3 - Ite (e1, rt, e2, e3) - | Cast (op, rt, e) -> Cast (op, rt, foldWithConstant cpState e) - | Extract (e, rt, pos) -> Extract (foldWithConstant cpState e, rt, pos) - | e -> e - -let resolveExpr cpState needConstFolding expr = - expr - |> symbolicExpand cpState - |> fun expr -> - if needConstFolding then foldWithConstant cpState expr else expr - |> simplify - -let tryResolveExprToBV cpState expr = - match resolveExpr cpState true expr with - | Num addr -> Some addr - | _ -> None - -let tryConvertBVToUInt32 bv = - let bv = BitVector.cast bv 256 - let maxVal = BitVector.cast BitVector.maxUInt32 256 - let isConvertible = BitVector.le bv maxVal |> BitVector.isTrue - if isConvertible then bv |> BitVector.toUInt32 |> Some - else None - -let tryConvertBVToUInt64 bv = - let bv = BitVector.cast bv 256 - let maxVal = BitVector.cast BitVector.maxUInt64 256 - let isConvertible = BitVector.le bv maxVal |> BitVector.isTrue - if isConvertible then bv |> BitVector.toUInt64 |> Some - else None - -let tryResolveExprToUInt32 cpState expr = - match tryResolveExprToBV cpState expr with - | Some addr -> addr |> tryConvertBVToUInt32 - | _ -> None - -let tryResolveExprToUInt64 cpState expr = - match tryResolveExprToBV cpState expr with - | Some addr -> addr |> tryConvertBVToUInt64 - | _ -> None diff --git a/src/MiddleEnd/ControlFlowAnalysis/IndirectCallResolution.fs b/src/MiddleEnd/ControlFlowAnalysis/IndirectCallResolution.fs deleted file mode 100644 index a7baf649..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/IndirectCallResolution.fs +++ /dev/null @@ -1,131 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.DataFlow -open B2R2.MiddleEnd.ControlFlowAnalysis - -[] -module private IndirectCallResolution = - - let [] Myname = "IndCallRecovery" - - /// Try to look up the CPState to find a potential call target - let resolveCallTarget st = function - | Var v -> - match v.Kind with - | TempVar _ -> CPState.findReg st v - | _ -> Utils.futureFeature () - | _ -> Utils.futureFeature () - - let updateCallInfo (func: RegularFunction) callSiteAddr target = -#if CFGDEBUG - dbglog Myname "@%x => %x" callSiteAddr target -#endif - let callee = IndirectCallees <| Set.singleton target - func.UpdateCallEdgeInfo (callSiteAddr, callee) - - let handleDiscoveredTarget func callSiteAddr target evts = - updateCallInfo func callSiteAddr target - evts - - let handleUndiscoveredTarget hdl codeMgr func callSiteAddr target evts = - updateCallInfo func callSiteAddr target - (codeMgr: CodeManager).FunctionMaintainer.GetOrAddFunction (hdl, target) - |> ignore - CFGEvents.addFuncEvt target ArchOperationMode.NoMode evts - - let handleUnresolvedCase func codeMgr callSiteAddr evts = - let bbl = (codeMgr: CodeManager).GetBBL callSiteAddr - let caller = Set.maxElement bbl.IRLeaders - let callee = IndirectCallees Set.empty - let lastInsAddr = Set.maxElement bbl.InstrAddrs - let lastIns = codeMgr.GetInstruction lastInsAddr - let ftAddr = uint64 lastIns.Instruction.Length + lastInsAddr - (func: RegularFunction).UpdateCallEdgeInfo (callSiteAddr, callee) - CFGEvents.addPerFuncAnalysisEvt func.Entry evts - |> CFGEvents.addRetEvt func 0UL ftAddr callSiteAddr - |> CFGEvents.addEdgeEvt func caller ftAddr CallFallThroughEdge - - let resolve cpState ssaCFG acc callSiteAddr = - let v = SSACFG.findVertexByAddr ssaCFG callSiteAddr - match v.VData.GetLastStmt () with - | Jmp (InterJmp e) -> (* The only possible form for an indrect call *) -#if CFGDEBUG - dbglog Myname "@%x call exp %s" callSiteAddr (Pp.expToString e) -#endif - match resolveCallTarget cpState e with - | Const bv -> - let target = BitVector.toUInt64 bv - if target <> 0UL then Map.add callSiteAddr (Some target) acc - else Map.add callSiteAddr None acc - | NotAConst -> Map.add callSiteAddr None acc - | _ -> Utils.impossible () - | _ -> Utils.impossible () - - let update hdl (codeMgr: CodeManager) func evts result = - result - |> Map.fold (fun evts callSiteAddr target -> - match target with - | Some target -> - if codeMgr.FunctionMaintainer.Contains (addr=target) then - handleDiscoveredTarget func callSiteAddr target evts - else handleUndiscoveredTarget hdl codeMgr func callSiteAddr target evts - | None -> handleUnresolvedCase func codeMgr callSiteAddr evts) evts - - let reader hdl (codeMgr: CodeManager) addr rt = - if hdl.FileInfo.IsValidAddr addr then - match hdl.FileInfo.GetSections addr |> Seq.tryHead with - | Some sec -> - if sec.Name = ".rodata" || sec.Name = ".data" then - let v = BinHandle.ReadUInt (hdl, addr, RegType.toByteWidth rt) - Some <| BitVector.ofUInt64 v rt - elif sec.Name = ".got" then - if codeMgr.FunctionMaintainer.Contains (addr=addr) then - Some <| BitVector.ofUInt64 addr rt - else None - else None - | None -> None - else None - -/// IndirectCallResolution tries to find indirect call target by constant -/// propagation. We should fix this if we meet a table-like indirect call -/// targets. -type IndirectCallResolution () = - inherit PerFunctionAnalysis () - - override __.Name = Myname - - override __.Run hdl codeMgr _dataMgr func evts = - let reader = reader hdl codeMgr |> Some - let struct (cpState, ssaCFG) = PerFunctionAnalysis.runCP hdl func reader - func.UnresolvedIndirectCallEdges - |> Seq.fold (resolve cpState ssaCFG) Map.empty - |> update hdl codeMgr func evts - |> Ok diff --git a/src/MiddleEnd/ControlFlowAnalysis/IndirectJumpResolution.fs b/src/MiddleEnd/ControlFlowAnalysis/IndirectJumpResolution.fs deleted file mode 100644 index 8c4961f7..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/IndirectJumpResolution.fs +++ /dev/null @@ -1,172 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.DataFlow - -type BranchPattern = - /// This encodes an indirect jump with a jump table where baseAddr is the jump - /// target's base address, tblAddr is the start address of a jump table, and - /// rt is the size of each entry in the jump table. - | JmpTablePattern of baseAddr: Addr * tblAddr: Addr * rt: RegType - /// Jump to a single constant target. - | ConstJmpPattern of addr: Addr - /// Conditional jump for constant targets. This pattern appears in EVM. - | ConstCJmpPattern of tAddr: Addr * fAddr: Addr - /// Call to a single constant target. - | ConstCallPattern of calleeAddr: Addr * ftAddr: Addr - /// Return back to caller pattern found in EVM. - | ReturnPattern of sp: Addr - /// Unknown pattern. - | UnknownPattern - -/// The resulting status of RecoverTarget. -type RecoveryStatus = - /// Recovery process should stop. - | RecoverDone of Result - /// Recovery process should continue. - | RecoverContinue - -/// Indirect jump resolution. -[] -type IndirectJumpResolution () = - inherit PerFunctionAnalysis () - - override __.Name = "IndirectJumpResolution" - - /// Analyze the given indirect jump type (JmpType) and return a BranchPattern. - abstract member Classify: - BinHandle - -> SSAVertex - -> CPState - -> JmpType - -> BranchPattern - - /// Check the given BranchPattern and mark the indirect jump as an analysis - /// target. - abstract member MarkIndJmpAsTarget: - DataManager - -> RegularFunction - -> Addr - -> ProgramPoint - -> CFGEvents - -> BranchPattern - -> Result - - /// Recover the current target. - abstract member RecoverTarget: - BinHandle - -> CodeManager - -> DataManager - -> RegularFunction - -> CFGEvents - -> RecoveryStatus - - /// Process recovery error(s). - abstract member OnError: - CodeManager - -> DataManager - -> RegularFunction - -> CFGEvents - -> (JumpTable * Addr) - -> Result - - member private __.FindIndJmpKind ssaCFG srcBlkAddr fstV (vs: SSAVertex list) = - match vs with - | v :: rest -> - match v.VData.GetLastStmt () with - | Jmp (InterJmp _ as jk) - | Jmp (InterCJmp _ as jk) -> jk - | _ -> - let vs = - DiGraph.getSuccs ssaCFG v - |> List.fold (fun acc succ -> - if succ <> fstV then succ :: acc else acc) rest - __.FindIndJmpKind ssaCFG srcBlkAddr fstV vs - | [] -> Utils.impossible () - - /// Symbolically expand the indirect jump expression with the constant - /// information obtained from the constatnt propagation step, and see if the - /// jump target is in the form of loading a jump table. - member private __.AnalyzeBranchPattern hdl ssaCFG cpState blkAddr = - let srcV = (* may not contain Jmp: get the right one @ FindIndJmpKind. *) - DiGraph.findVertexBy ssaCFG (fun (v: SSAVertex) -> - v.VData.PPoint.Address = blkAddr) - let srcBlkAddr = (srcV: SSAVertex).VData.PPoint.Address - __.FindIndJmpKind ssaCFG srcBlkAddr srcV [ srcV ] - |> __.Classify hdl srcV cpState - - member private __.Analyze - hdl codeMgr dataMgr fn cpSt ssaCFG addrs needRecovery evts = - match addrs with - | iAddr :: rest -> -#if CFGDEBUG - dbglog "IndJmpRecovery" "@%x Detected indjmp @ %x" - (fn: RegularFunction).Entry iAddr -#endif - let bblInfo = (codeMgr: CodeManager).GetBBL iAddr - let blkAddr = Set.minElement bblInfo.InstrAddrs - let src = Set.maxElement bblInfo.IRLeaders - __.AnalyzeBranchPattern hdl ssaCFG cpSt blkAddr - |> __.MarkIndJmpAsTarget dataMgr fn iAddr src evts - |> function - | Ok (true, evts) -> - __.Analyze hdl codeMgr dataMgr fn cpSt ssaCFG rest true evts - | Ok (false, evts) -> - __.Analyze hdl codeMgr dataMgr fn cpSt ssaCFG rest needRecovery evts - | Error err -> Error err - | [] -> Ok (needRecovery, evts) - - member private __.AnalyzeIndJmps hdl codeMgr dataMgr fn evts = - let addrs = (fn: RegularFunction).YetAnalyzedIndirectJumpAddrs - if List.isEmpty addrs then Ok (true, evts) - else - let struct (cpState, ssaCFG) = PerFunctionAnalysis.runCP hdl fn None - __.Analyze hdl codeMgr dataMgr fn cpState ssaCFG addrs false evts - - member private __.Resolve hdl codeMgr dataMgr fn evts = - match __.AnalyzeIndJmps hdl codeMgr dataMgr fn evts with - | Ok (true, evts) -> - match __.RecoverTarget hdl codeMgr dataMgr fn evts with - | RecoverDone res -> res - | RecoverContinue -> __.Resolve hdl codeMgr dataMgr fn evts - | Ok (false, evts) -> - (* We are in a nested update call, and found nothing to resolve. So, just - return to the caller, and keep resolving the rest entries. *) - Ok evts - | Error err -> - __.OnError codeMgr dataMgr fn evts err - - override __.Run hdl codeMgr dataMgr fn evts = - codeMgr.HistoryManager.StartRecordingFunctionHistory fn.Entry - let res = __.Resolve hdl codeMgr dataMgr fn evts - codeMgr.HistoryManager.StopRecordingFunctionHistory fn.Entry - res diff --git a/src/MiddleEnd/ControlFlowAnalysis/JmpTableResolution.fs b/src/MiddleEnd/ControlFlowAnalysis/JmpTableResolution.fs deleted file mode 100644 index 8b610e04..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/JmpTableResolution.fs +++ /dev/null @@ -1,405 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.ControlFlowAnalysis.IRHelper -open B2R2.MiddleEnd.DataFlow - -[] -module private JmpTableResolution = - - let rec isJmpTblAddr cpState = function - | Var v -> - match Map.tryFind v cpState.SSAEdges.Defs with - | Some (Def (_, e)) -> isJmpTblAddr cpState e - | _ -> false - | BinOp (BinOpType.MUL, _, _, Num _) - | BinOp (BinOpType.MUL, _, Num _, _) - | BinOp (BinOpType.SHL, _, _, Num _) -> true - | BinOp (_, _, e1, e2) -> - isJmpTblAddr cpState e1 || isJmpTblAddr cpState e2 - | _ -> false - - let rec extractTableExpr = function - | BinOp (BinOpType.ADD, _, BinOp (BinOpType.MUL, _, _, Num _), e) - | BinOp (BinOpType.ADD, _, BinOp (BinOpType.MUL, _, Num _, _), e) - | BinOp (BinOpType.ADD, _, BinOp (BinOpType.SHL, _, _, Num _), e) - | BinOp (BinOpType.ADD, _, e, BinOp (BinOpType.MUL, _, _, Num _)) - | BinOp (BinOpType.ADD, _, e, BinOp (BinOpType.MUL, _, Num _, _)) - | BinOp (BinOpType.ADD, _, e, BinOp (BinOpType.SHL, _, _, Num _)) -> e - | BinOp (op, rt, e1, e2) -> - BinOp (op, rt, extractTableExpr e1, extractTableExpr e2) - | UnOp (op, rt, e) -> UnOp (op, rt, extractTableExpr e) - | Cast (op, rt, e) -> Cast (op, rt, extractTableExpr e) - | Extract (e, rt, pos) -> Extract (extractTableExpr e, rt, pos) - | e -> e - - let computeMask size = - let rt = RegType.fromByteWidth size - (* It is reasonable enough to assume that jump target addresses will never - overflow when rt is greater than 64. *) - if rt > 64 then 0xFFFFFFFFFFFFFFFFUL - else BitVector.unsignedMax rt |> BitVector.toUInt64 - - /// Read a table entry and compute jump target - let readTable hdl bAddr (entryAddr: Addr) size = - let addr = bAddr + BinHandle.ReadUInt (hdl, entryAddr, size) - addr &&& computeMask size - - let recoverIndirectEdge bld fn src dst = - let evts = - CFGEvents.empty - |> CFGEvents.addPerFuncAnalysisEvt (fn: RegularFunction).Entry - |> CFGEvents.addEdgeEvt fn src dst IndirectJmpEdge - (bld: ICFGBuildable).Update evts - - let recoverOneEntry bld hdl codeMgr (dataMgr: DataManager) fn jt entryAddr = - let dst = readTable hdl jt.BranchBaseAddr entryAddr jt.JTEntrySize - let brAddr = jt.InstructionAddr - let bblInfo = (codeMgr: CodeManager).GetBBL brAddr - let src = bblInfo.IRLeaders |> Set.maxElement -#if CFGDEBUG - dbglog "IndJmpRecovery" "@%x Recovering %x -> %x (%x)" - (fn: RegularFunction).Entry src.Address dst entryAddr -#endif - recoverIndirectEdge bld fn src dst - |> Result.bind (fun _ -> - (* This is really an exceptional case where we found a nested switch - table, whose location is overlapping with our current entryAddr. - Thus, the potential end-point address has been updated during the - Update process, and we found out late that our attempt with entryAddr - was wrong. *) - let ep = dataMgr.JumpTables.FindPotentialEndPoint jt.JTStartAddr - if entryAddr >= ep then Error ErrorLateDetection - else Ok dst) - |> function - | Ok recoveredAddr -> -#if CFGDEBUG - dbglog "IndJmpRecovery" "Successfully recovered %x from %x (tbl %x)" - recoveredAddr entryAddr jt.JTStartAddr -#endif - let ep = entryAddr + uint64 jt.JTEntrySize - dataMgr.JumpTables.UpdateConfirmedEndPoint jt.JTStartAddr ep |> Ok - | Error e -> Error e - - let getJumpTables (fn: RegularFunction) = - fn.IndirectJumps.Values - |> Seq.fold (fun acc jmpKind -> - match jmpKind with - | JmpTbl tAddr -> tAddr :: acc - | _ -> acc - ) [] - |> List.rev - - /// Analyze less explored jump tables first. - let sortJumpTablesByProgress (dataMgr: DataManager) jmpTbls = - jmpTbls - |> List.sortBy (fun addr -> - (dataMgr.JumpTables.FindConfirmedEndPoint addr) - addr) - - /// We first recover the very first entry, since we are 100% sure about it. - let rec getInitialRecoveryTarget (dataMgr: DataManager) = function - | tAddr :: tl -> - let endPoint = dataMgr.JumpTables.FindConfirmedEndPoint tAddr - if tAddr = endPoint then (* First entry *) - Some (dataMgr.JumpTables[tAddr], tAddr) - else getInitialRecoveryTarget dataMgr tl - | [] -> None - - let isSemanticallyNop hdl (ins: Instruction) = - if ins.IsNop () then true - else - match BinHandle.LiftOptimizedInstr hdl ins with - | [| { LowUIR.S = LowUIR.ISMark (_) } - { LowUIR.S = LowUIR.IEMark (_) } |] -> true - | _ -> false - - let rec findNextNonNopAddr hdl addr = - match BinHandle.TryParseInstr (hdl, addr=addr) with - | Ok ins -> - if isSemanticallyNop hdl ins then - findNextNonNopAddr hdl (addr + uint64 ins.Length) - else Ok addr - | Error e -> Error e - - /// We examine every gap address and see if each gap starts with a no-op - /// chunk. If so, we add the first non-no-op instruction's address in the gap - /// to gaps. This way, we do not miss valid indirect jumps that may point to a - /// gap right after no-op instruction(s). - let rearrangeGapsByNoOp hdl gaps = - gaps - |> Map.fold (fun gaps sAddr eAddr -> - match findNextNonNopAddr hdl sAddr with - | Ok nonNopAddr -> - if sAddr <> nonNopAddr && nonNopAddr < eAddr then - Map.remove sAddr gaps - |> Map.add sAddr nonNopAddr - |> Map.add nonNopAddr eAddr - elif nonNopAddr = eAddr then Map.remove sAddr gaps - else gaps - | Error _ -> - (* The gap contains data (as we cannot parse it), so we remove it. *) - Map.remove sAddr gaps - ) gaps - - /// Incrementally search for a jump table entry pointing to the current gap. - /// The search continues until we find an invalid address in the table. - let rec findGapPointingAddr hdl (dataMgr: DataManager) jt entryAddr gaps = - let size = jt.JTEntrySize - if dataMgr.JumpTables.FindPotentialEndPoint jt.JTStartAddr <= entryAddr then -#if CFGDEBUG - dbglog "IndJmpRecovery" "Nothing from gap (tbl %x) (potential = %x)" - jt.JTStartAddr - (dataMgr.JumpTables.FindPotentialEndPoint jt.JTStartAddr) -#endif - None - else - let addr = readTable hdl jt.BranchBaseAddr entryAddr size - if hdl.FileInfo.IsValidAddr addr then - let nextAddr = entryAddr + uint64 size - if Map.containsKey addr gaps then - let confirmedEndPoint = - dataMgr.JumpTables.FindConfirmedEndPoint jt.JTStartAddr - let entryAddr = min confirmedEndPoint entryAddr -#if CFGDEBUG - dbglog "IndJmpRecovery" "Found entry %x (for tbl %x) from gap" - entryAddr jt.JTStartAddr -#endif - Some (jt, entryAddr) - else findGapPointingAddr hdl dataMgr jt nextAddr gaps - else -#if CFGDEBUG - dbglog "IndJmpRecovery" "Invalid gap pointing addr %x => %x (tbl %x)" - entryAddr addr jt.JTStartAddr -#endif - None - - /// Find a recovery end-point address that can fill in the gap. - let rec getRecoveryTargetFromGap hdl (dataMgr: DataManager) gaps = function - | tAddr :: tl -> - let jt = dataMgr.JumpTables[tAddr] - let entryAddr = dataMgr.JumpTables.FindConfirmedEndPoint tAddr - match findGapPointingAddr hdl dataMgr jt entryAddr gaps with - | Some _ as target -> target - | None -> getRecoveryTargetFromGap hdl dataMgr gaps tl - | [] -> None - - /// Increment the current entry address of a jump table only if it can point - /// to a valid entry. - let incEntryAddr hdl fn nextFnAddr jt entryAddr = - let addr = readTable hdl jt.BranchBaseAddr entryAddr jt.JTEntrySize -#if CFGDEBUG - dbglog "IndJmpRecovery" "Read %x from %x" addr entryAddr -#endif - if addr < (fn: RegularFunction).Entry || addr >= nextFnAddr then None - else Some entryAddr - - /// This is a less safer path than the gap-oriented search. We compute the - /// next recovery end-point address by simply pointing to the next entry. - let rec getNextRecoveryTargetFromTable hdl codeMgr dataMgr fn gaps = function - | tAddr :: tl -> - let jt = (dataMgr: DataManager).JumpTables[tAddr] - let deadEnd = dataMgr.JumpTables.FindPotentialEndPoint tAddr - let entryAddr = dataMgr.JumpTables.FindConfirmedEndPoint tAddr -#if CFGDEBUG - dbglog "IndJmpRecovery" "Last resort (tbl %x) %x < %x" - tAddr entryAddr deadEnd -#endif - if entryAddr < deadEnd then - let nextFnAddr = - (codeMgr: CodeManager).FunctionMaintainer.FindNextFunctionAddr fn - match incEntryAddr hdl fn nextFnAddr jt entryAddr with - | Some entry -> -#if CFGDEBUG - dbglog "IndJmpRecovery" "Found entry %x from table (%x)" - entry jt.JTStartAddr -#endif - Some (jt, entry) - | None -> getNextRecoveryTargetFromTable hdl codeMgr dataMgr fn gaps tl - else getNextRecoveryTargetFromTable hdl codeMgr dataMgr fn gaps tl - | [] -> None - - /// Get the next analysis target information, such as end-point addresses - /// where we should stop our recovery process, for recovering jump tables. - let getNextAnalysisTarget hdl codeMgr (dataMgr: DataManager) func = - let jmpTbls = - getJumpTables func - |> sortJumpTablesByProgress dataMgr -#if CFGDEBUG - dbglog "IndJmpRecovery" "%d table(s) at hand" (List.length jmpTbls) -#endif - match getInitialRecoveryTarget dataMgr jmpTbls with - | Some (jt, _) as target -> -#if CFGDEBUG - dbglog "IndJmpRecovery" "Found the first entry from table (%x)" - jt.JTStartAddr -#endif - target - | None -> - let gaps = (func: RegularFunction).GapAddresses |> rearrangeGapsByNoOp hdl - match getRecoveryTargetFromGap hdl dataMgr gaps jmpTbls with - | Some _ as target -> target - | None -> - getNextRecoveryTargetFromTable hdl codeMgr dataMgr func gaps jmpTbls - - let rec rollback - (codeMgr: CodeManager) (dataMgr: DataManager) fn evts jt entryAddr e = - let fnAddr = (fn: RegularFunction).Entry - let brAddr = jt.InstructionAddr -#if CFGDEBUG - dbglog "IndJmpRecovery" "@%x Failed to recover %x (tbl %x), so rollback %s" - fnAddr entryAddr jt.JTStartAddr (CFGError.toString e) -#endif - dataMgr.JumpTables.UpdateConfirmedEndPoint jt.JTStartAddr jt.JTStartAddr - match e with - | ErrorBranchRecovery (errFnAddr, errBrAddr, rollbackFuncs) -> - let rollbackFuncs = Set.add fnAddr rollbackFuncs - if codeMgr.HistoryManager.HasFunctionLater fnAddr then - Error <| ErrorBranchRecovery (errFnAddr, errBrAddr, rollbackFuncs) - else codeMgr.RollBack (evts, Set.toList rollbackFuncs) |> Ok - | ErrorLateDetection -> - dataMgr.JumpTables.UpdatePotentialEndPoint jt.JTStartAddr entryAddr - finishIfEmpty codeMgr fnAddr brAddr evts - | ErrorConnectingEdge | ErrorParsing -> - dataMgr.JumpTables.UpdatePotentialEndPoint jt.JTStartAddr entryAddr - finishIfEmpty codeMgr fnAddr brAddr evts - - and finishIfEmpty codeMgr fnAddr brAddr evts = - if codeMgr.HistoryManager.HasFunctionLater fnAddr then - Error (ErrorBranchRecovery (fnAddr, brAddr, Set.singleton fnAddr)) - else Ok <| (codeMgr: CodeManager).RollBack (evts, [ fnAddr ]) - - let classifyWithSymbolicExpr cpState baseExpr tblExpr rt = - let baseExpr = foldWithConstant cpState baseExpr |> simplify - let tblExpr = - symbolicExpand cpState tblExpr - |> extractTableExpr - |> foldWithConstant cpState -#if CFGDEBUG - dbglog "IndJmpRecovery" "base(%s); table(%s)" - (Pp.expToString baseExpr) (Pp.expToString tblExpr) -#endif - match baseExpr, tblExpr with - | Num b, Num t - | Num b, BinOp (BinOpType.ADD, _, Num t, _) - | Num b, BinOp (BinOpType.ADD, _, _, Num t) -> - let baseAddr = BitVector.toUInt64 b - let tblAddr = BitVector.toUInt64 t - JmpTablePattern (baseAddr, tblAddr, rt) - | _ -> UnknownPattern - - let classifyJmpExpr cpState = function - | BinOp (BinOpType.ADD, _, Num b, Load (_, t, memExpr)) - | BinOp (BinOpType.ADD, _, Load (_, t, memExpr), Num b) - | BinOp (BinOpType.ADD, _, Num b, Cast (_, _, Load (_, t, memExpr))) - | BinOp (BinOpType.ADD, _, Cast (_, _, Load (_, t, memExpr)), Num b) -> - if isJmpTblAddr cpState memExpr then - classifyWithSymbolicExpr cpState (Num b) memExpr t - else UnknownPattern - (* Symbolic patterns should be resolved with our constant analysis. *) - | BinOp (BinOpType.ADD, _, (Load (_, _, e1) as l1), - (Load (_, t, e2) as l2)) -> - if isJmpTblAddr cpState e1 then classifyWithSymbolicExpr cpState l2 e1 t - elif isJmpTblAddr cpState e2 then classifyWithSymbolicExpr cpState l1 e2 t - else UnknownPattern - | BinOp (BinOpType.ADD, _, baseExpr, Load (_, t, tblExpr)) - | BinOp (BinOpType.ADD, _, Load (_, t, tblExpr), baseExpr) -> - if isJmpTblAddr cpState tblExpr then - classifyWithSymbolicExpr cpState baseExpr tblExpr t - else UnknownPattern - (* Patterns from non-pie executables. *) - | Load (_, t, memExpr) - | Cast (_, _, Load (_, t, memExpr)) -> - if isJmpTblAddr cpState memExpr then - classifyWithSymbolicExpr cpState (Num <| BitVector.zero t) memExpr t - else UnknownPattern - | _ -> UnknownPattern - -/// JmpTableResolution recovers jump targets of indirect jumps by inferring -/// their jump tables. It first identifies jump table bases with constant -/// propagation and recovers the entire table ranges by leveraging the -/// structural properties of the binary. -type JmpTableResolution (bld) = - inherit IndirectJumpResolution () - - override __.Name = "JmpTableResolution" - - override __.Classify _hdl _srcV cpState jmpType = - match jmpType with - | InterJmp jmpExpr -> - let symbExpr = resolveExpr cpState false jmpExpr -#if CFGDEBUG - dbglog "IndJmpRecovery" "Pattern indjmp: %s" (Pp.expToString symbExpr) -#endif - classifyJmpExpr cpState symbExpr - | _ -> Utils.impossible () - - override __.MarkIndJmpAsTarget dataMgr fn insAddr _ evts pattern = - match pattern with - | JmpTablePattern (bAddr, tAddr, rt) -> -#if CFGDEBUG - dbglog "IndJmpRecovery" "Found known pattern %x, %x" bAddr tAddr -#endif - let tbls = dataMgr.JumpTables - match tbls.Register fn.Entry insAddr bAddr tAddr rt with - | Ok () -> - fn.MarkIndJumpAsJumpTbl insAddr tAddr - Ok (true, evts) - | Error jt -> Error (jt, tAddr) (* Overlapping jump table. *) - | _ -> - fn.MarkIndJumpAsUnknown insAddr - Ok (false, evts) - - override __.RecoverTarget hdl codeMgr dataMgr fn evts = - match getNextAnalysisTarget hdl codeMgr dataMgr fn with - | Some (jt, entryAddr) -> - match recoverOneEntry bld hdl codeMgr dataMgr fn jt entryAddr with - | Ok () -> RecoverContinue - | Error e -> - let res = rollback codeMgr dataMgr fn evts jt entryAddr e - RecoverDone res - | None -> RecoverDone <| Ok evts - - override __.OnError codeMgr dataMgr fn evts errInfo = - match errInfo with - | oldJT, newTblAddr -> - let oldBrAddr = oldJT.InstructionAddr - let oldFnAddr = oldJT.HostFunctionEntry - let oldTblAddr = oldJT.JTStartAddr -#if CFGDEBUG - dbglog "IndJmpRecovery" "@%x Failed to make jmptbl due to overlap: %x@%x" - fn.Entry oldBrAddr oldFnAddr -#endif - dataMgr.JumpTables.UpdatePotentialEndPoint oldTblAddr newTblAddr - let fnToRollback = codeMgr.FunctionMaintainer.FindRegular oldFnAddr - fnToRollback.JumpTableAddrs |> List.iter (fun tAddr -> - dataMgr.JumpTables.UpdateConfirmedEndPoint tAddr tAddr) - finishIfEmpty codeMgr oldFnAddr oldBrAddr evts diff --git a/src/MiddleEnd/ControlFlowAnalysis/JumpTableMaintainer.fs b/src/MiddleEnd/ControlFlowAnalysis/JumpTableMaintainer.fs deleted file mode 100644 index 60c6ca8c..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/JumpTableMaintainer.fs +++ /dev/null @@ -1,105 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open System.Collections.Generic -open B2R2 - -/// Indirect branch jump table information. -type JumpTable = { - /// The address of the owner function of the indirect branch. - HostFunctionEntry: Addr - /// The indirect branch instruction address. - InstructionAddr: Addr - /// The base address used to compute the final target address. - BranchBaseAddr: Addr - /// Start address of the jump table, i.e., the first table entry's address. - JTStartAddr: Addr - /// Jump table's entry size. Typically this is 4-byte. - JTEntrySize: int -} -with - static member Init entry ins bAddr tAddr rt = - { HostFunctionEntry = entry - InstructionAddr = ins - BranchBaseAddr = bAddr - JTStartAddr = tAddr - JTEntrySize = RegType.toByteWidth rt } - -type JumpTableMaintainer () = - let jumpTables = SortedList () - let potentialEndPoints = Dictionary () - let confirmedEndPoints = Dictionary () - - member private __.FindOverlappingJumpTable addr = - jumpTables.Values - |> Seq.tryFind (fun jt -> - jt.JTStartAddr <= addr && addr < confirmedEndPoints[jt.JTStartAddr]) - - /// Register a new jump table. - member __.Register funcEntry insAddr bAddr tAddr rt = - let jt = JumpTable.Init funcEntry insAddr bAddr tAddr rt - if jumpTables.ContainsKey tAddr then - (* We had another jump table at the exactly the same location earlier. - This means our rollback mechanism removed some history, and we just - encountered the same indirect branch again. In this case, we will just - reuse it. *) - Ok () - else - confirmedEndPoints[tAddr] <- tAddr - potentialEndPoints[tAddr] <- System.UInt64.MaxValue - match __.FindOverlappingJumpTable tAddr with - | Some jt -> Error jt - | None -> - match SortedList.findGreatestLowerBoundKey tAddr jumpTables with - | Some lbAddr -> potentialEndPoints[lbAddr] <- tAddr - | None -> () - match SortedList.findLeastUpperBoundKey tAddr jumpTables with - | Some ubAddr -> potentialEndPoints[tAddr] <- ubAddr - | None -> () - jumpTables[tAddr] <- jt - Ok () - - /// Update the potential end-point information. - member __.UpdatePotentialEndPoint tAddr pAddr = - potentialEndPoints[tAddr] <- pAddr - - /// Find the current potential end-point for the given table address. - member __.FindPotentialEndPoint tAddr = - potentialEndPoints[tAddr] - - /// Update the confirmed end-point of the jump table located at the tAddr. - member __.UpdateConfirmedEndPoint tAddr epAddr = - confirmedEndPoints[tAddr] <- epAddr - - /// Find the currently confirmed end-point for the given table address. - member __.FindConfirmedEndPoint tAddr = - confirmedEndPoints[tAddr] - - member __.Item - with get(addr) = jumpTables[addr] - and set addr jt = jumpTables[addr] <- jt - - member __.ToSeq () = jumpTables |> seq diff --git a/src/MiddleEnd/ControlFlowAnalysis/NoReturnFunctionIdentification.fs b/src/MiddleEnd/ControlFlowAnalysis/NoReturnFunctionIdentification.fs deleted file mode 100644 index 9687ce6c..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/NoReturnFunctionIdentification.fs +++ /dev/null @@ -1,330 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.DataFlow -open B2R2.MiddleEnd.ControlFlowAnalysis -open B2R2.MiddleEnd.ControlFlowAnalysis.EvalHelper - -type NoReturnDecision = - | IsReturning - | IsNoReturning - | IsUndecidable - -module NoReturnDecision = - let meet a b = - match a, b with - | IsNoReturning, IsUndecidable - | IsUndecidable, IsNoReturning - | IsNoReturning, IsNoReturning -> IsNoReturning - | _ -> IsReturning - -[] -module private NoReturnFunctionIdentificationHelper = - - let hasConditionallyInvalidFallEdge codeMgr fn callSiteAddr entry = - let callee = (codeMgr: CodeManager).FunctionMaintainer.Find (addr=entry) - match callee.NoReturnProperty with - | ConditionalNoRet _ -> - let bbl = codeMgr.GetBBL callSiteAddr - let caller = Set.maxElement bbl.IRLeaders - let v = (fn: RegularFunction).FindVertex caller - DiGraph.getSuccs (fn: RegularFunction).IRCFG v - |> List.exists (fun w -> - (* Since the fall-through edge exists, block-level constant propagation - were not able to remove the edge. So this is a non-trivial case. *) - DiGraph.findEdgeData fn.IRCFG v w = CallFallThroughEdge) - | _ -> false - - let isPotentiallyNonTrivialConditionalNoRet codeMgr (fn: RegularFunction) = - fn.CallEdges - |> Array.exists (fun (callSiteAddr, callee) -> - match callee with - | RegularCallee addr -> - hasConditionallyInvalidFallEdge codeMgr fn callSiteAddr addr - | IndirectCallees addrs -> - addrs - |> Set.exists (hasConditionallyInvalidFallEdge codeMgr fn callSiteAddr) - | UnresolvedIndirectCallees (_) | NullCallee -> false) - - /// We disregard jump trampolines and consider them as NotNoRet. - let checkTrampoline (vertices: IRVertex list) = - match vertices with - | [ v ] when not (v.VData.IsFakeBlock ()) -> (* Only single exit node. *) - let ins = v.VData.LastInstruction - if ins.IsIndirectBranch () then (* This is really a trampoline. *) [] - else vertices - | _ -> vertices - - let rec analyzeExits (codeMgr: CodeManager) fn cond = function - | (v: IRVertex) :: tl when cond = IsNoReturning || cond = IsUndecidable -> - if v.VData.IsFakeBlock () then - let cond = - (fn: RegularFunction).CallTargets v.VData.FakeBlockInfo.CallSite - |> Set.fold (fun cond callee -> - let calleeFunc = codeMgr.FunctionMaintainer.Find callee - match calleeFunc.NoReturnProperty with - (* Since we are analyzing exit nodes, the fall-through edge does - not exist at this point. Thus, ConditionalNoRet here implies - the call will not return. *) - | NoRet | ConditionalNoRet _ -> - NoReturnDecision.meet cond IsNoReturning - | _ -> - if v.VData.FakeBlockInfo.IsTailCall then IsReturning - elif fn.Entry = callee then cond - else Utils.impossible () (* We are only considering exit nodes. *) - ) cond - analyzeExits codeMgr fn cond tl - else - let cond = NoReturnDecision.meet cond IsNoReturning - analyzeExits codeMgr fn cond tl - | _ -> cond - - /// The algorithm is simple: if there exists a return block (with a ret - /// instruction), we consider it as a returning function. - let performBasicNoRetAnalysis codeMgr (func: RegularFunction) = - let decision = - DiGraph.getExits func.IRCFG - |> checkTrampoline - |> analyzeExits codeMgr func IsUndecidable - match decision with - | IsReturning -> func.NoReturnProperty <- NotNoRet - | IsNoReturning -> func.NoReturnProperty <- NoRet - | IsUndecidable -> - (* This is an exceptional case, e.g., jump stubs, and compilers will not - make it as a no-return function. So making it NotNoRet is safe. *) - func.NoReturnProperty <- NotNoRet - - let confirmArgX86 fakeBlk (uvState: CPState) arg = - match (fakeBlk: SSAVertex).VData.FakeBlockInfo.FrameDistance with - | Some offset -> - let argOffset = offset - 4 * arg - let varKind = SSA.StackVar (32, argOffset) - match SSACFG.findReachingDef fakeBlk varKind with - | Some (SSA.Def (v, _)) -> - match CPState.findReg uvState v with - | Untouched (RegisterTag { Kind = SSA.StackVar (_, offset) }) -> - Some (- offset / 4) - | _ -> None - | _ -> None - | None -> None - - let ssaRegToArgX64 hdl (r: SSA.Variable) = - match r.Kind with - | SSA.RegVar (_, rid, _) -> - if rid = CallingConvention.functionArgRegister hdl 1 then Some 1 - elif rid = CallingConvention.functionArgRegister hdl 2 then Some 2 - elif rid = CallingConvention.functionArgRegister hdl 3 then Some 3 - elif rid = CallingConvention.functionArgRegister hdl 4 then Some 4 - elif rid = CallingConvention.functionArgRegister hdl 5 then Some 5 - elif rid = CallingConvention.functionArgRegister hdl 6 then Some 6 - else None - | _ -> None - - let confirmArgX64 hdl fakeBlk uvState arg = - let rid = CallingConvention.functionArgRegister hdl arg - let name = hdl.RegisterBay.RegIDToString rid - let varKind = SSA.RegVar (64, rid, name) - match SSACFG.findReachingDef fakeBlk varKind with - | Some (SSA.Def (v, _)) -> - match CPState.findReg uvState v with - | Untouched (RegisterTag r) -> ssaRegToArgX64 hdl r - | _ -> None - | _ -> - (* If no definition is found, this means the parameter register is - untouched, thus, conditional no return. *) - Some arg - - let confirmArg hdl fakeBlk uvState arg = - match hdl.ISA.Arch with - | Arch.IntelX86 -> confirmArgX86 fakeBlk uvState arg - | Arch.IntelX64 -> confirmArgX64 hdl fakeBlk uvState arg - | _ -> None - - /// For every conditionally no-returning function callee, check if the `func` - /// only uses the constant value originated from the function argument. This - /// function returns a set of confirmed call info (caller bbl, untouched - /// argument number). We say a call to a conditionally no-returning function - /// is "confirmed" if the function is called directly from an argument of the - /// calling function `func`, and the argument is never redefined until it - /// reaches the function call. - let getConfirmedNoRets hdl codeMgr func ssaCFG uvState = - (func: RegularFunction).CallEdges - |> Array.fold (fun acc (callSiteAddr, callee) -> - match callee with - | RegularCallee entry -> - let callee = (codeMgr: CodeManager).FunctionMaintainer.Find entry - match callee.NoReturnProperty with - | ConditionalNoRet arg -> - let caller = SSACFG.findVertexByAddr ssaCFG callSiteAddr - let fake = - DiGraph.getSuccs ssaCFG caller - |> List.find (fun w -> w.VData.IsFakeBlock ()) - match confirmArg hdl fake uvState arg with - | Some arg -> Set.add (caller, arg) acc - | None -> acc - (* XXX: handling IndirectCallees? *) - | _ -> acc - | _ -> acc) Set.empty - - /// Since we removed all confirmed fall-through edges (which were all - /// connected in the original graph), if all the exit nodes of the current CFG - /// are either NoRet or ConditionalNoRet, then we can say that this function - /// is a conditionally no-returning function. - let isConditionalNoret (codeMgr: CodeManager) ssaCFG = - DiGraph.getExits ssaCFG - |> List.forall (fun (v: SSAVertex) -> - if v.VData.IsFakeBlock () then - match codeMgr.FunctionMaintainer.TryFind v.VData.PPoint.Address with - | Some callee -> - match callee.NoReturnProperty with - | NoRet | ConditionalNoRet _ -> true - | _ -> false - | None -> false - else false) - - let removeFallThroughAndRetFromConfirmedBlocks ssaCFG norets = - norets - |> Set.fold (fun ssaCFG (caller, _) -> - let ftNode = - DiGraph.getSuccs ssaCFG caller - |> List.find (fun w -> - DiGraph.findEdgeData ssaCFG caller w = CallFallThroughEdge) - let fakeNode = - DiGraph.getSuccs ssaCFG caller - |> List.find (fun w -> DiGraph.findEdgeData ssaCFG caller w = CallEdge) - DiGraph.getPreds ssaCFG ftNode - |> List.fold (fun acc u -> - match DiGraph.findEdgeData ssaCFG u ftNode with - | CallFallThroughEdge when u = caller -> (u, ftNode) :: acc - | RetEdge when u = fakeNode -> (u, ftNode) :: acc - | _ -> acc) [] - |> List.fold (fun ssaCFG (v, w) -> DiGraph.removeEdge ssaCFG v w) ssaCFG - ) ssaCFG - - let trimSSACFG ssaCFG ssaRoot norets = - let ssaCFG = removeFallThroughAndRetFromConfirmedBlocks ssaCFG norets - let reachables = - Set.empty - |> Traversal.foldPostorder ssaCFG [ssaRoot] (fun acc v -> Set.add v acc) - let allVertices = DiGraph.getVertices ssaCFG - Set.difference allVertices reachables - |> Set.fold (fun ssaCFG v -> DiGraph.removeVertex ssaCFG v) ssaCFG - - let updateProperty codeMgr (func: RegularFunction) norets = - let cond = - norets - |> Set.fold (fun acc (_, arg) -> Set.add arg acc) Set.empty - if Set.count cond = 1 then - let cond = Set.minElement cond - func.NoReturnProperty <- ConditionalNoRet cond - elif Set.count cond = 0 then - (* We potentially had a wrong decision, so perform the basic analysis - again. *) - performBasicNoRetAnalysis codeMgr func - else Utils.futureFeature () (* This is an interesting case. *) - - /// Since we cannot decide by simply looking at call instructions, we now - /// perform a data-flow analysis on the function's parameters to know if one - /// of the parameters defines the input of the conditionally no-returning - /// function's parameter. - let performParamAnalysis hdl codeMgr (fn: RegularFunction) = - let ssaCFG, ssaRoot = fn.GetSSACFG hdl - let uvp = UntouchedValuePropagation (hdl, ssaCFG) - let uvState = uvp.Compute ssaRoot - let norets = getConfirmedNoRets hdl codeMgr fn ssaCFG uvState - let ssaCFG' = trimSSACFG ssaCFG ssaRoot norets - if isConditionalNoret codeMgr ssaCFG' then updateProperty codeMgr fn norets - else fn.NoReturnProperty <- NotNoRetConfirmed - - let hasNonZeroOnX86 st arg = - let esp = (Intel.Register.ESP |> Intel.Register.toRegID) - match readReg st esp with - | Some sp -> - let p = BitVector.add (BitVector.ofInt32 (4 * arg) 32) sp - match readMem st p Endian.Little 32 with - | Some v -> v <> 0UL - | None -> false - | None -> false - - let hasNonZeroOnX64 hdl st arg = - let reg = CallingConvention.functionArgRegister hdl arg - match readReg st reg with - | Some bv -> BitVector.toUInt64 bv <> 0UL - | None -> false - -/// NoReturnFunctionIdentification has two roles: (1) identify whether a -/// function is non-returning or not, and (2) add return and fall-through edges -/// if callee function is non-returning. -type NoReturnFunctionIdentification () = - inherit PerFunctionAnalysis () - - override __.Name = "NoReturnFunctionIdentification" - - override __.Run hdl codeMgr _dataMgr func evts = -#if CFGDEBUG - dbglog "NoRetAnalysis" "@%x before: %A" func.Entry func.NoReturnProperty -#endif - match func.NoReturnProperty with - | UnknownNoRet -> performBasicNoRetAnalysis codeMgr func - | NotNoRet when isPotentiallyNonTrivialConditionalNoRet codeMgr func -> - performParamAnalysis hdl codeMgr func - | _ -> () -#if CFGDEBUG - dbglog "NoRetAnalysis" "@%x after: %A" func.Entry func.NoReturnProperty -#endif - Ok evts - - /// Check whether the (nth) argument is always non-zero. This is used only for - /// known error functions, which can conditionally become a no-ret function - /// depending on the given argument value. - member __.HasNonZeroArg hdl caller nth = - let st = evalBlock hdl caller - match hdl.ISA.Arch with - | Arch.IntelX86 -> hasNonZeroOnX86 st nth - | Arch.IntelX64 -> hasNonZeroOnX64 hdl st nth - | _ -> Utils.futureFeature () - - /// Check whether the given bbl has a no-return syscall (e.g., exit). - member __.IsNoRetSyscallBlk hdl bbl = - let st = evalBlock hdl bbl - match hdl.FileInfo.FileFormat with - | FileFormat.ELFBinary | FileFormat.RawBinary -> - let arch = hdl.ISA.Arch - let exitSyscall = LinuxSyscall.toNumber arch LinuxSyscall.Exit - let exitGrpSyscall = LinuxSyscall.toNumber arch LinuxSyscall.ExitGroup - let reg = CallingConvention.returnRegister hdl - match readReg st reg with - | None -> false - | Some v -> - let n = BitVector.toInt32 v - n = exitSyscall || n = exitGrpSyscall - | _ -> false diff --git a/src/MiddleEnd/ControlFlowAnalysis/PerFunctionAnalysis.fs b/src/MiddleEnd/ControlFlowAnalysis/PerFunctionAnalysis.fs deleted file mode 100644 index cfd8d37f..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/PerFunctionAnalysis.fs +++ /dev/null @@ -1,63 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.DataFlow -open B2R2.MiddleEnd.ControlFlowAnalysis - -/// PerFunctionAnalysis implements a core CFG-recovery algorithm, which modifies -/// a function-level CFG by analyzing the function. Though it works per -/// function, It can modify other functions (thus, the entire CFGInfo). An -/// analysis appends CFGEvents to modify function, but it can also modify the -/// function directly. -[] -type PerFunctionAnalysis () = - - /// Name of the analysis. This is for debugging. - abstract Name: string - - /// Run the analysis. - abstract Run: - BinHandle - -> CodeManager - -> DataManager - -> RegularFunction - -> CFGEvents - -> Result - -/// Helper module for per-function analyses. -[] -module PerFunctionAnalysis = - - /// Run constant propagation on the function. - let runCP hdl (func: RegularFunction) reader = - let ssaCFG, ssaRoot = func.GetSSACFG hdl - let cp = - match reader with - | Some reader -> SparseConstantPropagation (hdl, ssaCFG, reader) - | None -> SparseConstantPropagation (hdl, ssaCFG) - let cpState = cp.Compute ssaRoot - struct (cpState, ssaCFG) diff --git a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/ConditionRetriever.fs b/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/ConditionRetriever.fs deleted file mode 100644 index e10dfb35..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/ConditionRetriever.fs +++ /dev/null @@ -1,217 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.MiddleEnd.ControlFlowGraph - -(* -/// How do we compare vars? For example, in x86, there are two comparison -/// instructions: CMP vs. TEST. -type ComparisonKind = - | CompareAfterSubtract - | CompareAfterAnd - -/// Intermediate information about a comparison instruction. -type IntermediateComparisonInfo = ComparisonKind * Expr * BitVector - -/// Final information about a comparison instruction. -type ComparisonInfo = RelOpType * Expr * BitVector - -/// Retrieve a high-level condition from a given condition expression pattern. -[] -type ConditionRetriever () = - /// Find the corresponding comparison instruction from the given variable, and - /// return its operands. - abstract member FindComparison: - BinEssence - -> SSAVertex - -> Variable - -> IntermediateComparisonInfo option - - /// Pattern 1: CF (or ZF). - abstract member RetrievePattern1: - Variable -> IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 2: (CF | ZF). - abstract member RetrievePattern2: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 3: (ZF | (OF <> SF)). - abstract member RetrievePattern3: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 4: (OF <> SF). - abstract member RetrievePattern4: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 5: ((not ZF) & (OF = SF)). (negation of pattern 3) - abstract member RetrievePattern5: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Pattern 6: (OF = SF). (negation of pattern 4) - abstract member RetrievePattern6: - IntermediateComparisonInfo -> ComparisonInfo option - - /// Find an address where myVar is defined. - member __.FindAddr myVar addr stmts = - match stmts with - | (_, Def (v, _)) :: _ when myVar = v -> addr - | (_, Def (v, Num bv)) :: stmts -> - if Variable.IsPC v then - __.FindAddr myVar (BitVector.toUInt64 bv) stmts - else - __.FindAddr myVar addr stmts - | _ :: stmts -> __.FindAddr myVar addr stmts - | [] -> addr - - /// Retrieve a condition based on the patterns defined in WYSINWYX: What You - /// See Is Not What You eXecute p. 24. - member __.Retrieve app vertex condExpr = - match condExpr with - | RelOp (RelOpType.EQ, 1, e, Num bv) -> - let n = BitVector.toUInt64 bv - if n = 0UL then - __.Retrieve app vertex e - |> Option.bind ConditionRetriever.Negate - elif n = 1UL then __.Retrieve app vertex e - else Utils.impossible () - | Var v -> - __.FindComparison app vertex v |> Option.bind (__.RetrievePattern1 v) - | BinOp (BinOpType.OR, 1, Var v, Var _) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern2 - | BinOp (BinOpType.OR, 1, Var v, - RelOp (RelOpType.NEQ, _, Var _, Var _)) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern3 - | RelOp (RelOpType.NEQ, 1, Var v, Var _) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern4 - | BinOp (BinOpType.AND, 1, RelOp (RelOpType.EQ, _, Var v, Num bv), - RelOp (RelOpType.EQ, _, Var _, Var _)) -> - if BitVector.toUInt64 bv = 0UL then - __.FindComparison app vertex v |> Option.bind __.RetrievePattern5 - else Utils.impossible () - | RelOp (RelOpType.EQ, 1, Var v, Var _) -> - __.FindComparison app vertex v |> Option.bind __.RetrievePattern6 - | _ -> None - - static member Negate = function - | (RelOpType.EQ, v, bv) -> Some (RelOpType.NEQ, v, bv) - | (RelOpType.NEQ, v, bv) -> Some (RelOpType.EQ, v, bv) - | (RelOpType.GT, v, bv) -> Some (RelOpType.LE, v, bv) - | (RelOpType.GE, v, bv) -> Some (RelOpType.LT, v, bv) - | (RelOpType.SGT, v, bv) -> Some (RelOpType.SLE, v, bv) - | (RelOpType.SGE, v, bv) -> Some (RelOpType.SLT, v, bv) - | (RelOpType.LT, v, bv) -> Some (RelOpType.GE, v, bv) - | (RelOpType.LE, v, bv) -> Some (RelOpType.GT, v, bv) - | (RelOpType.SLT, v, bv) -> Some (RelOpType.SGE, v, bv) - | (RelOpType.SLE, v, bv) -> Some (RelOpType.SGT, v, bv) - | _ -> None - - static member Init (isa: ISA) = - match isa.Arch with - | Arch.IntelX86 - | Arch.IntelX64 -> IntelConditionRetriever () :> ConditionRetriever - | _ -> DefaultRetriever () :> ConditionRetriever - -and DefaultRetriever () = - inherit ConditionRetriever () - override __.FindComparison _ _ _ = None - override __.RetrievePattern1 _ _ = None - override __.RetrievePattern2 _ = None - override __.RetrievePattern3 _ = None - override __.RetrievePattern4 _ = None - override __.RetrievePattern5 _ = None - override __.RetrievePattern6 _ = None - -and IntelConditionRetriever () = - inherit ConditionRetriever () - - /// XXX: Two operands used to compare are first two expressions appeared at - /// specific address - let rec findTwoOperands addr isTarget first = function - | (_, Def (v, Num bv)) :: stmts -> - (* The second operand should be bitvector *) - if isTarget && Option.isSome first then Option.get first, bv - elif Variable.IsPC v then - let addr_ = BitVector.toUInt64 bv - findTwoOperands addr (addr = addr_) first stmts - else findTwoOperands addr isTarget first stmts - | (_, Def (_, e)) :: stmts -> - (* We are at a right address, but none of operands are found until now *) - if isTarget && Option.isNone first then - findTwoOperands addr isTarget (Some e) stmts - else findTwoOperands addr isTarget first stmts - | _ :: stmts -> findTwoOperands addr isTarget first stmts - | [] -> Utils.impossible () - - override __.FindComparison ess v condVar = - let ppoint = v.VData.PPoint - let stmts = Array.toList v.VData.SSAStmtInfos - let addr = __.FindAddr condVar ppoint.Address stmts - let ins = ess.InstrManager[addr].Instruction :?> Intel.IntelInternalInstruction - match ins.Opcode, ins.Operands with - | Intel.Opcode.CMP, Intel.TwoOperands (Intel.OprMem _, Intel.OprImm _) - | Intel.Opcode.CMP, Intel.TwoOperands (Intel.OprReg _, Intel.OprImm _) - | Intel.Opcode.SUB, Intel.TwoOperands (Intel.OprMem _, Intel.OprImm _) - | Intel.Opcode.SUB, Intel.TwoOperands (Intel.OprReg _, Intel.OprImm _) -> - let oprnd1, oprnd2 = - findTwoOperands addr (ppoint.Address = addr) None stmts - Some (CompareAfterSubtract, oprnd1, oprnd2) - | _ -> None - - override __.RetrievePattern1 v info = - match v.Kind, info with - | RegVar (_, rid, _), (CompareAfterSubtract, e, bv) -> - if rid = Intel.Register.toRegID Intel.Register.CF then - Some (RelOpType.SLT, e, bv) - elif rid = Intel.Register.toRegID Intel.Register.ZF then - Some (RelOpType.EQ, e, bv) - else None - | _, _ -> None - - override __.RetrievePattern2 info = - match info with - | CompareAfterSubtract, e, bv -> Some (RelOpType.LE, e, bv) - | _ -> None - - override __.RetrievePattern3 info = - match info with - | CompareAfterSubtract, e, bv -> Some (RelOpType.SLE, e, bv) - | _ -> None - - override __.RetrievePattern4 info = - match info with - | CompareAfterSubtract, e, bv -> Some (RelOpType.SLT, e, bv) - | _ -> None - - override __.RetrievePattern5 info = - __.RetrievePattern3 info |> Option.bind ConditionRetriever.Negate - - override __.RetrievePattern6 info = - __.RetrievePattern4 info |> Option.bind ConditionRetriever.Negate -*) diff --git a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/EVMCodeCopyAnalysis.fs b/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/EVMCodeCopyAnalysis.fs deleted file mode 100644 index c2190727..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/EVMCodeCopyAnalysis.fs +++ /dev/null @@ -1,82 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowAnalysis -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.DataFlow - -type EVMCodeCopyAnalysis () = - let accumulateCodeCopyInfo (cpState: CPState) (stmt: SSA.Stmt) acc = - match stmt with - | SideEffect (ExternalCall ( - BinOp (BinOpType.APP, _, FuncName "codecopy", - BinOp (BinOpType.CONS, _, tmpVarDst, - BinOp (BinOpType.CONS, _, tmpVarSrc, - BinOp (BinOpType.CONS, _, tmpVarLen, _))))), _, _) -> - let dst = tmpVarDst |> IRHelper.tryResolveExprToUInt64 cpState - let src = tmpVarSrc |> IRHelper.tryResolveExprToUInt64 cpState - let len = tmpVarLen |> IRHelper.tryResolveExprToUInt64 cpState - (dst, src, len) :: acc - | _ -> acc - - let rec pickValidCopyInfo hdl = function - | (Some 0UL, Some src, Some len) :: restCopyInfos -> - let bin = hdl.FileInfo.Span.ToArray () - let binLen = uint64 bin.Length - let srcStart = src - let srcEnd = src + len - 1UL - if srcEnd < binLen then - let codeArea = bin[ int (srcStart) .. int (srcEnd) ] - let newHdl = BinHandle.Init (hdl.ISA, codeArea) - PluggableAnalysisNewBinary newHdl - else pickValidCopyInfo hdl restCopyInfos - | _ :: restCopyInfos -> pickValidCopyInfo hdl restCopyInfos - | _ -> failwith "Failed to find codecopy" - - let recoverCopiedCode hdl codeMgr = - (codeMgr: CodeManager).FunctionMaintainer.RegularFunctions - |> Seq.fold (fun acc fn -> - let struct (cpState, ssaCFG) = PerFunctionAnalysis.runCP hdl fn None - DiGraph.foldVertex ssaCFG (fun acc v -> - v.VData.SSAStmtInfos - |> Array.fold (fun acc (_, stmt) -> - accumulateCodeCopyInfo cpState stmt acc - ) acc - ) acc) [] - |> pickValidCopyInfo hdl - - interface IPluggableAnalysis with - - member __.Name = "EVM Code Copy Analysis" - - member __.Run _builder hdl codeMgr _dataMgr = - match hdl.FileInfo.ISA.Arch with - | Architecture.EVM -> recoverCopiedCode hdl codeMgr - | _ -> PluggableAnalysisOk diff --git a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/EVMTrampolineAnalysis.fs b/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/EVMTrampolineAnalysis.fs deleted file mode 100644 index f7d09c96..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/EVMTrampolineAnalysis.fs +++ /dev/null @@ -1,126 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open FSharp.Data -open FSharp.Data.JsonExtensions -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinGraph - -[] -module private EVMTrampolineAnalysis = - let computeKeccak256 (keccak: SHA3Core.Keccak.Keccak) (str: string) = - let hashStr = (keccak.Hash str)[ 0 .. 7 ] - System.UInt32.Parse (hashStr, System.Globalization.NumberStyles.HexNumber) - - // Parse function information and update signature to name mapping. - let parseFunc keccak accMap (funcJson: JsonValue) = - let name = funcJson?name.AsString () - let argTypes = [ for v in funcJson?inputs -> v?``type``.AsString () ] - let argStr = String.concat "," argTypes - let signature = sprintf "%s(%s)" name argStr |> computeKeccak256 keccak - Map.add signature name accMap - - // Returns a mapping from a function signature to its name. - let parseABI abiFile = - let keccak = SHA3Core.Keccak.Keccak (SHA3Core.Enums.KeccakBitType.K256) - let abiStr = System.IO.File.ReadAllText (abiFile) - let abiJson = JsonValue.Parse (abiStr) - let isFunc (json: JsonValue) = json?``type``.AsString () = "function" - let funcJsons = [ for v in abiJson -> v ] |> List.filter isFunc - List.fold (parseFunc keccak) Map.empty funcJsons - - let tryGetTrampolineInfo cpState = function - (* It's based on heuristics. *) - | SSA.Jmp (SSA.InterCJmp (cond, tExpr, _)) -> - let cond = cond |> IRHelper.resolveExpr cpState true - let tAddr = tExpr |> IRHelper.tryResolveExprToUInt64 cpState - match cond, tAddr with - | SSA.RelOp (RelOpType.EQ, _, v1, v2), Some tAddr -> - let v1 = v1 |> IRHelper.tryResolveExprToUInt32 cpState - let v2 = v2 |> IRHelper.tryResolveExprToUInt32 cpState - match v1, v2 with - (* One is variable, and the other one is a constant which represents a - signature of a function. Note that it's common for constants to come - first while EVM handles function signatures. *) - | Some v, None -> - let sign = v - let addr = tAddr - Some (sign, addr) - | _ -> None - | _ -> None - | _ -> None - - // Iterate trampolines in the entry function. - let iterateTrampoline hdl codeMgr fn = - let entryOffset = 0UL - (codeMgr: CodeManager).FunctionMaintainer.TryFindRegular entryOffset - |> function - | Some func -> - let struct (cpState, ssaCFG) = PerFunctionAnalysis.runCP hdl func None - DiGraph.iterVertex ssaCFG (fun v -> - Array.iter (fun (_, stmt) -> - match tryGetTrampolineInfo cpState stmt with - | Some (sign, addr) -> fn sign addr - | _ -> ()) v.VData.SSAStmtInfos) - | _ -> failwith "Could not find its entry function at 0x0" - -type EVMTrampolineAnalysis (abiFile) = - member private __.MakeSymbol name addr = - { Address = addr - Name = name - Kind = SymFunctionType - Target = TargetKind.StaticSymbol - LibraryName = "" - ArchOperationMode = ArchOperationMode.NoMode } - - member private __.UpdateSymbols (fi: FileInfo) addr name = - fi.AddSymbol addr (__.MakeSymbol name addr) - - member private __.AnalyzeTrampoline hdl codeMgr = - let bytes = hdl.FileInfo.Span.ToArray () - let isa = hdl.FileInfo.ISA - let newHdl = BinHandle.Init (isa, bytes) - let newFi = newHdl.FileInfo - let sigToName = if abiFile <> "" then parseABI abiFile else Map.empty - let fn sign addr = - let name = - match Map.tryFind sign sigToName with - | Some name -> name - | _ -> sprintf "func_%x" addr - __.UpdateSymbols newFi addr name - iterateTrampoline hdl codeMgr fn - PluggableAnalysisNewBinary newHdl - - interface IPluggableAnalysis with - member __.Name = "EVM Trampoline Analysis" - - member __.Run _builder hdl codeMgr _dataMgr = - match hdl.FileInfo.ISA.Arch with - | Architecture.EVM -> __.AnalyzeTrampoline hdl codeMgr - | _ -> PluggableAnalysisOk diff --git a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/LibcAnalysis.fs b/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/LibcAnalysis.fs deleted file mode 100644 index 64793f91..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/LibcAnalysis.fs +++ /dev/null @@ -1,136 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ConcEval -open B2R2.MiddleEnd.ControlFlowAnalysis.EvalHelper - -module private LibcAnalysisHelper = - let retrieveAddrsForx86 (builder: CFGBuilder) codeMgr st = - let esp = (Intel.Register.ESP |> Intel.Register.toRegID) - match (st: EvalState).TryGetReg esp with - | Def sp -> - let p1 = BitVector.add (BitVector.ofInt32 4 32) sp - let p4 = BitVector.add (BitVector.ofInt32 16 32) sp - let p5 = BitVector.add (BitVector.ofInt32 20 32) sp - let p6 = BitVector.add (BitVector.ofInt32 24 32) sp - [ readMem st p1 Endian.Little 32 - readMem st p4 Endian.Little 32 - readMem st p5 Endian.Little 32 - readMem st p6 Endian.Little 32 ] - |> List.choose id - |> List.filter (fun addr -> - addr <> 0UL && ((codeMgr: CodeManager).HasInstruction addr |> not)) - |> function - | [] -> false - | addrs -> - let mode = ArchOperationMode.NoMode - let entries = addrs |> List.map (fun addr -> addr, mode) - match builder.AddNewFunctions entries with - | Ok () -> true - | _ -> Utils.impossible () - | Undef -> false - - let retrieveAddrsForx64 (builder: CFGBuilder) codeMgr st = - [ readReg st (Intel.Register.RDI |> Intel.Register.toRegID) - readReg st (Intel.Register.RCX |> Intel.Register.toRegID) - readReg st (Intel.Register.R8 |> Intel.Register.toRegID) - readReg st (Intel.Register.R9 |> Intel.Register.toRegID) ] - |> List.choose id - |> List.map BitVector.toUInt64 - |> List.filter (fun addr -> - addr <> 0UL && ((codeMgr: CodeManager).HasInstruction addr |> not)) - |> function - | [] -> false - | addrs -> - let mode = ArchOperationMode.NoMode - let entries = addrs |> List.map (fun addr -> addr, mode) - match builder.AddNewFunctions entries with - | Ok () -> true - | _ -> Utils.impossible () - - let retrieveLibcStartAddresses builder hdl codeMgr = function - | None -> false - | Some st -> - match hdl.ISA.Arch with - | Arch.IntelX86 -> retrieveAddrsForx86 builder codeMgr st - | Arch.IntelX64 -> retrieveAddrsForx64 builder codeMgr st - | _ -> false - - let tryFindFunction (codeMgr: CodeManager) entry = - match codeMgr.TryGetBBL entry with - | Some bblInfo -> - if bblInfo.FunctionEntry = entry then - codeMgr.FunctionMaintainer.TryFindRegular entry - else None - | None -> None - - let analyzeLibcStartMain builder hdl codeMgr entry callSite = - match tryFindFunction codeMgr entry with - | None -> false - | Some fn -> - evalFunctionUntilStopFn hdl fn - (fun blk -> blk.VData.Range.IsIncluding callSite) - |> retrieveLibcStartAddresses builder hdl codeMgr - - let recoverAddrsFromLibcStartMain builder hdl (codeMgr: CodeManager) = - match codeMgr.FunctionMaintainer.TryFind "__libc_start_main" with - | Some func when func.FunctionKind = FunctionKind.External -> - let _, trampoline = (func :?> ExternalFunction).TrampolineAddr () - let isLibcStartMain addr = addr = func.Entry || addr = trampoline - match List.tryExactlyOne <| Seq.toList func.Callers with - | None -> false - | Some caller -> - let start = codeMgr.FunctionMaintainer.FindRegular (addr=caller) - let callSite = - start.CallEdges - |> Array.find (fun (_, callee) -> - match callee with - | RegularCallee target -> isLibcStartMain target - | IndirectCallees addrs -> Set.exists isLibcStartMain addrs - | UnresolvedIndirectCallees (_) | NullCallee -> false) - |> fst - analyzeLibcStartMain builder hdl codeMgr start.Entry callSite - | _ -> false - |> function - | true -> PluggableAnalysisOk - | false -> PluggableAnalysisError - - let recoverLibcEntries builder hdl codeMgr = - match hdl.FileInfo.FileFormat with - | FileFormat.ELFBinary -> - recoverAddrsFromLibcStartMain builder hdl codeMgr - | _ -> PluggableAnalysisError - -type LibcAnalysis () = - interface IPluggableAnalysis with - - member __.Name = "LibC Analysis" - - member __.Run builder hdl codeMgr _dataMgr = - LibcAnalysisHelper.recoverLibcEntries builder hdl codeMgr diff --git a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/SpeculativeGapCompletion.fs b/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/SpeculativeGapCompletion.fs deleted file mode 100644 index 9eb856b0..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/PluggableAnalyses/SpeculativeGapCompletion.fs +++ /dev/null @@ -1,113 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowAnalysis - -open B2R2 - -module private SpeculativeGapCompletionHelper = - (* - /// XXX: Should be fixed - let findGaps (ess: BinEssence) sAddr eAddr = - ess.CodeManager.Keys - |> Seq.filter (fun addr -> addr >= sAddr && addr < eAddr) - |> Seq.sort - |> Seq.fold (fun (gaps, prevAddr) addr -> - let nextAddr = - addr + uint64 ess.CodeManager[addr].Instruction.Length - if prevAddr >= addr then gaps, nextAddr - else AddrRange (prevAddr, addr) :: gaps, nextAddr - ) ([], sAddr) - |> fun (gaps, nextAddr) -> - if nextAddr >= eAddr then gaps - else AddrRange (nextAddr, eAddr) :: gaps - - let rec shiftUntilValid ess entries (gap: AddrRange) = - let entry = [ gap.Min, ess.BinHandle.Parser.OperationMode ] - match BinEssence.initByEntries ess.BinHandle entry with - | Ok _ -> AddrRange (gap.Min, gap.Max) :: entries - | Error _ -> - if gap.Min + 1UL = gap.Max then entries - else - let gap' = AddrRange (gap.Min + 1UL, gap.Max) - shiftUntilValid ess entries gap' - - let shiftByOne entries (gap: AddrRange) = - let nextAddr = gap.Min + 1UL - if gap.Max <= nextAddr then entries - else AddrRange (nextAddr, gap.Max) :: entries - - let shiftGaps fn gaps = - gaps |> List.fold fn [] - - let updateResults branchRecovery ess ess' = - let mode = ess'.BinHandle.Parser.OperationMode - let entries = - ess'.CalleeMap.Entries |> Set.toList |> List.map (fun a -> a, mode) - match BinEssence.addEntries ess entries with - | Ok ess -> - { ess with IndirectBranchMap = ess'.IndirectBranchMap } - |> (branchRecovery: BranchRecovery).CalculateTable - | Error _ -> ess - - let rec recoverGaps branchRecovery ess gaps = - match shiftGaps (shiftUntilValid ess) gaps with - | [] -> ess - | gaps -> - let mode = ess.BinHandle.Parser.OperationMode - let ents = gaps |> List.map (fun g -> g.Min, mode) - match BinEssence.initByEntries ess.BinHandle ents with - | Ok partial -> - let isTarget addr = - ess.IndirectBranchMap - |> Map.exists (fun _ { HostFunctionAddr = entry } -> entry = addr) - |> not - let ess = - isTarget - |> (branchRecovery: BranchRecovery).RunWith partial - |> updateResults branchRecovery ess - gaps - |> List.map (fun gap -> findGaps ess gap.Min gap.Max) - |> List.concat - |> recoverGaps branchRecovery ess - | Error _ -> - recoverGaps branchRecovery ess (shiftGaps shiftByOne gaps) - - let run branchRecovery ess = - ess.BinHandle.FileInfo.GetTextSections () - |> Seq.map (fun sec -> - let sAddr, eAddr = sec.Address, sec.Address + sec.Size - findGaps ess sAddr eAddr) - |> List.concat - |> recoverGaps branchRecovery ess - *) - let run hdl codeMgr dataMgr = false - -type SpeculativeGapCompletion () = - interface IPluggableAnalysis with - - member __.Name = "Speculative Gap Completion" - - member __.Run _builder hdl codeMgr dataMgr = - PluggableAnalysisOk // SpeculativeGapCompletionHelper.run hdl codeMgr dataMgr diff --git a/src/MiddleEnd/ControlFlowAnalysis/SSAPromotion.fs b/src/MiddleEnd/ControlFlowAnalysis/SSAPromotion.fs deleted file mode 100644 index 3b00aeec..00000000 --- a/src/MiddleEnd/ControlFlowAnalysis/SSAPromotion.fs +++ /dev/null @@ -1,127 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -[] -module B2R2.MiddleEnd.ControlFlowAnalysis.SSAPromotion - -open System.Collections.Generic -open B2R2 -open B2R2.FrontEnd.BinInterface -open B2R2.BinIR.SSA -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.MiddleEnd.DataFlow - -let private extractStackVar stmt = - match stmt with - | Def (v, _) -> v - | _ -> Utils.impossible () - -let private findLastStackDef v targetVarKind = - SSACFG.findReachingDef v targetVarKind - |> Option.map extractStackVar - -let private updateIfStackValueIsConstant (v: Vertex) spState sp = - match CPState.findReg spState sp with - | SPValue.Const bv -> - let spValue = BitVector.toUInt64 bv - let offset = Utils.InitialStackPointer - spValue |> int |> Some - v.VData.FakeBlockInfo <- - { v.VData.FakeBlockInfo with FrameDistance = offset } - | _ -> () - -/// If the vertex is fake, it means the vertex represents a function. We check -/// if the function's stack frame (activation record) is located at a constant -/// stack offset. If so, we remember the offset. -let private updateStackFrameDistance hdl g (v: Vertex) spState = - match hdl.RegisterBay.StackPointer with - | Some rid -> - let spName = hdl.RegisterBay.RegIDToString rid - let spRegKind = RegVar (hdl.ISA.WordSize |> WordSize.toRegType, rid, spName) - match findLastStackDef v spRegKind with - | Some sp -> updateIfStackValueIsConstant v spState sp - | None -> () - | None -> () - -let private memStore ((pp, _) as stmtInfo) rt addr src = - match addr with - | SPValue.Const addr -> - let addr = BitVector.toUInt64 addr - let offset = int (int64 Utils.InitialStackPointer - int64 addr) - let v = { Kind = StackVar (rt, offset); Identifier = 0 } - Some (pp, Def (v, src)) - | _ -> Some stmtInfo - -let private loadToVar rt addr = - match addr with - | SPValue.Const addr -> - let addr = BitVector.toUInt64 addr - let offset = int (int64 Utils.InitialStackPointer - int64 addr) - let v = { Kind = StackVar (rt, offset); Identifier = 0 } - Some (Var v) - | _ -> None - -let rec private replaceLoad spState v e = - match e with - | Load (_, rt, addr) -> - let addr = SPTransfer.evalExpr spState v addr - loadToVar rt addr - | Cast (ck, rt, e) -> - replaceLoad spState v e - |> Option.map (fun e -> Cast (ck, rt, e)) - | Extract (e, rt, sPos) -> - replaceLoad spState v e - |> Option.map (fun e -> Extract (e, rt, sPos)) - | _ -> None - -let private stmtChooser spState v ((pp, stmt) as stmtInfo) = - match stmt with - | Phi (_, _) -> None - | Def ({ Kind = MemVar }, Store (_, rt, addr, src)) -> - let addr = SPTransfer.evalExpr spState v addr - memStore stmtInfo rt addr src - | Def (dstVar, e) -> - match replaceLoad spState v e with - | Some e -> Some (pp, Def (dstVar, e)) - | None -> Some stmtInfo - | _ -> Some stmtInfo - -/// The basic preparation step: remove Phis and replace stack variables. -let prepare hdl ssaCFG spState vertices (v: Vertex) = - (vertices: List).Add v - if v.VData.IsFakeBlock () then updateStackFrameDistance hdl ssaCFG v spState - else () - v.VData.SSAStmtInfos - |> Array.choose (stmtChooser spState v) - |> fun stmts -> v.VData.SSAStmtInfos <- stmts - -/// Promote the given SSA CFG into another SSA CFG that contains resolved -/// stack/global variables. -let promote hdl (ssaCFG: DiGraph) ssaRoot = - let spp = StackPointerPropagation (hdl, ssaCFG) - let spState = spp.Compute ssaRoot - let vertices = List () - DiGraph.iterVertex ssaCFG (prepare hdl ssaCFG spState vertices) - SSACFG.installPhis vertices ssaCFG ssaRoot - struct (ssaCFG, ssaRoot) diff --git a/src/MiddleEnd/ControlFlowGraph/B2R2.MiddleEnd.ControlFlowGraph.fsproj b/src/MiddleEnd/ControlFlowGraph/B2R2.MiddleEnd.ControlFlowGraph.fsproj deleted file mode 100644 index 1a3a106d..00000000 --- a/src/MiddleEnd/ControlFlowGraph/B2R2.MiddleEnd.ControlFlowGraph.fsproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - LICENSE.md - b2r2-240x240.png - README.md - B2R2 CFG library. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/ControlFlowGraph/BasicBlock.fs b/src/MiddleEnd/ControlFlowGraph/BasicBlock.fs deleted file mode 100644 index 468f52f3..00000000 --- a/src/MiddleEnd/ControlFlowGraph/BasicBlock.fs +++ /dev/null @@ -1,46 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.MiddleEnd.BinGraph - -/// The base type for basic block. -[] -type BasicBlock (pp: ProgramPoint) = - inherit VertexData (VertexData.genID ()) - - /// The start position (ProgramPoint) of the basic block. - member __.PPoint with get() = pp - - /// The instruction address range of the basic block. - abstract Range: AddrRange with get - - /// Check if this is a fake basic block inserted by our analysis. We create a - /// fake block to represent call target vertices in a function-level CFG. - abstract IsFakeBlock: unit -> bool - - /// Convert this basic block to a visual representation. - abstract ToVisualBlock: unit -> VisualBlock diff --git a/src/MiddleEnd/ControlFlowGraph/CFGEdgeKind.fs b/src/MiddleEnd/ControlFlowGraph/CFGEdgeKind.fs deleted file mode 100644 index f17189da..00000000 --- a/src/MiddleEnd/ControlFlowGraph/CFGEdgeKind.fs +++ /dev/null @@ -1,104 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -/// TODO: Make DU types for Call, Jmp, FallThrough edges -/// We distinguish edges of a CFG by classifying them into several kinds. -type CFGEdgeKind = - /// An edge of a direct jump, e.g., JMP +0x42. - | InterJmpEdge - /// An edge of a conditional jump that is exercised when the condition is - /// true. - | InterCJmpTrueEdge - /// An edge of a conditional jump that is exercised when the condition is - /// false. - | InterCJmpFalseEdge - /// A direct jump edge only visible from an IR-level CFG, because there is a - /// control-flow inside a machine instruction. - | IntraJmpEdge - /// A true conditional edge only visible from an IR-level CFG, because there - /// is a control-flow inside a machine instruction. - | IntraCJmpTrueEdge - /// A false conditional edge only visible from an IR-level CFG, because there - /// is a control-flow inside a machine instruction. - | IntraCJmpFalseEdge - /// An edge of a regular call instruction. - | CallEdge - /// An edge of a recursive call instruction. - | RecursiveCallEdge - /// An edge from an indirect jmp instruction. - | IndirectJmpEdge - /// An edge from an indirect call instruction. - | IndirectCallEdge - /// An edge of a jmp instruction to an external function or PLT. - | ExternalJmpEdge - /// An edge of a call instruction to an external function or PLT. - | ExternalCallEdge - /// An edge of a function return. - | RetEdge - /// A simple fall-through case. This type is created when an edge cuts in two - /// consecutive instructions. - | FallThroughEdge - /// A fall-through after a call instruction. This is indeed a pseudo edge from - /// a caller block to its fall-through block as there is no direct control - /// flow between them. - | CallFallThroughEdge - /// A fall-through after a no return call instruction. This edge will never be - /// executed. We have this edge to include all "codes" compiler emitted. If we - /// do not consider such "unreachable" codes from CFG building, we'll never - /// see this edge in the result CFG. - | NoReturnFallThroughEdge - /// A fall-through representing C++ exception flows. If there is a function - /// call which causes raising exceptions, then this edge will be used. - | ExceptionFallThroughEdge - /// An implicit edge that is not explicitly visible from the current CALL - /// instruction, but visible within the function. If there is a path in the - /// callee that calls a function, then we create an implicit edge from a - /// caller to any of the callees. - | ImplicitCallEdge - /// Unknown edge type. This should be an error case. - | UnknownEdge - -module CFGEdgeKind = - let toString = function - | InterJmpEdge -> "InterJmpEdge" - | InterCJmpTrueEdge -> "InterCJmpTrueEdge" - | InterCJmpFalseEdge -> "InterCJmpFalseEdge" - | IntraJmpEdge -> "IntraJmpEdge" - | IntraCJmpTrueEdge -> "IntraCJmpTrueEdge" - | IntraCJmpFalseEdge -> "IntraCJmpFalseEdge" - | CallEdge -> "CallEdge" - | RecursiveCallEdge -> "RecursiveCallEdge" - | IndirectJmpEdge -> "IndirectJmpEdge" - | IndirectCallEdge -> "IndirectCallEdge" - | ExternalJmpEdge -> "ExternalJmpEdge" - | ExternalCallEdge -> "ExternalCallEdge" - | RetEdge -> "RetEdge" - | FallThroughEdge -> "FallThroughEdge" - | CallFallThroughEdge -> "CallFallThroughEdge" - | NoReturnFallThroughEdge -> "NoReturnFallThroughEdge" - | ExceptionFallThroughEdge -> "ExceptionFallThroughEdge" - | ImplicitCallEdge -> "ImplicitCallEdge" - | UnknownEdge -> "UnknownEdge" diff --git a/src/MiddleEnd/ControlFlowGraph/CFGExport.fs b/src/MiddleEnd/ControlFlowGraph/CFGExport.fs deleted file mode 100644 index 4bab6f7e..00000000 --- a/src/MiddleEnd/ControlFlowGraph/CFGExport.fs +++ /dev/null @@ -1,74 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.ControlFlowGraph.CFGExport - -open B2R2 -open B2R2.MiddleEnd.BinGraph -open System.IO -open System.Text -open System.Runtime.Serialization -open System.Runtime.Serialization.Json - -[] -type EdgeData = { - [] - From: string - [] - To: string - [] - Type: string -} - -[] -type CFGData = { - [] - Nodes: string [] - [] - Edges: EdgeData [] -} - -let toJson cfg jsonPath = - let enc = Encoding.UTF8 - use fs = File.Create (jsonPath) - use writer = - JsonReaderWriterFactory.CreateJsonWriter (fs, enc, true, true, " ") - let nodes = - [] - |> DiGraph.foldVertex cfg (fun acc (v: Vertex<#BasicBlock>) -> - String.u64ToHexNoPrefix v.VData.PPoint.Address :: acc) - |> List.rev - |> List.toArray - let edges = - [] - |> DiGraph.foldEdge cfg (fun acc f t e -> - { From = String.u64ToHexNoPrefix f.VData.PPoint.Address - To = String.u64ToHexNoPrefix t.VData.PPoint.Address - Type = e.ToString () } :: acc) - |> List.rev - |> List.toArray - let data = { Nodes = nodes; Edges = edges } - let ser = DataContractJsonSerializer (typedefof) - ser.WriteObject (writer, data) - writer.Flush () diff --git a/src/MiddleEnd/ControlFlowGraph/CallGraph.fs b/src/MiddleEnd/ControlFlowGraph/CallGraph.fs deleted file mode 100644 index 90870329..00000000 --- a/src/MiddleEnd/ControlFlowGraph/CallGraph.fs +++ /dev/null @@ -1,49 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2.MiddleEnd.BinGraph - -/// Call graph, where each node represents a function. -type CallCFG = ControlFlowGraph - -module CallCFG = - let private initializer core = - CallCFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> CallCFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> CallCFG - :> DiGraph - - /// Initialize CallCFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () diff --git a/src/MiddleEnd/ControlFlowGraph/CallGraphBlock.fs b/src/MiddleEnd/ControlFlowGraph/CallGraphBlock.fs deleted file mode 100644 index 1992a7a5..00000000 --- a/src/MiddleEnd/ControlFlowGraph/CallGraphBlock.fs +++ /dev/null @@ -1,53 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.MiddleEnd.BinGraph - -/// Basic block type for a call graph (CallCFG). -type CallGraphBlock (addr, id, name, isFake, isExternal) = - inherit BasicBlock (ProgramPoint (addr, 0)) - - member __.ID with get () = id - - member __.Name with get () = name - - member __.IsExternal with get () = isExternal - - override __.Range = AddrRange (addr) - - override __.IsFakeBlock () = isFake - - override __.ToVisualBlock () = - [| [| { AsmWordKind = AsmWordKind.Address - AsmWordValue = Addr.toString WordSize.Bit32 addr } - { AsmWordKind = AsmWordKind.String - AsmWordValue = ": " } - { AsmWordKind = AsmWordKind.Value - AsmWordValue = id } |] |] - -type CGVertex = Vertex diff --git a/src/MiddleEnd/ControlFlowGraph/DisasmBasicBlock.fs b/src/MiddleEnd/ControlFlowGraph/DisasmBasicBlock.fs deleted file mode 100644 index 04f62068..00000000 --- a/src/MiddleEnd/ControlFlowGraph/DisasmBasicBlock.fs +++ /dev/null @@ -1,73 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.MiddleEnd.BinGraph - -/// Basic block type for a disassembly-based CFG (DisasmCFG). -type DisasmBasicBlock (instrs: Instruction [], pp(*, ?funcID*)) = - inherit BasicBlock (pp) - - let mutable instructions = instrs - - /// Temporarily disable this - (* - let symbolize (words: AsmWord []) = - match funcID with - | Some funcID -> - words[words.Length - 1] <- - { AsmWordKind = AsmWordKind.Value; AsmWordValue = funcID } - | None -> () - words - *) - - override __.Range = - let last = instructions[instructions.Length - 1] - AddrRange (pp.Address, last.Address + uint64 last.Length - 1UL) - - override __.IsFakeBlock () = Array.isEmpty instructions - - override __.ToVisualBlock () = - instructions - |> Array.mapi (fun idx i -> - if idx = Array.length instructions - 1 then - i.Decompose (true)(* |> symbolize *) - else i.Decompose (true)) - - member __.Instructions - with get () = instructions - and set (i) = instructions <- i - - member __.Disassemblies - with get () = - instructions |> Array.map (fun i -> i.Disasm ()) - - override __.ToString () = - if instrs.Length = 0 then "DisasmBBLK(Dummy)" - else "DisasmBBLK(" + String.u64ToHexNoPrefix __.PPoint.Address + ")" - -type DisasmVertex = Vertex diff --git a/src/MiddleEnd/ControlFlowGraph/FakeBlockInfo.fs b/src/MiddleEnd/ControlFlowGraph/FakeBlockInfo.fs deleted file mode 100644 index e39b266a..00000000 --- a/src/MiddleEnd/ControlFlowGraph/FakeBlockInfo.fs +++ /dev/null @@ -1,65 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 - -/// Is this a get-pc-thunk function? -type GetPCThunkInfo = - /// It is not a get-pc-thunk. - | NoGetPCThunk - /// It is a get-pc-thunk, and the register wlil be assigned after this - /// function. - | YesGetPCThunk of RegisterID - -module GetPCThunkInfo = - let isGetPCThunk = function - | YesGetPCThunk _ -> true - | _ -> false - -/// IRBasicBlock can be either a fake block or a regular block. FakeBlockInfo -/// exists only for fake blocks. -type FakeBlockInfo = { - /// Call site address, i.e., the call instruction's address. - CallSite: Addr - /// How many bytes of the stack does this function unwind when return? - UnwindingBytes: int64 - /// What is the distance between the caller's stack frame (activation record) - /// and the callee's stack frame? If the distance is always constant, we - /// remember the value here. - FrameDistance: int option - /// If this fake block represents a "get_pc" thunk, then return the register - /// ID holding the current PC value after this function returns. - GetPCThunkInfo: GetPCThunkInfo - /// Is this fake block points to a PLT entry? - IsPLT: bool - /// Is this fake block represents a tail call? So, this fake block is - /// connected with a regular jump edge, not with a call edge. - IsTailCall: bool - /// Is the caller invoke this fake block as an indirect call? - IsIndirectCall: bool - /// Is the callee is not really a function, e.g., PC-getter. - IsNoFunction: bool -} diff --git a/src/MiddleEnd/ControlFlowGraph/IRBasicBlock.fs b/src/MiddleEnd/ControlFlowGraph/IRBasicBlock.fs deleted file mode 100644 index 4ed2f1f4..00000000 --- a/src/MiddleEnd/ControlFlowGraph/IRBasicBlock.fs +++ /dev/null @@ -1,170 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.BinIR -open B2R2.MiddleEnd.BinGraph - -/// A basic block that consists of IR (LowUIR) statements. It contains all the -/// InstructionInfo of the basic block. We say an IRBasicBlock is a fake block -/// if it contains no instruction, i.e., when the instrs is [||]. -[] -type IRBasicBlock (instrs: InstructionInfo [], ppoint: ProgramPoint) = - inherit BasicBlock (ppoint) - - /// The first instruction of the basic block. - member __.FirstInstruction with get() = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs[0].Instruction - - /// The first InstructionInfo of the basic block. - member __.FirstInsInfo with get() = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs[0] - - /// The last instruction of the basic block. - member __.LastInstruction with get() = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs[Array.length instrs - 1].Instruction - - /// The last InstructionInfo of the basic block. - member __.LastInsInfo with get() = - if Array.isEmpty instrs then raise DummyDataAccessException - else instrs[Array.length instrs - 1] - - /// Get an array of IR statements of a basic block. - member __.IRStatements with get() = instrs |> Array.map (fun i -> i.Stmts) - - /// Get an array of instructions that corresponds to each statement in the - /// IRStatements. - member __.Instructions - with get() = instrs |> Array.map (fun i -> i.Instruction) - - /// Get the array of InstructionInfo of the basic block. - member __.InsInfos with get() = instrs - - /// Get the last IR statement of the bblock. - member __.LastStmt with get() = - let stmts = instrs[instrs.Length - 1].Stmts - stmts[stmts.Length - 1] - - /// The address range of the basic block. Even if the block contains a partial - /// IR statements of an instruction, we include the instruction to compute the - /// range. - override __.Range = - let lastAddr = __.LastInstruction.Address + uint64 __.LastInstruction.Length - AddrRange (__.PPoint.Address, lastAddr - 1UL) - - override __.ToVisualBlock () = - __.IRStatements - |> Array.concat - |> Array.map (fun stmt -> - [| { AsmWordKind = AsmWordKind.String - AsmWordValue = LowUIR.Pp.stmtToString stmt } |]) - - /// Fake block info, which exists only for a fake block. - abstract FakeBlockInfo: FakeBlockInfo with get, set - - /// Unique identifier for IRBasicBlocks, which is a tuple of bbl's address and - /// caller's address. Note the bbl's address many not exist for fake blocks, - /// and the caller's address only exists for fake blocks. So we use dummy - /// values in such cases, but the uniqueness is still guaranteed. - abstract UniqueID: Addr * Addr - - /// Return the system call (at the end) instruction information if exists. If - /// the block does not ends with a syscall this will return NoSyscallTail. - abstract SyscallTail: SyscallTailInfo with get, set - -/// Regular IRBasicBlock; a basic block with IR statements. -type RegularIRBasicBlock (instrs, ppoint) = - inherit IRBasicBlock (instrs, ppoint) - - let mutable syscallTail = NoSyscallTail - - do assert (not (Array.isEmpty instrs)) - let stmts = instrs[instrs.Length - 1].Stmts - let len = stmts.Length - if len >= 2 then - match stmts[len - 2] with - | { S = LowUIR.SideEffect SysCall } -> - syscallTail <- UnknownSyscallTail - | _ -> () - else () - - override __.IsFakeBlock () = false - - override __.ToString () = - "IRBBLK(" + String.u64ToHexNoPrefix __.PPoint.Address + ")" - - override __.FakeBlockInfo - with get() = Utils.impossible () and set(_) = Utils.impossible () - - override __.UniqueID with get() = (ppoint.Address, 0UL) - - override __.SyscallTail - with get() = syscallTail and set(v) = syscallTail <- v - -/// Fake IRBasicBlock. We create a fake block when there is a function call, and -/// thus, a fake block represents a function. Note, fake blocks do not uniquely -/// represent a function. That is, when there are multiple function calls to the -/// same function, we create a fake block for each of the call sites. -type FakeIRBasicBlock (ppoint, callSiteAddr, ?isTailCall, ?isIndCall) = - inherit IRBasicBlock ([||], ppoint) - - let mutable info = - { CallSite = callSiteAddr - UnwindingBytes = 0L - FrameDistance = None - GetPCThunkInfo = NoGetPCThunk - IsPLT = false - IsTailCall = defaultArg isTailCall false - IsIndirectCall = defaultArg isIndCall false - IsNoFunction = false } - - override __.IsFakeBlock () = true - - override __.FakeBlockInfo with get() = info and set(i) = info <- i - - override __.ToString () = "IRBBLK(Dummy)" - - override __.UniqueID with get() = (ppoint.Address, callSiteAddr) - - override __.SyscallTail - with get() = Utils.impossible () and set(_) = Utils.impossible () - -[] -module IRBasicBlock = - let initRegular instrs ppoint = - RegularIRBasicBlock (instrs, ppoint) :> IRBasicBlock - - let initCallBlock callee callSiteAddr isTailCall = - FakeIRBasicBlock (ProgramPoint (callee, 0), callSiteAddr, isTailCall) - :> IRBasicBlock - - let initIndirectCallBlock callSiteAddr = - FakeIRBasicBlock (ProgramPoint.GetFake (), callSiteAddr, false, true) - :> IRBasicBlock diff --git a/src/MiddleEnd/ControlFlowGraph/InlinedAssembly.fs b/src/MiddleEnd/ControlFlowGraph/InlinedAssembly.fs deleted file mode 100644 index 98630b59..00000000 --- a/src/MiddleEnd/ControlFlowGraph/InlinedAssembly.fs +++ /dev/null @@ -1,121 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface - -/// Sometimes, inlined assembly creates branches that jump into the middle of an -/// instruction. For example, the following pattern is commonly found in Libc. -/// -/// 41af15: 64 83 3c 25 18 00 00 00 00 cmpl $0x0,%fs:0x18 -/// 41af1e: 74 01 je 41af21 -/// 41af20: f0 48 ff 0d c0 57 0a 00 lock decq 0xa57c0(%rip) -/// -/// We call the above code pattern as the "jump-after-lock" pattern. -type InlinedAssemblyTypes = - /// The jump-after-lock pattern that spans multiple instruction addresses. - | JumpAfterLock of addrs: Addr list - /// No known pattern. - | NotInlinedAssembly - -module InlinedAssemblyPattern = - - let private computeJumpAfterLockAddrs hdl targetBlkAddr = - [ ([| 0x64uy; 0x83uy; 0x3cuy; 0x25uy; 0x18uy; - 0x00uy; 0x00uy; 0x00uy; 0x00uy; 0x74uy; 0x01uy; 0xf0uy |], 9UL, 2UL) - ([| 0x65uy; 0x83uy; 0x3Duy; 0x0Cuy; - 0x00uy; 0x00uy; 0x00uy; 0x00uy; 0x74uy; 0x01uy; 0xf0uy |], 8UL, 2UL) ] - |> List.tryPick (fun (pattern, cmpLen, jeLen) -> - let len = uint64 pattern.Length - if targetBlkAddr >= len then - let ins1Addr = targetBlkAddr - len - let ins2Addr = ins1Addr + cmpLen - let ins3Addr = ins2Addr + jeLen - let bs = BinHandle.ReadBytes (hdl, targetBlkAddr - len, pattern.Length) - if bs = pattern then Some [ ins1Addr; ins2Addr; ins3Addr ] - else None - else None) - - let checkInlinedAssemblyPattern hdl targetBlkAddr = - match computeJumpAfterLockAddrs hdl targetBlkAddr with - | Some addrs -> JumpAfterLock addrs - | _ -> NotInlinedAssembly - -type InlinedAssembly (addr, len, wordSize, stmts) = - inherit Instruction (addr, len, wordSize) - - override __.IsBranch () = false - - override __.IsModeChanging () = false - - override __.IsDirectBranch () = false - - override __.IsIndirectBranch () = false - - override __.IsCondBranch () = false - - override __.IsCJmpOnTrue () = false - - override __.IsCall () = false - - override __.IsRET () = false - - override __.IsInterrupt () = false - - override __.IsExit () = false - - override __.IsBBLEnd () = false - - override __.IsNop () = false - - override __.DirectBranchTarget _ = false - - override __.IndirectTrampolineAddr _ = false - - override __.Immediate _ = false - - override __.GetNextInstrAddrs () = - let ftAddr = addr + uint64 len - Seq.singleton (ftAddr, ArchOperationMode.NoMode) - - override __.InterruptNum _ = false - - override __.Translate _ = stmts - - override __.TranslateToList _ = System.Collections.Generic.List stmts - - override __.Disasm (showAddr, resolveSymbol, disasmHelper) = - Utils.futureFeature () - - override __.Disasm () = Utils.futureFeature () - - override __.Decompose _ = Utils.futureFeature () - - override __.IsInlinedAssembly () = true - - static member Init addr len wordSize stmts = - InlinedAssembly (addr, len, wordSize, stmts) :> Instruction diff --git a/src/MiddleEnd/ControlFlowGraph/README.md b/src/MiddleEnd/ControlFlowGraph/README.md deleted file mode 100644 index e9e0065b..00000000 --- a/src/MiddleEnd/ControlFlowGraph/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# B2R2.MiddleEnd.ControlFlowGraph - -### B2R2? - -B2R2 is a binary analysis and reversing framework written purely in F#. Since it -does not rely on any native (unmanaged) code, it is readily usable in any -platform or OS that .NET runs on. - -### B2R2.MiddleEnd.ControlFlowGraph Package? - -`B2R2.MiddleEnd.ControlFlowGraph` defines CFG-related types and functions. While -`B2R2.MiddleEnd.BinGraph` defines low-level graph data structures and functions, -this package provides more specific implementation. diff --git a/src/MiddleEnd/ControlFlowGraph/SSABasicBlock.fs b/src/MiddleEnd/ControlFlowGraph/SSABasicBlock.fs deleted file mode 100644 index 3dfea1dd..00000000 --- a/src/MiddleEnd/ControlFlowGraph/SSABasicBlock.fs +++ /dev/null @@ -1,220 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinGraph - -[] -module private SSABasicBlockHelper = - let private buildRegVar hdl reg = - let wordSize = hdl.ISA.WordSize |> WordSize.toRegType - RegVar (wordSize, reg, hdl.RegisterBay.RegIDToString reg) - - let private addReturnValDef hdl defs = - match (hdl: BinHandle).ISA.Arch with - | Arch.EVM -> defs - | _ -> - let reg = CallingConvention.returnRegister hdl |> buildRegVar hdl - let def = { Kind = reg; Identifier = -1 } - Set.add def defs - - let private addStackDef hdl defs = - match hdl.RegisterBay.StackPointer with - | Some sp -> - let def = { Kind = buildRegVar hdl sp; Identifier = -1 } - Set.add def defs - | None -> defs - - let private addMemDef defs = - let def = { Kind = MemVar; Identifier = - 1 } - Set.add def defs - - let computeDefinedVars hdl getPCThunkInfo isPLT = - let defs = addStackDef hdl Set.empty - if isPLT then defs |> addReturnValDef hdl |> addMemDef |> Set.toArray - else - match getPCThunkInfo with - | YesGetPCThunk rid -> - let def = { Kind = buildRegVar hdl rid; Identifier = -1 } - Set.singleton def |> addStackDef hdl |> addMemDef |> Set.toArray - | _ -> - Set.empty - |> addStackDef hdl |> addReturnValDef hdl |> addMemDef |> Set.toArray - - let computeNextPPoint (ppoint: ProgramPoint) = function - | Def (v, Num bv) -> - match v.Kind with - | PCVar _ -> ProgramPoint (BitVector.toUInt64 bv, 0) - | _ -> ProgramPoint.Next ppoint - | _ -> ProgramPoint.Next ppoint - - let private addInOutMemVars inVars outVars = - let inVar = { Kind = MemVar; Identifier = -1 } - let outVar = { Kind = MemVar; Identifier = -1 } - inVar :: inVars, outVar :: outVars - - let private postprocessStmtForEVM = function - | SideEffect (eff, _, _) as stmt -> - match eff with - | ExternalCall (BinOp (BinOpType.APP, _, - FuncName "calldatacopy", _)) -> - let inVars, outVars = addInOutMemVars [] [] - SideEffect (eff, inVars, outVars) - | _ -> stmt - | stmt -> stmt - - let private postprocessOthers stmt = stmt - - let postprocessStmt hdl s = - match hdl.ISA.Arch with - | Arch.EVM -> postprocessStmtForEVM s - | _ -> postprocessOthers s - -/// SSA statement information. -type SSAStmtInfo = ProgramPoint * Stmt - -/// Basic block type for an SSA-based CFG (SSACFG). It holds an array of -/// SSAStmtInfos (ProgramPoint * Stmt). -[] -type SSABasicBlock (pp, instrs: InstructionInfo []) = - inherit BasicBlock (pp) - - let mutable idom: Vertex option = None - let mutable frontier: Vertex list = [] - - override __.Range = - if Array.isEmpty instrs then Utils.impossible () else () - let last = instrs[instrs.Length - 1].Instruction - AddrRange (pp.Address, last.Address + uint64 last.Length - 1UL) - - override __.IsFakeBlock () = Array.isEmpty instrs - - override __.ToVisualBlock () = - __.SSAStmtInfos - |> Array.map (fun (_, stmt) -> - [| { AsmWordKind = AsmWordKind.String - AsmWordValue = Pp.stmtToString stmt } |]) - - /// Return the corresponding InstructionInfo array. - member __.InsInfos with get () = instrs - - /// Get the last SSA statement of the bblock. - member __.GetLastStmt () = - snd __.SSAStmtInfos[__.SSAStmtInfos.Length - 1] - - /// Immediate dominator of this block. - member __.ImmDominator with get() = idom and set(d) = idom <- d - - /// Dominance frontier of this block. - member __.DomFrontier with get() = frontier and set(f) = frontier <- f - - /// Prepend a Phi node to this SSA basic block. - member __.PrependPhi varKind count = - let var = { Kind = varKind; Identifier = -1 } - let ppoint = ProgramPoint.GetFake () - __.SSAStmtInfos <- - Array.append [| ppoint, Phi (var, Array.zeroCreate count) |] - __.SSAStmtInfos - - /// Update program points. This must be called after updating SSA stmts. - member __.UpdatePPoints () = - __.SSAStmtInfos - |> Array.foldi (fun ppoint idx (_, stmt) -> - let ppoint' = computeNextPPoint ppoint stmt - __.SSAStmtInfos[idx] <- (ppoint', stmt) - ppoint') pp - |> ignore - - /// Return the array of SSAStmtInfos. - abstract SSAStmtInfos: SSAStmtInfo [] with get, set - - /// Return the corresponding fake block information. This is only valid for a - /// fake SSABasicBlock. - abstract FakeBlockInfo: FakeBlockInfo with get, set - -/// Regular SSABasicBlock with regular instructions. -type RegularSSABasicBlock (hdl: BinHandle, pp, instrs) = - inherit SSABasicBlock (pp, instrs) - - let mutable stmts: SSAStmtInfo [] = - (instrs: InstructionInfo []) - |> Array.map (fun i -> - let wordSize = i.Instruction.WordSize |> WordSize.toRegType - let stmts = i.Stmts - let address = i.Instruction.Address - AST.translateStmts wordSize address (postprocessStmt hdl) stmts) - |> Array.concat - |> Array.map (fun s -> ProgramPoint.GetFake (), s) - - override __.SSAStmtInfos with get() = stmts and set(s) = stmts <- s - - override __.FakeBlockInfo - with get() = Utils.impossible () and set(_) = Utils.impossible () - - override __.ToString () = - "SSABBLK(" + String.u64ToHexNoPrefix __.PPoint.Address + ")" - -/// Fake SSABasicBlock, which may or may not hold a function summary with -/// ReturnVal expressions. -type FakeSSABasicBlock (hdl, pp, retPoint: ProgramPoint, fakeBlkInfo) = - inherit SSABasicBlock (pp, [||]) - - let mutable stmts: SSAStmtInfo [] = - let stmts = (* For a fake block, we check which var can be modified. *) - computeDefinedVars hdl fakeBlkInfo.GetPCThunkInfo fakeBlkInfo.IsPLT - |> Array.map (fun dst -> - let src = { Kind = dst.Kind; Identifier = -1 } - Def (dst, ReturnVal (pp.Address, retPoint.Address, src))) - let wordSize = hdl.ISA.WordSize |> WordSize.toRegType - let fallThrough = BitVector.ofUInt64 retPoint.Address wordSize - let jmpToFallThrough = Jmp (InterJmp (Num fallThrough)) - Array.append stmts [| jmpToFallThrough |] - |> Array.map (fun s -> ProgramPoint.GetFake (), s) - - let mutable fakeBlkInfo = fakeBlkInfo - - override __.SSAStmtInfos with get() = stmts and set(s) = stmts <- s - - override __.FakeBlockInfo - with get() = fakeBlkInfo and set(f) = fakeBlkInfo <- f - - override __.ToString () = - "SSABBLK(Dummy;" + pp.ToString () + ";" + retPoint.ToString () + ")" - -/// SSACFG's vertex. -type SSAVertex = Vertex - -[] -module SSABasicBlock = - let initRegular hdl pp instrs = - RegularSSABasicBlock (hdl, pp, instrs) :> SSABasicBlock - - let initFake hdl pp retPoint fakeBlkInfo = - FakeSSABasicBlock (hdl, pp, retPoint, fakeBlkInfo) :> SSABasicBlock diff --git a/src/MiddleEnd/ControlFlowGraph/SSACFG.fs b/src/MiddleEnd/ControlFlowGraph/SSACFG.fs deleted file mode 100644 index e45a9fbd..00000000 --- a/src/MiddleEnd/ControlFlowGraph/SSACFG.fs +++ /dev/null @@ -1,150 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.BinIR.SSA -open B2R2.MiddleEnd.BinGraph - -/// SSA-based CFG, where each node contains disassembly code. -type SSACFG = ControlFlowGraph - -[] -module SSACFG = - let private initializer core = - SSACFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> SSACFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> SSACFG - :> DiGraph - - /// Initialize SSACFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () - - let private getVertex hdl g (vMap: SSAVMap) oldSrc = - let vData = (oldSrc: Vertex).VData - let pos = vData.PPoint - match vMap.TryGetValue pos with - | false, _ -> - let instrs = vData.InsInfos - let blk = SSABasicBlock.initRegular hdl pos instrs - let v, g = DiGraph.addVertex g blk - vMap.Add (pos, v) - v, g - | true, v -> v, g - - let private getFakeVertex hdl g (fMap: FakeVMap) src ftPos = - let srcPos = (src: Vertex).VData.PPoint - let pos = (srcPos, ftPos) - match fMap.TryGetValue pos with - | false, _ -> - let blk = SSABasicBlock.initFake hdl srcPos ftPos src.VData.FakeBlockInfo - let v, g = DiGraph.addVertex g blk - fMap.Add (pos, v) - v, g - | true, v -> v, g - - let private convertToSSA hdl irCFG ssaCFG vMap fMap root = - let root, ssaCFG = getVertex hdl ssaCFG vMap root - let ssaCFG = - ssaCFG - |> DiGraph.foldEdge irCFG (fun ssaCFG src dst e -> - (* If a node is fake, it is a call target. *) - if (dst: Vertex).VData.IsFakeBlock () then - let last = src.VData.LastInstruction - let fall = ProgramPoint (last.Address + uint64 last.Length, 0) - let srcV, ssaCFG = getVertex hdl ssaCFG vMap src - let dstV, ssaCFG = getFakeVertex hdl ssaCFG fMap dst fall - DiGraph.addEdge ssaCFG srcV dstV e - elif src.VData.IsFakeBlock () then - let srcV, ssaCFG = getFakeVertex hdl ssaCFG fMap src dst.VData.PPoint - let dstV, ssaCFG = getVertex hdl ssaCFG vMap dst - DiGraph.addEdge ssaCFG srcV dstV e - else - let srcV, ssaCFG = getVertex hdl ssaCFG vMap src - let dstV, ssaCFG = getVertex hdl ssaCFG vMap dst - DiGraph.addEdge ssaCFG srcV dstV e) - ssaCFG, root - - /// Add phis and rename all the variables. - let installPhis vertices ssaCFG ssaRoot = - let defSites = DefSites () - SSAUtils.computeDominatorInfo ssaCFG ssaRoot - |> SSAUtils.placePhis ssaCFG vertices defSites - |> SSAUtils.renameVars ssaCFG defSites - - /// Convert IRCFG to an SSA CFG. - let ofIRCFG hdl (g: DiGraph<_, _>) root = - let ssaCFG = init g.ImplementationType - let vMap = SSAVMap () - let fMap = FakeVMap () - let ssaCFG, root = convertToSSA hdl g ssaCFG vMap fMap root - let vertices = Seq.append vMap.Values fMap.Values - DiGraph.findVertexBy ssaCFG (fun v -> - v.VData.PPoint = root.VData.PPoint && not <| v.VData.IsFakeBlock ()) - |> installPhis vertices ssaCFG - DiGraph.iterVertex ssaCFG (fun v -> v.VData.UpdatePPoints ()) - struct (ssaCFG, root) - - /// Find SSAVertex that includes the given instruction address. - let findVertexByAddr ssaCFG addr = - DiGraph.findVertexBy ssaCFG (fun (v: SSAVertex) -> - if v.VData.IsFakeBlock () then false - else v.VData.Range.IsIncluding addr) - - /// Find the definition of the given variable kind (targetVarKind) at the - /// given node v. We simply follow the dominator tree of the given SSACFG - /// until we find a definition. - let rec findDef (v: SSAVertex) targetVarKind = - let stmtInfo = - v.VData.SSAStmtInfos - |> Array.tryFindBack (fun (_, stmt) -> - match stmt with - | Def ({ Kind = k }, _) when k = targetVarKind -> true - | _ -> false) - match stmtInfo with - | Some stmtInfo -> Some (snd stmtInfo) - | None -> - match v.VData.ImmDominator with - | Some idom -> - findDef idom targetVarKind - | None -> None - - /// Find the reaching definition of the given variable kind (targetVarKind) at - /// the entry of node v. We simply follow the dominator tree of the given - /// SSACFG until we find a definition. - let findReachingDef (v: SSAVertex) targetVarKind = - match v.VData.ImmDominator with - | Some idom -> - findDef idom targetVarKind - | None -> None diff --git a/src/MiddleEnd/ControlFlowGraph/SSAEdges.fs b/src/MiddleEnd/ControlFlowGraph/SSAEdges.fs deleted file mode 100644 index 00c61052..00000000 --- a/src/MiddleEnd/ControlFlowGraph/SSAEdges.fs +++ /dev/null @@ -1,105 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.ControlFlowGraph.SSAEdges - -open B2R2 -open B2R2.BinIR -open B2R2.MiddleEnd.BinGraph - -type SSAStmtLocation = VertexID * int - -type EdgeInfo = { - /// A mapping from an SSA var to a set of use locations. - Uses: Map> - /// A mapping from an SSA var to its def stmt. - Defs: Map -} - -let private addUse var loc info = - match Map.tryFind var info.Uses with - | Some set -> Set.add loc set - | None -> Set.singleton loc - |> fun set -> { info with Uses = Map.add var set info.Uses } - -let private addUses vars loc info = - vars |> List.fold (fun acc v -> addUse v loc acc) info - -let private addDef var stmt info = - { info with Defs = Map.add var stmt info.Defs } - -let private addDefs vars stmt info = - vars |> List.fold (fun acc v -> addDef v stmt acc) info - -let rec private computeUses loc expr acc = - match expr with - | SSA.Var v -> addUse v loc acc - | SSA.Load (mem, _, addr) -> addUse mem loc acc |> computeUses loc addr - | SSA.Store (mem, _, addr, v) -> - addUse mem loc acc |> computeUses loc addr |> computeUses loc v - | SSA.UnOp (_, _, e) -> computeUses loc e acc - | SSA.BinOp (_, _, e1, e2) -> computeUses loc e1 acc |> computeUses loc e2 - | SSA.RelOp (_, _, e1, e2) -> computeUses loc e1 acc |> computeUses loc e2 - | SSA.Ite (cond, _, e1, e2) -> - computeUses loc cond acc |> computeUses loc e1 |> computeUses loc e2 - | SSA.Cast (_, _, e) -> computeUses loc e acc - | SSA.Extract (e, _, _) -> computeUses loc e acc - | SSA.ReturnVal (_, _, v) -> addUse v loc acc - | _ -> acc - -/// Compute SSA edge map (SSA Var -> a set of (VertexID, Stmt idx)). From a -/// given ssa var, this function returns a set of SSA-edge destination. -let compute ssaCFG = - let emptyInfo = { Uses = Map.empty; Defs = Map.empty } - emptyInfo - |> DiGraph.foldVertex ssaCFG (fun acc (v: SSAVertex) -> - let vid = v.GetID () - v.VData.SSAStmtInfos - |> Array.foldi (fun acc idx (_, stmt) -> - match stmt with - | SSA.LMark _ -> acc - | SSA.SideEffect (SSA.ExternalCall expr, inVars, outVars) -> - let loc = vid, idx - computeUses loc expr acc - |> addDefs outVars stmt - |> addUses inVars loc - | SSA.SideEffect _ -> acc - | SSA.Jmp (SSA.IntraJmp _) -> acc - | SSA.Jmp (SSA.IntraCJmp (cond, _, _)) -> computeUses (vid, idx) cond acc - | SSA.Jmp (SSA.InterJmp (target)) -> computeUses (vid, idx) target acc - | SSA.Jmp (SSA.InterCJmp (cond, t1, t2)) -> - let loc = vid, idx - computeUses loc cond acc |> computeUses loc t1 |> computeUses loc t2 - | SSA.Def (v, e) -> - let loc = vid, idx - addDef v stmt acc - |> computeUses loc e - | SSA.Phi (v, ns) -> - let loc = vid, idx - let acc = addDef v stmt acc - ns - |> Array.fold (fun acc n -> - let u = { v with Identifier = n } - addUse u loc acc) acc - ) acc |> fst) diff --git a/src/MiddleEnd/ControlFlowGraph/SSATypes.fs b/src/MiddleEnd/ControlFlowGraph/SSATypes.fs deleted file mode 100644 index 7a362c21..00000000 --- a/src/MiddleEnd/ControlFlowGraph/SSATypes.fs +++ /dev/null @@ -1,52 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.BinIR -open System.Collections.Generic - -/// A mapping from an address to a SSACFG vertex. -type SSAVMap = Dictionary - -/// This is a mapping from an edge to a dummy vertex (for external function -/// calls). We first separately create dummy vertices even if they are -/// associated with the same node (address) in order to compute dominance -/// relationships without introducing incorrect paths or cycles. For -/// convenience, we will always consider as a key "a return edge" from a fake -/// vertex to a fall-through vertex. -type FakeVMap = Dictionary - -/// Mapping from a variable to a set of defining SSA basic blocks. -type DefSites = Dictionary> - -/// Defined variables per node in a SSACFG. -type DefsPerNode = Dictionary> - -/// Counter for each variable. -type VarCountMap = Dictionary - -/// Variable ID stack. -type IDStack = Dictionary diff --git a/src/MiddleEnd/ControlFlowGraph/SSAUtils.fs b/src/MiddleEnd/ControlFlowGraph/SSAUtils.fs deleted file mode 100644 index 6b39dc49..00000000 --- a/src/MiddleEnd/ControlFlowGraph/SSAUtils.fs +++ /dev/null @@ -1,201 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module internal B2R2.MiddleEnd.ControlFlowGraph.SSAUtils - -open B2R2 -open B2R2.BinIR -open B2R2.MiddleEnd.BinGraph - -let computeDominatorInfo g root = - let domCtxt = Dominator.initDominatorContext g root - let frontiers = Dominator.frontiers domCtxt - DiGraph.iterVertex g (fun (v: SSAVertex) -> - let dfnum = domCtxt.ForwardDomInfo.DFNumMap[v.GetID ()] - v.VData.ImmDominator <- Dominator.idom domCtxt v - v.VData.DomFrontier <- frontiers[dfnum]) - domCtxt - -let collectDefVars defs (_, stmt) = - match stmt with - | SSA.Def ({ Kind = k }, _) -> Set.add k defs - | _ -> defs - -let findPhiSites g defsPerNode variable (phiSites, workList) v = - if Set.contains v phiSites then phiSites, workList - else - match variable with - (* Temporary vars are only meaningful in an instruction boundary. Thus, a - PhiSite for a TempVar should be an intra-instruction bbl, but not the - start of an instruction. *) - | SSA.TempVar _ when (v: SSAVertex).VData.PPoint.Position = 0 -> - phiSites, workList - | _ -> - (* Insert Phi for v *) - DiGraph.getPreds g v - |> List.length - |> v.VData.PrependPhi variable - let phiSites = Set.add v phiSites - let defs = (defsPerNode: DefsPerNode)[v] - if not <| Set.contains variable defs then phiSites, v :: workList - else phiSites, workList - -let rec iterDefs g phiSites defsPerNode variable = function - | [] -> phiSites - | (v: SSAVertex) :: workList -> - let phiSites, workList = - v.VData.DomFrontier - |> List.fold (findPhiSites g defsPerNode variable) (phiSites, workList) - iterDefs g phiSites defsPerNode variable workList - -let placePhis g vertices (defSites: DefSites) domCtxt = - let defsPerNode = DefsPerNode () - vertices - |> Seq.iter (fun (v: SSAVertex) -> - let defs = v.VData.SSAStmtInfos |> Array.fold collectDefVars Set.empty - defsPerNode[v] <- defs - defs |> Set.iter (fun d -> - if defSites.ContainsKey d then defSites[d] <- Set.add v defSites[d] - else defSites[d] <- Set.singleton v)) - for KeyValue (variable, defs) in defSites do - Set.toList defs - |> iterDefs g Set.empty defsPerNode variable - |> ignore - domCtxt - -let renameVar (stack: IDStack) (v: SSA.Variable) = - match stack.TryGetValue v.Kind with - | false, _ -> v.Identifier <- 0 - | true, ids -> v.Identifier <- List.head ids - -let rec renameVarList stack = function - | [] -> () - | v :: vs -> renameVar stack v; renameVarList stack vs - -let rec renameExpr stack = function - | SSA.Num (_) - | SSA.Undefined (_) - | SSA.FuncName (_) - | SSA.Nil -> () - | SSA.ReturnVal (_, _, v) -> renameVar stack v - | SSA.Var v -> renameVar stack v - | SSA.Load (v, _, expr) -> - renameVar stack v - renameExpr stack expr - | SSA.Store (mem, _, addr, expr) -> - renameVar stack mem - renameExpr stack addr - renameExpr stack expr - | SSA.UnOp (_, _, expr) -> - renameExpr stack expr - | SSA.BinOp (_, _, expr1, expr2) -> - renameExpr stack expr1 - renameExpr stack expr2 - | SSA.RelOp (_, _, expr1, expr2) -> - renameExpr stack expr1 - renameExpr stack expr2 - | SSA.Ite (expr1, _, expr2, expr3) -> - renameExpr stack expr1 - renameExpr stack expr2 - renameExpr stack expr3 - | SSA.Cast (_, _, expr) -> - renameExpr stack expr - | SSA.Extract (expr, _, _) -> - renameExpr stack expr - -let renameJmp stack = function - | SSA.IntraJmp _ -> () - | SSA.IntraCJmp (expr, _, _) -> - renameExpr stack expr - | SSA.InterJmp (expr) -> - renameExpr stack expr - | SSA.InterCJmp (cond, target1, target2) -> - renameExpr stack cond - renameExpr stack target1 - renameExpr stack target2 - -let introduceDef (count: VarCountMap) (stack: IDStack) (v: SSA.Variable) = - count[v.Kind] <- count[v.Kind] + 1 - let i = count[v.Kind] - stack[v.Kind] <- i :: stack[v.Kind] - v.Identifier <- i - -let rec introduceDefList count stack = function - | [] -> () - | v :: vs -> introduceDef count stack v; introduceDefList count stack vs - -let renameStmt count stack (_, stmt) = - match stmt with - | SSA.LMark _ -> () - | SSA.SideEffect (SSA.ExternalCall e, inVars, outVars) -> - renameExpr stack e - renameVarList stack inVars - introduceDefList count stack outVars - | SSA.SideEffect _ -> () - | SSA.Jmp jmpTy -> renameJmp stack jmpTy - | SSA.Def (def, e) -> - renameExpr stack e - introduceDef count stack def - | SSA.Phi (def, _) -> - introduceDef count stack def - -let renamePhiAux (stack: IDStack) preds (parent: SSAVertex) (_, stmt) = - match stmt with - | SSA.Phi (def, nums) -> - let idx = - List.findIndex (fun (v: SSAVertex) -> - v.VData = parent.VData) preds - nums[idx] <- List.head stack[def.Kind] - | _ -> () - -let renamePhi g stack parent (succ: SSAVertex) = - succ.VData.SSAStmtInfos - |> Array.iter (renamePhiAux stack (DiGraph.getPreds g succ) parent) - -let popStack (stack: IDStack) (_, stmt) = - match stmt with - | SSA.Def (def, _) - | SSA.Phi (def, _) -> stack[def.Kind] <- List.tail stack[def.Kind] - | _ -> () - -let rec rename g domTree count stack (v: SSAVertex) = - v.VData.SSAStmtInfos |> Array.iter (renameStmt count stack) - DiGraph.getSuccs g v |> List.iter (renamePhi g stack v) - traverseChildren g domTree count stack (Map.find v domTree) - v.VData.SSAStmtInfos |> Array.iter (popStack stack) - -and traverseChildren g domTree count stack = function - | child :: rest -> - rename g domTree count stack child - traverseChildren g domTree count stack rest - | [] -> () - -let renameVars g (defSites: DefSites) domCtxt = - let domTree, root = Dominator.dominatorTree domCtxt - let count = VarCountMap () - let stack = IDStack () - defSites.Keys |> Seq.iter (fun variable -> - count[variable] <- 0 - stack[variable] <- [0]) - rename g domTree count stack root |> ignore diff --git a/src/MiddleEnd/ControlFlowGraph/SyscallTailInfo.fs b/src/MiddleEnd/ControlFlowGraph/SyscallTailInfo.fs deleted file mode 100644 index 76d5a442..00000000 --- a/src/MiddleEnd/ControlFlowGraph/SyscallTailInfo.fs +++ /dev/null @@ -1,38 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -/// A basic block may end with a syscall instruction, and the syscall may -/// terminate the program or not. We store such information for each basic -/// block to easily track them. -type SyscallTailInfo = - /// The basic block has no syscall. - | NoSyscallTail - /// The basic block has a syscall, but we didn't yet analyzed its type. - | UnknownSyscallTail - /// The basic block has a regular (non-exit) syscall. - | RegularSyscallTail - /// The basic block has an exit syscall. - | ExitSyscallTail diff --git a/src/MiddleEnd/ControlFlowGraph/VisualBlock.fs b/src/MiddleEnd/ControlFlowGraph/VisualBlock.fs deleted file mode 100644 index c6f20f49..00000000 --- a/src/MiddleEnd/ControlFlowGraph/VisualBlock.fs +++ /dev/null @@ -1,51 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.ControlFlowGraph - -open B2R2 -open B2R2.FrontEnd.BinLifter - -/// A visual line of a basic block. -type VisualLine = AsmWord [] - -module VisualLine = - [] - let lineWidth terms = - terms |> Array.fold (fun width term -> width + AsmWord.Width term) 0 - - [] - let toString terms = - terms |> Array.map AsmWord.ToString |> String.concat " " - -/// A visual representation of a basic block. -type VisualBlock = VisualLine [] - -module VisualBlock = - let empty (addr: Addr): VisualBlock = - [| - [| { AsmWordKind = AsmWordKind.String - AsmWordValue = "# fake block @ " + (String.u64ToHexNoPrefix addr) } - |] - |] diff --git a/src/MiddleEnd/DataFlow.Tests/B2R2.MiddleEnd.DataFlow.Tests.fsproj b/src/MiddleEnd/DataFlow.Tests/B2R2.MiddleEnd.DataFlow.Tests.fsproj deleted file mode 100644 index 2e579b77..00000000 --- a/src/MiddleEnd/DataFlow.Tests/B2R2.MiddleEnd.DataFlow.Tests.fsproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - false - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/DataFlow.Tests/DataFlow.Tests.fs b/src/MiddleEnd/DataFlow.Tests/DataFlow.Tests.fs deleted file mode 100644 index a4a238d1..00000000 --- a/src/MiddleEnd/DataFlow.Tests/DataFlow.Tests.fs +++ /dev/null @@ -1,173 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow.Tests - -open Microsoft.VisualStudio.TestTools.UnitTesting - -open B2R2 -open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.BinEssence -open B2R2.MiddleEnd.DataFlow -open B2R2.MiddleEnd.BinGraph - -[] -type PersistentDataFlowTests () = - - (* - Example 1: Fibonacci function - - unsigned int fib(unsigned int m) - { - unsigned int f0 = 0, f1 = 1, f2, i; - if (m <= 1) return m; - else { - for (i = 2; i <= m; i++) { - f2 = f0 + f1; - f0 = f1; - f1 = f2; - } - return f2; - } - } - - 00000000: 8B 54 24 04 mov edx,dword ptr [esp+4] - 00000004: 56 push esi - 00000005: 33 F6 xor esi,esi - 00000007: 8D 4E 01 lea ecx,[esi+1] - 0000000A: 3B D1 cmp edx,ecx - 0000000C: 77 04 ja 00000012 - 0000000E: 8B C2 mov eax,edx - 00000010: 5E pop esi - 00000011: C3 ret - 00000012: 4A dec edx - 00000013: 8D 04 31 lea eax,[ecx+esi] - 00000016: 8D 31 lea esi,[ecx] - 00000018: 8B C8 mov ecx,eax - 0000001A: 83 EA 01 sub edx,1 - 0000001D: 75 F4 jne 00000013 - 0000001F: 5E pop esi - 00000020: C3 ret - - 8B5424045633F68D4E013BD177048BC25EC34A8D04318D318BC883EA0175F45EC3 - *) - - let binary = - [| 0x8Buy; 0x54uy; 0x24uy; 0x04uy; 0x56uy; 0x33uy; 0xF6uy; 0x8Duy; 0x4Euy; - 0x01uy; 0x3Buy; 0xD1uy; 0x77uy; 0x04uy; 0x8Buy; 0xC2uy; 0x5Euy; 0xC3uy; - 0x4Auy; 0x8Duy; 0x04uy; 0x31uy; 0x8Duy; 0x31uy; 0x8Buy; 0xC8uy; 0x83uy; - 0xEAuy; 0x01uy; 0x75uy; 0xF4uy; 0x5Euy; 0xC3uy |] - - let isa = ISA.Init Architecture.IntelX86 Endian.Little - let hdl = BinHandle.Init (isa, binary) - let ess = BinEssence.init hdl [] [] [] - -#if !EMULATION - [] - member __.``Reaching Definitions Test 1``() = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let rd = LowUIRReachingDefinitions (cfg) - let ins, _outs = rd.Compute cfg root - let v = cfg.FindVertexBy (fun b -> b.VData.PPoint.Address = 0xEUL) (* 2nd *) - let result = ins[v.GetID ()] |> Set.filter (fun v -> - match v.VarExpr with - | Regular _ -> true - | _ -> false) - let solution = [ - { ProgramPoint = ProgramPoint (0UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - { ProgramPoint = ProgramPoint (4UL, 2) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ESP) } - { ProgramPoint = ProgramPoint (5UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ESI) } - { ProgramPoint = ProgramPoint (5UL, 2) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.OF) } - { ProgramPoint = ProgramPoint (5UL, 3) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.CF) } - { ProgramPoint = ProgramPoint (5UL, 4) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.SF) } - { ProgramPoint = ProgramPoint (5UL, 5) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ZF) } - { ProgramPoint = ProgramPoint (5UL, 6) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.PF) } - { ProgramPoint = ProgramPoint (5UL, 7) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.AF) } - { ProgramPoint = ProgramPoint (7UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ECX) } - { ProgramPoint = ProgramPoint (0xAUL, 4) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.CF) } - { ProgramPoint = ProgramPoint (0xAUL, 5) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.OF) } - { ProgramPoint = ProgramPoint (0xAUL, 6) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.AF) } - { ProgramPoint = ProgramPoint (0xAUL, 7) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.SF) } - { ProgramPoint = ProgramPoint (0xAUL, 8) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.ZF) } - { ProgramPoint = ProgramPoint (0xAUL, 11) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.PF) } ] - Assert.AreEqual (result, Set.ofList solution) -#endif - - [] - member __.``Use-Def Test 1``() = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let chain = DataFlowChain.init cfg root false - let vp = - { ProgramPoint = ProgramPoint (0xEUL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - let res = chain.UseDefChain |> Map.find vp |> Set.toArray - let solution = [| - { ProgramPoint = ProgramPoint (0x0UL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } |] - CollectionAssert.AreEqual (solution, res) - - [] - member __.``Use-Def Test 2``() = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let chain = DataFlowChain.init cfg root true - let vp = - { ProgramPoint = ProgramPoint (0xEUL, 0) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - let res = chain.UseDefChain |> Map.find vp |> Set.toArray - let solution = [| - { ProgramPoint = ProgramPoint (0x0UL, 0) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } |] - CollectionAssert.AreEqual (solution, res) - - [] - member __.``Use-Def Test 3``() = - let cfg, root = BinEssence.getFunctionCFG ess 0UL |> Result.get - let chain = DataFlowChain.init cfg root false - let vp = - { ProgramPoint = ProgramPoint (0x1AUL, 1) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - let res = chain.UseDefChain |> Map.find vp |> Set.toArray - let solution = [| - { ProgramPoint = ProgramPoint (0x12UL, 3) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } - { ProgramPoint = ProgramPoint (0x1AUL, 3) - VarExpr = Regular (Intel.Register.toRegID Intel.Register.EDX) } |] - CollectionAssert.AreEqual (solution, res) diff --git a/src/MiddleEnd/DataFlow/B2R2.MiddleEnd.DataFlow.fsproj b/src/MiddleEnd/DataFlow/B2R2.MiddleEnd.DataFlow.fsproj deleted file mode 100644 index fdc9a3f6..00000000 --- a/src/MiddleEnd/DataFlow/B2R2.MiddleEnd.DataFlow.fsproj +++ /dev/null @@ -1,36 +0,0 @@ - - - - LICENSE.md - b2r2-240x240.png - README.md - B2R2 data-flow engine. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MiddleEnd/DataFlow/CPState.fs b/src/MiddleEnd/DataFlow/CPState.fs deleted file mode 100644 index eaff1b65..00000000 --- a/src/MiddleEnd/DataFlow/CPState.fs +++ /dev/null @@ -1,184 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open B2R2 -open B2R2.FrontEnd.BinInterface -open B2R2.BinIR.SSA -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph -open System.Collections.Generic - -/// An ID of an SSA memory instance. -type SSAMemID = int - -/// Constant propagation analysis state. -type CPState<'L when 'L: equality> = { - /// BinHandle of the current binary. - BinHandle: BinHandle - /// SSA edges - SSAEdges: SSAEdges.EdgeInfo - /// SSA var values. - RegState : Dictionary - /// SSA mem values. Only store values of constant addresses. The second set - /// contains addresses changed throughout the analysis (after initialization). - MemState : Dictionary * Set> - /// Executable edges from vid to vid. If there's no element for an edge, that - /// means the edge is not executable. - ExecutableEdges: HashSet - /// Executed edges from vid to vid. - ExecutedEdges: HashSet - /// Default word size of the current analysis. - DefaultWordSize : RegType - /// Worklist for blocks. - FlowWorkList: Queue - /// Worklist for SSA stmt, this stack stores a list of def variables, and we - /// will use SSAEdges to find all related SSA statements. - SSAWorkList: Stack - /// Uninitialized memory addresses found during CP. - UninitializedMemAddrs: HashSet - /// CP core interface. - CPCore: IConstantPropagationCore<'L> -} - -/// The core interface of a Constant Propagation (CP) algorithm. -and IConstantPropagationCore<'L when 'L: equality> = - /// Bottom of the lattice. - abstract Bottom: 'L - - /// Check if toV is up in the lattice compared to fromV. - abstract GoingUp: fromV: 'L -> toV: 'L -> bool - - /// The meet operator. - abstract Meet: 'L -> 'L -> 'L - - /// The transfer function. - abstract Transfer: - CPState<'L> - -> DiGraph - -> Vertex - -> ProgramPoint - -> Stmt - -> unit - - /// Read memory. Some analyses require reading data section values, and this - /// function is used in such cases. - abstract MemoryRead: Addr -> RegType -> BitVector option - -module CPState = - - let initState hdl ssaCfg initRegs initMems core = - { BinHandle = hdl - SSAEdges = SSAEdges.compute ssaCfg - RegState = initRegs - MemState = initMems - ExecutableEdges = HashSet () - ExecutedEdges = HashSet () - DefaultWordSize = hdl.ISA.WordSize |> WordSize.toRegType - FlowWorkList = Queue () - SSAWorkList = Stack () - UninitializedMemAddrs = HashSet () - CPCore = core } - - let markExecutable st src dst = - if st.ExecutableEdges.Add (src, dst) then st.FlowWorkList.Enqueue (src, dst) - else () - - let isExecuted st src dst = - st.ExecutedEdges.Contains (src, dst) - - let markAllSuccessors st cfg (blk: SSAVertex) = - let myid = blk.GetID () - DiGraph.getSuccs cfg blk - |> List.iter (fun succ -> - let succid = succ.GetID () - markExecutable st myid succid) - - let markExceptCallFallThrough st cfg (blk: SSAVertex) = - let myid = blk.GetID () - DiGraph.getSuccs cfg blk - |> List.iter (fun succ -> - if DiGraph.findEdgeData cfg blk succ <> CallFallThroughEdge then - let succid = succ.GetID () - markExecutable st myid succid - else ()) - - let getExecutableSources st cfg (blk: Vertex<_>) srcIDs = - let preds = DiGraph.getPreds cfg blk |> List.toArray - srcIDs - |> Array.mapi (fun i srcID -> - if isExecuted st (preds[i].GetID ()) (blk.GetID ()) then Some srcID - else None) - |> Array.choose id - - let inline updateConst st r v = - if not (st.RegState.ContainsKey r) then - st.RegState[r] <- v - st.SSAWorkList.Push r - elif st.RegState[r] = v then () - elif st.CPCore.GoingUp st.RegState[r] v then () - else - st.RegState[r] <- st.CPCore.Meet st.RegState[r] v - st.SSAWorkList.Push r - - let tryFindReg st lazyInit r = - match st.RegState.TryGetValue r with - | true, v -> Some v - | false, _ -> - if r.Identifier = 0 && lazyInit then Some st.CPCore.Bottom - else None - - let findReg st r = - match st.RegState.TryGetValue r with - | true, v -> v - | false, _ -> st.CPCore.Bottom - - let inline tryGetMemState st id = - st.MemState.TryGetValue id |> Utils.tupleToOpt - - let inline private initMemState st mid = - if st.MemState.ContainsKey mid then () - else st.MemState[mid] <- (Map.empty, Set.empty) - - let inline private isAligned st rt addr = - let align = RegType.toByteWidth rt |> uint64 - (rt = st.DefaultWordSize) && (addr % align = 0UL) - - let tryFindMem st m rt addr = - let mid = m.Identifier - initMemState st mid - if isAligned st rt addr then Map.tryFind addr <| fst st.MemState[mid] - else st.CPCore.Bottom |> Some - - let updateUninitialized st m addr = - let mid = m.Identifier - let mem, updated = st.MemState[mid] - let mem = Map.add addr st.CPCore.Bottom mem - st.MemState[mid] <- (mem, updated) - st.UninitializedMemAddrs.Add addr |> ignore - st.CPCore.Bottom - - let copyMem st dstid srcid = - st.MemState[dstid] <- st.MemState[srcid] diff --git a/src/MiddleEnd/DataFlow/Chains.fs b/src/MiddleEnd/DataFlow/Chains.fs deleted file mode 100644 index faca7d3f..00000000 --- a/src/MiddleEnd/DataFlow/Chains.fs +++ /dev/null @@ -1,118 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open System.Collections.Generic -open B2R2 -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph - -type DataFlowChain = { - UseDefChain: Map, Set>> - DefUseChain: Map, Set>> -} - -module DataFlowChain = - let private computeInBlockDefs pp u (outset: Set>) = - outset - |> Seq.filter (fun vp -> - vp.VarExpr = u - && vp.ProgramPoint < (pp: ProgramPoint)) - |> Seq.sortBy (fun vp -> vp.ProgramPoint) - |> Seq.tryLast (* Picking the def that has the largest position idx *) - - /// When there are more than one defs for the same variable, we should choose - /// the last one. - let private filterLastDefInBlock defs = - defs - |> Set.fold (fun map d -> - let addr = d.ProgramPoint.Address - match Map.tryFind addr map with - | None -> Map.add addr d map - | Some old -> - if old.ProgramPoint.Position > d.ProgramPoint.Position then map - else Map.add addr d map) Map.empty - |> Map.toList - |> List.map snd - - let private computeOutBlockDefs u (inset: Set>) = - inset - |> Set.filter (fun d -> d.VarExpr = u) - |> filterLastDefInBlock - - let private initUDChain cfg (ins: Dictionary<_,_>) (outs: Dictionary<_, _>) = - Map.empty - |> DiGraph.foldVertex cfg (fun map (v: Vertex) -> - v.VData.InsInfos - |> Array.fold (fun map info -> - info.Stmts - |> Array.foldi (fun map idx stmt -> - let pp = ProgramPoint (info.Instruction.Address, idx) - let inset = ins[v.GetID ()] - let outset = outs[v.GetID ()] - let uses = Utils.extractUses stmt - uses |> Set.fold (fun map u -> - let usepoint = { VarExpr = u; ProgramPoint = pp } - let set = computeOutBlockDefs u inset |> Set.ofList - let set = - match computeInBlockDefs pp u outset with - | Some def -> Set.add def set - | None -> set - Map.add usepoint set map - ) map - ) map |> fst - ) map) - - let private initDUChain udchain = - udchain - |> Map.fold (fun map u ds -> - ds - |> Set.fold (fun map d -> - match Map.tryFind d map with - | None -> Map.add d (Set.singleton u) map - | Some us -> Map.add d (Set.add u us) map) map) Map.empty - - let private normalizeVP (vp: VarPoint) = - let addr = vp.ProgramPoint.Address - { vp with ProgramPoint = ProgramPoint (addr, 0) } - - let private filterDisasm isDisasmLevel chain = - if not isDisasmLevel then chain - else - chain - |> Map.fold (fun map vp set -> - let vp = normalizeVP vp - let newSet = set |> Set.map normalizeVP - match Map.tryFind vp map with - | None -> Map.add vp newSet map - | Some old -> Map.add vp (Set.union old newSet) map) Map.empty - - [] - let init cfg root isDisasmLevel = - let rd = LowUIRReachingDefinitions (cfg) - let ins, outs = rd.Compute cfg root - let udchain = initUDChain cfg ins outs |> filterDisasm isDisasmLevel - let duchain = initDUChain udchain |> filterDisasm isDisasmLevel - { UseDefChain = udchain; DefUseChain = duchain } diff --git a/src/MiddleEnd/DataFlow/ConstantPropagation.fs b/src/MiddleEnd/DataFlow/ConstantPropagation.fs deleted file mode 100644 index 70304521..00000000 --- a/src/MiddleEnd/DataFlow/ConstantPropagation.fs +++ /dev/null @@ -1,84 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open B2R2 -open B2R2.BinIR.SSA -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph - -/// The constant propagation framework, which is a modified version of sparse -/// conditional constant propagation of Wegman et al. -[] -type ConstantPropagation<'L when 'L: equality> (ssaCFG) = - inherit DataFlowAnalysis<'L, SSABasicBlock> () - - /// Constant propagation state. - abstract State: CPState<'L> - - member private __.GetNumIncomingExecutedEdges st (blk: SSAVertex) = - let myid = blk.GetID () - DiGraph.getPreds ssaCFG blk - |> List.map (fun p -> p.GetID (), myid) - |> List.filter (fun (src, dst) -> CPState.isExecuted st src dst) - |> List.length - - member private __.ProcessSSA st = - while st.SSAWorkList.Count > 0 do - let def = st.SSAWorkList.Pop () - match Map.tryFind def st.SSAEdges.Uses with - | Some uses -> - uses - |> Set.iter (fun (vid, idx) -> - let v = DiGraph.findVertexByID ssaCFG vid - if __.GetNumIncomingExecutedEdges st v > 0 then - let ppoint, stmt = v.VData.SSAStmtInfos[idx] - st.CPCore.Transfer st ssaCFG v ppoint stmt - else ()) - | None -> () - - member private __.ProcessFlow st = - if st.FlowWorkList.Count > 0 then - let parentid, myid = st.FlowWorkList.Dequeue () - st.ExecutedEdges.Add (parentid, myid) |> ignore - let blk = DiGraph.findVertexByID ssaCFG myid - blk.VData.SSAStmtInfos - |> Array.iter (fun (ppoint, stmt) -> - st.CPCore.Transfer st ssaCFG blk ppoint stmt) - match blk.VData.GetLastStmt () with - | Jmp _ -> () - | _ -> (* Fall-through cases. *) - DiGraph.getSuccs ssaCFG blk - |> List.iter (fun succ -> - let succid = succ.GetID () - CPState.markExecutable st myid succid) - else () - - member __.Compute (root: Vertex<_>) = - __.State.FlowWorkList.Enqueue (0, root.GetID ()) - while __.State.FlowWorkList.Count > 0 || __.State.SSAWorkList.Count > 0 do - __.ProcessFlow __.State - __.ProcessSSA __.State - __.State diff --git a/src/MiddleEnd/DataFlow/DataFlowAnalysis.fs b/src/MiddleEnd/DataFlow/DataFlowAnalysis.fs deleted file mode 100644 index 7d31f92e..00000000 --- a/src/MiddleEnd/DataFlow/DataFlowAnalysis.fs +++ /dev/null @@ -1,134 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open B2R2 -open B2R2.MiddleEnd.BinGraph -open System.Collections.Generic - -/// Defined variable. -type VarExpr = - | Regular of RegisterID - | Temporary of int - | Memory of Addr - -/// Program point of a defined variable. -type VarPoint<'E> = { - ProgramPoint: ProgramPoint - VarExpr: 'E -} - -/// Either forward or backward analysis. -type DataFlowDirection = - | Forward - | Backward - -[] -type DataFlowHelper () = - /// Obtain the neighboring vertices. - abstract Neighbor: DiGraph<'V, 'E> -> Vertex<'V> -> Vertex<'V> list - - /// Add next vertices to the worklist queue. - abstract AddToWorkList: - DiGraph<'V, 'E> -> Vertex<'V> -> Queue> -> unit - -type private ForwardDataFlowHelper () = - inherit DataFlowHelper () - override __.Neighbor g v = DiGraph.getPreds g v - override __.AddToWorkList g v worklist = - DiGraph.getSuccs g v |> List.iter worklist.Enqueue - -type BackwardDataFlowHelper () = - inherit DataFlowHelper () - override __.Neighbor g v = DiGraph.getSuccs g v - override __.AddToWorkList g v worklist = - DiGraph.getPreds g v |> List.iter worklist.Enqueue - -/// Data-flow analysis framework. 'L is a lattice, 'V is a vertex data type of a -/// graph. -[] -type DataFlowAnalysis<'L, 'V when 'L: equality - and 'V :> VertexData> () = - /// The top of the lattice. A data-flow analysis solution is computed by - /// iterating down from top to bottom. - abstract Top: 'L - -/// Classic data-flow analysis with topological worklist algorithm. -[] -type TopologicalDataFlowAnalysis<'L, 'V - when 'L: equality - and 'V :> VertexData and 'V : equality> (direction) = - inherit DataFlowAnalysis<'L, 'V> () - - /// Exit lattice per vertex. - let outs = Dictionary () - - /// Entry lattice per vertex. - let ins = Dictionary () - - /// Accessor of the vertices to compute dataflow. This is dependent on the - /// direction of the analysis. - let helper = - match direction with - | Forward -> ForwardDataFlowHelper () :> DataFlowHelper - | Backward -> BackwardDataFlowHelper () :> DataFlowHelper - - /// Initialize worklist queue. This should be a topologically sorted list to - /// be efficient. - let initWorklist g (root: Vertex<'V>) = - let q = Queue> () - Traversal.iterRevPostorder g [root] q.Enqueue - q - - /// Meet operation of the lattice. - abstract Meet: 'L -> 'L -> 'L - - /// The transfer function from an input lattice to an output lattice. The - /// second parameter is to specify the current block of interest. - abstract Transfer: 'L -> Vertex<'V> -> 'L - - /// Initialize ints and outs. - member private __.InitInsOuts g (root: Vertex<'V>) = - Traversal.iterPreorder g [root] (fun v -> - let blkid = v.GetID () - outs[blkid] <- __.Top - ins[blkid] <- __.Top) - - /// Compute data-flow with the iterative worklist algorithm. - member __.Compute g (root: Vertex<'V>) = - __.InitInsOuts g root - let worklist = initWorklist g root - while worklist.Count <> 0 do - let blk = worklist.Dequeue () - let blkid = blk.GetID () - ins[blkid] <- - helper.Neighbor g blk - |> List.fold (fun eff v -> __.Meet eff outs[v.GetID()]) __.Top - let outeffect = __.Transfer ins[blkid] blk - if outs[blkid] <> outeffect then - outs[blkid] <- outeffect - helper.AddToWorkList g blk worklist - else () - ins, outs diff --git a/src/MiddleEnd/DataFlow/ReachingDefinitions.fs b/src/MiddleEnd/DataFlow/ReachingDefinitions.fs deleted file mode 100644 index bb5043b3..00000000 --- a/src/MiddleEnd/DataFlow/ReachingDefinitions.fs +++ /dev/null @@ -1,98 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open System.Collections.Generic -open B2R2 -open B2R2.BinIR -open B2R2.MiddleEnd.BinGraph -open B2R2.MiddleEnd.ControlFlowGraph - -[] -type ReachingDefinitions<'Expr, 'BBL when 'Expr: comparison - and 'BBL: equality - and 'BBL :> BasicBlock> - (_cfg: DiGraph<'BBL, CFGEdgeKind>) = - inherit TopologicalDataFlowAnalysis>, 'BBL> (Forward) - - let gens = Dictionary>> () - let kills = Dictionary>> () - - member __.Gens with get() = gens - - member __.Kills with get() = kills - - override __.Meet a b = Set.union a b - - override __.Top = Set.empty - - override __.Transfer i v = - let vid = v.GetID () - Set.union gens[vid] (Set.difference i kills[vid]) - -/// Reaching definition analysis with a LowUIR-based CFG. -type LowUIRReachingDefinitions (cfg) as this = - inherit ReachingDefinitions (cfg) - - do this.Initialize this.Gens this.Kills - - member private __.FindDefs (v: Vertex) = - v.VData.InsInfos - |> Array.fold (fun list info -> - info.Stmts - |> Array.foldi (fun list idx stmt -> - match stmt.S with - | LowUIR.Put ({ LowUIR.E = LowUIR.TempVar (_, n) }, _) -> - let pp = ProgramPoint (info.Instruction.Address, idx) - { ProgramPoint = pp; VarExpr = Temporary n } :: list - | LowUIR.Put ({ LowUIR.E = LowUIR.Var (_, id, _, _) }, _) -> - let pp = ProgramPoint (info.Instruction.Address, idx) - { ProgramPoint = pp; VarExpr = Regular id } :: list - | _ -> list) list - |> fst) [] - - member private __.Initialize - (gens: Dictionary<_, _>) (kills: Dictionary<_, _>) = - let vpPerVar = Dictionary>> () - let vpPerVertex = Dictionary list> () - DiGraph.iterVertex cfg (fun v -> - let vid = v.GetID () - let defs = __.FindDefs v - gens[vid] <- defs |> Set.ofList - vpPerVertex[vid] <- defs - defs |> List.iter (fun ({ VarExpr = v } as vp) -> - if vpPerVar.ContainsKey v then vpPerVar[v] <- Set.add vp vpPerVar[v] - else vpPerVar[v] <- Set.singleton vp - ) - ) - DiGraph.iterVertex cfg (fun v -> - let vid = v.GetID () - let defVarPoints = vpPerVertex[vid] - let vars = defVarPoints |> List.map (fun vp -> vp.VarExpr) - let vps = defVarPoints |> Set.ofList - let alldefs = - vars |> List.fold (fun set v -> Set.union set vpPerVar[v]) Set.empty - kills[vid] <- Set.difference alldefs vps - ) diff --git a/src/MiddleEnd/DataFlow/SCPTransfer.fs b/src/MiddleEnd/DataFlow/SCPTransfer.fs deleted file mode 100644 index 20af92d3..00000000 --- a/src/MiddleEnd/DataFlow/SCPTransfer.fs +++ /dev/null @@ -1,173 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.DataFlow.SCPTransfer - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph - -let private updateReadOnlyMem st mDst rt addr c = - let align = RegType.toByteWidth rt |> uint64 - let dstid = mDst.Identifier - let mem, updated = st.MemState[dstid] - if (rt = st.DefaultWordSize) && (addr % align = 0UL) then - let mem = Map.add addr c mem - st.MemState[dstid] <- (mem, updated) - else () - -let evalLoad st m rt addr = - match addr with - | Const addr -> - let addr = BitVector.toUInt64 addr - match CPState.tryFindMem st m rt addr with - | Some v -> v - | None -> - match st.CPCore.MemoryRead addr rt with - | Some v -> - let v = Const v (* Found a read-only memory contents, so update it. *) - updateReadOnlyMem st m rt addr v - v - | None -> CPState.updateUninitialized st m addr - | _ -> NotAConst - -let evalUnOp op c = - match op with - | UnOpType.NEG -> SCPValue.neg c - | UnOpType.NOT -> SCPValue.not c - | _ -> NotAConst - -let evalBinOp op c1 c2 = - match op with - | BinOpType.ADD -> SCPValue.add c1 c2 - | BinOpType.SUB -> SCPValue.sub c1 c2 - | BinOpType.MUL -> SCPValue.mul c1 c2 - | BinOpType.DIV -> SCPValue.div c1 c2 - | BinOpType.SDIV -> SCPValue.sdiv c1 c2 - | BinOpType.MOD -> SCPValue.``mod`` c1 c2 - | BinOpType.SMOD -> SCPValue.smod c1 c2 - | BinOpType.SHL -> SCPValue.shl c1 c2 - | BinOpType.SHR -> SCPValue.shr c1 c2 - | BinOpType.SAR -> SCPValue.sar c1 c2 - | BinOpType.AND -> SCPValue.``and`` c1 c2 - | BinOpType.OR -> SCPValue.``or`` c1 c2 - | BinOpType.XOR -> SCPValue.xor c1 c2 - | BinOpType.CONCAT -> SCPValue.concat c1 c2 - | _ -> NotAConst - -let evalRelOp op c1 c2 = - match op with - | RelOpType.EQ -> SCPValue.eq c1 c2 - | RelOpType.NEQ -> SCPValue.neq c1 c2 - | RelOpType.GT -> SCPValue.gt c1 c2 - | RelOpType.GE -> SCPValue.ge c1 c2 - | RelOpType.SGT -> SCPValue.sgt c1 c2 - | RelOpType.SGE -> SCPValue.sge c1 c2 - | RelOpType.LT -> SCPValue.lt c1 c2 - | RelOpType.LE -> SCPValue.le c1 c2 - | RelOpType.SLT -> SCPValue.slt c1 c2 - | RelOpType.SLE -> SCPValue.sle c1 c2 - | _ -> NotAConst - -let evalCast op rt c = - match op with - | CastKind.SignExt -> SCPValue.signExt rt c - | CastKind.ZeroExt -> SCPValue.zeroExt rt c - | _ -> NotAConst - -let evalReturn st (blk: SSAVertex) ret var = - match var.Kind with - | RegVar (rt, rid, _) -> - let hdl = st.BinHandle - if hdl.RegisterBay.IsStackPointer rid then - let value = CPState.findReg st var - let shiftAmount = Const (Utils.computeStackShift rt blk) - evalBinOp BinOpType.ADD value shiftAmount - elif GetPCThunkInfo.isGetPCThunk blk.VData.FakeBlockInfo.GetPCThunkInfo then - Thunk (BitVector.ofUInt64 ret rt) - elif CallingConvention.isNonVolatile hdl rid then - CPState.findReg st var - else NotAConst - | _ -> Utils.impossible () - -let rec evalExpr st blk = function - | Num bv -> Const bv - | Var v -> CPState.findReg st v - | Load (m, rt, addr) -> evalExpr st blk addr |> evalLoad st m rt - | UnOp (op, _, e) -> evalExpr st blk e |> evalUnOp op - | BinOp (op, _, e1, e2) -> - let c1 = evalExpr st blk e1 - let c2 = evalExpr st blk e2 - evalBinOp op c1 c2 - | RelOp (op, _, e1, e2) -> - let c1 = evalExpr st blk e1 - let c2 = evalExpr st blk e2 - evalRelOp op c1 c2 - | Ite (e1, _, e2, e3) -> - let c1 = evalExpr st blk e1 - let c2 = evalExpr st blk e2 - let c3 = evalExpr st blk e3 - SCPValue.ite c1 c2 c3 - | Cast (op, rt, e) -> - let c = evalExpr st blk e - evalCast op rt c - | Extract (e, rt, pos) -> - let c = evalExpr st blk e - SCPValue.extract c rt pos - | ReturnVal (_addr, ret, v) -> - evalReturn st blk ret v - | FuncName _ - | Nil - | Undefined _ -> NotAConst - | _ -> Utils.impossible () - -let evalDef (st: CPState) blk v e = - match v.Kind with - | MemVar -> () - | _ -> evalExpr st blk e |> CPState.updateConst st v - -let evalPhi st cfg blk dst srcIDs = - match CPState.getExecutableSources st cfg blk srcIDs with - | [||] -> () - | executableSrcIDs -> - match dst.Kind with - | MemVar -> () - | _ -> - executableSrcIDs - |> Array.choose (fun i -> - { dst with Identifier = i } |> CPState.tryFindReg st true) - |> Array.reduce SCPValue.meet - |> fun merged -> CPState.updateConst st dst merged - -let evalJmp st cfg blk = function - | InterJmp _ -> CPState.markExceptCallFallThrough st cfg blk - | _ -> CPState.markAllSuccessors st cfg blk - -let evalStmt st cfg blk = function - | Def (v, e) -> evalDef st blk v e - | Phi (v, ns) -> evalPhi st cfg blk v ns - | Jmp jmpTy -> evalJmp st cfg blk jmpTy - | LMark _ | SideEffect _ -> () diff --git a/src/MiddleEnd/DataFlow/SCPValue.fs b/src/MiddleEnd/DataFlow/SCPValue.fs deleted file mode 100644 index 3f2af724..00000000 --- a/src/MiddleEnd/DataFlow/SCPValue.fs +++ /dev/null @@ -1,171 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open B2R2 - -/// Thunk and Pointer are the only special kind of SCPValue, which should not -/// be invalidated across function calls. This is to correctly track GOT -/// pointers. -type SCPValue = - | NotAConst - | Const of BitVector - /// Special value type representing a return value of *_get_pc_thunk. - | Thunk of BitVector - | Pointer of BitVector - | Undef - -[] -module SCPValue = - - /// Are we going towards TOP from a given value "fromV" to a new value "toV"? - /// If so, our meet operation will not change the value, and we don't need to - /// push a new task to the SSAWorkList. - let goingUp fromV toV = - match fromV, toV with - | Const _, Undef - | Pointer _, Undef - | Thunk _, Undef - | NotAConst, Undef - | NotAConst, Const _ - | NotAConst, Thunk _ - | NotAConst, Pointer _ -> true - | _ -> false - - /// The meet operator. - let meet c1 c2 = - match c1, c2 with - | Undef, c | c, Undef -> c - | Const bv1, Const bv2 -> if bv1 = bv2 then c1 else NotAConst - | Thunk bv1, Thunk bv2 -> if bv1 = bv2 then c1 else NotAConst - | Pointer bv1, Pointer bv2 -> if bv1 = bv2 then c1 else NotAConst - | _ -> NotAConst - - let unOp op = function - | Const bv -> Const (op bv) - | Thunk bv -> Const (op bv) - | Pointer bv -> Const (op bv) - | c -> c - - let neg c = unOp BitVector.neg c - - let not c = unOp BitVector.bnot c - - let binOp op c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | Pointer bv1, Pointer bv2 - | Pointer bv1, Const bv2 - | Const bv1, Pointer bv2 - | Const bv1, Const bv2 -> Const (op bv1 bv2) - | _ -> NotAConst - - let add c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | Thunk bv1, Const bv2 - | Const bv1, Thunk bv2 -> Pointer (BitVector.add bv1 bv2) - | Pointer bv1, Pointer bv2 - | Pointer bv1, Const bv2 - | Const bv1, Pointer bv2 - | Const bv1, Const bv2 -> Const (BitVector.add bv1 bv2) - | _ -> NotAConst - - let sub c1 c2 = binOp BitVector.sub c1 c2 - - let mul c1 c2 = binOp BitVector.mul c1 c2 - - let divAux divop c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | Pointer bv1, Pointer bv2 - | Pointer bv1, Const bv2 - | Const bv1, Pointer bv2 - | Const bv1, Const bv2 -> - if BitVector.isZero bv2 then NotAConst - else Const (divop bv1 bv2) - | _ -> NotAConst - - let div c1 c2 = divAux BitVector.div c1 c2 - - let sdiv c1 c2 = divAux BitVector.sdiv c1 c2 - - let ``mod`` c1 c2 = divAux BitVector.modulo c1 c2 - - let smod c1 c2 = divAux BitVector.smodulo c1 c2 - - let shl c1 c2 = binOp BitVector.shl c1 c2 - - let shr c1 c2 = binOp BitVector.shr c1 c2 - - let sar c1 c2 = binOp BitVector.sar c1 c2 - - let ``and`` c1 c2 = binOp BitVector.band c1 c2 - - let ``or`` c1 c2 = binOp BitVector.bor c1 c2 - - let xor c1 c2 = binOp BitVector.bxor c1 c2 - - let concat c1 c2 = binOp BitVector.concat c1 c2 - - let relOp op c1 c2 = binOp op c1 c2 - - let eq c1 c2 = relOp BitVector.eq c1 c2 - - let neq c1 c2 = relOp BitVector.neq c1 c2 - - let gt c1 c2 = relOp BitVector.gt c1 c2 - - let ge c1 c2 = relOp BitVector.ge c1 c2 - - let sgt c1 c2 = relOp BitVector.sgt c1 c2 - - let sge c1 c2 = relOp BitVector.sge c1 c2 - - let lt c1 c2 = relOp BitVector.lt c1 c2 - - let le c1 c2 = relOp BitVector.le c1 c2 - - let slt c1 c2 = relOp BitVector.slt c1 c2 - - let sle c1 c2 = relOp BitVector.sle c1 c2 - - let ite cond c1 c2 = - match cond with - | Undef -> Undef - | Pointer bv - | Thunk bv - | Const bv -> if BitVector.isZero bv then c2 else c1 - | NotAConst -> meet c1 c2 - - let cast op rt c = - unOp (fun bv -> op bv rt) c - - let signExt rt c = cast BitVector.sext rt c - - let zeroExt rt c = cast BitVector.zext rt c - - let extract c rt pos = - unOp (fun bv -> BitVector.extract bv rt pos) c diff --git a/src/MiddleEnd/DataFlow/SPTransfer.fs b/src/MiddleEnd/DataFlow/SPTransfer.fs deleted file mode 100644 index e9ff383a..00000000 --- a/src/MiddleEnd/DataFlow/SPTransfer.fs +++ /dev/null @@ -1,105 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.DataFlow.SPTransfer - -open B2R2 -open B2R2.BinIR -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.ControlFlowGraph -open B2R2.BinIR.SSA - -let evalBinOp op c1 c2 = - match op with - | BinOpType.ADD -> SPValue.add c1 c2 - | BinOpType.SUB -> SPValue.sub c1 c2 - | BinOpType.AND -> SPValue.``and`` c1 c2 - | _ -> NotAConst - -let isStackRelatedRegister (st: CPState) regid = - st.BinHandle.RegisterBay.IsStackPointer regid - || st.BinHandle.RegisterBay.IsFramePointer regid - -let evalReturn (st: CPState) (blk: SSAVertex) var = - match var.Kind with - | RegVar (rt, rid, _) -> - let hdl = st.BinHandle - if isStackRelatedRegister st rid then - if hdl.RegisterBay.IsStackPointer rid then - let value = CPState.findReg st var - let shiftAmount = Const (Utils.computeStackShift rt blk) - evalBinOp BinOpType.ADD value shiftAmount - else CPState.findReg st var - else NotAConst - | _ -> Utils.impossible () - -let rec evalExpr st blk = function - | Num bv -> Const bv - | Var v -> CPState.findReg st v - | Nil -> NotAConst - | Load _ -> NotAConst - | UnOp _ -> NotAConst - | FuncName _ -> NotAConst - | BinOp (op, _, e1, e2) -> - let c1 = evalExpr st blk e1 - let c2 = evalExpr st blk e2 - evalBinOp op c1 c2 - | RelOp _ -> NotAConst - | Ite _ -> NotAConst - | Cast _ -> NotAConst - | Extract _ -> NotAConst - | Undefined _ -> NotAConst - | ReturnVal (addr, _, v) -> evalReturn st blk v - | _ -> Utils.impossible () - -let evalDef (st: CPState) blk v e = - match v.Kind with - | RegVar (_, regid, _) when isStackRelatedRegister st regid -> - evalExpr st blk e |> CPState.updateConst st v - | RegVar _ -> CPState.updateConst st v NotAConst - | TempVar _ -> evalExpr st blk e |> CPState.updateConst st v - | _ -> () - -let evalPhi st cfg blk dst srcIDs = - match CPState.getExecutableSources st cfg blk srcIDs with - | [||] -> () - | executableSrcIDs -> - match dst.Kind with - | RegVar _ | TempVar _ -> - executableSrcIDs - |> Array.choose (fun i -> - { dst with Identifier = i } |> CPState.tryFindReg st true) - |> Array.reduce st.CPCore.Meet - |> fun merged -> CPState.updateConst st dst merged - | _ -> () - -let evalJmp st cfg blk = function - | InterJmp _ -> CPState.markExceptCallFallThrough st cfg blk - | _ -> CPState.markAllSuccessors st cfg blk - -let evalStmt st cfg blk = function - | Def (v, e) -> evalDef st blk v e - | Phi (v, ns) -> evalPhi st cfg blk v ns - | Jmp jmpTy -> evalJmp st cfg blk jmpTy - | LMark _ | SideEffect _ -> () diff --git a/src/MiddleEnd/DataFlow/SPValue.fs b/src/MiddleEnd/DataFlow/SPValue.fs deleted file mode 100644 index cb0c3fe5..00000000 --- a/src/MiddleEnd/DataFlow/SPValue.fs +++ /dev/null @@ -1,64 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open B2R2 - -/// StackPointerPropagation values. -type SPValue = - | NotAConst - | Const of BitVector - | Undef - -module SPValue = - - let goingUp fromV toV = - match fromV, toV with - | Const _, Undef - | NotAConst, Undef - | NotAConst, Const _ -> true - | _ -> false - - let meet c1 c2 = - match c1, c2 with - | Undef, c | c, Undef -> c - | Const bv1, Const bv2 -> if bv1 = bv2 then c1 else NotAConst - | _ -> NotAConst - - let binOp op c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | Const bv1, Const bv2 -> Const (op bv1 bv2) - | _ -> NotAConst - - let add c1 c2 = - match c1, c2 with - | Undef, _ | _, Undef -> Undef - | Const bv1, Const bv2 -> Const (BitVector.add bv1 bv2) - | _ -> NotAConst - - let sub c1 c2 = binOp BitVector.sub c1 c2 - - let ``and`` c1 c2 = binOp BitVector.band c1 c2 diff --git a/src/MiddleEnd/DataFlow/SparseConstantPropagation.fs b/src/MiddleEnd/DataFlow/SparseConstantPropagation.fs deleted file mode 100644 index c66d05ee..00000000 --- a/src/MiddleEnd/DataFlow/SparseConstantPropagation.fs +++ /dev/null @@ -1,67 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open System.Collections.Generic -open B2R2 -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.DataFlow.Utils - -[] -module private SparseConstantPropagation = - - let initRegister hdl = - let dict = Dictionary () - match hdl.RegisterBay.StackPointer with - | Some sp -> - let rt = hdl.RegisterBay.RegIDToRegType sp - let str = hdl.RegisterBay.RegIDToString sp - let var = { Kind = RegVar (rt, sp, str); Identifier = 0 } - dict[var] <- Const (BitVector.ofUInt64 InitialStackPointer rt) - dict - | None -> dict - -/// The most basic constant propagation algorithm, which can track stack-based -/// memory objects and GOT pointers. The reader is to enable reading data -/// from external sections, e.g., rodata. If the reader is not given, we simply -/// ignore such global data. -type SparseConstantPropagation (hdl, ssaCFG, ?reader) as this = - - inherit ConstantPropagation (ssaCFG) - - let reader = defaultArg reader (fun _ _ -> None) - let st = CPState.initState hdl ssaCFG (initRegister hdl) (initMemory ()) this - - override __.State = st - - override __.Top = Undef - - interface IConstantPropagationCore with - member __.Bottom = NotAConst - member __.GoingUp a b = SCPValue.goingUp a b - member __.Meet a b = SCPValue.meet a b - member __.Transfer st cfg blk _ stmt = SCPTransfer.evalStmt st cfg blk stmt - member __.MemoryRead addr rt = reader addr rt diff --git a/src/MiddleEnd/DataFlow/StackPointerPropagation.fs b/src/MiddleEnd/DataFlow/StackPointerPropagation.fs deleted file mode 100644 index b655b190..00000000 --- a/src/MiddleEnd/DataFlow/StackPointerPropagation.fs +++ /dev/null @@ -1,65 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open System.Collections.Generic -open B2R2 -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface - -[] -module private StackPointerPropagation = - - let initRegister hdl = - let dict = Dictionary () - match hdl.RegisterBay.StackPointer with - | Some sp -> - let rt = hdl.RegisterBay.RegIDToRegType sp - let str = hdl.RegisterBay.RegIDToString sp - let var = { Kind = RegVar (rt, sp, str); Identifier = 0 } - dict[var] <- Const (BitVector.ofUInt64 Utils.InitialStackPointer rt) - dict - | None -> dict - -/// This is a variant of the SparseConstantPropagation, which only tracks -/// the stack pointer used in a function. We initiate the stack pointer with a -/// constant first, and check how it propagates within the function. -/// StackPointerPropagation is generally much faster than -/// SparseConstantPropagation due to its simplicity. -type StackPointerPropagation (hdl, ssaCFG) as this = - inherit ConstantPropagation (ssaCFG) - - let st = CPState.initState hdl ssaCFG (initRegister hdl) (Dictionary ()) this - - override __.State = st - - override __.Top = Undef - - interface IConstantPropagationCore with - member __.Bottom = NotAConst - member __.GoingUp a b = SPValue.goingUp a b - member __.Meet a b = SPValue.meet a b - member __.Transfer st cfg v _ stmt = SPTransfer.evalStmt st cfg v stmt - member __.MemoryRead _addr _rt = None diff --git a/src/MiddleEnd/DataFlow/UVTransfer.fs b/src/MiddleEnd/DataFlow/UVTransfer.fs deleted file mode 100644 index 9976f88b..00000000 --- a/src/MiddleEnd/DataFlow/UVTransfer.fs +++ /dev/null @@ -1,75 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.DataFlow.UVTransfer - -open B2R2 -open B2R2.BinIR -open B2R2.BinIR.SSA - -let evalVar st v = - match CPState.tryFindReg st false v with - | None -> - if v.Identifier = 0 then Untouched (RegisterTag v) (* Initialize here. *) - else Touched - | Some c -> c - -let rec evalExpr st blk = function - | Var v -> evalVar st v - | Extract (e, _, _) - | Cast (CastKind.ZeroExt, _, e) - | Cast (CastKind.SignExt, _, e) -> evalExpr st blk e - | _ -> Touched (* Any other operations will be considered "touched". *) - -let evalDef st blk dstVar e = - match dstVar.Kind with - | MemVar - | PCVar _ -> () (* Just ignore PCVar as it will always be "touched". *) - | _ -> evalExpr st blk e |> CPState.updateConst st dstVar - -let evalPhi st cfg blk dst srcIDs = - match CPState.getExecutableSources st cfg blk srcIDs with - | [||] -> () - | executableSrcIDs -> - match dst.Kind with - | MemVar | PCVar _ -> () - | _ -> - match CPState.tryFindReg st true dst with - | Some Touched -> () - | _ -> - executableSrcIDs - |> Array.choose (fun i -> - { dst with Identifier = i } |> CPState.tryFindReg st true) - |> Array.reduce UVValue.meet - |> fun merged -> CPState.updateConst st dst merged - -let evalJmp st cfg blk = function - | InterJmp _ -> CPState.markExceptCallFallThrough st cfg blk - | _ -> CPState.markAllSuccessors st cfg blk - -let evalStmt st cfg blk = function - | Def (v, e) -> evalDef st blk v e - | Phi (v, ns) -> evalPhi st cfg blk v ns - | Jmp jmpTy -> evalJmp st cfg blk jmpTy - | LMark _ | SideEffect _ -> () diff --git a/src/MiddleEnd/DataFlow/UntouchedValuePropagation.fs b/src/MiddleEnd/DataFlow/UntouchedValuePropagation.fs deleted file mode 100644 index 605d24cc..00000000 --- a/src/MiddleEnd/DataFlow/UntouchedValuePropagation.fs +++ /dev/null @@ -1,71 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -namespace B2R2.MiddleEnd.DataFlow - -open System.Collections.Generic -open B2R2.BinIR.SSA -open B2R2.FrontEnd.BinInterface -open B2R2.MiddleEnd.DataFlow.Utils - -[] -module private UntouchedValuePropagation = - - let initRegister hdl = - let dict = Dictionary () - hdl.RegisterBay.GetGeneralRegExprs () - |> List.iter (fun regExpr -> - let rid = hdl.RegisterBay.RegIDFromRegExpr regExpr - let rt = hdl.RegisterBay.RegIDToRegType rid - let str = hdl.RegisterBay.RegIDToString rid - let var = { Kind = RegVar (rt, rid, str); Identifier = 0 } - dict[var] <- Untouched (RegisterTag var) - ) - match hdl.RegisterBay.StackPointer with - | Some sp -> - let rt = hdl.RegisterBay.RegIDToRegType sp - let str = hdl.RegisterBay.RegIDToString sp - let var = { Kind = RegVar (rt, sp, str); Identifier = 0 } - dict[var] <- Touched - dict - | None -> dict - -/// This is a variant of the SparseConstantPropagation, which computes which -/// registers or memory cells are not re-defined (i.e., are untouched) within a -/// function. This algorithm assumes that the SSA has been promoted. -type UntouchedValuePropagation (hdl, ssaCFG) as this = - inherit ConstantPropagation (ssaCFG) - - let st = CPState.initState hdl ssaCFG (initRegister hdl) (initMemory ()) this - - override __.State = st - - override __.Top = Undef - - interface IConstantPropagationCore with - member __.Bottom = Touched - member __.GoingUp a b = UVValue.goingUp a b - member __.Meet a b = UVValue.meet a b - member __.Transfer st cfg v _ppoint stmt = UVTransfer.evalStmt st cfg v stmt - member __.MemoryRead _addr _rt = None diff --git a/src/MiddleEnd/DataFlow/Utils.fs b/src/MiddleEnd/DataFlow/Utils.fs deleted file mode 100644 index ab84d82d..00000000 --- a/src/MiddleEnd/DataFlow/Utils.fs +++ /dev/null @@ -1,77 +0,0 @@ -(* - B2R2 - the Next-Generation Reversing Platform - - Copyright (c) SoftSec Lab. @ KAIST, since 2016 - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*) - -module B2R2.MiddleEnd.DataFlow.Utils - -open System.Collections.Generic -open B2R2 -open B2R2.BinIR.LowUIR -open B2R2.MiddleEnd.ControlFlowGraph - -/// We use this constant for our data-flow analyses. -let [] InitialStackPointer = 0x80000000UL - -let rec private extractUseFromExpr e = - match e.E with - | Var (_, id, _, _) -> [ Regular id ] - | TempVar (_, n) -> [ Temporary n ] - | UnOp (_, e, _) -> extractUseFromExpr e - | BinOp (_, _, e1, e2, _) -> extractUseFromExpr e1 @ extractUseFromExpr e2 - | RelOp (_, e1, e2, _) -> extractUseFromExpr e1 @ extractUseFromExpr e2 - | Load (_, _, e, _) -> extractUseFromExpr e - | Ite (c, e1, e2, _) -> - extractUseFromExpr c @ extractUseFromExpr e1 @ extractUseFromExpr e2 - | Cast (_, _, e, _) -> extractUseFromExpr e - | Extract (e, _, _, _) -> extractUseFromExpr e - | _ -> [] - -let private extractUseFromStmt s = - match s.S with - | Put (_, e) - | Store (_, _, e) - | Jmp (e) - | CJmp (e, _, _) - | InterJmp (e, _) -> extractUseFromExpr e - | InterCJmp (c, e1, e2) -> - extractUseFromExpr c @ extractUseFromExpr e1 @ extractUseFromExpr e2 - | _ -> [] - -let extractUses stmt = - extractUseFromStmt stmt - |> Set.ofList - -let filterRegularVars vars = - vars |> Set.filter (function - | Regular _ -> true - | _ -> false) - -let inline initMemory () = - let dict = Dictionary () - dict[0] <- (Map.empty, Set.empty) - dict - -let computeStackShift rt (blk: SSAVertex) = - let retAddrSize = RegType.toByteWidth rt |> int64 - let adj = blk.VData.FakeBlockInfo.UnwindingBytes - BitVector.ofInt64 (retAddrSize + adj) rt diff --git a/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj b/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj index bef5ac74..23ebe316 100644 --- a/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj +++ b/src/Peripheral/Assembly.Tests/B2R2.Peripheral.Assembly.Tests.fsproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/src/Peripheral/Assembly.Tests/Intel.Tests.fs b/src/Peripheral/Assembly.Tests/Intel.Tests.fs index 816ba581..cf68c7a3 100644 --- a/src/Peripheral/Assembly.Tests/Intel.Tests.fs +++ b/src/Peripheral/Assembly.Tests/Intel.Tests.fs @@ -30,7 +30,7 @@ open B2R2.Peripheral.Assembly.Intel [] type X86Tests () = - let isa = ISA.Init Arch.IntelX86 Endian.Little + let isa = ISA.Init Architecture.IntelX86 Endian.Little let asm = IntelAsmParser (isa, 0UL) [] @@ -55,5 +55,5 @@ done: [| 0x8buy; 0x05uy; 0x0fuy; 0x00uy; 0x00uy; 0x00uy |] [| 0x43uy |] [| 0xc3uy |] ] - List.forall2 (fun a b -> a = b) result expectation + List.forall2 (=) result expectation |> Assert.IsTrue diff --git a/src/Peripheral/Assembly.Tests/LowUIR.Tests.fs b/src/Peripheral/Assembly.Tests/LowUIR.Tests.fs index 7ae7434e..f2ad6304 100644 --- a/src/Peripheral/Assembly.Tests/LowUIR.Tests.fs +++ b/src/Peripheral/Assembly.Tests/LowUIR.Tests.fs @@ -32,17 +32,17 @@ open B2R2.Peripheral.Assembly.LowUIR [] type LowUIRTests () = - let regbay = Intel.Basis.initRegBay (WordSize.Bit64) - let p = LowUIRParser (ISA.DefaultISA, regbay) + let wsz = WordSize.Bit64 + let regFactory = Intel.IntelRegisterFactory (wsz, Intel.RegExprs wsz) + let p = LowUIRParser (ISA.DefaultISA, regFactory) let size1Num = BitVector.T - let size64Num = BitVector.cast size1Num 64 + let size64Num = BitVector.Cast (size1Num, 64) [] member __.``[IntelAssemblerLowUIR] Test Register Assignment ``() = let result = p.Parse "RAX := 0x1:I64" |> Result.get |> Array.head let regID = Intel.Register.toRegID (Intel.Register.RAX) - let regSet = Intel.IntelRegisterSet.singleton regID - let answer = AST.put (AST.var 64 regID "RAX" regSet) (AST.num size64Num) + let answer = AST.put (AST.var 64 regID "RAX") (AST.num size64Num) Assert.AreEqual (answer, result) [] @@ -62,8 +62,7 @@ type LowUIRTests () = let result = p.Parse "RAX := (0x1:I64 - 0x1:I64)" |> Result.get |> Array.head let regID = Intel.Register.toRegID (Intel.Register.RAX) - let regSet = Intel.IntelRegisterSet.singleton regID let answer = - AST.put (AST.var 64 regID "RAX" regSet) - (AST.num (BitVector.cast BitVector.F 64)) + AST.put (AST.var 64 regID "RAX") + (AST.num (BitVector.Cast (BitVector.F, 64))) Assert.AreEqual (answer, result) diff --git a/src/Peripheral/Assembly.Tests/MIPS.Tests.fs b/src/Peripheral/Assembly.Tests/MIPS.Tests.fs index ff5b36b1..b3ff2d14 100644 --- a/src/Peripheral/Assembly.Tests/MIPS.Tests.fs +++ b/src/Peripheral/Assembly.Tests/MIPS.Tests.fs @@ -32,7 +32,9 @@ open B2R2.FrontEnd.BinLifter.MIPS [] type MIPSTests () = let mips = - { Arch = Arch.MIPS32; Endian = Endian.Big; WordSize = WordSize.Bit32 } + { Arch = Architecture.MIPS32 + Endian = Endian.Big + WordSize = WordSize.Bit32 } let assembler = MIPS.AsmParser (mips, 0UL) let newInfo = MIPS.ParserHelper.newInfo diff --git a/src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs b/src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs index ad1e4e60..2f701e1f 100644 --- a/src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs +++ b/src/Peripheral/Assembly/ARM32/ARM32AsmParser.fs @@ -31,7 +31,7 @@ open FParsec open System type UserState = Map -type Parser<'a> = Parser<'a, unit> +type Parser<'A> = Parser<'A, unit> type AsmParser (startAddress: Addr) = @@ -106,10 +106,9 @@ type AsmParser (startAddress: Addr) = let pPSRFlag = [ "c"; "x"; "xc"; "s"; "sc"; "sx"; "sxc"; "f"; "fc"; "fx"; "fxc"; - "fs"; "fsc"; "fsx"; "fsxc"; "nzcv"; "nzcvq"; "g"; "nzcvqg" ] + "fs"; "fsc"; "fsx"; "fsxc"; "nzcv"; "nzcvq"; "g"; "nzcvqg" ] |> Seq.rev - |> Seq.map pstringCI - |> Seq.map attempt + |> Seq.map (pstringCI >> attempt) |> choice |>> getPSRFlagFromStr |>> Some @@ -117,22 +116,19 @@ type AsmParser (startAddress: Addr) = let pOptionOpr = [ "sy"; "ld"; "ishst"; "ishld"; "ish"; "nshst"; "nshld"; "nsh"; "oshst"; "oshld"; "osh" ] - |> Seq.map pstringCI - |> Seq.map attempt + |> Seq.map (pstringCI >> attempt) |> choice |>> optionOprFromStr let pSRType = [ "lsl"; "lsr"; "asr"; "ror"; "rrx" ] - |> Seq.map pstringCI - |> Seq.map attempt + |> Seq.map (pstringCI >> attempt) |> choice |>> getSRType let pIflag = [ "ai"; "af"; "if"; "aif"; "a"; "i" ] - |> Seq.map pstringCI - |> Seq.map attempt + |> Seq.map (pstringCI >> attempt) |> choice |>> iFlagFromStr @@ -157,21 +153,18 @@ type AsmParser (startAddress: Addr) = (Enum.GetNames typeof) |> Array.map (pstringCI) |> Array.rev (* This is so that (eg. ADD does not get parsed for 'ADDS' *) - |> Array.map (fun p -> attempt (p)) - |> Array.map - (fun p -> - p |>> - (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Opcode)) + |> Array.map (fun p -> + attempt p + |>> (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Opcode)) |> choice let pCondition = ((Enum.GetNames typeof) - |> Array.map pstringCI |> Array.map - (fun p -> - p |>> - (fun name -> - Enum.Parse(typeof, name.ToUpper()) :?> Condition)) + (fun s -> + pstringCI s + |>> (fun name -> + Enum.Parse(typeof, name.ToUpper()) :?> Condition)) |> choice) let numberFormat = @@ -332,7 +325,7 @@ type AsmParser (startAddress: Addr) = pOpcode .>>. pCondition .>>. opt (attempt pSIMDDataTypes) .>>. opt pQualifier >>= pOperands |>> (fun ((((opcode, cond), simd), qual), operands) -> - let qual = match qual with | Some W -> W | _ -> N /// XXX + let qual = match qual with | Some W -> W | _ -> N newInsInfo address opcode cond 0uy wBackFlag qual simd operands (getInsLength ()) opMode None ) diff --git a/src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs b/src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs index 13a2f8f3..4ed59fca 100644 --- a/src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs +++ b/src/Peripheral/Assembly/ARM32/ARM32ParserHelper.fs @@ -68,7 +68,7 @@ let parseShiftOperation opcode imm = else preturn (srType.Value, imm) let getSRType (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "lsl" -> SRTypeLSL | "lsr" -> SRTypeLSR | "asr" -> SRTypeASR @@ -109,7 +109,7 @@ let getOperandsAsList operands = | SixOperands (op1, op2, op3, op4, op5, op6) -> [op1; op2; op3; op4; op5; op6] let getSIMDTypFromStr (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "8" -> SIMDTyp8 | "16" -> SIMDTyp16 | "32" -> SIMDTyp32 @@ -133,7 +133,7 @@ let getSIMDTypFromStr (str: string) = | _ -> failwith "unknown SIMD Type" let getPSRFlagFromStr (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "c" -> PSRc | "x" -> PSRx | "xc" -> PSRxc @@ -156,7 +156,7 @@ let getPSRFlagFromStr (str: string) = | _ -> failwith "unknown PSRFlag" let optionOprFromStr (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "sy" -> BarrierOption.SY | "st" -> BarrierOption.ST | "ld" -> BarrierOption.LD @@ -172,7 +172,7 @@ let optionOprFromStr (str: string) = | _ -> failwith "unknown OptionOperand" let iFlagFromStr (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "a" -> A | "i" -> I | "f" -> F diff --git a/src/Peripheral/Assembly/AsmInterface/AsmInterface.fs b/src/Peripheral/Assembly/AsmInterface/AsmInterface.fs index 4120c126..ee5f7054 100644 --- a/src/Peripheral/Assembly/AsmInterface/AsmInterface.fs +++ b/src/Peripheral/Assembly/AsmInterface/AsmInterface.fs @@ -25,39 +25,30 @@ namespace B2R2.Peripheral.Assembly open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface - -type AsmInterface (hdl: BinHandle, startAddress) = +type AsmInterface (isa: ISA, startAddress) = let asmParser = - match hdl.ISA.Arch with + match isa.Arch with | Architecture.IntelX64 | Architecture.IntelX86 -> - Intel.IntelAsmParser (hdl.ISA, startAddress) :> AsmParser - | Architecture.MIPS1 - | Architecture.MIPS2 - | Architecture.MIPS3 + Intel.IntelAsmParser (isa, startAddress) :> AsmParser | Architecture.MIPS32 - | Architecture.MIPS32R2 - | Architecture.MIPS32R6 - | Architecture.MIPS4 - | Architecture.MIPS5 | Architecture.MIPS64 | _ -> raise InvalidISAException - - let uirParser = LowUIR.LowUIRParser (hdl.ISA, hdl.RegisterBay) - - new (isa: ISA, startAddress) = - AsmInterface (BinHandle.Init (isa), startAddress) + let struct (ctxt, regFactory) = Basis.load isa + let uirParser = LowUIR.LowUIRParser (isa, regFactory) /// Parse the given assembly input, and assemble a list of byte arrays, where /// each array corresponds to a binary instruction. member __.AssembleBin asm = asmParser.Assemble asm + member __.Parser with get() = asmParser.Parser + /// Parse the given string input, and lift it to an array of LowUIR /// statements. If the given string represents LowUIR instructions, then we /// simply parse the assembly instructions and return the corresponding AST. member __.LiftLowUIR isFromLowUIR asm = if isFromLowUIR then uirParser.Parse asm - else asmParser.Lift hdl asm startAddress + else asmParser.Lift ctxt asm startAddress diff --git a/src/Peripheral/Assembly/Core/AsmParser.fs b/src/Peripheral/Assembly/Core/AsmParser.fs index 47475d5f..0407c035 100644 --- a/src/Peripheral/Assembly/Core/AsmParser.fs +++ b/src/Peripheral/Assembly/Core/AsmParser.fs @@ -24,23 +24,26 @@ namespace B2R2.Peripheral.Assembly -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd /// Assembly code parser interface. [] -type AsmParser () = +type AsmParser (isa, mode) = + let parser = Parser.init isa mode None + /// Run parsing from a given assembly string, and assemble binary code. abstract Assemble: string -> Result + member __.Parser with get() = parser + /// Run parsing from a given assembly string, and lift it to LowUIR code. - member __.Lift hdl asm addr = + member __.Lift ctxt asm addr = __.Assemble asm |> Result.bind (fun bins -> bins |> List.fold (fun acc bs -> - let hdl = BinHandle.UpdateCode hdl addr bs - let ins = BinHandle.ParseInstr (hdl, addr) - BinHandle.LiftInstr hdl ins :: acc + let ins = parser.Parse (bs, addr) + ins.Translate ctxt :: acc ) [] |> List.rev |> Array.concat diff --git a/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj b/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj index add7374d..0d413f39 100644 --- a/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj +++ b/src/Peripheral/Assembly/Core/B2R2.Peripheral.Assembly.Core.fsproj @@ -20,7 +20,7 @@ - + diff --git a/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj b/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj index dbbcbeb0..b9a92764 100644 --- a/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj +++ b/src/Peripheral/Assembly/Intel/B2R2.Peripheral.Assembly.Intel.fsproj @@ -21,7 +21,7 @@ - + diff --git a/src/Peripheral/Assembly/Intel/IntelAsmMain.fs b/src/Peripheral/Assembly/Intel/IntelAsmMain.fs index e43a787a..f163032d 100644 --- a/src/Peripheral/Assembly/Intel/IntelAsmMain.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmMain.fs @@ -329,7 +329,7 @@ let finalize arch parserState realLenArr baseAddr myIdx comp = IncompLabel sz |] -> let labelIdx = Map.find lbl parserState.LabelMap let addr = - if arch = Arch.IntelX86 then computeAddr labelIdx realLenArr + if arch = Architecture.IntelX86 then computeAddr labelIdx realLenArr else computeDistance myIdx labelIdx realLenArr [| yield! bs; yield! concretizeLabel sz (addr + int64 baseAddr) yield! getImm imm |] diff --git a/src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs b/src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs index 3b184274..6cdfb820 100644 --- a/src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmOpcode.fs @@ -31,10 +31,10 @@ open B2R2.Peripheral.Assembly.Intel.AsmPrefix open B2R2.Peripheral.Assembly.Intel.AsmOperands let no32Arch arch = - if arch = Arch.IntelX86 then raise InvalidISAException else () + if arch = Architecture.IntelX86 then raise InvalidISAException else () let no64Arch arch = - if arch = Arch.IntelX64 then raise InvalidISAException else () + if arch = Architecture.IntelX64 then raise InvalidISAException else () let isInt8 i = 0xFFFFFFFFFFFFFF80L <= i && i <= 0x7FL let isInt16 i = 0xFFFFFFFFFFFF8000L <= i && i <= 0x7FFFL @@ -723,7 +723,7 @@ let bt (ctxt: EncContext) ins = let call (ctxt: EncContext) ins = match ins.Operands with | OneOperand (OprDirAddr (Relative rel)) - when isInt16 rel && ctxt.Arch = Arch.IntelX86 -> + when isInt16 rel && ctxt.Arch = Architecture.IntelX86 -> encD ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xE8uy |] rel 16 | OneOperand (OprDirAddr (Relative rel)) @@ -1070,13 +1070,13 @@ let dec (ctxt: EncContext) ins = | OneOperand (OprMem (b, s, d, 8)) -> encM ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xFEuy |] b s d 1uy | OneOperand (OprReg r) when isReg16 r -> - if isClassicGPReg r && ctxt.Arch = Arch.IntelX86 then + if isClassicGPReg r && ctxt.Arch = Architecture.IntelX86 then encClassicR true 0x48uy (regTo3Bit r) else encR ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xFFuy |] r 1uy | OneOperand (OprMem (b, s, d, 16)) -> encM ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xFFuy |] b s d 1uy | OneOperand (OprReg r) when isReg32 r -> - if isClassicGPReg r && ctxt.Arch = Arch.IntelX86 then + if isClassicGPReg r && ctxt.Arch = Architecture.IntelX86 then encClassicR false 0x48uy (regTo3Bit r) else encR ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xFFuy |] r 1uy | OneOperand (OprMem (b, s, d, 32)) -> @@ -1471,13 +1471,13 @@ let inc (ctxt: EncContext) ins = | OneOperand (OprMem (b, s, d, 8)) -> encM ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xFEuy |] b s d 0uy | OneOperand (OprReg r) when isReg16 r -> - if isClassicGPReg r && ctxt.Arch = Arch.IntelX86 then + if isClassicGPReg r && ctxt.Arch = Architecture.IntelX86 then encClassicR true 0x40uy (regTo3Bit r) else encR ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xFFuy |] r 0uy | OneOperand (OprMem (b, s, d, 16)) -> encM ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal [| 0xFFuy |] b s d 0uy | OneOperand (OprReg r) when isReg32 r -> - if isClassicGPReg r && ctxt.Arch = Arch.IntelX86 then + if isClassicGPReg r && ctxt.Arch = Architecture.IntelX86 then encClassicR false 0x40uy (regTo3Bit r) else encR ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| 0xFFuy |] r 0uy | OneOperand (OprMem (b, s, d, 32)) -> @@ -1506,7 +1506,7 @@ let jcc (ctxt: EncContext) ins op8Byte opByte op = encD ins ctxt.Arch ctxt.PrefNormal ctxt.RexNormal [| op8Byte |] rel 8 | OneOperand (OprDirAddr (Relative rel)) - when isInt16 rel && ctxt.Arch = Arch.IntelX86 -> + when isInt16 rel && ctxt.Arch = Architecture.IntelX86 -> encD ins ctxt.Arch ctxt.Pref66 ctxt.RexNormal opByte rel 16 | OneOperand (OprDirAddr (Relative rel)) when isInt32 rel -> @@ -2934,11 +2934,13 @@ let vpalignr (ctxt: EncContext) ins = encVexRRRI ins ctxt.Arch (Some r2) ctxt.VEX256n66n0F3A [| 0x0Fuy |] r1 r3 imm 8 (* Reg - Reg - Mem - Imm8 *) - | FourOperands (OprReg r1, OprReg r2, OprMem (b, s, d, 128), OprImm (imm, _)) + | FourOperands (OprReg r1, OprReg r2, + OprMem (b, s, d, 128), OprImm (imm, _)) when isXMMReg r1 && isXMMReg r2 -> encVexRRMI ins ctxt.Arch (Some r2) ctxt.VEX128n66n0F3A [| 0x0Fuy |] r1 b s d imm 8 - | FourOperands (OprReg r1, OprReg r2, OprMem (b, s, d, 256), OprImm (imm, _)) + | FourOperands (OprReg r1, OprReg r2, + OprMem (b, s, d, 256), OprImm (imm, _)) when isYMMReg r1 && isYMMReg r2 -> encVexRRMI ins ctxt.Arch (Some r2) ctxt.VEX256n66n0F3A [| 0x0Fuy |] r1 b s d imm 8 diff --git a/src/Peripheral/Assembly/Intel/IntelAsmOperands.fs b/src/Peripheral/Assembly/Intel/IntelAsmOperands.fs index 15760c31..e08e195e 100644 --- a/src/Peripheral/Assembly/Intel/IntelAsmOperands.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmOperands.fs @@ -31,35 +31,35 @@ open B2R2.FrontEnd.BinLifter.Intel let regTo3Bit = function | Register.AL | Register.AX | Register.EAX | Register.RAX | Register.BND0 | Register.MM0 | Register.XMM0 | Register.YMM0 | Register.ES - | Register.R8L | Register.R8W | Register.R8D | Register.R8 + | Register.R8B | Register.R8W | Register.R8D | Register.R8 | Register.XMM8 | Register.YMM8 | Register.ST0 -> 0b000uy | Register.CL | Register.CX | Register.ECX | Register.RCX | Register.BND1 | Register.MM1 | Register.XMM1 | Register.YMM1 | Register.CS - | Register.R9L | Register.R9W | Register.R9D | Register.R9 + | Register.R9B | Register.R9W | Register.R9D | Register.R9 | Register.XMM9 | Register.YMM9 | Register.ST1 -> 0b001uy | Register.DL | Register.DX | Register.EDX | Register.RDX | Register.BND2 | Register.MM2 | Register.XMM2 | Register.YMM2 | Register.SS - | Register.R10L | Register.R10W | Register.R10D | Register.R10 + | Register.R10B | Register.R10W | Register.R10D | Register.R10 | Register.XMM10 | Register.YMM10 | Register.ST2 -> 0b010uy | Register.BL | Register.BX | Register.EBX | Register.RBX | Register.BND3 | Register.MM3 | Register.XMM3 | Register.YMM3 | Register.DS - | Register.R11L | Register.R11W | Register.R11D | Register.R11 + | Register.R11B | Register.R11W | Register.R11D | Register.R11 | Register.XMM11 | Register.YMM11 | Register.ST3 -> 0b011uy | Register.AH | Register.SP | Register.ESP | Register.RSP | Register.MM4 | Register.XMM4 | Register.YMM4 | Register.FS - | Register.SPL | Register.R12L | Register.R12W | Register.R12D | Register.R12 + | Register.SPL | Register.R12B | Register.R12W | Register.R12D | Register.R12 | Register.XMM12 | Register.YMM12 | Register.ST4 -> 0b100uy | Register.CH | Register.BP | Register.EBP | Register.RBP | Register.MM5 | Register.XMM5 | Register.YMM5 | Register.GS - | Register.BPL | Register.R13L | Register.R13W | Register.R13D | Register.R13 + | Register.BPL | Register.R13B | Register.R13W | Register.R13D | Register.R13 | Register.XMM13 | Register.YMM13 | Register.ST5 | Register.RIP -> 0b101uy | Register.DH | Register.SI | Register.ESI | Register.RSI | Register.MM6 | Register.XMM6 | Register.YMM6 - | Register.SIL | Register.R14L | Register.R14W | Register.R14D | Register.R14 + | Register.SIL | Register.R14B | Register.R14W | Register.R14D | Register.R14 | Register.XMM14 | Register.YMM14 | Register.ST6 -> 0b110uy | Register.BH | Register.DI | Register.EDI | Register.RDI | Register.MM7 | Register.XMM7 | Register.YMM7 - | Register.DIL | Register.R15L | Register.R15W | Register.R15D | Register.R15 + | Register.DIL | Register.R15B | Register.R15W | Register.R15D | Register.R15 | Register.XMM15 | Register.YMM15 | Register.ST7 -> 0b111uy | _ -> Utils.impossible () @@ -140,7 +140,7 @@ let private getDispSz disp = if isDisp8 disp then 8 else 32 let private isRegFld4 = function | Register.RSP | Register.ESP | Register.SP | Register.AH - | Register.R12 | Register.R12D | Register.R12W | Register.R12L | Register.SPL + | Register.R12 | Register.R12D | Register.R12W | Register.R12B | Register.SPL -> true | _ -> false diff --git a/src/Peripheral/Assembly/Intel/IntelAsmParser.fs b/src/Peripheral/Assembly/Intel/IntelAsmParser.fs index 7174699a..bca0532b 100644 --- a/src/Peripheral/Assembly/Intel/IntelAsmParser.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmParser.fs @@ -36,7 +36,7 @@ open System type LabelDefs = Map type IntelAsmParser (isa, baseAddr: Addr) = - inherit AsmParser () + inherit AsmParser (isa, ArchOperationMode.NoMode) let mutable inferredPrefix = Prefix.PrxNone let defaultRegType = isa.WordSize |> WordSize.toRegType @@ -80,13 +80,10 @@ type IntelAsmParser (isa, baseAddr: Addr) = let pOpcode = (Enum.GetNames typeof) - |> Array.map pstringCI - |> Array.map (fun p -> p .>> (lookAhead (anyOf "\n;. " |>> ignore) <|> eof)) - |> Array.map attempt - |> Array.map - (fun (p) -> - p - |>> (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Opcode)) + |> Array.map (fun s -> + attempt (pstringCI s .>> (lookAhead (anyOf "\n;. " |>> ignore) <|> eof)) + |>> fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Opcode + ) |> choice (* Since far calls, jmps, and rets are unnatural they are ignored *) <|> (pstringCI "jmp" >>. preturn Opcode.JMPNear) @@ -110,9 +107,9 @@ type IntelAsmParser (isa, baseAddr: Addr) = let registersList = (Enum.GetNames typeof) - |> Array.map pstringCI - |> Array.map (fun p -> p .>> (notFollowedBy (satisfy isLetter)) ) - |> Array.map attempt + |> Array.map (fun s -> + attempt (pstringCI s .>> (notFollowedBy (satisfy isLetter))) + ) let pReg = registersList |> choice @@ -148,8 +145,7 @@ type IntelAsmParser (isa, baseAddr: Addr) = [ "byte ptr"; "word ptr"; "word far ptr"; "dword ptr"; "dword far ptr"; "qword ptr"; "qword far ptr"; "tword ptr"; "xmmword ptr"; "ymmword ptr"; "zmmword ptr" ] - |> Seq.map pstringCI - |> Seq.map attempt + |> Seq.map (pstringCI >> attempt) |> choice |>> ptrStringToBitSize diff --git a/src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs b/src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs index 712523e0..38d45ddc 100644 --- a/src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs +++ b/src/Peripheral/Assembly/Intel/IntelAsmPrefix.fs @@ -40,8 +40,8 @@ let isFPUReg reg = Register.Kind.FPU = Register.getKind reg let private isAddrSz arch reg = match arch, Register.toRegType reg with - | Arch.IntelX64, 32 -> true - | Arch.IntelX86, 16 -> true + | Architecture.IntelX64, 32 -> true + | Architecture.IntelX86, 16 -> true | _ -> false let private isAddrSize isa = function @@ -104,14 +104,14 @@ let encodeRex = function | _ -> 0x0uy let isExtendReg = function - | Register.R8L | Register.R8W | Register.R8D | Register.R8 - | Register.R9L | Register.R9W | Register.R9D | Register.R9 - | Register.R10L | Register.R10W | Register.R10D | Register.R10 - | Register.R11L | Register.R11W | Register.R11D | Register.R11 - | Register.R12L | Register.R12W | Register.R12D | Register.R12 - | Register.R13L | Register.R13W | Register.R13D | Register.R13 - | Register.R14L | Register.R14W | Register.R14D | Register.R14 - | Register.R15L | Register.R15W | Register.R15D | Register.R15 + | Register.R8B | Register.R8W | Register.R8D | Register.R8 + | Register.R9B | Register.R9W | Register.R9D | Register.R9 + | Register.R10B | Register.R10W | Register.R10D | Register.R10 + | Register.R11B | Register.R11W | Register.R11D | Register.R11 + | Register.R12B | Register.R12W | Register.R12D | Register.R12 + | Register.R13B | Register.R13W | Register.R13D | Register.R13 + | Register.R14B | Register.R14W | Register.R14D | Register.R14 + | Register.R15B | Register.R15W | Register.R15D | Register.R15 | Register.XMM8 | Register.XMM9 | Register.XMM10 | Register.XMM11 | Register.XMM12 | Register.XMM13 | Register.XMM14 | Register.XMM15 -> true | _ -> false @@ -123,11 +123,11 @@ let encodeRexB reg = if isExtendReg reg then 0x41uy else 0x0uy let convVEXRexByte rexByte = (~~~ rexByte) &&& 0b111uy let encodeVEXRexRB arch r1 r2 = - if arch = Arch.IntelX86 then 0b101uy + if arch = Architecture.IntelX86 then 0b101uy else convVEXRexByte (encodeRexR r1 ||| encodeRexB r2) let encodeVEXRexRXB arch reg rmOrSBase sIdx = - if arch = Arch.IntelX86 then 0b111uy + if arch = Architecture.IntelX86 then 0b111uy else match rmOrSBase, sIdx with | Some r1, Some (r2, _) -> @@ -189,7 +189,7 @@ let encodeRexRXB isMR = function | o -> printfn "Inavlid Operand (%A)" o; Utils.futureFeature () let encodeREXPref ins arch (rexPrx: EncREXPrefix) = - if arch = Arch.IntelX86 then [||] + if arch = Architecture.IntelX86 then [||] else (* Arch.IntelX64 *) let rexW = if rexPrx.RexW then 0x48uy else 0uy let rxb = encodeRexRXB rexPrx.IsMemReg ins.Operands diff --git a/src/Peripheral/Assembly/Intel/IntelParserHelper.fs b/src/Peripheral/Assembly/Intel/IntelParserHelper.fs index bd9eb972..faf28c14 100644 --- a/src/Peripheral/Assembly/Intel/IntelParserHelper.fs +++ b/src/Peripheral/Assembly/Intel/IntelParserHelper.fs @@ -76,7 +76,7 @@ let ptrStringToBitSize = function | _ -> Utils.impossible () let prefixFromRegString (str: string) = - match str.ToLower () with + match str.ToLowerInvariant () with | "cs" -> Prefix.PrxCS | "ds" -> Prefix.PrxDS | "es" -> Prefix.PrxES diff --git a/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs b/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs index 2c8b980e..d31d711d 100644 --- a/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs +++ b/src/Peripheral/Assembly/LowUIR/LowUIRParser.fs @@ -35,10 +35,9 @@ open B2R2.BinIR.LowUIR open B2R2.Peripheral.Assembly.Utils open B2R2.Peripheral.Assembly.LowUIR.Helper -type Parser<'t> = Parser<'t, RegType> - -type LowUIRParser (isa, regbay: RegisterBay) = +type Parser<'T> = Parser<'T, RegType> +type LowUIRParser (isa, regFactory: RegisterFactory) = let isAllowedFirstCharForID c = isAsciiLetter c let isAllowedCharForID c = isAsciiLetter c || isDigit c @@ -62,7 +61,7 @@ type LowUIRParser (isa, regbay: RegisterBay) = if s.StartsWith ("0x") then BigInteger.Parse ("0" + s.Substring (2), NumberStyles.AllowHexSpecifier) else BigInteger.Parse (s) - |> BitVector.ofBInt + |> BitVector.OfBInt let pRegType = (anyOf "IiFf") >>. pint32 |>> RegType.fromBitWidth @@ -72,28 +71,33 @@ type LowUIRParser (isa, regbay: RegisterBay) = .>>. opt (pchar ':' >>. ws >>. pRegType) >>= (fun (toBV, typ) -> match typ with - | None -> getUserState |>> (fun t -> toBV t) + | None -> getUserState |>> toBV | Some typ -> preturn (toBV typ)) let pUnaryOperator = [ "-"; "~"; "sqrt"; "cos"; "sin"; "tan"; "atan" ] - |> List.map pstring |> List.map attempt |> choice |>> UnOpType.ofString + |> List.map (pstring >> attempt) + |> choice + |>> UnOpType.ofString let pCastType = - [ "sext"; "zext"; "float"; "round"; "ceil"; "floor"; "trunc"; "fext" ] - |> List.map pstring |> List.map attempt |> choice |>> CastKind.ofString + [ "sext"; "zext"; "float"; "round"; "ceil"; "floor"; "trunc"; "fext" + "roundf"; "ceilf"; "floorf"; "truncf" ] + |> List.map (pstring >> attempt) + |> choice + |>> CastKind.ofString let pExpr, pExprRef = createParserForwardedToRef () let pNum = pBitVector |>> AST.num - let regnames = regbay.GetAllRegNames () + let regnames = regFactory.GetAllRegNames () let pVar = - List.map pstringCI regnames - |> List.map attempt + regnames + |> List.map (pstringCI >> attempt) |> choice - |>> regbay.StrToRegExpr + |>> regFactory.StrToRegExpr let pTempVar = pstring "T_" >>. pint32 .>> ws @@ -186,7 +190,7 @@ type LowUIRParser (isa, regbay: RegisterBay) = let () = opp.TermParser <- term - pExprRef := pOps + pExprRef.Value <- pOps [ AST.binop BinOpType.ADD, "+", 3, Associativity.Left AST.binop BinOpType.SUB, "-", 3, Associativity.Left @@ -221,6 +225,8 @@ type LowUIRParser (isa, regbay: RegisterBay) = AST.relop RelOpType.LE, "<=", 2, Associativity.Left AST.relop RelOpType.SLT, "?<", 2, Associativity.Left AST.relop RelOpType.SLE, "?<=", 2, Associativity.Left + AST.relop RelOpType.FEQ, "=.", 2, Associativity.Left + AST.relop RelOpType.FNEQ, "!=.", 2, Associativity.Left AST.relop RelOpType.FGT, ">.", 2, Associativity.Left AST.relop RelOpType.FGE, ">=.", 2, Associativity.Left AST.relop RelOpType.FLT, "<.", 2, Associativity.Left @@ -292,6 +298,24 @@ type LowUIRParser (isa, regbay: RegisterBay) = let rt = TypeCheck.typeOf tExp AST.intercjmp cond tExp fExp) + let comma = pstring "," + + let pArgs = + sepBy (ws >>. pExpr) comma + + let pApp = + ws + >>. pIdentifier + .>>. pBetweenParen pArgs + .>> ws .>> pchar ':' .>> ws .>>. pRegType + |>> (fun ((fnName, args), rt) -> AST.app fnName args rt) + + let pExtCall = + ws + >>. pstringCI "call" + >>. pApp + |>> AST.extCall + let pException = pstringCI "Exception" >>. ws >>. pchar '(' >>. ws >>. pIdentifier .>> ws .>> pchar ')' @@ -313,7 +337,6 @@ type LowUIRParser (isa, regbay: RegisterBay) = <|> attempt (pstringCI "privinstr" >>% UnsupportedPrivInstr) <|> attempt (pstringCI "far" >>% UnsupportedFAR) <|> attempt (pstringCI "cpu extension" >>% UnsupportedExtension) - <|> attempt (pstringCI "call " >>. pExpr |>> ExternalCall) let pSideEffect = ws @@ -330,6 +353,7 @@ type LowUIRParser (isa, regbay: RegisterBay) = <|> attempt pCJmp <|> attempt pInterJmp <|> attempt pInterCJmp + <|> attempt pExtCall <|> attempt pSideEffect >>= typeCheck diff --git a/src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs b/src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs index 1fa4d498..3e220dd9 100644 --- a/src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs +++ b/src/Peripheral/Assembly/MIPS/MIPSAsmParser.fs @@ -71,37 +71,37 @@ type AsmParser (mipsISA: ISA, startAddress: Addr) = let pOpcode = (Enum.GetNames typeof) - |> Array.map (pstringCI) - |> Array.map - (fun p -> p .>> (lookAhead (pchar '.') <|> lookAhead (pchar ' '))) - |> Array.map (fun p -> attempt (p)) - |> Array.map - (fun (p) -> - p |>> - (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Opcode)) + |> Array.map (fun s -> + attempt (pstringCI s + .>> (lookAhead (pchar '.') <|> lookAhead (pchar ' '))) + |>> fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Opcode + ) |> choice let pCondition = pchar '.' >>. - ((Enum.GetNames typeof) - |> Array.map pstringCI - |> Array.map - (fun p -> - p |>> - (fun name -> + ( + (Enum.GetNames typeof) + |> Array.map + (fun s -> + pstringCI s + |>> (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Condition)) - |> choice) + |> choice + ) let pFmtTemp = pchar '.' >>. - ((Enum.GetNames typeof) - |> Array.map pstringCI - |> Array.map - (fun p -> - p |>> (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Fmt)) - |> choice) + ( + (Enum.GetNames typeof) + |> Array.map + (fun s -> + pstringCI s + |>> (fun name -> Enum.Parse(typeof, name.ToUpper()) :?> Fmt)) + |> choice + ) let pFmt = pFmtTemp .>> (opt pFmtTemp) diff --git a/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj b/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj index cadbb70d..92b81183 100644 --- a/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj +++ b/src/RearEnd/Assembler/B2R2.RearEnd.Assembler.fsproj @@ -19,7 +19,7 @@ - + diff --git a/src/RearEnd/Assembler/Program.fs b/src/RearEnd/Assembler/Program.fs index 06b67e14..4974b7e3 100644 --- a/src/RearEnd/Assembler/Program.fs +++ b/src/RearEnd/Assembler/Program.fs @@ -26,7 +26,7 @@ module B2R2.RearEnd.Assembler.Program open System open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.RearEnd open B2R2.BinIR.LowUIR open B2R2.Peripheral.Assembly @@ -36,27 +36,25 @@ let internal out = ConsolePrinter () :> Printer let [] private NormalPrompt = "> " -let private printIns hdl addr bs = +let private printIns (asm: AsmInterface) addr bs = let bCode = (BitConverter.ToString (bs)).Replace ("-", "") - let hdl = BinHandle.UpdateCode hdl addr bs - let ins = BinHandle.ParseInstr (hdl, addr) + let ins = asm.Parser.Parse (bs, addr) out.PrintLine (sprintf "%08x: %-20s %s" addr bCode (ins.Disasm ())) addr + uint64 (Array.length bs) let inline private printResult fn = function | Ok res -> fn res - | Error err -> Printer.printErrorToConsole err + | Error err -> Printer.PrintErrorToConsole err let getAssemblyPrinter (opts: AssemblerOpts) = match opts.Mode with | GeneralMode (isa) -> - let hdl = BinHandle.Init (isa) let baseAddr = opts.BaseAddress - let asm = AsmInterface (hdl, baseAddr) + let asm = AsmInterface (isa, baseAddr) fun str -> asm.AssembleBin str |> printResult (fun res -> - List.fold (printIns hdl) baseAddr res + List.fold (printIns asm) baseAddr res |> ignore) | LowUIRMode (isa) -> let asm = AsmInterface (isa, opts.BaseAddress) @@ -91,7 +89,7 @@ let showBasicInfo (opts: AssemblerOpts) = let private asmFromFiles files printer = files - |> List.iter (fun file -> IO.File.ReadAllText file |> printer) + |> List.iter (IO.File.ReadAllText >> printer) let asmMain files opts = let printer = getAssemblyPrinter opts diff --git a/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj b/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj index 910ce91d..a279a8f2 100644 --- a/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj +++ b/src/RearEnd/BinDump/B2R2.RearEnd.BinDump.fsproj @@ -12,7 +12,7 @@ - + diff --git a/src/RearEnd/BinDump/Cmd.fs b/src/RearEnd/BinDump/Cmd.fs index f81de3b8..38822d5c 100644 --- a/src/RearEnd/BinDump/Cmd.fs +++ b/src/RearEnd/BinDump/Cmd.fs @@ -25,6 +25,7 @@ namespace B2R2.RearEnd.BinDump open B2R2 +open B2R2.FrontEnd.BinLifter open B2R2.RearEnd open System @@ -110,6 +111,14 @@ type BinDumpOpts () = descr = "Always display disassembly for all sections.", callback = cb, long = "--only-disasm") + /// "--att" for using AT&T syntax. + static member OptATTSyntax () = + let cb opts _ = + Intel.Disasm.setDisassemblyFlavor ATTSyntax + opts + CmdOpts.New (descr = "Use AT&T syntax for disassembling Intel instructions", + callback = cb, long = "--att") + /// "-S" or "--section" for displaying contents of a specific section. static member OptDumpSection () = let cb opts (arg: string []) = @@ -214,6 +223,7 @@ module Cmd = CmdOpts.New (descr = "[Output Configuration]", dummy = true) CmdOpts.New (descr = "", dummy = true) + BinDumpOpts.OptATTSyntax () BinDumpOpts.OptDumpSection () BinDumpOpts.OptOnlyDisasm () BinDumpOpts.OptShowAddr () diff --git a/src/RearEnd/BinDump/DisasmLiftHelper.fs b/src/RearEnd/BinDump/DisasmLiftHelper.fs index c7ac804c..a11251d1 100644 --- a/src/RearEnd/BinDump/DisasmLiftHelper.fs +++ b/src/RearEnd/BinDump/DisasmLiftHelper.fs @@ -27,9 +27,9 @@ module internal B2R2.RearEnd.BinDump.DisasmLiftHelper open System.Collections.Generic open B2R2 open B2R2.BinIR +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface /// The monotonic console printer. let internal out = ConsoleCachedPrinter () :> Printer @@ -42,32 +42,36 @@ let [] IllegalStr = "(illegal)" let getOptimizer (opts: BinDumpOpts) = match opts.DoOptimization with | NoOptimize -> id - | Optimize -> BinHandle.Optimize + | Optimize -> LocalOptimizer.Optimize -let makeFuncSymbolDic hdl = +let makeFuncSymbolDic (hdl: BinHandle) = let funcs = Dictionary () - hdl.FileInfo.GetFunctionSymbols () - |> Seq.iter (fun s -> funcs.Add (s.Address, s.Name) |> ignore) - hdl.FileInfo.GetFunctionAddresses () + hdl.File.GetFunctionSymbols () + |> Seq.iter (fun s -> funcs.TryAdd (s.Address, s.Name) |> ignore) + hdl.File.GetFunctionAddresses () |> Seq.iter (fun a -> if funcs.ContainsKey a then () else funcs[a] <- Addr.toFuncName a) + hdl.File.GetLinkageTableEntries () + |> Seq.iter (fun e -> + if e.TrampolineAddress = 0UL then () + else funcs.TryAdd (e.TrampolineAddress, e.FuncName) |> ignore) funcs -let makeLinkageTblSymbolDic hdl = +let makeLinkageTblSymbolDic (hdl: BinHandle) = let funcs = Dictionary () - hdl.FileInfo.GetLinkageTableEntries () + hdl.File.GetLinkageTableEntries () |> Seq.iter (fun e -> if e.TrampolineAddress = 0UL then () else funcs.TryAdd (e.TrampolineAddress, e.FuncName) |> ignore) funcs -let makeArchModeDic hdl = +let makeArchModeDic (hdl: BinHandle) = let modes = Dictionary () - match hdl.FileInfo.FileFormat, hdl.ISA.Arch with - | FileFormat.ELFBinary, Arch.ARMv7 - | FileFormat.ELFBinary, Arch.AARCH32 -> - hdl.FileInfo.GetSymbols () + match hdl.File.Format, hdl.File.ISA.Arch with + | FileFormat.ELFBinary, Architecture.ARMv7 + | FileFormat.ELFBinary, Architecture.AARCH32 -> + hdl.File.GetSymbols () |> Seq.iter (fun s -> if s.ArchOperationMode <> ArchOperationMode.NoMode then modes[s.Address] <- s.ArchOperationMode @@ -75,23 +79,23 @@ let makeArchModeDic hdl = | _ -> () modes -let getInstructionAlignment hdl = - match hdl.ISA.Arch with - | Arch.IntelX86 | Arch.IntelX64 -> 1 - | Arch.ARMv7 | Arch.AARCH32 -> - match hdl.Parser.OperationMode with +let getInstructionAlignment (isa: ISA) mode = + match isa.Arch with + | Architecture.IntelX86 | Architecture.IntelX64 -> 1 + | Architecture.ARMv7 | Architecture.AARCH32 -> + match mode with | ArchOperationMode.ThumbMode -> 2 | _ -> 4 - | Arch.AARCH64 -> 4 - | Arch.MIPS1 | Arch.MIPS2 | Arch.MIPS3 | Arch.MIPS4 | Arch.MIPS5 - | Arch.MIPS32 | Arch.MIPS32R2 | Arch.MIPS32R6 - | Arch.MIPS64 | Arch.MIPS64R2 | Arch.MIPS64R6 -> 4 - | Arch.EVM -> 1 - | Arch.AVR -> 2 - | Arch.SH4 -> 2 - | Arch.PPC32 -> 4 - | Arch.RISCV64 -> 4 (* FIXME *) - | Arch.WASM -> 1 + | Architecture.AARCH64 -> 4 + | Architecture.MIPS32 | Architecture.MIPS64 -> 4 + | Architecture.EVM -> 1 + | Architecture.TMS320C6000 -> 4 + | Architecture.AVR -> 2 + | Architecture.SH4 -> 2 + | Architecture.PPC32 -> 4 + | Architecture.RISCV64 -> 2 + | Architecture.WASM -> 1 + | Architecture.SPARC -> 2 | _ -> Utils.futureFeature () let convertToHexStr bytes = @@ -110,16 +114,15 @@ let printRegularDisasm disasmStr wordSize addr bytes cfg = let addrStr = Addr.toString wordSize addr + ":" out.PrintRow (false, cfg, [ addrStr; hexStr; disasmStr ]) -let regularDisPrinter (hdl: BinHandle) showSymbs bp ins cfg = - let disasmStr = BinHandle.DisasmInstr hdl false showSymbs ins - let wordSize = hdl.FileInfo.WordSize - let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int ins.Length) - printRegularDisasm disasmStr wordSize bp.Addr bytes cfg +let regularDisPrinter hdl wordSize showSymbs ptr (ins: Instruction) cfg = + let disasmStr = (hdl: BinHandle).DisasmInstr (ins, false, showSymbs) + let bytes = hdl.ReadBytes (ptr=ptr, nBytes=int ins.Length) + printRegularDisasm disasmStr wordSize ptr.Addr bytes cfg -let regularIRPrinter (hdl: BinHandle) optimizer bp ins cfg = - let stmts = optimizer (BinHandle.LiftInstr hdl ins) +let regularIRPrinter (hdl: BinHandle) optimizer ptr ins cfg = + let stmts = optimizer (hdl.LiftInstr (ins=ins)) let lowUIRStr = LowUIR.Pp.stmtsToString stmts - let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int ins.Length) + let bytes = hdl.ReadBytes (ptr=ptr, nBytes=int ins.Length) printLowUIR lowUIRStr bytes cfg let convertToDisasmStr (words: AsmWord []) = @@ -141,19 +144,18 @@ let printColorDisasm words wordSize addr bytes cfg = colorout.PrintRow (false, cfg, [ [ Green, addrStr ]; [ NoColor, hexStr ]; disasStr ]) -let colorDisPrinter (hdl: BinHandle) _ bp (ins: Instruction) cfg = +let colorDisPrinter (hdl: BinHandle) wordSize _ ptr (ins: Instruction) cfg = let words = ins.Decompose (false) - let wordSize = hdl.FileInfo.WordSize - let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int ins.Length) - printColorDisasm words wordSize bp.Addr bytes cfg - -let handleInvalidIns (hdl: BinHandle) bp isLift cfg = - let wordSize = hdl.FileInfo.WordSize - let align = getInstructionAlignment hdl - let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=align) + let bytes = hdl.ReadBytes (ptr=ptr, nBytes=int ins.Length) + printColorDisasm words wordSize ptr.Addr bytes cfg + +let handleInvalidIns (hdl: BinHandle) ptr isLift cfg = + let wordSize = hdl.File.ISA.WordSize + let align = getInstructionAlignment hdl.File.ISA hdl.Parser.OperationMode + let bytes = hdl.ReadBytes (ptr=ptr, nBytes=align) if isLift then printLowUIR IllegalStr bytes cfg - else printRegularDisasm IllegalStr wordSize bp.Addr bytes cfg - BinaryPointer.Advance bp align + else printRegularDisasm IllegalStr wordSize ptr.Addr bytes cfg + BinFilePointer.Advance ptr align let printFuncSymbol (dict: Dictionary) addr = match (dict: Dictionary).TryGetValue (addr) with @@ -162,7 +164,7 @@ let printFuncSymbol (dict: Dictionary) addr = out.PrintLine (String.wrapAngleBracket name) | false, _ -> () -let updateMode dict hdl addr = +let updateMode dict (hdl: BinHandle) addr = match (dict: Dictionary).TryGetValue addr with | true, mode -> hdl.Parser.OperationMode <- mode | false, _ -> () @@ -171,25 +173,25 @@ type ISymbolPrinter = abstract member PrintSymbol: Addr -> unit type IInstrPrinter = - abstract member PrintInstr: BinHandle -> BinaryPointer -> Instruction -> unit + abstract member PrintInstr: BinHandle -> BinFilePointer -> Instruction -> unit [] type BinPrinter (hdl, cfg, isLift) = abstract member PrintFuncSymbol: Addr -> unit - abstract member PrintInstr: BinHandle -> BinaryPointer -> Instruction -> unit + abstract member PrintInstr: BinHandle -> BinFilePointer -> Instruction -> unit abstract member UpdateMode: BinHandle -> Addr -> unit - member __.Print bp = - if BinaryPointer.IsValid bp then - __.PrintFuncSymbol bp.Addr - __.UpdateMode hdl bp.Addr - match BinHandle.TryParseInstr (hdl, bp=bp) with + member __.Print ptr = + if BinFilePointer.IsValid ptr then + __.PrintFuncSymbol ptr.Addr + __.UpdateMode hdl ptr.Addr + match hdl.TryParseInstr (ptr=ptr) with | Ok (ins) -> - __.PrintInstr hdl bp ins - let bp' = BinaryPointer.Advance bp (int ins.Length) - __.Print bp' + __.PrintInstr hdl ptr ins + let ptr' = BinFilePointer.Advance ptr (int ins.Length) + __.Print ptr' | Error _ -> - __.Print (handleInvalidIns hdl bp isLift cfg) + __.Print (handleInvalidIns hdl ptr isLift cfg) else () [] @@ -206,46 +208,54 @@ type BinTablePrinter (hdl, cfg, isLift) = type BinCodeDisasmPrinter (hdl, cfg, showSym, showColor) = inherit BinFuncPrinter (hdl, cfg, false) + let wordSize = hdl.File.ISA.WordSize let disPrinter = if showColor then colorDisPrinter else regularDisPrinter - override _.PrintInstr hdl bp ins = disPrinter hdl showSym bp ins cfg + override _.PrintInstr hdl ptr ins = + disPrinter hdl wordSize showSym ptr ins cfg override _.UpdateMode _ _ = () type BinCodeIRPrinter (hdl, cfg, optimizer) = inherit BinFuncPrinter (hdl, cfg, true) - override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.PrintInstr hdl ptr ins = regularIRPrinter hdl optimizer ptr ins cfg override _.UpdateMode _ _ = () type BinTableDisasmPrinter (hdl, cfg) = inherit BinTablePrinter (hdl, cfg, false) - override _.PrintInstr hdl bp ins = regularDisPrinter hdl true bp ins cfg + let wordSize = hdl.File.ISA.WordSize + override _.PrintInstr hdl ptr ins = + regularDisPrinter hdl wordSize true ptr ins cfg override _.UpdateMode _ _ = () type BinTableIRPrinter (hdl, cfg, optimizer) = inherit BinTablePrinter (hdl, cfg, true) - override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.PrintInstr hdl ptr ins = regularIRPrinter hdl optimizer ptr ins cfg override _.UpdateMode _ _ = () type ContextSensitiveCodeDisasmPrinter (hdl, cfg, showSym, showColor) = inherit BinFuncPrinter (hdl, cfg, false) + let wordSize = hdl.File.ISA.WordSize let disPrinter = if showColor then colorDisPrinter else regularDisPrinter let archmodes = makeArchModeDic hdl - override _.PrintInstr hdl bp ins = disPrinter hdl showSym bp ins cfg + override _.PrintInstr hdl ptr ins = + disPrinter hdl wordSize showSym ptr ins cfg override _.UpdateMode hdl addr = updateMode archmodes hdl addr type ContextSensitiveCodeIRPrinter (hdl, cfg, optimizer) = inherit BinFuncPrinter (hdl, cfg, true) let archmodes = makeArchModeDic hdl - override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.PrintInstr hdl ptr ins = regularIRPrinter hdl optimizer ptr ins cfg override _.UpdateMode hdl addr = updateMode archmodes hdl addr type ContextSensitiveTableDisasmPrinter (hdl, cfg) = inherit BinTablePrinter (hdl, cfg, false) let archmodes = makeArchModeDic hdl - override _.PrintInstr hdl bp ins = regularDisPrinter hdl true bp ins cfg + let wordSize = hdl.File.ISA.WordSize + override _.PrintInstr hdl ptr ins = + regularDisPrinter hdl wordSize true ptr ins cfg override _.UpdateMode hdl addr = updateMode archmodes hdl addr type ContextSensitiveTableIRPrinter (hdl, cfg, optimizer) = inherit BinTablePrinter (hdl, cfg, true) let archmodes = makeArchModeDic hdl - override _.PrintInstr hdl bp ins = regularIRPrinter hdl optimizer bp ins cfg + override _.PrintInstr hdl ptr ins = regularIRPrinter hdl optimizer ptr ins cfg override _.UpdateMode hdl addr = updateMode archmodes hdl addr diff --git a/src/RearEnd/BinDump/Program.fs b/src/RearEnd/BinDump/Program.fs index b1f792ba..6b1d73bc 100644 --- a/src/RearEnd/BinDump/Program.fs +++ b/src/RearEnd/BinDump/Program.fs @@ -25,8 +25,8 @@ module B2R2.RearEnd.BinDump.Program open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface open B2R2.RearEnd open B2R2.RearEnd.BinDump.DisasmLiftHelper @@ -37,20 +37,20 @@ let private printFileName (filepath: string) = out.PrintLine (String.wrapSqrdBracket filepath) out.PrintLine () -let private getTableConfig hdl isLift = +let private getTableConfig (isa: ISA) isLift = if isLift then [ LeftAligned 10 ] else - let addrWidth = WordSize.toByteWidth hdl.ISA.WordSize * 2 + let addrWidth = WordSize.toByteWidth isa.WordSize * 2 let binaryWidth = - match hdl.ISA.Arch with - | Arch.IntelX86 | Arch.IntelX64 -> 36 + match isa.Arch with + | Architecture.IntelX86 | Architecture.IntelX64 -> 36 | _ -> 16 [ LeftAligned addrWidth; LeftAligned binaryWidth; LeftAligned 10 ] -let private isARM32 hdl = - match hdl.ISA.Arch with - | Arch.ARMv7 - | Arch.AARCH32 -> true +let private isARM32 (hdl: BinHandle) = + match hdl.File.ISA.Arch with + | Architecture.ARMv7 + | Architecture.AARCH32 -> true | _ -> false let private makeCodePrinter hdl cfg (opts: BinDumpOpts) = @@ -80,42 +80,37 @@ let private makeTablePrinter hdl cfg (opts: BinDumpOpts) = else BinTableDisasmPrinter (hdl, cfg) :> BinPrinter let private dumpRawBinary (hdl: BinHandle) (opts: BinDumpOpts) cfg = - let bp = hdl.FileInfo.ToBinaryPointer hdl.FileInfo.BaseAddress + let ptr = hdl.File.ToBinFilePointer hdl.File.BaseAddress let prn = makeCodePrinter hdl cfg opts - prn.Print bp + prn.Print ptr out.PrintLine () -let printHexdump (opts: BinDumpOpts) sec hdl = - let bp = BinaryPointer.OfSection sec - let bytes = BinHandle.ReadBytes (hdl, bp=bp, nBytes=int sec.Size) - let chunkSize = if opts.ShowWide then 32 else 16 - HexDumper.dump chunkSize hdl.FileInfo.WordSize opts.ShowColor bp.Addr bytes +let printHexdump (opts: BinDumpOpts) sec (hdl: BinHandle) = + let ptr = BinFilePointer.OfSection sec + let bytes = hdl.ReadBytes (ptr=ptr, nBytes=int sec.Size) + let chunkSz = if opts.ShowWide then 32 else 16 + HexDumper.dump chunkSz hdl.File.ISA.WordSize opts.ShowColor ptr.Addr bytes |> Array.iter out.PrintLine -let private hasNoContent (sec: Section) (fi: FileInfo) = - match fi with - | :? ELFFileInfo as fi -> - match fi.ELF.SecInfo.SecByName.TryFind sec.Name with - | Some section -> section.SecType = ELF.SectionType.SHTNoBits +let private hasNoContent (sec: Section) (file: IBinFile) = + match file with + | :? ELFBinFile as file -> + match file.TryFindSection sec.Name with + | Some section -> section.SecType = ELF.SectionType.SHT_NOBITS | None -> true | _ -> false -let dumpHex (opts: BinDumpOpts) (sec: Section) hdl = - if hasNoContent sec hdl.FileInfo then +let dumpHex (opts: BinDumpOpts) (sec: Section) (hdl: BinHandle) = + if hasNoContent sec hdl.File then out.PrintTwoCols "" "NOBITS section." else printHexdump opts sec hdl out.PrintLine () -let private createBinHandleFromPath (opts: BinDumpOpts) filepath = - BinHandle.Init ( - opts.ISA, - opts.ArchOperationMode, - opts.AutoDetect, - opts.BaseAddress, - fileName=filepath) +let private createBinHandleFromPath (opts: BinDumpOpts) filePath = + BinHandle (filePath, opts.ISA, opts.ArchOperationMode, opts.BaseAddress) -let private isRawBinary hdl = - match hdl.FileInfo.FileFormat with +let private isRawBinary (hdl: BinHandle) = + match hdl.File.Format with | FileFormat.ELFBinary | FileFormat.MachBinary | FileFormat.PEBinary @@ -123,39 +118,40 @@ let private isRawBinary hdl = | _ -> true let private printCodeOrTable (printer: BinPrinter) sec = - printer.Print (BinaryPointer.OfSection sec) + printer.Print (BinFilePointer.OfSection sec) out.PrintLine () let private printWasmCode (printer: BinPrinter) (code: Wasm.Code) = let locals = code.Locals let localsSize = List.sumBy (fun (l: Wasm.LocalDecl) -> l.LocalDeclLen) locals let offset = code.Offset + code.LenFieldSize + localsSize + 1 - let maxOffset = code.Offset + code.LenFieldSize + int32 code.CodeSize - let bp = BinaryPointer (uint64 offset, offset, maxOffset) - printer.Print bp + let maxOffset = code.Offset + code.LenFieldSize + int32 code.CodeSize - 1 + let ptr = BinFilePointer (uint64 offset, offset, maxOffset) + printer.Print ptr out.PrintLine () -let initHandleForTableOutput hdl = - match hdl.ISA.Arch with +let initHandleForTableOutput (hdl: BinHandle) = + match hdl.File.ISA.Arch with (* For ARM PLTs, we just assume the ARM mode (if no symbol is given). *) - | Arch.ARMv7 - | Arch.AARCH32 -> hdl.Parser.OperationMode <- ArchOperationMode.ARMMode + | Architecture.ARMv7 + | Architecture.AARCH32 -> + hdl.Parser.OperationMode <- ArchOperationMode.ARMMode | _ -> () let private dumpSections hdl (opts: BinDumpOpts) (sections: seq
) cfg = - let mymode = hdl.Parser.OperationMode + let mymode = (hdl: BinHandle).Parser.OperationMode let codeprn = makeCodePrinter hdl cfg opts let tableprn = makeTablePrinter hdl cfg opts sections |> Seq.iter (fun s -> - if s.Size > 0UL then + if s.Size > 0u then out.PrintSectionTitle (String.wrapParen s.Name) match s.Kind with | SectionKind.ExecutableSection -> hdl.Parser.OperationMode <- mymode - match hdl.FileInfo with - | :? WasmFileInfo as fi -> - match fi.WASM.CodeSection with + match hdl.File with + | :? WasmBinFile as file -> + match file.WASM.CodeSection with | Some sec -> match sec.Contents with | Some conts -> Seq.iter (printWasmCode codeprn) conts.Elements @@ -170,52 +166,49 @@ let private dumpSections hdl (opts: BinDumpOpts) (sections: seq
) cfg = else dumpHex opts s hdl else ()) -let private dumpRegularFile hdl (opts: BinDumpOpts) cfg = +let private dumpRegularFile (hdl: BinHandle) (opts: BinDumpOpts) cfg = opts.ShowSymbols <- true match opts.InputSecName with | Some secname -> - dumpSections hdl opts (hdl.FileInfo.GetSections (secname)) cfg + dumpSections hdl opts (hdl.File.GetSections (secname)) cfg | None -> - dumpSections hdl opts (hdl.FileInfo.GetSections ()) cfg + dumpSections hdl opts (hdl.File.GetSections ()) cfg let dumpFile (opts: BinDumpOpts) filepath = opts.ShowAddress <- true let hdl = createBinHandleFromPath opts filepath - let cfg = getTableConfig hdl opts.ShowLowUIR - printFileName hdl.FileInfo.FilePath + let cfg = getTableConfig hdl.File.ISA opts.ShowLowUIR + printFileName hdl.File.Path if isRawBinary hdl then dumpRawBinary hdl opts cfg else dumpRegularFile hdl opts cfg let dumpFileMode files (opts: BinDumpOpts) = match List.partition System.IO.File.Exists files with | [], [] -> - Printer.printErrorToConsole "File(s) must be given." + Printer.PrintErrorToConsole "File(s) must be given." CmdOpts.PrintUsage ToolName UsageTail Cmd.spec | files, [] -> files |> List.iter (dumpFile opts) | _, errs -> - Printer.printErrorToConsole ("File(s) " + errs.ToString() + " not found!") + Printer.PrintErrorToConsole ("File(s) " + errs.ToString() + " not found!") -let private assertBinaryLength hdl hexstr = - let multiplier = getInstructionAlignment hdl +let private assertBinaryLength isa mode hexstr = + let multiplier = getInstructionAlignment isa mode if (Array.length hexstr) % multiplier = 0 then () else - Printer.printErrorToConsole <| + Printer.PrintErrorToConsole <| "The hex string length must be multiple of " + multiplier.ToString () exit 1 let dumpHexStringMode (opts: BinDumpOpts) = - let hdl = BinHandle.Init (opts.ISA, - opts.ArchOperationMode, - false, - opts.BaseAddress, - opts.InputHexStr) - let cfg = getTableConfig hdl opts.ShowLowUIR - assertBinaryLength hdl opts.InputHexStr + let isa, mode = opts.ISA, opts.ArchOperationMode + let hdl = BinHandle (opts.InputHexStr, isa, mode, opts.BaseAddress, false) + let cfg = getTableConfig hdl.File.ISA opts.ShowLowUIR + assertBinaryLength isa mode opts.InputHexStr opts.ShowColor <- true let printer = makeCodePrinter hdl cfg opts let baseAddr = defaultArg opts.BaseAddress 0UL - let bp = BinaryPointer (baseAddr, 0, opts.InputHexStr.Length) - printer.Print bp + let ptr = BinFilePointer (baseAddr, 0, opts.InputHexStr.Length - 1) + printer.Print ptr out.PrintLine () let private dump files (opts: BinDumpOpts) = diff --git a/src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj b/src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj index 7144e7c4..d90dec49 100644 --- a/src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj +++ b/src/RearEnd/BinExplorer/B2R2.RearEnd.BinExplorer.fsproj @@ -35,16 +35,16 @@ - + - + - + diff --git a/src/RearEnd/BinExplorer/BinInfo.fs b/src/RearEnd/BinExplorer/BinInfo.fs index 36d8a2ea..a47247e0 100644 --- a/src/RearEnd/BinExplorer/BinInfo.fs +++ b/src/RearEnd/BinExplorer/BinInfo.fs @@ -27,6 +27,7 @@ namespace B2R2.RearEnd.BinExplorer open B2R2 open B2R2.FrontEnd.BinFile open B2R2.MiddleEnd.BinEssence +open B2R2.RearEnd.StringUtils type CmdBinInfo () = inherit Cmd () @@ -46,31 +47,26 @@ type CmdBinInfo () = override __.SubCommands = [] override __.CallBack _ ess _args = - let fileInfo = ess.BinHandle.FileInfo - let path = ess.BinHandle.FileInfo.FilePath - let isa = ess.BinHandle.ISA + let file = ess.BinHandle.File + let isa = ess.BinHandle.File.ISA let machine = isa.Arch |> ISA.ArchToString - let fmt = ess.BinHandle.FileInfo.FileFormat |> FileFormat.toString - let entry = fileInfo.EntryPoint |> FileInfo.EntryPointToString - let textAddr = fileInfo.TextStartAddr - let secNum = fileInfo.GetSections () |> Seq.length - let staticSymNum = fileInfo.GetStaticSymbols () |> Seq.length - let dynamicSymNum = fileInfo.GetDynamicSymbols () |> Seq.length - let fileType = fileInfo.FileType |> FileInfo.FileTypeToString - let nx = if fileInfo.IsNXEnabled then "Enabled" else "Disabled" - [| - "[*] Binary information:\n" - sprintf "- Executable Path: %s" path + let fmt = ess.BinHandle.File.Format |> FileFormat.toString + let entry = file.EntryPoint |> entryPointToString + let secNum = file.GetSections () |> Seq.length + let staticSymNum = file.GetStaticSymbols () |> Seq.length + let dynamicSymNum = file.GetDynamicSymbols () |> Seq.length + let fileType = file.Type |> FileType.toString + let nx = if file.IsNXEnabled then "Enabled" else "Disabled" + [| "[*] Binary information:\n" + sprintf "- Executable Path: %s" file.Path sprintf "- Machine: %s" machine sprintf "- File Format: %s" fmt sprintf "- File Type: %s" fileType - sprintf "- Start of Text Section Address: 0x%x" textAddr sprintf "- Entry Point Address: %s" entry sprintf "- Number of Sections: %d" secNum sprintf "- Number of Static Symbols: %d" staticSymNum sprintf "- Number of Dynamic Symbols: %d" dynamicSymNum - sprintf "- NX bit: %s" nx - |] + sprintf "- NX bit: %s" nx |] |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/RearEnd/BinExplorer/Demangle.fs b/src/RearEnd/BinExplorer/Demangle.fs index c783aad2..1159744a 100644 --- a/src/RearEnd/BinExplorer/Demangle.fs +++ b/src/RearEnd/BinExplorer/Demangle.fs @@ -41,9 +41,15 @@ type CmdDemangle () = override __.SubCommands = [] + member private __.MapResult = function + | Ok s -> [| OutputNormal s |] + | Error _ -> [| OutputNormal "[*] Invalid input." |] + override __.CallBack _ _ args = let mangled = String.concat " " args - match Demangler.demangle mangled with - | Ok s -> [| s |] - | Error _ -> [| "[*] Invalid input." |] - |> Array.map OutputNormal + match Demangler.detect mangled with + | MSMangler -> + (MSDemangler () :> IDemanglable).Demangle mangled |> __.MapResult + | ItaniumMangler -> + (ItaniumDemangler () :> IDemanglable).Demangle mangled |> __.MapResult + | UnknownMangler -> [| OutputNormal "[*] Unknown mangling scheme." |] diff --git a/src/RearEnd/BinExplorer/Disasm.fs b/src/RearEnd/BinExplorer/Disasm.fs index 30719221..e3ec66a9 100644 --- a/src/RearEnd/BinExplorer/Disasm.fs +++ b/src/RearEnd/BinExplorer/Disasm.fs @@ -26,7 +26,7 @@ namespace B2R2.RearEnd.BinExplorer open System open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.MiddleEnd.BinEssence type CmdDisasm () = @@ -40,12 +40,12 @@ type CmdDisasm () = try Ok (count, Convert.ToUInt64 (str, 16)) with _ -> Error "[*] Invalid address is given." - let rec disasmLoop acc hdl addr count = + let rec disasmLoop acc (hdl: BinHandle) addr count = if count <= 0 then List.rev acc |> List.toArray else - match BinHandle.TryParseInstr (hdl, addr=addr) with + match hdl.TryParseInstr (addr=addr) with | Ok ins -> - let d = ins.Disasm (true, true, hdl.DisasmHelper) + let d = ins.Disasm (true, hdl.File) disasmLoop (d :: acc) hdl (addr + uint64 ins.Length) (count - 1) | Error _ -> disasmLoop ("(invalid)" :: acc) hdl (addr + 1UL) (count - 1) diff --git a/src/RearEnd/BinExplorer/EvalExpr.fs b/src/RearEnd/BinExplorer/EvalExpr.fs index aa2817d8..592c5b71 100644 --- a/src/RearEnd/BinExplorer/EvalExpr.fs +++ b/src/RearEnd/BinExplorer/EvalExpr.fs @@ -62,7 +62,7 @@ type SimpleArithEvaluator () = let str = getIntegerPart value let intValue = BigInteger.Parse str let intValue = - if hasZeroFraction value = false && result.FloatValue < 0.0 then + if not (hasZeroFraction value) && result.FloatValue < 0.0 then intValue - 1I else intValue match typ with @@ -96,7 +96,7 @@ type SimpleArithEvaluator () = [| result + space + "\n" + "Wrong Input" |] let processASCIICharacters str = - match SimpleArithASCIIPArser.run str with + match SimpleArithASCIIParser.run str with | Success (v, _, position) -> if position.Column <> int64 (str.Length + 1) then processASCIIError str position diff --git a/src/RearEnd/BinExplorer/HTTPServer.fs b/src/RearEnd/BinExplorer/HTTPServer.fs index e12090c9..d78e3f55 100644 --- a/src/RearEnd/BinExplorer/HTTPServer.fs +++ b/src/RearEnd/BinExplorer/HTTPServer.fs @@ -29,7 +29,7 @@ open System.Net open System.Runtime.Serialization open System.Runtime.Serialization.Json open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.MiddleEnd.ControlFlowGraph open B2R2.MiddleEnd.ControlFlowAnalysis open B2R2.MiddleEnd.BinEssence @@ -97,15 +97,15 @@ let listener host handler = let defaultEnc = Text.Encoding.UTF8 -let json<'t> (obj: 't) = +let json<'T> (obj: 'T) = use ms = new IO.MemoryStream () - (new DataContractJsonSerializer(typeof<'t>)).WriteObject(ms, obj) + (DataContractJsonSerializer(typeof<'T>)).WriteObject(ms, obj) Text.Encoding.Default.GetString (ms.ToArray ()) -let jsonParser<'t> (jsonString:string) : 't = +let jsonParser<'T> (jsonString:string): 'T = use ms = new IO.MemoryStream (Text.Encoding.Default.GetBytes(jsonString)) - let obj = (new DataContractJsonSerializer(typeof<'t>)).ReadObject(ms) - obj :?> 't + let obj = (DataContractJsonSerializer(typeof<'T>)).ReadObject(ms) + obj :?> 'T let readIfExists path = if IO.File.Exists path then Some (IO.File.ReadAllBytes (path)) @@ -133,7 +133,7 @@ let answer (req: HttpListenerRequest) (resp: HttpListenerResponse) = function let handleBinInfo req resp arbiter = let ess = Protocol.getBinEssence arbiter - let txt = ess.BinHandle.FileInfo.FilePath + let txt = ess.BinHandle.File.Path let txt = "\"" + txt.Replace(@"\", @"\\") + "\"" Some (defaultEnc.GetBytes (txt)) |> answer req resp @@ -142,7 +142,7 @@ let cfgToJSON cfgType (ess: BinEssence) g root = | IRCFG -> Visualizer.getJSONFromGraph g [root] | DisasmCFG -> - let g, root = DisasmLens.filter ess.CodeManager g root + let g, root = DisasmLens.convert ess.CodeManager g root Visualizer.getJSONFromGraph g [root] | SSACFG -> let struct (g, root) = SSACFG.ofIRCFG ess.BinHandle g root @@ -155,7 +155,8 @@ let handleRegularCFG req resp (name: string) (ess: BinEssence) cfgType = | None -> answer req resp None | Some func -> try - let cfg, root = BinEssence.getFunctionCFG ess func.Entry |> Result.get + let cfg, root = + BinEssence.getFunctionCFG ess func.EntryPoint |> Result.get let s = cfgToJSON cfgType ess cfg root Some (defaultEnc.GetBytes s) |> answer req resp with e -> @@ -185,7 +186,7 @@ let handleFunctions req resp arbiter = let ess = Protocol.getBinEssence arbiter let names = ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.sortBy (fun c -> c.Entry) + |> Seq.sortBy (fun c -> c.EntryPoint) |> Seq.map (fun c -> { FuncID = c.FunctionID; FuncName = c.FunctionName }) |> Seq.toArray Some (json<(JsonFuncInfo) []> names |> defaultEnc.GetBytes) @@ -193,11 +194,11 @@ let handleFunctions req resp arbiter = let handleHexview req resp arbiter = let ess = Protocol.getBinEssence arbiter - ess.BinHandle.FileInfo.GetSegments () + ess.BinHandle.File.GetSegments () |> Seq.map (fun seg -> - let bs = BinHandle.ReadBytes (ess.BinHandle, seg.Address, int (seg.Size)) - let coloredHex = bs |> Array.map ColoredSegment.byteToHex - let coloredAscii = bs |> Array.map ColoredSegment.byteToAscii + let bs = ess.BinHandle.ReadBytes (seg.Address, int (seg.Size)) + let coloredHex = bs |> Array.map ColoredSegment.hexOfByte + let coloredAscii = bs |> Array.map ColoredSegment.asciiOfByte let cha = (* DataColoredHexAscii *) Array.map2 (fun (c, h) (_, a) -> { Color = Color.toString c @@ -229,10 +230,10 @@ let computeConnectedVars chain v = | None -> s | Some us -> Set.union us s) ds -let getVarNames handler = function +let getVarNames (hdl: BinHandle) = function | Regular v -> - handler.RegisterBay.GetRegisterAliases v - |> Array.map (handler.RegisterBay.RegIDToString) + hdl.RegisterFactory.GetRegisterAliases v + |> Array.map (hdl.RegisterFactory.RegIDToString) | _ -> [||] let handleDataflow req resp arbiter (args: string) = @@ -243,7 +244,7 @@ let handleDataflow req resp arbiter (args: string) = let tag = args[2] (* either variable or value. *) match tag with | "variable" -> - let var = args[3] |> ess.BinHandle.RegisterBay.RegIDFromString + let var = args[3] |> ess.BinHandle.RegisterFactory.RegIDFromString try let cfg, root = BinEssence.getFunctionCFG ess entry |> Result.get let chain = DataFlowChain.init cfg root true @@ -290,9 +291,9 @@ let handle (req: HttpListenerRequest) (resp: HttpListenerResponse) arbiter m = let startServer arbiter ip port verbose = let host = "http://" + ip + ":" + port.ToString () + "/" let cmdMap = CmdSpec.speclist |> CmdMap.build - let handler (req: HttpListenerRequest) (resp: HttpListenerResponse) = + let hdl (req: HttpListenerRequest) (resp: HttpListenerResponse) = try handle req resp arbiter cmdMap with e -> if verbose then eprintfn "%A" e else () - listener host handler + listener host hdl // vim: set tw=80 sts=2 sw=2: diff --git a/src/RearEnd/BinExplorer/HexDump.fs b/src/RearEnd/BinExplorer/HexDump.fs index b19fac1b..aded397a 100644 --- a/src/RearEnd/BinExplorer/HexDump.fs +++ b/src/RearEnd/BinExplorer/HexDump.fs @@ -65,7 +65,8 @@ type CmdHexDump () = |> Result.bind (readBytes binEssence) match result with | Ok (addr, bytes: byte []) -> - HexDumper.dump 16 binEssence.BinHandle.ISA.WordSize true addr bytes + let wordSize = binEssence.BinHandle.File.ISA.WordSize + HexDumper.dump 16 wordSize true addr bytes | Error e -> [| OutputColored [ ColoredSegment (NoColor, e) ] |] | _ -> [| __.CmdHelp |] |> Array.map OutputNormal diff --git a/src/RearEnd/BinExplorer/List.fs b/src/RearEnd/BinExplorer/List.fs index 640b503f..5a3032f6 100644 --- a/src/RearEnd/BinExplorer/List.fs +++ b/src/RearEnd/BinExplorer/List.fs @@ -25,48 +25,50 @@ namespace B2R2.RearEnd.BinExplorer open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface open B2R2.MiddleEnd.BinEssence type CmdList () = inherit Cmd () - let createFuncString hdl (addr, name) = - Addr.toString hdl.ISA.WordSize addr + ": " + name + let createFuncString (hdl: BinHandle) (addr, name) = + Addr.toString hdl.File.ISA.WordSize addr + ": " + name let listFunctions ess = ess.CodeManager.FunctionMaintainer.RegularFunctions - |> Seq.map (fun c -> c.Entry, c.FunctionID) + |> Seq.map (fun c -> c.EntryPoint, c.FunctionID) |> Seq.sortBy fst |> Seq.map (createFuncString ess.BinHandle) |> Seq.toArray - let createSegmentString handler (seg: Segment) = + let createSegmentString wordSize (seg: Segment) = "- " - + Addr.toString handler.ISA.WordSize seg.Address + + Addr.toString wordSize seg.Address + ":" - + Addr.toString handler.ISA.WordSize (seg.Address + seg.Size) + + Addr.toString wordSize (seg.Address + uint64 seg.Size) + " (" + seg.Size.ToString () + ") (" - + FileInfo.PermissionToString seg.Permission + ")" + + Permission.toString seg.Permission + ")" - let listSegments (handler: BinHandle) = - handler.FileInfo.GetSegments () - |> Seq.map (createSegmentString handler) + let listSegments (hdl: BinHandle) = + let wordSize = hdl.File.ISA.WordSize + hdl.File.GetSegments () + |> Seq.map (createSegmentString wordSize) |> Seq.toArray - let createSectionString handler (idx: int) (sec: Section) = + let createSectionString wordSize (idx: int) (sec: Section) = idx.ToString ("D2") + ". " - + Addr.toString handler.ISA.WordSize sec.Address + + Addr.toString wordSize sec.Address + ":" - + Addr.toString handler.ISA.WordSize (sec.Address + sec.Size) + + Addr.toString wordSize (sec.Address + uint64 sec.Size) + " (" + sec.Size.ToString ("D6") + ")" + " [" + sec.Name + "] " - let listSections (handler: BinHandle) = - handler.FileInfo.GetSections () - |> Seq.mapi (createSectionString handler) + let listSections (hdl: BinHandle) = + let wordSize = hdl.File.ISA.WordSize + hdl.File.GetSections () + |> Seq.mapi (createSectionString wordSize) |> Seq.toArray override __.CmdName = "list" diff --git a/src/RearEnd/BinExplorer/Print.fs b/src/RearEnd/BinExplorer/Print.fs index deb7c088..97e7aa17 100644 --- a/src/RearEnd/BinExplorer/Print.fs +++ b/src/RearEnd/BinExplorer/Print.fs @@ -27,7 +27,7 @@ namespace B2R2.RearEnd.BinExplorer open System open System.Text.RegularExpressions open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.MiddleEnd.BinEssence open B2R2.RearEnd @@ -93,7 +93,7 @@ type CmdPrint () = | UnknownSize -> Error ("[*] Invalid size letter given.") | sz -> Ok (sz, count, fmt) - let regexFormat = new Regex (@"(\d+)([duxs])([bhwg]?)") + let regexFormat = Regex (@"(\d+)([duxs])([bhwg]?)") let parseFormat fmt = let m = regexFormat.Match (fmt) @@ -111,51 +111,51 @@ type CmdPrint () = let hexPrint sz (i: uint64) = i.ToString ("x" + (sz * 2).ToString ()) - let print handler sz fmt addr = + let print (hdl: BinHandle) sz fmt addr = match fmt with | Hexadecimal -> - BinHandle.ReadUInt (handler, addr=addr, size=sz) |> hexPrint sz + hdl.ReadUInt (addr=addr, size=sz) |> hexPrint sz | UnsignedDecimal -> - BinHandle.ReadUInt(handler, addr=addr, size=sz).ToString () + hdl.ReadUInt(addr=addr, size=sz).ToString () | Decimal -> - BinHandle.ReadInt(handler, addr=addr, size=sz).ToString () + hdl.ReadInt(addr=addr, size=sz).ToString () | _ -> failwith "This is impossible" - let getAddressPrefix handler (addr: uint64) = - let hexWidth = WordSize.toByteWidth handler.ISA.WordSize * 2 + let getAddressPrefix (hdl: BinHandle) (addr: uint64) = + let hexWidth = WordSize.toByteWidth hdl.File.ISA.WordSize * 2 addr.ToString ("x" + hexWidth.ToString ()) + ": " - let rec iter handler sz fmt addr endAddr acc = + let rec iter hdl sz fmt addr endAddr acc = if addr >= endAddr then List.rev acc |> List.toArray else - let addrstr = getAddressPrefix handler addr + let addrstr = getAddressPrefix hdl addr let acc = - try (addrstr + print handler sz fmt addr) :: acc + try (addrstr + print hdl sz fmt addr) :: acc with _ -> (addrstr + "(invalid)") :: acc - iter handler sz fmt (addr + uint64 sz) endAddr acc + iter hdl sz fmt (addr + uint64 sz) endAddr acc - let rec printStrings handler addr cnt acc = + let rec printStrings (hdl: BinHandle) addr cnt acc = if cnt <= 0 then List.rev acc |> List.toArray else let s = - try BinHandle.ReadASCII (handler, addr=addr) |> Some with _ -> None + try hdl.ReadASCII (addr=addr) |> Some with _ -> None match s with - | None -> printStrings handler addr 0 acc + | None -> printStrings hdl addr 0 acc | Some s -> - let addrstr = getAddressPrefix handler addr + let addrstr = getAddressPrefix hdl addr let len = String.length s |> uint64 - printStrings handler (addr + len + 1UL) (cnt - 1) ((addrstr + s) :: acc) + printStrings hdl (addr + len + 1UL) (cnt - 1) ((addrstr + s) :: acc) let validateRequest (binEssence: BinEssence) = function | Ok (_, count, ASCII, addr) -> - let handler = binEssence.BinHandle - printStrings handler addr count [] + let hdl = binEssence.BinHandle + printStrings hdl addr count [] | Ok (sz, count, fmt, addr) -> - let handler = binEssence.BinHandle + let hdl = binEssence.BinHandle let sz = PrintSize.ToInt sz let endAddr = addr + uint64 (sz * count) if addr > endAddr then [| "[*] Invalid address range given."|] - else iter handler sz fmt addr endAddr [] + else iter hdl sz fmt addr endAddr [] | Error str -> [| str |] override __.CmdName = "print" diff --git a/src/RearEnd/BinExplorer/Program.fs b/src/RearEnd/BinExplorer/Program.fs index 59faf679..3dea7167 100644 --- a/src/RearEnd/BinExplorer/Program.fs +++ b/src/RearEnd/BinExplorer/Program.fs @@ -25,7 +25,7 @@ module B2R2.RearEnd.BinExplorer.Program open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.MiddleEnd.ControlFlowGraph open B2R2.MiddleEnd open B2R2.MiddleEnd.BinEssence @@ -77,7 +77,7 @@ type BinExplorerOpts (isa) = /// List of analyses to perform. member __.GetAnalyses arch = let preanalyses = - [ if arch = Arch.EVM then + [ if arch = Architecture.EVM then if __.EnableEVMAnalysis then EVMCodeCopyAnalysis () :> IPluggableAnalysis EVMTrampolineAnalysis (__.EVMAbiFile) :> IPluggableAnalysis @@ -206,10 +206,10 @@ let spec = long = "--batch" ) ] -let buildGraph (opts: BinExplorerOpts) handle = - let arch = handle.ISA.Arch +let buildGraph (opts: BinExplorerOpts) (hdl: BinHandle) = + let arch = hdl.File.ISA.Arch let preanalyses, iteranalyses, postanalyses = opts.GetAnalyses arch - BinEssence.init handle preanalyses iteranalyses postanalyses + BinEssence.init hdl preanalyses iteranalyses postanalyses let startGUI (opts: BinExplorerOpts) arbiter = HTTPServer.startServer arbiter opts.IP opts.Port opts.Verbose @@ -223,18 +223,18 @@ let dumpJsonFiles jsonDir ess = ess.CodeManager.FunctionMaintainer.RegularFunctions |> Seq.iter (fun func -> let id = func.FunctionID - let entry = func.Entry + let ep = func.EntryPoint let disasmJsonPath = Printf.sprintf "%s/%s.disasmCFG" jsonDir id - let cfg, root = BinEssence.getFunctionCFG ess entry |> Result.get - let disasmcfg, _ = DisasmLens.filter ess.CodeManager cfg root + let cfg, root = BinEssence.getFunctionCFG ess ep |> Result.get + let disasmcfg, _ = DisasmLens.convert ess.CodeManager cfg root CFGExport.toJson disasmcfg disasmJsonPath) let initBinHdl isa (name: string) = - let autoDetect = not (isa.Arch = Architecture.EVM) - BinHandle.Init (isa, ArchOperationMode.NoMode, autoDetect, None, name) + let autoDetect = (isa.Arch <> Architecture.EVM) + BinHandle (name, isa, ArchOperationMode.NoMode, None) let interactiveMain files (opts: BinExplorerOpts) = - if List.length files = 0 then + if List.isEmpty files then eprintfn "A file should be given as input.\n\n\ Type --help or --batch to see more info."; exit 1 else diff --git a/src/RearEnd/BinExplorer/ROP.fs b/src/RearEnd/BinExplorer/ROP.fs index 553009b4..57bbf0ab 100644 --- a/src/RearEnd/BinExplorer/ROP.fs +++ b/src/RearEnd/BinExplorer/ROP.fs @@ -72,7 +72,7 @@ type CmdROP () = override __.CallBack _ ess args = let hdl = ess.BinHandle - match hdl.ISA.Arch with + match hdl.File.ISA.Arch with | Architecture.IntelX86 -> let rop = ROPHandle.init hdl 0UL __.HandleSubCmd hdl rop args diff --git a/src/RearEnd/BinExplorer/Search.fs b/src/RearEnd/BinExplorer/Search.fs index 03714465..02b91db4 100644 --- a/src/RearEnd/BinExplorer/Search.fs +++ b/src/RearEnd/BinExplorer/Search.fs @@ -26,19 +26,21 @@ namespace B2R2.RearEnd.BinExplorer open System open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface type CmdSearch () = inherit Cmd () - let search hdl pattern = - hdl.FileInfo.GetSegments (Permission.Readable) - |> Seq.map (fun s -> BinHandle.ReadBytes (hdl, s.Address, int s.Size) - |> ByteArray.findIdxs 0UL pattern - |> List.map (fun idx -> idx + s.Address)) - |> Seq.concat - |> Seq.map (fun idx -> "Found @ " + String.u64ToHexNoPrefix idx) + let toResult (idx: uint64) = $"Found @ {idx:x}" + + let search (hdl: BinHandle) pattern = + hdl.File.GetSegments (Permission.Readable) + |> Seq.collect (fun s -> + hdl.ReadBytes (s.Address, int s.Size) + |> ByteArray.findIdxs 0UL pattern + |> List.map (fun idx -> idx + s.Address)) + |> Seq.map toResult |> Seq.toList override __.CmdName = "search" @@ -71,10 +73,10 @@ type CmdSearch () = | c -> [| "Unknown type " + c |] override __.CallBack _ ess args = - match args with - | [] - | _ :: [] -> [| __.CmdHelp |] - | t :: pattern :: _ -> t.ToLower () |> __.CmdHandle ess.BinHandle pattern - |> Array.map OutputNormal - -// vim: set tw=80 sts=2 sw=2: + let res = + match args with + | [] + | _ :: [] -> [| __.CmdHelp |] + | t :: pattern :: _ -> + t.ToLowerInvariant () |> __.CmdHandle ess.BinHandle pattern + Array.map OutputNormal res diff --git a/src/RearEnd/BinExplorer/Show.fs b/src/RearEnd/BinExplorer/Show.fs index 6b98809d..fa4000c7 100644 --- a/src/RearEnd/BinExplorer/Show.fs +++ b/src/RearEnd/BinExplorer/Show.fs @@ -49,11 +49,11 @@ type CmdShow () = override __.SubCommands = [] member private __.CallerToString (sb: StringBuilder) (addr: Addr) = - sb.Append (" - referenced by " + String.u64ToHexNoPrefix addr + "\n") + sb.Append $" - referenced by {addr:x}\n" - member private __.CalleeToSimpleString ess prefix (sb: StringBuilder) (callee: Function) = + member private __.CalleeToSimpleString prefix (sb: StringBuilder) callee = let noret = - match callee.NoReturnProperty with + match (callee: Function).NoReturnProperty with | NoRet -> " [no return]" | ConditionalNoRet _ -> " [conditional no return]" | NotNoRetConfirmed | NotNoRet -> "" @@ -62,10 +62,10 @@ type CmdShow () = sb.Append (prefix + callee.FunctionName + noret + "\n") else sb.Append (prefix + callee.FunctionName - + noret + " @ " + String.u64ToHexNoPrefix callee.Entry + "\n") + + noret + $" @ {callee.EntryPoint:x}\n") member private __.CalleeToString ess (sb: StringBuilder) callee = - __.CalleeToSimpleString ess "" sb callee + __.CalleeToSimpleString "" sb callee |> (fun sb -> callee.Callers |> Seq.fold __.CallerToString sb) member __.ShowCaller ess = function @@ -80,7 +80,7 @@ type CmdShow () = func.Callers |> Seq.fold (fun sb (addr: Addr) -> match ess.CodeManager.FunctionMaintainer.TryFind addr with - | Some callee -> __.CalleeToSimpleString ess " - " sb callee + | Some callee -> __.CalleeToSimpleString " - " sb callee | None -> sb) sb [| sb.ToString () |] | _ -> [| __.CmdHelp |] @@ -92,7 +92,8 @@ type CmdShow () = if Char.IsDigit expr[0] then ess.CodeManager.FunctionMaintainer.TryFind (addr) else ess.CodeManager.FunctionMaintainer.TryFind (expr) - |> Option.map (fun callee -> (__.CalleeToString ess sb callee).ToString ()) + |> Option.map (fun callee -> + (__.CalleeToString ess sb callee).ToString ()) |> Option.defaultValue "[*] Not found." |> Array.singleton | _ -> [| __.CmdHelp |] @@ -106,7 +107,7 @@ type CmdShow () = override __.CallBack _ ess args = match args with | [] -> [| __.CmdHelp |] - | c :: opts -> c.ToLower () |> __.CmdHandle ess opts + | c :: opts -> c.ToLowerInvariant () |> __.CmdHandle ess opts |> Array.map OutputNormal // vim: set tw=80 sts=2 sw=2: diff --git a/src/RearEnd/BinExplorer/SimpleArithParser.fs b/src/RearEnd/BinExplorer/SimpleArithParser.fs index 99750ba5..70fe7c8d 100644 --- a/src/RearEnd/BinExplorer/SimpleArithParser.fs +++ b/src/RearEnd/BinExplorer/SimpleArithParser.fs @@ -40,7 +40,7 @@ module SimpleArithParser = else (System.Numerics.BigInteger.Parse str, -1) - type Parser<'a> = Parser<'a,unit> + type Parser<'A> = Parser<'A, unit> let dummyValue = { IntValue = 0I; Type = CError Default ; FloatValue = 0.0 } @@ -134,8 +134,7 @@ module SimpleArithParser = let strWs s = pstring s >>. spaces - let opp = - new OperatorPrecedenceParser() + let opp = OperatorPrecedenceParser() let expr = opp.ExpressionParser @@ -171,12 +170,14 @@ module SimpleArithParser = opp.AddOperator(constructCastingOp "(float32)" (Float Bit32)) opp.AddOperator(constructCastingOp "(float)" (Float Bit64)) -module SimpleArithASCIIPArser = +module SimpleArithASCIIParser = let parseSingleByte = hex .>>. hex |>> (fun (a, b) -> "0x" + string a + string b) + let singleHexToString ch = "0x0" + string ch + let parseSingleHexDigit: Parser = - hex |>> (fun a -> "0x0" + string a) + hex |>> singleHexToString let parseOddNumberOfHexDigits = pstringCI "0x" >>. parseSingleHexDigit .>>. many parseSingleByte @@ -216,8 +217,10 @@ module SimpleArithASCIIPArser = let parseOctal = anyOf "01234567" + let singleOctalToString ch = "0o00" + string ch + let parseSingleOctalDigit = - parseOctal |>> (fun a -> "0o00" + string a) + parseOctal |>> singleOctalToString let parseDoubleOctalDigit = parseOctal .>>. parseOctal diff --git a/src/RearEnd/Core/B2R2.RearEnd.Core.fsproj b/src/RearEnd/Core/B2R2.RearEnd.Core.fsproj index 3e7a07fe..38187862 100644 --- a/src/RearEnd/Core/B2R2.RearEnd.Core.fsproj +++ b/src/RearEnd/Core/B2R2.RearEnd.Core.fsproj @@ -5,6 +5,7 @@ + diff --git a/src/RearEnd/Core/CmdOpts.fs b/src/RearEnd/Core/CmdOpts.fs index ab518b7a..4d0cda1a 100644 --- a/src/RearEnd/Core/CmdOpts.fs +++ b/src/RearEnd/Core/CmdOpts.fs @@ -28,17 +28,15 @@ open B2R2 open B2R2.FsOptParse open System -module CS = ColoredSegment - /// A common set of command-line options used in analyzing binaries. type CmdOpts () = /// Verbosity member val Verbose = false with get, set /// Just a wrapper function that instantiate an OptParse.Option object. - static member New<'a> (descr, ?callback, ?required, ?extra, ?help, + static member New<'T> (descr, ?callback, ?required, ?extra, ?help, ?short, ?long, ?dummy, ?descrColor) = - Option<'a> (descr, + Option<'T> (descr, ?callback=callback, ?required=required, ?extra=extra, ?help=help, @@ -60,25 +58,28 @@ type CmdOpts () = /// Write B2R2 logo to console. We can selectively append a new line at the /// end. static member WriteB2R2 newLine = - [ CS.dcyan "B"; CS.dyellow "2"; CS.dcyan "R"; CS.dyellow "2" ] - |> Printer.printToConsole - if newLine then Printer.printToConsoleLine () else () - - static member private WriteIntro () = + [ ColoredSegment (DarkCyan, "B") + ColoredSegment (DarkYellow, "2") + ColoredSegment (DarkCyan, "R") + ColoredSegment (DarkYellow, "2") ] + |> Printer.PrintToConsole + if newLine then Printer.PrintToConsoleLine () else () + + static member WriteIntro () = CmdOpts.WriteB2R2 false - Printer.printToConsoleLine (", the Next-Generation Reversing Platform") - Printer.printToConsoleLine (Attribution.Copyright + Environment.NewLine) + Printer.PrintToConsoleLine (", the Next-Generation Reversing Platform") + Printer.PrintToConsoleLine (Attribution.Copyright + Environment.NewLine) static member private CreateUsageGetter tool usageTail = fun () -> CmdOpts.WriteIntro () let tail = if String.IsNullOrEmpty usageTail then "" else " " + usageTail - String.Format ("[Usage]{0}{0}dotnet b2r2 {1} %o{2}", + String.Format ("[Usage]{0}{0}b2r2 {1} %o{2}", Environment.NewLine, tool, tail) static member private TermFunction () = exit 1 - static member private parseCmdOpts spec defaultOpts argv tool usageTail = + static member private ParseCmdOpts spec defaultOpts argv tool usageTail = let prog = Environment.GetCommandLineArgs()[0] let usageGetter = CmdOpts.CreateUsageGetter tool usageTail try @@ -101,7 +102,7 @@ type CmdOpts () = /// Parse command line arguments, and run the mainFn static member ParseAndRun mainFn tool usageTail spec (opts: #CmdOpts) args = - let rest, opts = CmdOpts.parseCmdOpts spec opts args tool usageTail + let rest, opts = CmdOpts.ParseCmdOpts spec opts args tool usageTail if opts.Verbose then CmdOpts.WriteIntro () else () try mainFn rest opts; 0 with e -> eprintfn "Error: %s" e.Message @@ -113,7 +114,7 @@ type CmdOpts () = let rec sanitize = function | (arg: string) :: rest -> if arg.StartsWith ('-') then - Printer.printErrorToConsole + Printer.PrintErrorToConsole <| sprintf "Invalid argument (%s) is used" arg exit 1 else sanitize rest diff --git a/src/RearEnd/Core/HexDumper.fs b/src/RearEnd/Core/HexDumper.fs index 2b8910f1..7ed967c3 100644 --- a/src/RearEnd/Core/HexDumper.fs +++ b/src/RearEnd/Core/HexDumper.fs @@ -26,8 +26,6 @@ namespace B2R2.RearEnd open B2R2 -module CS = ColoredSegment - module HexDumper = let internal padSpace chuckSize length = let m = length % chuckSize @@ -39,29 +37,31 @@ module HexDumper = | 8 | 16 | 24 -> " " + s | _ -> " " + s - let internal colorHexDumper addrStr chuckSize (bytes: byte []) = + let internal colorHexDumper addrStr chuckSize (bytes: byte[]) = let padding = padSpace chuckSize bytes.Length |> Array.map (fun pad -> ColoredSegment (NoColor, pad)) let coloredHex = - Array.append (bytes |> Array.map CS.byteToHex) padding + Array.append (bytes |> Array.map ColoredSegment.hexOfByte) padding |> Array.mapi (fun idx (color, hex) -> color, addSpace idx hex) - let coloredAscii = bytes |> Array.map CS.byteToAscii - Array.append [| ColoredSegment (NoColor, " | ") |] coloredAscii - |> Array.append coloredHex - |> Array.append [| ColoredSegment (NoColor, addrStr + ": ") |] + let coloredAscii = bytes |> Array.map ColoredSegment.asciiOfByte + [| [| ColoredSegment (NoColor, addrStr + ": ") |] + coloredHex + [| ColoredSegment (NoColor, " | ") |] + coloredAscii |] + |> Array.concat |> List.ofArray |> ColoredString.compile |> OutputColored - let internal regularHexDumper addrStr chuckSize (bytes: byte []) = + let internal regularHexDumper addrStr chuckSize (bytes: byte[]) = let padding = padSpace chuckSize (bytes.Length) let hex = Array.append (bytes |> Array.map (fun b -> b.ToString ("X2"))) padding - |> Array.mapi (fun idx s -> addSpace idx s) - |> Array.fold (fun arr s -> arr + s) "" + |> Array.mapi addSpace + |> Array.fold (+) "" let ascii = - bytes |> Array.fold (fun arr b -> arr + CS.getRepresentation b) "" + bytes |> Array.fold (fun arr b -> arr + Byte.getRepresentation b) "" addrStr + ": " + hex + " | " + ascii |> OutputNormal diff --git a/src/RearEnd/Core/StringUtils.fs b/src/RearEnd/Core/StringUtils.fs new file mode 100644 index 00000000..412765cf --- /dev/null +++ b/src/RearEnd/Core/StringUtils.fs @@ -0,0 +1,32 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.StringUtils + +open B2R2 + +let entryPointToString (entryPoint: Addr option) = + match entryPoint with + | None -> "none" + | Some entry -> $"0x{entry:x}" diff --git a/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj b/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj index 5923695c..8ba5313b 100644 --- a/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj +++ b/src/RearEnd/FileViewer/B2R2.RearEnd.FileViewer.fsproj @@ -16,8 +16,9 @@ - + + diff --git a/src/RearEnd/FileViewer/Cmd.fs b/src/RearEnd/FileViewer/Cmd.fs index 000453f3..a3ed59a2 100644 --- a/src/RearEnd/FileViewer/Cmd.fs +++ b/src/RearEnd/FileViewer/Cmd.fs @@ -116,6 +116,13 @@ type FileViewerOpts () = CmdOpts.New (descr = "Display the function symbols", callback = cb, short = "-f", long = "--functions") + /// "-x" or "--exceptions" option for displaying the exception table. + static member OptExceptionTable () = + let cb opts _ = + FileViewerOpts.AddOpt opts DisplayExceptionTable + CmdOpts.New (descr = "Display the exception table", + callback = cb, short = "-x", long = "--exceptions") + /// "--program-headers" option for displaying the program headers. static member OptProgramHeaders () = let cb opts _ = @@ -137,13 +144,13 @@ type FileViewerOpts () = CmdOpts.New (descr = "Display the eh_frame information", callback = cb, long = "--ehframe") - /// "--lsda" option for displaying the .gcc_except_table section information, - /// i.e., LSDAs. - static member OptLSDA () = + /// "--gcc-except-table" option for displaying the .gcc_except_table section + /// information. + static member OptGccExceptTable () = let cb opts _ = - FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayLSDA) - CmdOpts.New (descr = "Display the LSDA information", - callback = cb, long = "--lsda") + FileViewerOpts.AddOpt opts (DisplayELFSpecific ELFDisplayGccExceptTable) + CmdOpts.New (descr = "Display the gcc_except_table information", + callback = cb, long = "--gcc-except-table") /// "--notes" option for displaying the notes section information. static member OptNotes () = @@ -239,6 +246,7 @@ module Cmd = FileViewerOpts.OptSymbols () FileViewerOpts.OptRelocs () FileViewerOpts.OptFunctions () + FileViewerOpts.OptExceptionTable () CmdOpts.New (descr = "", dummy = true) CmdOpts.New (descr = "[ELF options]", dummy = true) @@ -247,7 +255,7 @@ module Cmd = FileViewerOpts.OptProgramHeaders () FileViewerOpts.OptPLT () FileViewerOpts.OptEHFrame () - FileViewerOpts.OptLSDA () + FileViewerOpts.OptGccExceptTable () FileViewerOpts.OptNotes () CmdOpts.New (descr = "", dummy = true) diff --git a/src/RearEnd/FileViewer/DisplayItem.fs b/src/RearEnd/FileViewer/DisplayItem.fs index 39cc5096..b4c3cbcf 100644 --- a/src/RearEnd/FileViewer/DisplayItem.fs +++ b/src/RearEnd/FileViewer/DisplayItem.fs @@ -29,7 +29,7 @@ type ELFDisplayItem = | ELFDisplayProgramHeader | ELFDisplayPLT | ELFDisplayEHFrame - | ELFDisplayLSDA + | ELFDisplayGccExceptTable | ELFDisplayNotes /// Display items for PE. @@ -53,16 +53,18 @@ type DisplayItem = | DisplayAll /// Basic file header information. | DisplayFileHeader - /// Section headers + /// Section headers. | DisplaySectionHeaders - /// Section details + /// Section details. | DisplaySectionDetails of string /// Symbols. | DisplaySymbols - /// Relocations + /// Relocations. | DisplayRelocations /// Functions. | DisplayFunctions + /// Exception table. + | DisplayExceptionTable /// ELF-specific item. | DisplayELFSpecific of ELFDisplayItem /// PE-specific item. diff --git a/src/RearEnd/FileViewer/ELFViewer.fs b/src/RearEnd/FileViewer/ELFViewer.fs index 7a5a9db5..8c34c382 100644 --- a/src/RearEnd/FileViewer/ELFViewer.fs +++ b/src/RearEnd/FileViewer/ELFViewer.fs @@ -25,33 +25,36 @@ module B2R2.RearEnd.FileViewer.ELFViewer open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile +open B2R2.FrontEnd.BinFile.ELF open B2R2.RearEnd.FileViewer.Helper +open B2R2.MiddleEnd.ControlFlowAnalysis let badAccess _ _ = - raise InvalidFileTypeException + raise InvalidFileFormatException -let computeMagicBytes (fi: ELFFileInfo) = - fi.ELF.BinReader.ReadBytes (fi.Span, 0, 16) |> ColoredSegment.colorBytes +let computeMagicBytes (file: IBinFile) = + let slice = file.Slice (offset=0, size=16) + slice.ToArray () |> ColoredString.ofBytes -let computeEntryPoint (hdr: ELF.ELFHeader) = - [ ColoredSegment.green <| String.u64ToHex hdr.EntryPoint ] +let computeEntryPoint (hdr: ELFHeader) = + [ ColoredSegment (Green, HexString.ofUInt64 hdr.EntryPoint) ] -let dumpFileHeader (_: FileViewerOpts) (fi: ELFFileInfo) = - let hdr = fi.ELF.ELFHdr - out.PrintTwoColsWithColorOnSnd "Magic:" (computeMagicBytes fi) +let dumpFileHeader (_: FileViewerOpts) (file: ELFBinFile) = + let hdr = file.Header + out.PrintTwoColsWithColorOnSnd "Magic:" (computeMagicBytes file) out.PrintTwoCols "Class:" ("ELF" + WordSize.toString hdr.Class) out.PrintTwoCols "Data:" (Endian.toString hdr.Endian + " endian") out.PrintTwoCols "Version:" (hdr.Version.ToString ()) - out.PrintTwoCols "ABI:" (hdr.OSABI.ToString ()) + out.PrintTwoCols "ABI:" (OSABI.toString hdr.OSABI) out.PrintTwoCols "ABI version:" (hdr.OSABIVersion.ToString ()) - out.PrintTwoCols "Type:" (hdr.ELFFileType.ToString ()) + out.PrintTwoCols "Type:" (ELFFileType.toString hdr.ELFFileType) out.PrintTwoCols "Machine:" (hdr.MachineType.ToString ()) out.PrintTwoColsWithColorOnSnd "Entry point:" (computeEntryPoint hdr) - out.PrintTwoCols "PHdr table offset:" (String.u64ToHex hdr.PHdrTblOffset) - out.PrintTwoCols "SHdr table offset:" (String.u64ToHex hdr.SHdrTblOffset) - out.PrintTwoCols "Flags:" (String.u64ToHex (uint64 hdr.ELFFlags)) + out.PrintTwoCols "PHdr table offset:" (HexString.ofUInt64 hdr.PHdrTblOffset) + out.PrintTwoCols "SHdr table offset:" (HexString.ofUInt64 hdr.SHdrTblOffset) + out.PrintTwoCols "Flags:" (HexString.ofUInt64 (uint64 hdr.ELFFlags)) out.PrintTwoCols "Header size:" (toNBytes (uint64 hdr.HeaderSize)) out.PrintTwoCols "PHdr Entry Size:" (toNBytes (uint64 hdr.PHdrEntrySize)) out.PrintTwoCols "PHdr Entry Num:" (hdr.PHdrNum.ToString ()) @@ -59,8 +62,9 @@ let dumpFileHeader (_: FileViewerOpts) (fi: ELFFileInfo) = out.PrintTwoCols "SHdr Entry Num:" (hdr.SHdrNum.ToString ()) out.PrintTwoCols "SHdr string index:" (hdr.SHdrStrIdx.ToString ()) -let dumpSectionHeaders (opts: FileViewerOpts) (fi: ELFFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpSectionHeaders (opts: FileViewerOpts) (elf: ELFBinFile) = + let addrColumn = columnWidthOfAddr elf |> LeftAligned + let file = elf :> IBinFile if opts.Verbose then let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24; LeftAligned 14; LeftAligned 12; LeftAligned 8; LeftAligned 10; @@ -69,126 +73,191 @@ let dumpSectionHeaders (opts: FileViewerOpts) (fi: ELFFileInfo) = "Type"; "Offset"; "Size"; "EntrySize" "Link"; "Info"; "Align"; "Flags" ]) out.PrintLine " ---" - fi.ELF.SecInfo.SecByNum + elf.SectionHeaders |> Array.iteri (fun idx s -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize s.SecAddr) - (Addr.toString fi.WordSize (s.SecAddr + s.SecSize - uint64 1)) + (Addr.toString file.ISA.WordSize s.SecAddr) + (Addr.toString file.ISA.WordSize (s.SecAddr + s.SecSize - uint64 1)) normalizeEmpty s.SecName s.SecType.ToString () - String.u64ToHex s.SecOffset - String.u64ToHex s.SecSize - String.u64ToHex s.SecEntrySize + HexString.ofUInt64 s.SecOffset + HexString.ofUInt64 s.SecSize + HexString.ofUInt64 s.SecEntrySize s.SecLink.ToString () s.SecInfo.ToString () - String.u64ToHex s.SecAlignment + HexString.ofUInt64 s.SecAlignment s.SecFlags.ToString () ])) else let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 ] out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" ]) out.PrintLine " ---" - fi.GetSections () + file.GetSections () |> Seq.iteri (fun idx s -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize s.Address) - (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + (Addr.toString file.ISA.WordSize s.Address) + (Addr.toString file.ISA.WordSize (s.Address + uint64 s.Size - 1UL)) normalizeEmpty s.Name ])) -let dumpSectionDetails (secname: string) (fi: ELFFileInfo) = - match fi.ELF.SecInfo.SecByName.TryFind secname with +let dumpSectionDetails (secname: string) (file: ELFBinFile) = + match file.TryFindSection secname with | Some section -> out.PrintTwoCols "Section number:" (section.SecNum.ToString ()) out.PrintTwoCols "Section name:" section.SecName out.PrintTwoCols "Type:" (section.SecType.ToString ()) - out.PrintTwoCols "Address:" (String.u64ToHex section.SecAddr) - out.PrintTwoCols "Offset:" (String.u64ToHex section.SecOffset) - out.PrintTwoCols "Size:" (String.u64ToHex section.SecSize) - out.PrintTwoCols "Entry Size:" (String.u64ToHex section.SecEntrySize) + out.PrintTwoCols "Address:" (HexString.ofUInt64 section.SecAddr) + out.PrintTwoCols "Offset:" (HexString.ofUInt64 section.SecOffset) + out.PrintTwoCols "Size:" (HexString.ofUInt64 section.SecSize) + out.PrintTwoCols "Entry Size:" (HexString.ofUInt64 section.SecEntrySize) out.PrintTwoCols "Flag:" (section.SecFlags.ToString ()) out.PrintTwoCols "Link:" (section.SecLink.ToString ()) out.PrintTwoCols "Info:" (section.SecInfo.ToString ()) - out.PrintTwoCols "Alignment:" (String.u64ToHex section.SecAlignment) + out.PrintTwoCols "Alignment:" (HexString.ofUInt64 section.SecAlignment) | None -> out.PrintLine "Not found." -let printSymbolInfoVerbose (fi: ELFFileInfo) s (elfSymbol: ELF.ELFSymbol) cfg = +let printSymbolInfoVerbose (file: IBinFile) s (elfSymbol: ELFSymbol) cfg = let sectionIndex = match elfSymbol.SecHeaderIndex with - | ELF.SectionHeaderIdx.SecIdx idx -> idx.ToString () - | _ as idx -> idx.ToString () + | SectionIndex idx -> idx.ToString () + | idx -> idx.ToString () out.PrintRow (true, cfg, - [ targetString s - Addr.toString fi.WordSize s.Address + [ visibilityString s + Addr.toString file.ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName - String.u64ToHex elfSymbol.Size + HexString.ofUInt64 elfSymbol.Size elfSymbol.SymType.ToString () elfSymbol.Bind.ToString () elfSymbol.Vis.ToString () String.wrapSqrdBracket sectionIndex ]) -let printSymbolInfoNone (fi: ELFFileInfo) s cfg = +let printSymbolInfoNone (file: IBinFile) s cfg = out.PrintRow (true, cfg, - [ targetString s - Addr.toString fi.WordSize s.Address + [ visibilityString s + Addr.toString file.ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)" ]) -let printSymbolInfo isVerbose (fi: ELFFileInfo) (symbols: seq) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let printSymbolInfo isVerbose (elf: ELFBinFile) (symbols: seq) = + let addrColumn = columnWidthOfAddr elf |> LeftAligned if isVerbose then let cfg = [ LeftAligned 4; addrColumn; LeftAligned 55; LeftAligned 15 LeftAligned 8; LeftAligned 12; LeftAligned 12; LeftAligned 12 LeftAligned 8 ] - out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" + out.PrintRow (true, cfg, [ "S/D"; "Address"; "Name"; "Lib Name" "Size"; "Type"; "Bind"; "Visibility" "SectionIndex" ]) out.PrintLine " ---" symbols |> Seq.sortBy (fun s -> s.Name) |> Seq.sortBy (fun s -> s.Address) - |> Seq.sortBy (fun s -> s.Target) + |> Seq.sortBy (fun s -> s.Visibility) |> Seq.iter (fun s -> - match fi.ELF.SymInfo.AddrToSymbTable.TryFind s.Address with - | Some elfSymbol -> printSymbolInfoVerbose fi s elfSymbol cfg - | None -> - match fi.ELF.RelocInfo.RelocByName.TryGetValue s.Name with + match elf.SymbolInfo.AddrToSymbTable.TryGetValue s.Address with + | true, elfSymbol -> printSymbolInfoVerbose elf s elfSymbol cfg + | false, _ -> + match elf.RelocationInfo.RelocByName.TryGetValue s.Name with | true, reloc -> match reloc.RelSymbol with - | Some elfSymbol -> printSymbolInfoVerbose fi s elfSymbol cfg - | None -> printSymbolInfoNone fi s cfg - | false, _ -> printSymbolInfoNone fi s cfg) + | Some elfSymbol -> printSymbolInfoVerbose elf s elfSymbol cfg + | None -> printSymbolInfoNone elf s cfg + | false, _ -> printSymbolInfoNone elf s cfg) else - let cfg = [ LeftAligned 15; addrColumn; LeftAligned 75; LeftAligned 15 ] - out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" ]) + let cfg = [ LeftAligned 3; LeftAligned 10 + addrColumn; LeftAligned 75; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "S/D"; "Kind"; "Address"; "Name"; "Lib Name" ]) out.PrintLine " ---" symbols |> Seq.sortBy (fun s -> s.Name) |> Seq.sortBy (fun s -> s.Address) - |> Seq.sortBy (fun s -> s.Target) + |> Seq.sortBy (fun s -> s.Visibility) |> Seq.iter (fun s -> out.PrintRow (true, cfg, - [ targetString s - Addr.toString fi.WordSize s.Address + [ visibilityString s + symbolKindString s + Addr.toString (elf :> IBinFile).ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName ])) -let dumpSymbols (opts: FileViewerOpts) (fi: ELFFileInfo) = - fi.GetSymbols () - |> printSymbolInfo opts.Verbose fi +let dumpSymbols (opts: FileViewerOpts) (elf: ELFBinFile) = + (elf :> IBinFile).GetSymbols () + |> printSymbolInfo opts.Verbose elf + +let dumpRelocs (_opts: FileViewerOpts) (elf: ELFBinFile) = + let addrColumn = columnWidthOfAddr elf |> LeftAligned + let cfg = [ addrColumn; LeftAligned 24; RightAligned 8; LeftAligned 12 ] + out.PrintRow (true, cfg, [ "Address"; "Type"; "Addended"; "Symbol" ]) + out.PrintLine " ---" + elf.RelocationInfo.RelocByAddr.Values + |> Seq.sortBy (fun reloc -> reloc.RelOffset) + |> Seq.iter (fun reloc -> + let symbol = + match reloc.RelSymbol with + | Some s when s.SymName.Length > 0 -> s.SymName + | _ -> "(n/a)" + out.PrintRow (true, cfg, [ + Addr.toString (elf :> IBinFile).ISA.WordSize reloc.RelOffset + RelocationType.ToString reloc.RelType + reloc.RelAddend.ToString ("x") + symbol + ]) + ) + +let dumpFunctions (opts: FileViewerOpts) (elf: ELFBinFile) = + (elf :> IBinFile).GetFunctionSymbols () + |> printSymbolInfo opts.Verbose elf + +let dumpExceptionTable hdl (_opts: FileViewerOpts) (file: ELFBinFile) = + let exnTbl, _ = ELFExceptionTable.build hdl file + exnTbl + |> ARMap.iter (fun range catchBlkAddr -> + out.PrintLine $"{range.Min:x}:{range.Max:x} -> {catchBlkAddr:x}") -let dumpRelocs (opts: FileViewerOpts) (fi: ELFFileInfo) = - fi.GetRelocationSymbols () - |> printSymbolInfo opts.Verbose fi +let makeStringTableReader (file: IBinFile) dynEntries = + dynEntries + |> Array.fold (fun (addr, len) (ent: DynamicSectionEntry) -> + match ent.DTag with + | DynamicTag.DT_STRTAB -> Some ent.DVal, len + | DynamicTag.DT_STRSZ -> addr, Some ent.DVal + | _ -> addr, len + ) (None, None) + ||> Option.map2 (fun addr len -> + fun v -> + let strtab = file.Slice (addr=addr, size=int len) + let buf = strtab.Slice (int v) + ByteArray.extractCStringFromSpan buf 0) -let dumpFunctions (opts: FileViewerOpts) (fi: ELFFileInfo) = - fi.GetFunctionSymbols () - |> printSymbolInfo opts.Verbose fi +let dumpDynamicSection _ (file: ELFBinFile) = + let cfg = [ LeftAligned 20; LeftAligned 20 ] + out.PrintRow (true, cfg, [ "Tag"; "Name/Value" ]) + out.PrintLine " ---" + let dynEntries = file.DynamicSectionEntries + let strtabReader = makeStringTableReader file dynEntries + dynEntries + |> Array.iter (fun ent -> + let tag = ent.DTag + match tag, strtabReader with + | DynamicTag.DT_NEEDED, Some reader -> + out.PrintRow (true, cfg, [ $"{tag}" + $"Shared library: [{reader ent.DVal}]" ]) + | DynamicTag.DT_SONAME, Some reader -> + out.PrintRow (true, cfg, [ $"{tag}" + $"Library soname: [{reader ent.DVal}]" ]) + | DynamicTag.DT_RPATH, Some reader -> + out.PrintRow (true, cfg, [ $"{tag}" + $"Library rpath: [{reader ent.DVal}]" ]) + | DynamicTag.DT_RUNPATH, Some reader -> + out.PrintRow (true, cfg, [ $"{tag}" + $"Library runpath: [{reader ent.DVal}]" ]) + | _ -> + out.PrintRow (true, cfg, [ $"{tag}"; "0x" + ent.DVal.ToString "x" ]) + ) -let dumpSegments (opts: FileViewerOpts) (fi: ELFFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpSegments (opts: FileViewerOpts) (elf: ELFBinFile) = + let addrColumn = columnWidthOfAddr elf |> LeftAligned + let file = elf :> IBinFile if opts.Verbose then let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 10 LeftAligned 12; LeftAligned 8; addrColumn; addrColumn @@ -197,48 +266,50 @@ let dumpSegments (opts: FileViewerOpts) (fi: ELFFileInfo) = "Type"; "Offset"; "VirtAddr"; "PhysAddr" "FileSize"; "MemSize"; "Alignment" ]) out.PrintLine " ---" - fi.ELF.ProgHeaders - |> List.iteri (fun idx ph -> + let wordSize = file.ISA.WordSize + elf.ProgramHeaders + |> Array.iteri (fun idx ph -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize ph.PHAddr) - (Addr.toString fi.WordSize (ph.PHAddr + ph.PHMemSize - uint64 1)) - (FileInfo.PermissionToString ph.PHFlags) + (Addr.toString wordSize ph.PHAddr) + (Addr.toString wordSize (ph.PHAddr + ph.PHMemSize - uint64 1)) + (Permission.toString ph.PHFlags) ph.PHType.ToString () - String.u64ToHex ph.PHOffset - String.u64ToHex ph.PHAddr - String.u64ToHex ph.PHPhyAddr - String.u64ToHex ph.PHFileSize - String.u64ToHex ph.PHMemSize - String.u64ToHex ph.PHAlignment ])) + HexString.ofUInt64 ph.PHOffset + HexString.ofUInt64 ph.PHAddr + HexString.ofUInt64 ph.PHPhyAddr + HexString.ofUInt64 ph.PHFileSize + HexString.ofUInt64 ph.PHMemSize + HexString.ofUInt64 ph.PHAlignment ])) else let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 10 ] out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Permission" ]) out.PrintLine " ---" - fi.GetSegments () + file.GetSegments () |> Seq.iteri (fun idx s -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize s.Address) - (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) - (FileInfo.PermissionToString s.Permission) ])) + (Addr.toString file.ISA.WordSize s.Address) + (Addr.toString file.ISA.WordSize (s.Address + uint64 s.Size - 1UL)) + (Permission.toString s.Permission) ])) -let dumpLinkageTable (opts: FileViewerOpts) (fi: ELFFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpLinkageTable (opts: FileViewerOpts) (elf: ELFBinFile) = + let addrColumn = columnWidthOfAddr elf |> LeftAligned + let file = elf :> IBinFile if opts.Verbose then let cfg = [ addrColumn; addrColumn; LeftAligned 40; LeftAligned 15 LeftAligned 8; LeftAligned 6; LeftAligned 4 ] out.PrintRow (true, cfg, - [ "PLT Addr"; "GOT Addr"; "FunctionName"; "LibraryName" + [ "PLT Addr"; "GOT Addr"; "FunctionName"; "Lib Name" "Addend"; "SecIdx"; "Type" ]) out.PrintLine " ---" - fi.GetLinkageTableEntries () + file.GetLinkageTableEntries () |> Seq.iter (fun e -> - match fi.ELF.RelocInfo.RelocByAddr.TryGetValue e.TableAddress with + match elf.RelocationInfo.RelocByAddr.TryGetValue e.TableAddress with | true, reloc -> out.PrintRow (true, cfg, - [ (Addr.toString fi.WordSize e.TrampolineAddress) - (Addr.toString fi.WordSize e.TableAddress) + [ (Addr.toString file.ISA.WordSize e.TrampolineAddress) + (Addr.toString file.ISA.WordSize e.TableAddress) normalizeEmpty e.FuncName (toLibString >> normalizeEmpty) e.LibraryName reloc.RelAddend.ToString () @@ -246,40 +317,40 @@ let dumpLinkageTable (opts: FileViewerOpts) (fi: ELFFileInfo) = reloc.RelType.ToString () ]) | false, _ -> out.PrintRow (true, cfg, - [ (Addr.toString fi.WordSize e.TrampolineAddress) - (Addr.toString fi.WordSize e.TableAddress) + [ (Addr.toString file.ISA.WordSize e.TrampolineAddress) + (Addr.toString file.ISA.WordSize e.TableAddress) normalizeEmpty e.FuncName (toLibString >> normalizeEmpty) e.LibraryName "(n/a)"; "(n/a)"; "(n/a)" ])) else let cfg = [ addrColumn; addrColumn; LeftAligned 20; LeftAligned 15 ] out.PrintRow (true, cfg, - [ "PLT"; "GOT"; "FunctionName"; "LibraryName" ]) + [ "PLT"; "GOT"; "FunctionName"; "Lib Name" ]) out.PrintLine " ---" - fi.GetLinkageTableEntries () + file.GetLinkageTableEntries () |> Seq.iter (fun e -> out.PrintRow (true, cfg, - [ (Addr.toString fi.WordSize e.TrampolineAddress) - (Addr.toString fi.WordSize e.TableAddress) + [ (Addr.toString file.ISA.WordSize e.TrampolineAddress) + (Addr.toString file.ISA.WordSize e.TableAddress) normalizeEmpty e.FuncName (toLibString >> normalizeEmpty) e.LibraryName ])) let cfaToString (hdl: BinHandle) cfa = - ELF.CanonicalFrameAddress.toString hdl.RegisterBay cfa + CanonicalFrameAddress.toString hdl.RegisterFactory cfa -let ruleToString (hdl: BinHandle) (rule: ELF.Rule) = +let ruleToString (hdl: BinHandle) (rule: Rule) = rule |> Map.fold (fun s k v -> match k with - | ELF.ReturnAddress -> s + "(ra:" + ELF.Action.toString v + ")" - | ELF.NormalReg rid -> - let reg = hdl.RegisterBay.RegIDToString rid - s + "(" + reg + ":" + ELF.Action.toString v + ")") "" + | ReturnAddress -> s + "(ra:" + Action.toString v + ")" + | NormalReg rid -> + let reg = hdl.RegisterFactory.RegIDToString rid + s + "(" + reg + ":" + Action.toString v + ")") "" -let dumpEHFrame hdl (fi: ELFFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpEHFrame hdl (file: ELFBinFile) = + let addrColumn = columnWidthOfAddr file |> LeftAligned let cfg = [ addrColumn; LeftAligned 10; LeftAligned 50 ] - fi.ELF.ExceptionFrame + file.ExceptionInfo.ExceptionFrames |> List.iter (fun cfi -> out.PrintLine ("- CIE: \"{0}\" cf={1} df={2}", cfi.CIERecord.AugmentationString, @@ -289,8 +360,8 @@ let dumpEHFrame hdl (fi: ELFFileInfo) = cfi.FDERecord |> Array.iter (fun fde -> out.PrintLine (" FDE pc={0}..{1}", - String.u64ToHex fde.PCBegin, - String.u64ToHex fde.PCEnd) + HexString.ofUInt64 fde.PCBegin, + HexString.ofUInt64 fde.PCEnd) if fde.UnwindingInfo.IsEmpty then () else out.PrintLine " ---" @@ -298,26 +369,27 @@ let dumpEHFrame hdl (fi: ELFFileInfo) = fde.UnwindingInfo |> List.iter (fun i -> out.PrintRow (true, cfg, - [ String.u64ToHex i.Location + [ HexString.ofUInt64 i.Location cfaToString hdl i.CanonicalFrameAddress ruleToString hdl i.Rule ])) out.PrintLine () ) ) -let dumpLSDA _hdl (fi: ELFFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpGccExceptTable _hdl (elf: ELFBinFile) = + let addrColumn = columnWidthOfAddr elf |> LeftAligned + let file = elf :> IBinFile let cfg = [ addrColumn; LeftAligned 15; LeftAligned 15; addrColumn ] out.PrintRow (true, cfg, [ "Address"; "LP App"; "LP Val"; "TT End" ]) - fi.ELF.LSDAs + elf.ExceptionInfo.LSDAs |> Map.iter (fun lsdaAddr lsda -> - let ttbase = lsda.Header.TTBase |> Option.defaultValue 0UL + let ttbase = lsda.LSDAHeader.TTBase |> Option.defaultValue 0UL out.PrintRow (true, cfg, - [ Addr.toString fi.WordSize lsdaAddr - lsda.Header.LPAppEncoding.ToString () - lsda.Header.LPValueEncoding.ToString () - ttbase |> Addr.toString fi.WordSize ]) + [ Addr.toString file.ISA.WordSize lsdaAddr + lsda.LSDAHeader.LPAppEncoding.ToString () + lsda.LSDAHeader.LPValueEncoding.ToString () + ttbase |> Addr.toString file.ISA.WordSize ]) ) -let dumpNotes _hdl (fi: ELFFileInfo) = +let dumpNotes _hdl (file: ELFBinFile) = Utils.futureFeature () diff --git a/src/RearEnd/FileViewer/Helper.fs b/src/RearEnd/FileViewer/Helper.fs index 0ad2febc..32ce51f9 100644 --- a/src/RearEnd/FileViewer/Helper.fs +++ b/src/RearEnd/FileViewer/Helper.fs @@ -36,14 +36,25 @@ let normalizeEmpty s = let toNBytes (v: uint64) = v.ToString () + " bytes" -let columnWidthOfAddr (fi: FileInfo) = - WordSize.toByteWidth fi.WordSize * 2 +let columnWidthOfAddr (file: IBinFile) = + WordSize.toByteWidth file.ISA.WordSize * 2 -let targetString s = - match s.Target with - | TargetKind.StaticSymbol -> "(s)" - | TargetKind.DynamicSymbol -> "(d)" +let visibilityString s = + match s.Visibility with + | SymbolVisibility.StaticSymbol -> "(s)" + | SymbolVisibility.DynamicSymbol -> "(d)" | _ -> Utils.impossible () +let symbolKindString (s: Symbol) = + match s.Kind with + | SymNoType -> "unknown" + | SymObjectType -> "object" + | SymFunctionType -> "function" + | SymExternFunctionType -> "extfunc" + | SymTrampolineType -> "trampoline" + | SymSectionType -> "section" + | SymFileType -> "file" + | SymForwardType (bin, func) -> $"{func}@{bin}" + let toLibString s = if System.String.IsNullOrEmpty s then s else "@" + s diff --git a/src/RearEnd/FileViewer/MachViewer.fs b/src/RearEnd/FileViewer/MachViewer.fs index dff448aa..0f0976e0 100644 --- a/src/RearEnd/FileViewer/MachViewer.fs +++ b/src/RearEnd/FileViewer/MachViewer.fs @@ -30,7 +30,7 @@ open B2R2.FrontEnd.BinFile open B2R2.RearEnd.FileViewer.Helper let badAccess _ _ = - raise InvalidFileTypeException + raise InvalidFileFormatException let translateFlags flags = let enumFlags = @@ -45,18 +45,18 @@ let translateFlags flags = loop acc flags tail loop [] flags enumFlags -let dumpFileHeader _ (fi: MachFileInfo) = - let hdr = fi.Mach.MachHdr +let dumpFileHeader _ (file: MachBinFile) = + let hdr = file.Header out.PrintTwoCols "Magic:" - (String.u64ToHex (uint64 hdr.Magic) + (HexString.ofUInt64 (uint64 hdr.Magic) + String.wrapParen (hdr.Magic.ToString ())) out.PrintTwoCols "Cpu type:" (hdr.CPUType.ToString ()) out.PrintTwoCols "Cpu subtype:" - (String.u32ToHex (uint32 hdr.CPUSubType)) + (HexString.ofInt32 (int hdr.CPUSubType)) out.PrintTwoCols "File type:" (hdr.FileType.ToString ()) @@ -68,7 +68,7 @@ let dumpFileHeader _ (fi: MachFileInfo) = (hdr.SizeOfCmds.ToString ()) out.PrintTwoCols "Flags:" - (String.u64ToHex (uint64 hdr.Flags)) + (HexString.ofUInt64 (uint64 hdr.Flags)) translateFlags (uint64 hdr.Flags) |> List.iter (fun str -> out.PrintTwoCols "" str) @@ -86,8 +86,9 @@ let translateAttribs attribs = loop acc attribs tail loop [] attribs enumAttribs -let dumpSectionHeaders (opts: FileViewerOpts) (fi: MachFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpSectionHeaders (opts: FileViewerOpts) (mach: MachBinFile) = + let addrColumn = columnWidthOfAddr mach |> LeftAligned + let file = mach :> IBinFile if opts.Verbose then let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 16 LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 @@ -98,23 +99,23 @@ let dumpSectionHeaders (opts: FileViewerOpts) (fi: MachFileInfo) = "SecRelOff"; "#Reloc"; "Type" "Res1"; "Res2"; "Attrib" ]) out.PrintLine " ---" - fi.Mach.Sections.SecByNum + mach.Sections |> Array.iteri (fun idx s -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize s.SecAddr) - (Addr.toString fi.WordSize (s.SecAddr + s.SecSize - uint64 1)) + (Addr.toString file.ISA.WordSize s.SecAddr) + (Addr.toString file.ISA.WordSize (s.SecAddr + s.SecSize - uint64 1)) normalizeEmpty s.SecName normalizeEmpty s.SegName - String.u64ToHex s.SecSize - String.u64ToHex (uint64 s.SecOffset) - String.u64ToHex (uint64 s.SecAlignment) + HexString.ofUInt64 s.SecSize + HexString.ofUInt64 (uint64 s.SecOffset) + HexString.ofUInt64 (uint64 s.SecAlignment) s.SecRelOff.ToString () s.SecNumOfReloc.ToString () s.SecType.ToString () s.SecReserved1.ToString () s.SecReserved2.ToString () - String.u32ToHex (uint32 s.SecAttrib) ]) + HexString.ofUInt32 (uint32 s.SecAttrib) ]) translateAttribs (uint64 s.SecAttrib) |> List.iter (fun str -> out.PrintRow (true, cfg, [ ""; ""; ""; ""; ""; ""; ""; ""; "" @@ -124,16 +125,16 @@ let dumpSectionHeaders (opts: FileViewerOpts) (fi: MachFileInfo) = let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 ] out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" ]) out.PrintLine " ---" - fi.GetSections () + file.GetSections () |> Seq.iteri (fun idx s -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize s.Address) - (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + (Addr.toString file.ISA.WordSize s.Address) + (Addr.toString file.ISA.WordSize (s.Address + uint64 s.Size - 1UL)) normalizeEmpty s.Name ])) -let dumpSectionDetails (secname: string) (fi: MachFileInfo) = - match fi.Mach.Sections.SecByName.TryFind secname with +let dumpSectionDetails (secName: string) (file: MachBinFile) = + match file.Sections |> Array.tryFind (fun s -> s.SecName = secName) with | Some section -> out.PrintTwoCols "SecName:" @@ -143,19 +144,19 @@ let dumpSectionDetails (secname: string) (fi: MachFileInfo) = section.SegName out.PrintTwoCols "SecAddr:" - (String.u64ToHex section.SecAddr) + (HexString.ofUInt64 section.SecAddr) out.PrintTwoCols "SecSize:" - (String.u64ToHex section.SecSize) + (HexString.ofUInt64 section.SecSize) out.PrintTwoCols "SecOffset:" - (String.u64ToHex (uint64 section.SecOffset)) + (HexString.ofUInt64 (uint64 section.SecOffset)) out.PrintTwoCols "SecAlignment:" - (String.u64ToHex (uint64 section.SecAlignment)) + (HexString.ofUInt64 (uint64 section.SecAlignment)) out.PrintTwoCols "SecRelOff:" - (String.u64ToHex (uint64 section.SecRelOff)) + (HexString.ofUInt64 (uint64 section.SecRelOff)) out.PrintTwoCols "SecNumOfReloc:" (section.SecNumOfReloc.ToString ()) @@ -164,7 +165,7 @@ let dumpSectionDetails (secname: string) (fi: MachFileInfo) = (section.SecType.ToString ()) out.PrintTwoCols "SecAttrib:" - (String.u32ToHex (uint32 section.SecAttrib)) + (HexString.ofInt32 (int section.SecAttrib)) translateAttribs (uint64 section.SecAttrib) |> List.iter (fun str -> out.PrintTwoCols "" str ) out.PrintTwoCols @@ -181,7 +182,7 @@ let toVersionString (v: uint32) = let minor2 = v &&& uint32 0x000000FF major.ToString () + "." + minor1.ToString () + "." + minor2.ToString () -let printSymbolInfoVerbose fi s (machSymbol: Mach.MachSymbol) cfg = +let printSymbolInfoVerbose file s (machSymbol: Mach.MachSymbol) cfg = let externLibVerinfo = match machSymbol.VerInfo with | Some info -> @@ -191,8 +192,8 @@ let printSymbolInfoVerbose fi s (machSymbol: Mach.MachSymbol) cfg = + "current version" + toVersionString info.DyLibCurVer | None -> "(n/a)" out.PrintRow (true, cfg, - [ targetString s - Addr.toString (fi: MachFileInfo).WordSize s.Address + [ visibilityString s + Addr.toString (file: IBinFile).ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName machSymbol.SymType.ToString () @@ -201,71 +202,72 @@ let printSymbolInfoVerbose fi s (machSymbol: Mach.MachSymbol) cfg = externLibVerinfo String.wrapSqrdBracket (machSymbol.SecNum.ToString ()); ""; ""; "" ]) -let printSymbolInfoNone fi s cfg = +let printSymbolInfoNone file s cfg = out.PrintRow (true, cfg, - [ targetString s - Addr.toString (fi: MachFileInfo).WordSize s.Address + [ visibilityString s + Addr.toString (file: IBinFile).ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)"; "(n/a)" ]) -let printSymbolInfo isVerbose (fi: MachFileInfo) (symbols: seq) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let printSymbolInfo isVerbose (mach: MachBinFile) (symbols: seq) = + let addrColumn = columnWidthOfAddr mach |> LeftAligned if isVerbose then - let cfg = [ LeftAligned 10; addrColumn; LeftAligned 40; LeftAligned 35 + let cfg = [ LeftAligned 3; addrColumn; LeftAligned 40; LeftAligned 35 LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 LeftAligned 8 ] - out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" + out.PrintRow (true, cfg, [ "S/D"; "Address"; "Name"; "Lib Name" "Type"; "Description"; "External"; "Version" "SectionIndex" ]) out.PrintLine " ---" symbols |> Seq.sortBy (fun s -> s.Name) |> Seq.sortBy (fun s -> s.Address) - |> Seq.sortBy (fun s -> s.Target) + |> Seq.sortBy (fun s -> s.Visibility) |> Seq.iter (fun s -> - match fi.Mach.SymInfo.SymbolMap.TryFind s.Address with - | Some machSymbol -> printSymbolInfoVerbose fi s machSymbol cfg - | None -> printSymbolInfoNone fi s cfg) + match mach.SymbolInfo.SymbolMap.TryFind s.Address with + | Some machSymbol -> printSymbolInfoVerbose mach s machSymbol cfg + | None -> printSymbolInfoNone mach s cfg) else - let cfg = [ LeftAligned 10; addrColumn; LeftAligned 55; LeftAligned 15 ] - out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" ]) + let cfg = [ LeftAligned 3; LeftAligned 10 + addrColumn; LeftAligned 55; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "S/D"; "Kind"; "Address"; "Name"; "Lib Name" ]) out.PrintLine " ---" symbols |> Seq.sortBy (fun s -> s.Name) |> Seq.sortBy (fun s -> s.Address) - |> Seq.sortBy (fun s -> s.Target) + |> Seq.sortBy (fun s -> s.Visibility) |> Seq.iter (fun s -> out.PrintRow (true, cfg, - [ targetString s - Addr.toString fi.WordSize s.Address + [ visibilityString s + symbolKindString s + Addr.toString (mach :> IBinFile).ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName ])) -let dumpSymbols (opts: FileViewerOpts) (fi: MachFileInfo) = - fi.GetSymbols () - |> printSymbolInfo opts.Verbose fi +let dumpSymbols (opts: FileViewerOpts) (mach: MachBinFile) = + (mach :> IBinFile).GetSymbols () + |> printSymbolInfo opts.Verbose mach -let dumpRelocs (opts: FileViewerOpts) (fi: MachFileInfo) = - fi.GetRelocationSymbols () - |> printSymbolInfo opts.Verbose fi +let dumpRelocs (opts: FileViewerOpts) (mach: MachBinFile) = + (mach :> IBinFile).GetRelocationSymbols () + |> printSymbolInfo opts.Verbose mach -let dumpFunctions (opts: FileViewerOpts) (fi: MachFileInfo) = - fi.GetFunctionSymbols () - |> printSymbolInfo opts.Verbose fi +let dumpFunctions (opts: FileViewerOpts) (mach: MachBinFile) = + (mach :> IBinFile).GetFunctionSymbols () + |> printSymbolInfo opts.Verbose mach -let dumpArchiveHeader (opts: FileViewerOpts) (fi: MachFileInfo) = +let dumpArchiveHeader (opts: FileViewerOpts) (file: MachBinFile) = Utils.futureFeature () -let dumpUniversalHeader (_opts: FileViewerOpts) (fi: MachFileInfo) = - let span = fi.Span - let reader = fi.Mach.BinReader - if Mach.Header.isFat span reader then - Mach.Fat.loadFats span reader - |> List.iteri (fun idx fat -> +let dumpUniversalHeader (_opts: FileViewerOpts) (mach: MachBinFile) = + let bytes = (mach :> IBinFile).Slice(0, 4).ToArray() + if Mach.Header.isFat bytes then + Mach.Fat.loadFatArchs bytes + |> Array.iteri (fun idx fat -> let cpu = fat.CPUType let cpusub = fat.CPUSubType - let arch = Mach.Header.cpuTypeToArch cpu cpusub + let arch = Mach.CPUType.toArch cpu cpusub out.PrintSubsectionTitle ("Architecture #" + idx.ToString ()) out.PrintTwoCols "CPU Type:" (cpu.ToString ()) out.PrintTwoCols "CPU Subtype:" ("0x" + (uint32 cpusub).ToString ("x")) @@ -280,22 +282,22 @@ let printSegCmd (segCmd: Mach.SegCmd) idx = out.PrintTwoCols "Cmd:" (segCmd.Cmd.ToString ()) out.PrintTwoCols "CmdSize:" (segCmd.CmdSize.ToString ()) out.PrintTwoCols "SegCmdName:" segCmd.SegCmdName - out.PrintTwoCols "VMAddr:" (String.u64ToHex segCmd.VMAddr) - out.PrintTwoCols "VMSize:" (String.u64ToHex segCmd.VMSize) + out.PrintTwoCols "VMAddr:" (HexString.ofUInt64 segCmd.VMAddr) + out.PrintTwoCols "VMSize:" (HexString.ofUInt64 segCmd.VMSize) out.PrintTwoCols "FileOff:" (segCmd.FileOff.ToString ()) out.PrintTwoCols "FileSize:" (segCmd.FileSize.ToString ()) - out.PrintTwoCols "MaxProt:" (String.u64ToHex (uint64 segCmd.MaxProt)) - out.PrintTwoCols "InitProt:" (String.u64ToHex (uint64 segCmd.InitProt)) + out.PrintTwoCols "MaxProt:" (HexString.ofUInt64 (uint64 segCmd.MaxProt)) + out.PrintTwoCols "InitProt:" (HexString.ofUInt64 (uint64 segCmd.InitProt)) out.PrintTwoCols "NumSecs:" (segCmd.NumSecs.ToString ()) - out.PrintTwoCols "SegFlag:" (String.u64ToHex (uint64 segCmd.SegFlag)) + out.PrintTwoCols "SegFlag:" (HexString.ofUInt64 (uint64 segCmd.SegFlag)) let printSymTabCmd (symTabCmd: Mach.SymTabCmd) idx = out.PrintSubsectionTitle ("Load command " + idx.ToString ()) out.PrintTwoCols "Cmd:" (symTabCmd.Cmd.ToString ()) out.PrintTwoCols "CmdSize:" (symTabCmd.CmdSize.ToString ()) - out.PrintTwoCols "SymOff:" (String.u64ToHex (uint64 symTabCmd.SymOff)) + out.PrintTwoCols "SymOff:" (HexString.ofUInt64 (uint64 symTabCmd.SymOff)) out.PrintTwoCols "NumOfSym:" (symTabCmd.NumOfSym.ToString ()) - out.PrintTwoCols "StrOff:" (String.u64ToHex (uint64 symTabCmd.StrOff)) + out.PrintTwoCols "StrOff:" (HexString.ofUInt64 (uint64 symTabCmd.StrOff)) out.PrintTwoCols "StrSize:" (toNBytes (uint64 symTabCmd.StrSize)) let printDySymTabCmd (dySymTabCmd: Mach.DySymTabCmd) idx = @@ -366,18 +368,18 @@ let printUnhandledCmd (unhandledCmd: Mach.UnhandledCommand) idx = out.PrintTwoCols "Cmd:" (unhandledCmd.Cmd.ToString ()) out.PrintTwoCols "CmdSize:" (unhandledCmd.CmdSize.ToString ()) -let dumpLoadCommands _ (fi: MachFileInfo) = - fi.Mach.Cmds - |> List.iteri (fun idx cmd -> +let dumpLoadCommands _ (file: MachBinFile) = + file.Commands + |> Array.iteri (fun idx cmd -> match cmd with | Mach.Segment segCmd -> printSegCmd segCmd idx - fi.Mach.Sections.SecByNum + file.Sections |> Array.iter (fun s -> if s.SegName = segCmd.SegCmdName then out.PrintLine () out.PrintSubsubsectionTitle (String.wrapSqrdBracket "Section") - dumpSectionDetails s.SecName fi) + dumpSectionDetails s.SecName file) | Mach.SymTab symTabCmd -> printSymTabCmd symTabCmd idx | Mach.DySymTab dySymTabCmd -> printDySymTabCmd dySymTabCmd idx | Mach.DyLib dyLibCmd -> printDyLibCmd dyLibCmd idx @@ -387,11 +389,11 @@ let dumpLoadCommands _ (fi: MachFileInfo) = | Mach.Unhandled unhandledCmd -> printUnhandledCmd unhandledCmd idx out.PrintLine ()) -let dumpSharedLibs _ (fi: MachFileInfo) = +let dumpSharedLibs _ (file: MachBinFile) = let cfg = [ LeftAligned 35; LeftAligned 15; LeftAligned 15 ] - out.PrintRow (true, cfg, [ "LibraryName"; "CurVersion"; "CompatVersion" ]) - fi.Mach.Cmds - |> List.iter (fun cmd -> + out.PrintRow (true, cfg, [ "Lib Name"; "CurVersion"; "CompatVersion" ]) + file.Commands + |> Array.iter (fun cmd -> match cmd with | Mach.DyLib dyLibCmd -> out.PrintRow (true, cfg, diff --git a/src/RearEnd/FileViewer/PEViewer.fs b/src/RearEnd/FileViewer/PEViewer.fs index f6d19ec1..51b8ee32 100644 --- a/src/RearEnd/FileViewer/PEViewer.fs +++ b/src/RearEnd/FileViewer/PEViewer.fs @@ -30,7 +30,7 @@ open B2R2.RearEnd.FileViewer.Helper open System.Reflection.PortableExecutable let badAccess _ _ = - raise InvalidFileTypeException + raise InvalidFileFormatException let translateChracteristics chars = let enumChars = @@ -46,11 +46,11 @@ let translateChracteristics chars = loop acc chars tail loop [] chars enumChars -let dumpFileHeader _ (fi: PEFileInfo) = - let hdr = fi.PE.PEHeaders.CoffHeader +let dumpFileHeader _ (file: PEBinFile) = + let hdr = file.PE.PEHeaders.CoffHeader out.PrintTwoCols "Machine:" - (String.u64ToHex (uint64 hdr.Machine) + (HexString.ofUInt64 (uint64 hdr.Machine) + String.wrapParen (hdr.Machine.ToString ())) out.PrintTwoCols "Number of sections:" @@ -60,13 +60,13 @@ let dumpFileHeader _ (fi: PEFileInfo) = (hdr.TimeDateStamp.ToString ()) out.PrintTwoCols "Pointer to symbol table:" - (String.u64ToHex (uint64 hdr.PointerToSymbolTable)) + (HexString.ofUInt64 (uint64 hdr.PointerToSymbolTable)) out.PrintTwoCols "Size of optional header:" - (String.u64ToHex (uint64 hdr.SizeOfOptionalHeader)) + (HexString.ofUInt64 (uint64 hdr.SizeOfOptionalHeader)) out.PrintTwoCols "Characteristics:" - (String.u64ToHex (uint64 hdr.Characteristics)) + (HexString.ofUInt64 (uint64 hdr.Characteristics)) translateChracteristics (uint64 hdr.Characteristics) |> List.iter (fun str -> out.PrintTwoCols "" str) @@ -82,14 +82,15 @@ let translateSectionChracteristics chars = | [] -> List.rev acc | enumChar :: t -> if uint64 enumChar &&& chars = uint64 enumChar - && not (uint64 enumChar = uint64 0) then + && (uint64 enumChar <> 0UL) then loop ((" - " + enumChar.ToString ()) :: acc) chars t else loop acc chars t loop [] chars enumChars -let dumpSectionHeaders (opts: FileViewerOpts) (fi: PEFileInfo) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned +let dumpSectionHeaders (opts: FileViewerOpts) (pe: PEBinFile) = + let addrColumn = columnWidthOfAddr pe |> LeftAligned + let file = pe :> IBinFile if opts.Verbose then let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 LeftAligned 8; LeftAligned 8; LeftAligned 8; LeftAligned 8 @@ -101,26 +102,26 @@ let dumpSectionHeaders (opts: FileViewerOpts) (fi: PEFileInfo) = "RelocPtr"; "LineNPtr"; "RelocNum"; "LineNNum" "Characteristics" ]) out.PrintLine " ---" - fi.PE.SectionHeaders + pe.PE.SectionHeaders |> Array.iteri (fun idx s -> - let startAddr = fi.PE.BaseAddr + uint64 s.VirtualAddress + let startAddr = pe.PE.BaseAddr + uint64 s.VirtualAddress let size = uint64 (if s.VirtualSize = 0 then s.SizeOfRawData else s.VirtualSize) let characteristics = uint64 s.SectionCharacteristics out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize startAddr) - (Addr.toString fi.WordSize (startAddr + size - uint64 1)) + (Addr.toString file.ISA.WordSize startAddr) + (Addr.toString file.ISA.WordSize (startAddr + size - uint64 1)) normalizeEmpty s.Name - String.u64ToHex (uint64 s.VirtualSize) - String.u64ToHex (uint64 s.VirtualAddress) - String.u64ToHex (uint64 s.SizeOfRawData) - String.u64ToHex (uint64 s.PointerToRawData) - String.u64ToHex (uint64 s.PointerToRelocations) - String.u64ToHex (uint64 s.PointerToLineNumbers) + HexString.ofUInt64 (uint64 s.VirtualSize) + HexString.ofUInt64 (uint64 s.VirtualAddress) + HexString.ofUInt64 (uint64 s.SizeOfRawData) + HexString.ofUInt64 (uint64 s.PointerToRawData) + HexString.ofUInt64 (uint64 s.PointerToRelocations) + HexString.ofUInt64 (uint64 s.PointerToLineNumbers) s.NumberOfRelocations.ToString () s.NumberOfLineNumbers.ToString () - String.u64ToHex characteristics ]) + HexString.ofUInt64 characteristics ]) translateSectionChracteristics characteristics |> List.iter (fun str -> out.PrintRow (true, cfg, [ ""; ""; ""; ""; ""; ""; "" @@ -129,21 +130,21 @@ let dumpSectionHeaders (opts: FileViewerOpts) (fi: PEFileInfo) = let cfg = [ LeftAligned 4; addrColumn; addrColumn; LeftAligned 24 ] out.PrintRow (true, cfg, [ "Num"; "Start"; "End"; "Name" ]) out.PrintLine " ---" - fi.GetSections () + file.GetSections () |> Seq.iteri (fun idx s -> out.PrintRow (true, cfg, [ String.wrapSqrdBracket (idx.ToString ()) - (Addr.toString fi.WordSize s.Address) - (Addr.toString fi.WordSize (s.Address + s.Size - uint64 1)) + (Addr.toString file.ISA.WordSize s.Address) + (Addr.toString file.ISA.WordSize (s.Address + uint64 s.Size - 1UL)) normalizeEmpty s.Name ])) -let dumpSectionDetails (secname: string) (fi: PEFileInfo) = +let dumpSectionDetails (secname: string) (file: PEBinFile) = let idx = Array.tryFindIndex (fun (s: SectionHeader) -> - s.Name = secname) fi.PE.SectionHeaders + s.Name = secname) file.PE.SectionHeaders match idx with | Some idx -> - let section = fi.PE.SectionHeaders[idx] + let section = file.PE.SectionHeaders[idx] let characteristics = uint64 section.SectionCharacteristics out.PrintTwoCols "Section number:" @@ -153,22 +154,22 @@ let dumpSectionDetails (secname: string) (fi: PEFileInfo) = section.Name out.PrintTwoCols "Virtual size:" - (String.u64ToHex (uint64 section.VirtualSize)) + (HexString.ofUInt64 (uint64 section.VirtualSize)) out.PrintTwoCols "Virtual address:" - (String.u64ToHex (uint64 section.VirtualAddress)) + (HexString.ofUInt64 (uint64 section.VirtualAddress)) out.PrintTwoCols "Size of raw data:" - (String.u64ToHex (uint64 section.SizeOfRawData)) + (HexString.ofUInt64 (uint64 section.SizeOfRawData)) out.PrintTwoCols "Pointer to raw data:" - (String.u64ToHex (uint64 section.PointerToRawData)) + (HexString.ofUInt64 (uint64 section.PointerToRawData)) out.PrintTwoCols "Pointer to relocations:" - (String.u64ToHex (uint64 section.PointerToRelocations)) + (HexString.ofUInt64 (uint64 section.PointerToRelocations)) out.PrintTwoCols "Pointer to line numbers:" - (String.u64ToHex (uint64 section.PointerToLineNumbers)) + (HexString.ofUInt64 (uint64 section.PointerToLineNumbers)) out.PrintTwoCols "Number of relocations:" (section.NumberOfRelocations.ToString ()) @@ -177,78 +178,80 @@ let dumpSectionDetails (secname: string) (fi: PEFileInfo) = (section.NumberOfLineNumbers.ToString ()) out.PrintTwoCols "Characteristics:" - (String.u64ToHex characteristics) + (HexString.ofUInt64 characteristics) translateSectionChracteristics characteristics |> List.iter (fun str -> out.PrintTwoCols "" str) | None -> out.PrintTwoCols "" "Not found." -let printSymbolInfo (fi: PEFileInfo) (symbols: seq) = - let addrColumn = columnWidthOfAddr fi |> LeftAligned - let cfg = [ LeftAligned 5; addrColumn; LeftAligned 50; LeftAligned 15 ] - out.PrintRow (true, cfg, [ "Kind"; "Address"; "Name"; "LibraryName" ]) +let printSymbolInfo (pe: PEBinFile) (symbols: seq) = + let addrColumn = columnWidthOfAddr pe |> LeftAligned + let cfg = [ LeftAligned 3; LeftAligned 10 + addrColumn; LeftAligned 50; LeftAligned 15 ] + out.PrintRow (true, cfg, [ "S/D"; "Kind"; "Address"; "Name"; "Lib Name" ]) out.PrintLine " ---" symbols |> Seq.sortBy (fun s -> s.Name) |> Seq.sortBy (fun s -> s.Address) - |> Seq.sortBy (fun s -> s.Target) + |> Seq.sortBy (fun s -> s.Visibility) |> Seq.iter (fun s -> out.PrintRow (true, cfg, - [ targetString s - Addr.toString fi.WordSize s.Address + [ visibilityString s + symbolKindString s + Addr.toString (pe :> IBinFile).ISA.WordSize s.Address normalizeEmpty s.Name (toLibString >> normalizeEmpty) s.LibraryName ])) -let dumpSymbols _ (fi: PEFileInfo) = - fi.GetSymbols () - |> printSymbolInfo fi +let dumpSymbols _ (pe: PEBinFile) = + (pe :> IBinFile).GetSymbols () + |> printSymbolInfo pe -let dumpRelocs _ (fi: PEFileInfo) = - fi.GetRelocationSymbols () - |> printSymbolInfo fi +let dumpRelocs _ (pe: PEBinFile) = + (pe :> IBinFile).GetRelocationSymbols () + |> printSymbolInfo pe -let dumpFunctions _ (fi: PEFileInfo) = - fi.GetFunctionSymbols () - |> printSymbolInfo fi +let dumpFunctions _ (pe: PEBinFile) = + (pe :> IBinFile).GetFunctionSymbols () + |> printSymbolInfo pe let inline addrFromRVA baseAddr rva = uint64 rva + baseAddr -let dumpImports _ (fi: PEFileInfo) = +let dumpImports _ (file: PEBinFile) = let cfg = [ LeftAligned 50; LeftAligned 50; LeftAligned 20 ] out.PrintRow (true, cfg, - [ "FunctionName"; "LibraryName"; "TableAddress" ]) + [ "FunctionName"; "Lib Name"; "TableAddress" ]) out.PrintLine " ---" - fi.PE.ImportMap + file.PE.ImportMap |> Map.iter (fun addr info -> match info with | PE.ImportInfo.ImportByOrdinal (ordinal, dllname) -> out.PrintRow (true, cfg, [ "#" + ordinal.ToString () dllname - String.u64ToHex (addrFromRVA fi.PE.BaseAddr addr) ]) + HexString.ofUInt64 (addrFromRVA file.PE.BaseAddr addr) ]) | PE.ImportInfo.ImportByName (_, fname, dllname) -> out.PrintRow (true, cfg, [ fname dllname - String.u64ToHex (addrFromRVA fi.PE.BaseAddr addr) ])) + HexString.ofUInt64 (addrFromRVA file.PE.BaseAddr addr) ])) -let dumpExports _ (fi: PEFileInfo) = +let dumpExports _ (file: PEBinFile) = let cfg = [ LeftAligned 45; LeftAligned 20 ] out.PrintRow (true, cfg, [ "FunctionName"; "TableAddress" ]) out.PrintLine " ---" - fi.PE.ExportMap + file.PE.ExportMap |> Map.iter (fun addr names -> - let rva = int (addr - fi.PE.BaseAddr) - match fi.PE.FindSectionIdxFromRVA rva with + let rva = int (addr - file.PE.BaseAddr) + match file.PE.FindSectionIdxFromRVA rva with | -1 -> () | idx -> names |> List.iter (fun name -> - out.PrintRow (true, cfg, [ name; String.u64ToHex addr ]))) + out.PrintRow (true, cfg, [ name; HexString.ofUInt64 addr ]))) out.PrintLine "" out.PrintRow (true, cfg, [ "FunctionName"; "ForwardName" ]) out.PrintLine " ---" - fi.PE.ForwardMap + file.PE.ForwardMap |> Map.iter (fun name (bin, func) -> out.PrintRow (true, cfg, [ name; bin + "!" + func ])) @@ -270,13 +273,14 @@ let translateDllChracteristcs chars = loop acc chars tail loop [] chars enumChars -let dumpOptionalHeader _ (fi: PEFileInfo) = - let hdr = fi.PE.PEHeaders.PEHeader +let dumpOptionalHeader _ (file: PEBinFile) = + let hdr = file.PE.PEHeaders.PEHeader let imageBase = hdr.ImageBase let sizeOfImage = uint64 hdr.SizeOfImage - let entryPoint = String.u64ToHex (imageBase + uint64 hdr.AddressOfEntryPoint) - let startImage = String.u64ToHex imageBase - let endImage = String.u64ToHex (imageBase + sizeOfImage - uint64 1) + let entryPoint = + HexString.ofUInt64 (imageBase + uint64 hdr.AddressOfEntryPoint) + let startImage = HexString.ofUInt64 imageBase + let endImage = HexString.ofUInt64 (imageBase + sizeOfImage - uint64 1) let exportDir = hdr.ExportTableDirectory let importDir = hdr.ImportTableDirectory let resourceDir = hdr.ResourceTableDirectory @@ -294,7 +298,7 @@ let dumpOptionalHeader _ (fi: PEFileInfo) = let comDescDir = hdr.CorHeaderTableDirectory out.PrintTwoCols "Magic:" - (String.u64ToHex (uint64 hdr.Magic) + (HexString.ofUInt64 (uint64 hdr.Magic) + String.wrapParen (hdr.Magic.ToString ())) out.PrintTwoCols "Linker version:" @@ -302,29 +306,29 @@ let dumpOptionalHeader _ (fi: PEFileInfo) = + "." + hdr.MinorLinkerVersion.ToString ()) out.PrintTwoCols "Size of code:" - (String.u64ToHex (uint64 hdr.SizeOfCode)) + (HexString.ofUInt64 (uint64 hdr.SizeOfCode)) out.PrintTwoCols "Size of initialized data:" - (String.u64ToHex (uint64 hdr.SizeOfInitializedData)) + (HexString.ofUInt64 (uint64 hdr.SizeOfInitializedData)) out.PrintTwoCols "Size of uninitialized data:" - (String.u64ToHex (uint64 hdr.SizeOfUninitializedData)) + (HexString.ofUInt64 (uint64 hdr.SizeOfUninitializedData)) out.PrintTwoCols "Entry point:" entryPoint out.PrintTwoCols "Base of code:" - (String.u64ToHex (uint64 hdr.BaseOfCode)) + (HexString.ofUInt64 (uint64 hdr.BaseOfCode)) out.PrintTwoCols "Image base:" - (String.u64ToHex imageBase + (HexString.ofUInt64 imageBase + String.wrapParen (startImage + " to " + endImage)) out.PrintTwoCols "Section alignment:" - (String.u64ToHex (uint64 hdr.SectionAlignment)) + (HexString.ofUInt64 (uint64 hdr.SectionAlignment)) out.PrintTwoCols "File Alignment:" - (String.u64ToHex (uint64 hdr.FileAlignment)) + (HexString.ofUInt64 (uint64 hdr.FileAlignment)) out.PrintTwoCols "Operating system version:" (hdr.MajorOperatingSystemVersion.ToString () @@ -339,34 +343,34 @@ let dumpOptionalHeader _ (fi: PEFileInfo) = + "." + hdr.MinorSubsystemVersion.ToString ()) out.PrintTwoCols "Size of image:" - (String.u64ToHex sizeOfImage) + (HexString.ofUInt64 sizeOfImage) out.PrintTwoCols "Size of headers:" - (String.u64ToHex (uint64 hdr.SizeOfHeaders)) + (HexString.ofUInt64 (uint64 hdr.SizeOfHeaders)) out.PrintTwoCols "Checksum:" - (String.u64ToHex (uint64 hdr.CheckSum)) + (HexString.ofUInt64 (uint64 hdr.CheckSum)) out.PrintTwoCols "Subsystem:" - (String.u64ToHex (uint64 hdr.Subsystem) + (HexString.ofUInt64 (uint64 hdr.Subsystem) + String.wrapParen (hdr.Subsystem.ToString ())) out.PrintTwoCols "DLL characteristics:" - (String.u64ToHex (uint64 hdr.DllCharacteristics)) + (HexString.ofUInt64 (uint64 hdr.DllCharacteristics)) translateDllChracteristcs (uint64 hdr.DllCharacteristics) |> List.iter (fun str -> out.PrintTwoCols "" str) out.PrintTwoCols "Size of stack reserve:" - (String.u64ToHex (uint64 hdr.SizeOfStackReserve)) + (HexString.ofUInt64 (uint64 hdr.SizeOfStackReserve)) out.PrintTwoCols "Size of stack commit:" - (String.u64ToHex (uint64 hdr.SizeOfStackCommit)) + (HexString.ofUInt64 (uint64 hdr.SizeOfStackCommit)) out.PrintTwoCols "Size of heap reserve:" - (String.u64ToHex (uint64 hdr.SizeOfHeapReserve)) + (HexString.ofUInt64 (uint64 hdr.SizeOfHeapReserve)) out.PrintTwoCols "Size of heap commit:" - (String.u64ToHex (uint64 hdr.SizeOfHeapCommit)) + (HexString.ofUInt64 (uint64 hdr.SizeOfHeapCommit)) out.PrintTwoCols "Loader flags (reserved):" "0x0" @@ -375,64 +379,64 @@ let dumpOptionalHeader _ (fi: PEFileInfo) = (hdr.NumberOfRvaAndSizes.ToString ()) out.PrintTwoCols "RVA[size] of Export Table Directory:" - (String.u64ToHex (uint64 exportDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 exportDir.Size))) + (HexString.ofUInt64 (uint64 exportDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 exportDir.Size))) out.PrintTwoCols "RVA[size] of Import Table Directory:" - (String.u64ToHex (uint64 importDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 importDir.Size))) + (HexString.ofUInt64 (uint64 importDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 importDir.Size))) out.PrintTwoCols "RVA[size] of Resource Table Directory:" - (String.u64ToHex (uint64 resourceDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 resourceDir.Size))) + (HexString.ofUInt64 (uint64 resourceDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 resourceDir.Size))) out.PrintTwoCols "RVA[size] of Exception Table Directory:" - (String.u64ToHex (uint64 exceptionDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 exceptionDir.Size))) + (HexString.ofUInt64 (uint64 exceptionDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 exceptionDir.Size))) out.PrintTwoCols "RVA[size] of Certificate Table Directory:" - (String.u64ToHex (uint64 certificateDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 certificateDir.Size))) + (HexString.ofUInt64 (uint64 certificateDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 certificateDir.Size))) out.PrintTwoCols "RVA[size] of Base Relocation Table Directory:" - (String.u64ToHex (uint64 baseRelocDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 baseRelocDir.Size))) + (HexString.ofUInt64 (uint64 baseRelocDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 baseRelocDir.Size))) out.PrintTwoCols "RVA[size] of Debug Table Directory:" - (String.u64ToHex (uint64 debugDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 debugDir.Size))) + (HexString.ofUInt64 (uint64 debugDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 debugDir.Size))) out.PrintTwoCols "RVA[size] of Architecture Table Directory:" - (String.u64ToHex (uint64 architectureDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 architectureDir.Size))) + (HexString.ofUInt64 (uint64 architectureDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 architectureDir.Size))) out.PrintTwoCols "RVA[size] of Global Pointer Table Directory:" - (String.u64ToHex (uint64 globalPtrDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 globalPtrDir.Size))) + (HexString.ofUInt64 (uint64 globalPtrDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 globalPtrDir.Size))) out.PrintTwoCols "RVA[size] of Thread Storage Table Directory:" - (String.u64ToHex (uint64 threadLoStorDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 threadLoStorDir.Size))) + (HexString.ofUInt64 (uint64 threadLoStorDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 threadLoStorDir.Size))) out.PrintTwoCols "RVA[size] of Load Configuration Table Directory:" - (String.u64ToHex (uint64 loadConfigDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 loadConfigDir.Size))) + (HexString.ofUInt64 (uint64 loadConfigDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 loadConfigDir.Size))) out.PrintTwoCols "RVA[size] of Bound Import Table Directory:" - (String.u64ToHex (uint64 boundImpDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 boundImpDir.Size))) + (HexString.ofUInt64 (uint64 boundImpDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 boundImpDir.Size))) out.PrintTwoCols "RVA[size] of Import Address Table Directory:" - (String.u64ToHex (uint64 importAddrDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 importAddrDir.Size))) + (HexString.ofUInt64 (uint64 importAddrDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 importAddrDir.Size))) out.PrintTwoCols "RVA[size] of Delay Import Table Directory:" - (String.u64ToHex (uint64 delayImpDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 delayImpDir.Size))) + (HexString.ofUInt64 (uint64 delayImpDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 delayImpDir.Size))) out.PrintTwoCols "RVA[size] of COM Descriptor Table Directory:" - (String.u64ToHex (uint64 comDescDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 comDescDir.Size))) + (HexString.ofUInt64 (uint64 comDescDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 comDescDir.Size))) out.PrintTwoCols "RVA[size] of Reserved Directory:" "0x0[0x0]" @@ -451,8 +455,8 @@ let translateCorFlags flags = loop acc flags tail loop [] flags enumFlags -let dumpCLRHeader _ (fi: PEFileInfo) = - let hdr = fi.PE.PEHeaders.CorHeader +let dumpCLRHeader _ (file: PEBinFile) = + let hdr = file.PE.PEHeaders.CorHeader if isNull hdr then out.PrintTwoCols "" "Not found." else @@ -469,41 +473,41 @@ let dumpCLRHeader _ (fi: PEFileInfo) = + "." + hdr.MinorRuntimeVersion.ToString ()) out.PrintTwoCols "RVA[size] of Meta Data Directory:" - (String.u64ToHex (uint64 metaDataDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 metaDataDir.Size))) + (HexString.ofUInt64 (uint64 metaDataDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 metaDataDir.Size))) out.PrintTwoCols "Flags:" - (String.u64ToHex (uint64 hdr.Flags)) + (HexString.ofUInt64 (uint64 hdr.Flags)) translateCorFlags (uint64 hdr.Flags) |> List.iter (fun str -> out.PrintTwoCols "" str) out.PrintTwoCols "RVA[size] of Resources Directory:" - (String.u64ToHex (uint64 resourcesDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 resourcesDir.Size))) + (HexString.ofUInt64 (uint64 resourcesDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 resourcesDir.Size))) out.PrintTwoCols "RVA[size] of Strong Name Signature Directory:" - (String.u64ToHex (uint64 strongNameSigDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 strongNameSigDir.Size))) + (HexString.ofUInt64 (uint64 strongNameSigDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofInt32 strongNameSigDir.Size)) out.PrintTwoCols "RVA[size] of Code Manager Table Directory:" - (String.u64ToHex (uint64 codeMgrTblDir.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 codeMgrTblDir.Size))) + (HexString.ofUInt64 (uint64 codeMgrTblDir.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 codeMgrTblDir.Size))) out.PrintTwoCols "RVA[size] of VTable Fixups Directory:" - (String.u64ToHex (uint64 vTableFixups.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 vTableFixups.Size))) + (HexString.ofUInt64 (uint64 vTableFixups.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofUInt64 (uint64 vTableFixups.Size))) out.PrintTwoCols "RVA[size] of Export Address Table Jumps Directory:" - (String.u64ToHex (uint64 exportAddrTblJmps.RelativeVirtualAddress) + (HexString.ofUInt64 (uint64 exportAddrTblJmps.RelativeVirtualAddress) + String.wrapSqrdBracket - (String.u64ToHex (uint64 exportAddrTblJmps.Size))) + (HexString.ofUInt64 (uint64 exportAddrTblJmps.Size))) out.PrintTwoCols "RVA[size] of Managed Native Header Directory:" - (String.u64ToHex (uint64 managedNativeHdr.RelativeVirtualAddress) - + String.wrapSqrdBracket (String.u64ToHex (uint64 managedNativeHdr.Size))) + (HexString.ofUInt64 (uint64 managedNativeHdr.RelativeVirtualAddress) + + String.wrapSqrdBracket (HexString.ofInt32 managedNativeHdr.Size)) -let dumpDependencies _ (fi: PEFileInfo) = - fi.GetLinkageTableEntries () +let dumpDependencies _ (file: IBinFile) = + file.GetLinkageTableEntries () |> Seq.map (fun e -> e.LibraryName) |> Set.ofSeq |> Set.iter (fun s -> out.PrintTwoCols "" s) diff --git a/src/RearEnd/FileViewer/Program.fs b/src/RearEnd/FileViewer/Program.fs index 171648ee..6933f36e 100644 --- a/src/RearEnd/FileViewer/Program.fs +++ b/src/RearEnd/FileViewer/Program.fs @@ -25,193 +25,207 @@ module B2R2.RearEnd.FileViewer.Program open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface open B2R2.RearEnd open B2R2.RearEnd.FileViewer.Helper -let dumpBasic (fi: FileInfo) = - let entry = FileInfo.EntryPointToString fi.EntryPoint |> ColoredSegment.green +let dumpBasic (file: IBinFile) = + let entry = + ColoredSegment (Green, StringUtils.entryPointToString file.EntryPoint) out.PrintSectionTitle "Basic Information" - out.PrintTwoCols "File format:" (FileFormat.toString fi.FileFormat) - out.PrintTwoCols "Architecture:" (ISA.ArchToString fi.ISA.Arch) - out.PrintTwoCols "Endianness:" (Endian.toString fi.ISA.Endian) - out.PrintTwoCols "Word size:" (WordSize.toString fi.WordSize + " bit") - out.PrintTwoCols "File type:" (FileInfo.FileTypeToString fi.FileType) + out.PrintTwoCols "File format:" (FileFormat.toString file.Format) + out.PrintTwoCols "Architecture:" (ISA.ArchToString file.ISA.Arch) + out.PrintTwoCols "Endianness:" (Endian.toString file.ISA.Endian) + out.PrintTwoCols "Word size:" (WordSize.toString file.ISA.WordSize + " bit") + out.PrintTwoCols "File type:" (FileType.toString file.Type) out.PrintTwoColsWithColorOnSnd "Entry point:" [ entry ] out.PrintLine () -let dumpSecurity (fi: FileInfo) = +let dumpSecurity (file: IBinFile) = out.PrintSectionTitle "Security Information" - out.PrintTwoCols "Stripped binary:" (fi.IsStripped.ToString ()) - out.PrintTwoCols "DEP (NX) enabled:" (fi.IsNXEnabled.ToString ()) - out.PrintTwoCols "Relocatable (PIE):" (fi.IsRelocatable.ToString ()) + out.PrintTwoCols "Stripped binary:" (file.IsStripped.ToString ()) + out.PrintTwoCols "DEP (NX) enabled:" (file.IsNXEnabled.ToString ()) + out.PrintTwoCols "Relocatable (PIE):" (file.IsRelocatable.ToString ()) out.PrintLine () -let dumpSpecific opts (fi: FileInfo) title elf pe mach = +let dumpSpecific opts (file: IBinFile) title elf pe mach = out.PrintSectionTitle title - match fi with - | :? ELFFileInfo as fi -> elf opts fi - | :? PEFileInfo as fi -> pe opts fi - | :? MachFileInfo as fi -> mach opts fi + match file with + | :? ELFBinFile as file -> elf opts file + | :? PEBinFile as file -> pe opts file + | :? MachBinFile as file -> mach opts file | _ -> Utils.futureFeature () out.PrintLine () -let dumpFileHeader (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "File Header Information" +let dumpFileHeader (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "File Header Information" ELFViewer.dumpFileHeader PEViewer.dumpFileHeader MachViewer.dumpFileHeader -let dumpSectionHeaders (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Section Header Information" +let dumpSectionHeaders (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Section Header Information" ELFViewer.dumpSectionHeaders PEViewer.dumpSectionHeaders MachViewer.dumpSectionHeaders -let dumpSectionDetails (secname: string) (fi: FileInfo) = - dumpSpecific secname fi "Section Details" +let dumpSectionDetails (secname: string) (file: IBinFile) = + dumpSpecific secname file "Section Details" ELFViewer.dumpSectionDetails PEViewer.dumpSectionDetails MachViewer.dumpSectionDetails -let dumpSymbols (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Symbol Information" +let dumpSymbols (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Symbol Information" ELFViewer.dumpSymbols PEViewer.dumpSymbols MachViewer.dumpSymbols -let dumpRelocs (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Relocation Information" +let dumpRelocs (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Relocation Information" ELFViewer.dumpRelocs PEViewer.dumpRelocs MachViewer.dumpRelocs -let dumpFunctions (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Function Information" +let dumpFunctions (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Function Information" ELFViewer.dumpFunctions PEViewer.dumpFunctions MachViewer.dumpFunctions -let dumpSegments (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Segment Information" +let dumpExceptionTable hdl (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Exception Table" + (ELFViewer.dumpExceptionTable hdl) + PEViewer.badAccess + MachViewer.badAccess + +let dumpDynamicSection (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Dynamic Section Information" + ELFViewer.dumpDynamicSection PEViewer.badAccess MachViewer.badAccess + +let dumpSegments (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Segment Information" ELFViewer.dumpSegments PEViewer.badAccess MachViewer.badAccess -let dumpLinkageTable (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Linkage Table Information" +let dumpLinkageTable (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Linkage Table Information" ELFViewer.dumpLinkageTable PEViewer.badAccess MachViewer.badAccess -let dumpEHFrame hdl (fi: FileInfo) = - dumpSpecific hdl fi ".eh_frame Information" +let dumpEHFrame hdl (file: IBinFile) = + dumpSpecific hdl file ".eh_frame Information" ELFViewer.dumpEHFrame PEViewer.badAccess MachViewer.badAccess -let dumpLSDA hdl (fi: FileInfo) = - dumpSpecific hdl fi ".gcc_except_table Information" - ELFViewer.dumpLSDA PEViewer.badAccess MachViewer.badAccess +let dumpGccExceptTable hdl (file: IBinFile) = + dumpSpecific hdl file ".gcc_except_table Information" + ELFViewer.dumpGccExceptTable PEViewer.badAccess MachViewer.badAccess -let dumpNotes hdl (fi: FileInfo) = - dumpSpecific hdl fi ".notes Information" +let dumpNotes hdl (file: IBinFile) = + dumpSpecific hdl file ".notes Information" ELFViewer.dumpNotes PEViewer.badAccess MachViewer.badAccess -let dumpImports (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Import table Information" +let dumpImports (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Import table Information" ELFViewer.badAccess PEViewer.dumpImports MachViewer.badAccess -let dumpExports (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Export table Information" +let dumpExports (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Export table Information" ELFViewer.badAccess PEViewer.dumpExports MachViewer.badAccess -let dumpOptionalHeader (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Optional Header Information" +let dumpOptionalHeader (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Optional Header Information" ELFViewer.badAccess PEViewer.dumpOptionalHeader MachViewer.badAccess -let dumpCLRHeader (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "CLR Header Information" +let dumpCLRHeader (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "CLR Header Information" ELFViewer.badAccess PEViewer.dumpCLRHeader MachViewer.badAccess -let dumpDependencies (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Dependencies Information" +let dumpDependencies (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Dependencies Information" ELFViewer.badAccess PEViewer.dumpDependencies MachViewer.badAccess -let dumpArchiveHeader (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Archive Header Information" +let dumpArchiveHeader (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Archive Header Information" ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpArchiveHeader -let dumpUnivHeader (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Universal Header Information" +let dumpUnivHeader (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Universal Header Information" ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpUniversalHeader -let dumpLoadCommands (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Load Commands Information" +let dumpLoadCommands (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Load Commands Information" ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpLoadCommands -let dumpSharedLibs (opts: FileViewerOpts) (fi: FileInfo) = - dumpSpecific opts fi "Shared Libs Information" +let dumpSharedLibs (opts: FileViewerOpts) (file: IBinFile) = + dumpSpecific opts file "Shared Libs Information" ELFViewer.badAccess PEViewer.badAccess MachViewer.dumpSharedLibs let printFileName filepath = [ Green, "["; Yellow, filepath; Green, "]" ] |> out.PrintLine out.PrintLine () -let printBasic fi = - dumpBasic fi - dumpSecurity fi - -let printAll opts hdl (fi: FileInfo) = - dumpBasic fi - dumpSecurity fi - dumpFileHeader opts fi - dumpSectionHeaders opts fi - dumpSymbols opts fi - dumpRelocs opts fi - dumpFunctions opts fi - match fi with - | :? ELFFileInfo as fi -> - dumpSegments opts fi - dumpLinkageTable opts fi - dumpEHFrame hdl fi - dumpLSDA hdl fi - | :? PEFileInfo as fi -> - dumpImports opts fi - dumpExports opts fi - dumpOptionalHeader opts fi - dumpCLRHeader opts fi - dumpDependencies opts fi - | :? MachFileInfo as fi -> - dumpLoadCommands opts fi - dumpSharedLibs opts fi +let printBasic file = + dumpBasic file + dumpSecurity file + +let printAll opts hdl (file: IBinFile) = + dumpBasic file + dumpSecurity file + dumpFileHeader opts file + dumpSectionHeaders opts file + dumpSymbols opts file + dumpRelocs opts file + dumpFunctions opts file + dumpExceptionTable hdl opts file + match file with + | :? ELFBinFile as file -> + dumpDynamicSection opts file + dumpSegments opts file + dumpLinkageTable opts file + dumpEHFrame hdl file + dumpGccExceptTable hdl file + | :? PEBinFile as file -> + dumpImports opts file + dumpExports opts file + dumpOptionalHeader opts file + dumpCLRHeader opts file + dumpDependencies opts file + | :? MachBinFile as file -> + dumpLoadCommands opts file + dumpSharedLibs opts file | _ -> Utils.futureFeature () -let printSelectively hdl opts fi = function +let printSelectively hdl opts file = function | DisplayAll -> Utils.impossible () - | DisplayFileHeader -> dumpFileHeader opts fi - | DisplaySectionHeaders -> dumpSectionHeaders opts fi - | DisplaySectionDetails s -> dumpSectionDetails s fi - | DisplaySymbols -> dumpSymbols opts fi - | DisplayRelocations -> dumpRelocs opts fi - | DisplayFunctions -> dumpFunctions opts fi - | DisplayELFSpecific ELFDisplayProgramHeader -> dumpSegments opts fi - | DisplayELFSpecific ELFDisplayPLT -> dumpLinkageTable opts fi - | DisplayELFSpecific ELFDisplayEHFrame -> dumpEHFrame hdl fi - | DisplayELFSpecific ELFDisplayLSDA -> dumpLSDA hdl fi - | DisplayELFSpecific ELFDisplayNotes -> dumpNotes hdl fi - | DisplayPESpecific PEDisplayImports -> dumpImports opts fi - | DisplayPESpecific PEDisplayExports -> dumpExports opts fi - | DisplayPESpecific PEDisplayOptionalHeader -> dumpOptionalHeader opts fi - | DisplayPESpecific PEDisplayCLRHeader -> dumpCLRHeader opts fi - | DisplayPESpecific PEDisplayDependencies -> dumpDependencies opts fi - | DisplayMachSpecific MachDisplayArchiveHeader -> dumpArchiveHeader opts fi - | DisplayMachSpecific MachDisplayUniversalHeader -> dumpUnivHeader opts fi - | DisplayMachSpecific MachDisplayLoadCommands -> dumpLoadCommands opts fi - | DisplayMachSpecific MachDisplaySharedLibs -> dumpSharedLibs opts fi - -let dumpFile (opts: FileViewerOpts) (filepath: string) = - let hdl = BinHandle.Init (opts.ISA, opts.BaseAddress, filepath) - let fi = hdl.FileInfo - printFileName fi.FilePath - if opts.DisplayItems.Count = 0 then printBasic fi - elif opts.DisplayItems.Contains DisplayAll then printAll opts hdl fi - else opts.DisplayItems |> Seq.iter (printSelectively hdl opts fi) + | DisplayFileHeader -> dumpFileHeader opts file + | DisplaySectionHeaders -> dumpSectionHeaders opts file + | DisplaySectionDetails s -> dumpSectionDetails s file + | DisplaySymbols -> dumpSymbols opts file + | DisplayRelocations -> dumpRelocs opts file + | DisplayFunctions -> dumpFunctions opts file + | DisplayExceptionTable -> dumpExceptionTable hdl opts file + | DisplayELFSpecific ELFDisplayProgramHeader -> dumpSegments opts file + | DisplayELFSpecific ELFDisplayPLT -> dumpLinkageTable opts file + | DisplayELFSpecific ELFDisplayEHFrame -> dumpEHFrame hdl file + | DisplayELFSpecific ELFDisplayGccExceptTable -> dumpGccExceptTable hdl file + | DisplayELFSpecific ELFDisplayNotes -> dumpNotes hdl file + | DisplayPESpecific PEDisplayImports -> dumpImports opts file + | DisplayPESpecific PEDisplayExports -> dumpExports opts file + | DisplayPESpecific PEDisplayOptionalHeader -> dumpOptionalHeader opts file + | DisplayPESpecific PEDisplayCLRHeader -> dumpCLRHeader opts file + | DisplayPESpecific PEDisplayDependencies -> dumpDependencies opts file + | DisplayMachSpecific MachDisplayArchiveHeader -> dumpArchiveHeader opts file + | DisplayMachSpecific MachDisplayUniversalHeader -> dumpUnivHeader opts file + | DisplayMachSpecific MachDisplayLoadCommands -> dumpLoadCommands opts file + | DisplayMachSpecific MachDisplaySharedLibs -> dumpSharedLibs opts file + +let dumpFile (opts: FileViewerOpts) (filePath: string) = + let hdl = BinHandle (filePath, opts.ISA, opts.BaseAddress) + let file = hdl.File + printFileName file.Path + if opts.DisplayItems.Count = 0 then printBasic file + elif opts.DisplayItems.Contains DisplayAll then printAll opts hdl file + else opts.DisplayItems |> Seq.iter (printSelectively hdl opts file) let [] private ToolName = "fileview" let [] private UsageTail = "" @@ -220,7 +234,7 @@ let dump files opts = CmdOpts.SanitizeRestArgs files match files with | [] -> - Printer.printErrorToConsole "File(s) must be given." + Printer.PrintErrorToConsole "File(s) must be given." CmdOpts.PrintUsage ToolName UsageTail Cmd.spec | files -> #if DEBUG @@ -236,4 +250,4 @@ let dump files opts = [] let main args = let opts = FileViewerOpts () - CmdOpts.ParseAndRun dump ToolName UsageTail Cmd.spec opts args \ No newline at end of file + CmdOpts.ParseAndRun dump ToolName UsageTail Cmd.spec opts args diff --git a/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj b/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj index e6d8dae8..a842ac92 100644 --- a/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj +++ b/src/RearEnd/Launcher/B2R2.RearEnd.Launcher.fsproj @@ -25,6 +25,7 @@ + diff --git a/src/RearEnd/Launcher/Program.fs b/src/RearEnd/Launcher/Program.fs index 75b4413c..d93c4191 100644 --- a/src/RearEnd/Launcher/Program.fs +++ b/src/RearEnd/Launcher/Program.fs @@ -29,7 +29,7 @@ open B2R2 open B2R2.RearEnd let showUsage () = - Printer.printToConsole """ + Printer.PrintToConsole """ '''''''''' .;' ';. ;' o o '; 888888b. 8888888b. @@ -96,10 +96,10 @@ let printMyVersion () = let asm = Assembly.GetEntryAssembly () let attr = asm.GetCustomAttribute () attr.InformationalVersion.ToString () - |> Printer.printToConsole + |> Printer.PrintToConsole let handleCommands (cmd: string) (rest: string []) = - match cmd.ToLower () with + match cmd.ToLowerInvariant () with | "help" | "--help" | "-h" -> showUsage (); 0 | "fileviewer" | "file" | "fileview" | "peek" -> FileViewer.Program.main rest | "bindump" | "disasm" | "dump" | "disas" | "dis" -> BinDump.Program.main rest diff --git a/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj b/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj index 9878ce4c..1956cae1 100644 --- a/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj +++ b/src/RearEnd/ROP/B2R2.RearEnd.ROP.fsproj @@ -16,7 +16,7 @@ - + diff --git a/src/RearEnd/ROP/Chain.fs b/src/RearEnd/ROP/Chain.fs index 257a87ca..9b4e297c 100644 --- a/src/RearEnd/ROP/Chain.fs +++ b/src/RearEnd/ROP/Chain.fs @@ -24,23 +24,24 @@ namespace B2R2.RearEnd.ROP +open System open System.Collections open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface type ROPHandle = { - BinBase : Addr - BinHdl : BinHandle - Gadgets : GadgetArr - Summaries : Concurrent.ConcurrentDictionary + BinBase: Addr + BinHdl: BinHandle + Gadgets: GadgetArr + Summaries: Concurrent.ConcurrentDictionary } module ROPHandle = - let inline getFileInfo hdl = hdl.BinHdl.FileInfo + let inline getFileInfo hdl = hdl.BinHdl.File let inline tryFindPlt hdl name = - hdl.BinHdl.FileInfo.GetLinkageTableEntries () + hdl.BinHdl.File.GetLinkageTableEntries () |> Seq.tryFind (fun entry -> entry.FuncName = name) let inline getKeys map = Map.fold (fun acc k _ -> Set.add k acc) Set.empty map @@ -53,7 +54,7 @@ module ROPHandle = BinBase = binBase BinHdl = binHdl Gadgets = Galileo.findGadgets binHdl |> Map.toArray |> GadgetArr.sort - Summaries = new Concurrent.ConcurrentDictionary () + Summaries = Concurrent.ConcurrentDictionary () } let private getSummary (hdl: ROPHandle) (gadget: Gadget) = @@ -63,7 +64,7 @@ module ROPHandle = |> Ok with | B2R2.BinIR.InvalidExprException as e -> Error <| sprintf "%A" e - | e -> raise e + | _ -> reraise () let private getSetterMap hdl = let folder acc info = @@ -97,7 +98,7 @@ module ROPHandle = getSubset 1 (Set.toList set) let private getRegsSetters hdl setterMap regs = - let cache = new Concurrent.ConcurrentDictionary, Option<_>> () + let cache = Concurrent.ConcurrentDictionary, Option<_>> () let getSetter todoSet doneSet = cache.GetOrAdd (todoSet, (fun k -> findSetter setterMap todoSet doneSet)) let rec finder todoSet doneSet = @@ -181,7 +182,7 @@ module ROPHandle = let private findBytes hdl bytes = let chooser (seg: Segment) = let min = seg.Address - BinHandle.ReadBytes (hdl.BinHdl, min, int seg.Size) + hdl.BinHdl.ReadBytes (min, int seg.Size) |> ByteArray.tryFindIdx min bytes (getFileInfo hdl).GetSegments Permission.Readable |> Seq.tryPick chooser @@ -193,13 +194,22 @@ module ROPHandle = |> Seq.maxBy (fun seg -> seg.Size) seg.Address + hdl.BinBase + let private toUInt32Arr (src: byte[]) = + let srcLen = Array.length src + let dstLen = + if srcLen % 4 = 0 then srcLen/4 + else (srcLen / 4) + 1 + let dst = Array.init dstLen (fun _ -> 0u) + Buffer.BlockCopy (src, 0, dst, 0, srcLen) + dst + let private getOrWriteStr hdl str = let bytes = String.toBytes str match findBytes hdl bytes with | None -> let addr = getWritableAddr hdl let payload = - ByteArray.toUInt32Arr bytes + toUInt32Arr bytes |> Array.map ROPExpr.ofUInt32 |> write32s hdl (ROPExpr.ofUInt32 addr) if Option.isSome payload then Some (payload, addr) diff --git a/src/RearEnd/ROP/Gadget.fs b/src/RearEnd/ROP/Gadget.fs index 971c8a7f..47cf880e 100644 --- a/src/RearEnd/ROP/Gadget.fs +++ b/src/RearEnd/ROP/Gadget.fs @@ -25,8 +25,8 @@ namespace B2R2.RearEnd.ROP open System +open B2R2.FrontEnd open B2R2.FrontEnd.BinLifter -open B2R2.FrontEnd.BinInterface /// Tail is a instruction sequence that needs to be placed at the end of each /// ROP gadget. @@ -52,13 +52,13 @@ module Gadget = Offset = offset NextOff = offset } - let toString hdl (gadget: Gadget) = + let toString (hdl: BinHandle) (gadget: Gadget) = let sb = Text.StringBuilder () let sb = sb.Append (sprintf "[*] Offset = %x\n" gadget.Offset) gadget.Instrs |> List.fold (fun (sb: Text.StringBuilder) i -> - let disasm = BinHandle.DisasmInstr hdl true false i - sb.Append(disasm).Append(Environment.NewLine)) sb + let disasm = hdl.DisasmInstr (i, true, false) + sb.Append(disasm).Append(Environment.NewLine)) sb |> fun sb -> sb.ToString () module GadgetMap = diff --git a/src/RearEnd/ROP/Galileo.fs b/src/RearEnd/ROP/Galileo.fs index ea4914b1..3733304d 100644 --- a/src/RearEnd/ROP/Galileo.fs +++ b/src/RearEnd/ROP/Galileo.fs @@ -25,8 +25,8 @@ module B2R2.RearEnd.ROP.Galileo open B2R2 +open B2R2.FrontEnd open B2R2.FrontEnd.BinFile -open B2R2.FrontEnd.BinInterface open B2R2.BinIR.LowUIR let filter = function @@ -35,31 +35,31 @@ let filter = function let private toTail bytes = { Pattern = bytes } -let private instrMaxLen hdl = - match hdl.ISA.Arch with - | Arch.IntelX86 | Arch.IntelX64 -> 15UL - | Arch.AARCH32 | Arch.AARCH64 | Arch.ARMv7 -> 4UL +let private instrMaxLen (hdl: BinHandle) = + match hdl.File.ISA.Arch with + | Architecture.IntelX86 | Architecture.IntelX64 -> 15UL + | Architecture.AARCH32 | Architecture.AARCH64 | Architecture.ARMv7 -> 4UL | _ -> raise InvalidISAException -let getTailPatterns hdl = - match hdl.ISA.Arch, hdl.ISA.Endian with - | Arch.IntelX86, Endian.Little -> +let getTailPatterns (hdl: BinHandle) = + match hdl.File.ISA.Arch, hdl.File.ISA.Endian with + | Architecture.IntelX86, Endian.Little -> [ [| 0xC3uy |] (* RET *) [| 0xCDuy; 0x80uy |] (* INT 0x80 *) [| 0xCDuy; 0x80uy; 0xC3uy |] (* INT 0x80; RET *) ] - | Arch.IntelX64, Endian.Little -> + | Architecture.IntelX64, Endian.Little -> [ [| 0xC3uy |] (* RET *) [| 0x0Fuy; 0x05uy |] (* SYSCALL *) [| 0x0Fuy; 0x05uy; 0xC3uy |] (* SYSCALL; RET *) ] | _ -> failwith "Unsupported arch." |> List.map toTail -let private getExecutableSegs hdl = - let fi = hdl.FileInfo +let private getExecutableSegs (hdl: BinHandle) = + let file = hdl.File let rxRanges = - fi.GetSegments (Permission.Readable ||| Permission.Executable) - if not fi.IsNXEnabled then - fi.GetSegments (Permission.Readable) + file.GetSegments (Permission.Readable ||| Permission.Executable) + if not file.IsNXEnabled then + file.GetSegments (Permission.Readable) |> Seq.append rxRanges |> Seq.distinct else @@ -74,10 +74,10 @@ let inline updateGadgets curAddr nextAddr ins gadgets = Map.add curAddr g gadgets |> Some | _ -> None -let rec buildBackward hdl minAddr curAddr lastAddr map = +let rec buildBackward (hdl: BinHandle) minAddr curAddr lastAddr map = if curAddr < minAddr || (curAddr + 1UL) = 0UL then map else - match BinHandle.TryParseInstr (hdl, curAddr) with + match hdl.TryParseInstr curAddr with | Ok ins -> let nextAddr = curAddr + (uint64 ins.Length) if ins.IsBBLEnd () then @@ -91,22 +91,22 @@ let rec buildBackward hdl minAddr curAddr lastAddr map = | None -> buildBackward hdl minAddr (curAddr - 1UL) lastAddr map | Error _ -> buildBackward hdl minAddr (curAddr - 1UL) lastAddr map -let parseTail hdl addr bytes = +let parseTail (hdl: BinHandle) addr bytes = let lastAddr = (Array.length bytes |> uint64) + addr let rec parseLoop acc addr = if lastAddr > addr then - let ins = BinHandle.ParseInstr (hdl, addr) + let ins = hdl.ParseInstr addr parseLoop (ins :: acc) (addr + uint64 ins.Length) else List.rev acc parseLoop [] addr -let private buildGadgetMap hdl (tail: Tail) map (seg: Segment) = +let private buildGadgetMap (hdl: BinHandle) (tail: Tail) map (seg: Segment) = let minAddr = seg.Address let build map idx = let sGadget = parseTail hdl idx tail.Pattern |> Gadget.create idx Map.add idx sGadget map |> buildBackward hdl (min 0UL (minAddr - instrMaxLen hdl)) (idx - 1UL) idx - BinHandle.ReadBytes (hdl, seg.Address, int (seg.Size)) + hdl.ReadBytes (seg.Address, int (seg.Size)) |> ByteArray.findIdxs minAddr tail.Pattern |> List.fold build map diff --git a/src/RearEnd/ROP/ROPPayload.fs b/src/RearEnd/ROP/ROPPayload.fs index 2f7af27a..1795eee9 100644 --- a/src/RearEnd/ROP/ROPPayload.fs +++ b/src/RearEnd/ROP/ROPPayload.fs @@ -40,14 +40,14 @@ module ROPPayload = let addExpr e p = Array.append p [|ROPValue.ofExpr e|] let addExprs exprs p = - Array.map (fun e -> ROPValue.ofExpr e) exprs |> Array.append p + Array.map ROPValue.ofExpr exprs |> Array.append p let setExpr e i p = Array.set p i (ROPValue.ofExpr e); p let addNum32 num p = Array.append p [|ROPValue.ofUInt32 num|] let addNum32s nums p = - Array.map (fun num -> ROPValue.ofUInt32 num) nums |> Array.append p + Array.map ROPValue.ofUInt32 nums |> Array.append p let setNum32 num i p = Array.set p i (ROPValue.ofUInt32 num); p diff --git a/src/RearEnd/ROP/ROPValue.fs b/src/RearEnd/ROP/ROPValue.fs index 6ded27c4..1ca1c8e7 100644 --- a/src/RearEnd/ROP/ROPValue.fs +++ b/src/RearEnd/ROP/ROPValue.fs @@ -26,7 +26,8 @@ namespace B2R2.RearEnd.ROP open System open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd +open B2R2.FrontEnd.BinLifter type ROPExpr = | Var of string @@ -35,25 +36,25 @@ type ROPExpr = | Add of ROPExpr * ROPExpr module ROPExpr = - let inline ofUInt32 num = BitVector.ofUInt32 (uint32 num) 32 |> Num + let inline ofUInt32 num = BitVector.OfUInt32 (uint32 num) 32 |> Num - let inline ofUInt64 num = BitVector.ofUInt64 (uint64 num) 64 |> Num + let inline ofUInt64 num = BitVector.OfUInt64 (uint64 num) 64 |> Num - let zero32 = BitVector.zero 32 |> Num + let zero32 = BitVector.Zero 32 |> Num let addNum32 expr (num: uint32) = match expr with - | Num n -> BitVector.ofUInt32 num 32 |> BitVector.add n |> Num + | Num n -> BitVector.Add (n, BitVector.OfUInt32 num 32) |> Num | _ -> Add (expr, ofUInt32 num) let subNum32 expr (num: uint32) = match expr with - | Num n -> BitVector.ofUInt32 num 32 |> BitVector.sub n |> Num + | Num n -> BitVector.Sub (n, BitVector.OfUInt32 num 32) |> Num | _ -> Add (expr, ofUInt32 num) let rec toString = function | Num vec -> - sprintf "[ %08x ]" (BitVector.toUInt32 vec) + Environment.NewLine + sprintf "[ %08x ]" (BitVector.ToUInt32 vec) + Environment.NewLine | expr -> // XXX FIXME sprintf "[ %A ]" expr + Environment.NewLine @@ -72,13 +73,13 @@ module ROPValue = let dummy32 = ofUInt32 0xdeadbeefu - let strFolder hdl acc ins = - let acc = acc + " " + BinHandle.DisasmInstr hdl true false ins + let strFolder (hdl: BinHandle) acc (ins: Instruction) = + let acc = acc + " " + hdl.DisasmInstr (ins, true, false) acc + Environment.NewLine let toString hdl binBase = function - | ROPValue.Expr expr -> ROPExpr.toString expr - | ROPValue.Gadget gadget -> + | Expr expr -> ROPExpr.toString expr + | Gadget gadget -> let s = sprintf "[ %08X ]" ((uint32 gadget.Offset) + binBase) let s = s + Environment.NewLine gadget.Instrs |> List.fold (strFolder hdl) s diff --git a/src/RearEnd/ROP/Simplify.fs b/src/RearEnd/ROP/Simplify.fs index 5380ee63..c52690cb 100644 --- a/src/RearEnd/ROP/Simplify.fs +++ b/src/RearEnd/ROP/Simplify.fs @@ -28,51 +28,51 @@ open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -let inline negNum x = BitVector.neg x |> AST.num +let inline negNum x = BitVector.Neg x |> AST.num -let inline zeroNum ty = BitVector.zero ty |> AST.num +let inline zeroNum ty = BitVector.Zero ty |> AST.num let inline maxNum ty = match ty with - | 8 -> BitVector.maxUInt8 |> AST.num - | 16 -> BitVector.maxUInt16 |> AST.num - | 32 -> BitVector.maxUInt32 |> AST.num - | 64 -> BitVector.maxUInt64 |> AST.num + | 8 -> BitVector.MaxUInt8 |> AST.num + | 16 -> BitVector.MaxUInt16 |> AST.num + | 32 -> BitVector.MaxUInt32 |> AST.num + | 64 -> BitVector.MaxUInt64 |> AST.num | _ -> failwith "maxNum fail" let inline isZero e = match e.E with - | Num n -> (BitVector.getValue n).IsZero + | Num n -> (BitVector.GetValue n).IsZero | _ -> false let inline isOne e = match e.E with - | Num n -> (BitVector.getValue n).IsOne + | Num n -> (BitVector.GetValue n).IsOne | _ -> false -let isFlippable x = (BitVector.isNegative x) && not (BitVector.isSignedMin x) +let isFlippable x = (BitVector.IsNegative x) && not (BitVector.IsSignedMin x) let inline isMax ty e = match e.E with - | Num n -> (BitVector.one ty |> BitVector.add n |> BitVector.getValue).IsZero + | Num n -> (BitVector.Add (n, BitVector.One ty) |> BitVector.GetValue).IsZero | _ -> false let inline binADD e1 e2 = AST.binop BinOpType.ADD e1 e2 let inline binSUB e1 e2 = AST.binop BinOpType.SUB e1 e2 -let inline subNum n1 n2 = BitVector.sub n1 n2 |> AST.num +let inline subNum n1 n2 = BitVector.Sub (n1, n2) |> AST.num -let inline addNum n1 n2 = BitVector.add n1 n2 |> AST.num +let inline addNum n1 n2 = BitVector.Add (n1, n2) |> AST.num let rec simplify expr = match expr.E with - | UnOp (op, e1, _) -> AST.unop op <| simplify e1 - | BinOp (op, ty, e1, e2, _) -> simplifyBinOp op ty e1 e2 - | RelOp (op, e1, e2, _) -> AST.relop op (simplify e1) (simplify e2) - | Load (endian, ty, e1, _) -> AST.load endian ty <| simplify e1 - | Ite (e1, e2, e3, _) -> AST.ite (simplify e1) (simplify e2) (simplify e3) - | Cast (kind, ty, e1, _) -> simplifyCast kind ty e1 + | UnOp (op, e1) -> AST.unop op <| simplify e1 + | BinOp (op, ty, e1, e2) -> simplifyBinOp op ty e1 e2 + | RelOp (op, e1, e2) -> AST.relop op (simplify e1) (simplify e2) + | Load (endian, ty, e1) -> AST.load endian ty <| simplify e1 + | Ite (e1, e2, e3) -> AST.ite (simplify e1) (simplify e2) (simplify e3) + | Cast (kind, ty, e1) -> simplifyCast kind ty e1 | _ -> expr (* Var, TempVar, Num, Name, PCVar *) and simplifyBinOp op ty e1 e2 = @@ -101,126 +101,126 @@ and simplifyBinOp op ty e1 e2 = | BinOpType.SUB, Num (n1), _ when isFlippable n1 -> simplify (binSUB e2 (negNum n1)) (* ADD + ADD *) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) -> simplify (binADD (binADD e2 e4) (addNum n1 n3)) (* SUB + SUB *) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4) -> simplify (binSUB (addNum n1 n3) (binADD e2 e4)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) -> + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }) -> simplify (binADD (subNum n1 n4) (binSUB e3 e2)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4) -> simplify (binADD (subNum n3 n1) (binSUB e2 e4)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.SUB, _, e4, { E = Num (n3) }, _) -> + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }), + BinOp (BinOpType.SUB, _, e4, { E = Num (n3) }) -> simplify (binSUB (binADD e2 e4) (addNum n1 n3)) (* Num + Num *) | BinOpType.ADD, Num (n1), Num (n2) -> addNum n1 n2 (* ADD + Num, Num + ADD *) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3, _) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3, _), Num (n1) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }, _), Num (n1) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3), Num (n1) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }), Num (n1) -> simplify (binADD e3 (addNum n1 n2)) (* Num + SUB, SUB + Num *) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3, _), Num (n1) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3), Num (n1) -> simplify (binSUB (addNum n1 n2) e3) - | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }, _), Num (n1) + | BinOpType.ADD, Num (n1), BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }), Num (n1) -> simplify (binADD e2 (subNum n1 n3)) (* SUB + ADD, ADD + SUB *) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _), - BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _), - BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _) -> + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4), + BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }), + BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2) -> simplify (binADD (addNum n1 n3) (binSUB e4 e2)) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _), - BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _) - | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _), - BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _) - | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4), + BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }) + | BinOpType.ADD, BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }), + BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }) + | BinOpType.ADD, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) -> simplify (binADD (subNum n3 n2) (binADD e1 e4)) (* ADD - ADD *) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) -> simplify (binADD (binSUB e2 e4) (subNum n1 n3)) (* SUB - SUB *) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4) -> simplify (binSUB (subNum n1 n3) (binSUB e2 e4)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) -> + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }) -> simplify (binSUB (addNum n1 n4) (binADD e2 e3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4) -> simplify (binSUB (binADD e2 e4) (addNum n1 n3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.SUB, _, e4, { E = Num (n3) }, _) -> + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e2, { E = Num (n1) }), + BinOp (BinOpType.SUB, _, e4, { E = Num (n3) }) -> simplify (binSUB (binSUB e2 e4) (subNum n1 n3)) (* Num - Num *) | BinOpType.SUB, Num (n1), Num (n2) -> subNum n1 n2 (* ADD - Num, Num - ADD *) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), Num (n3) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), Num (n3) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), Num (n3) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), Num (n3) -> simplify (binADD (subNum n1 n3) e2) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3, _) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }, _) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, { E = Num (n2) }, e3) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.ADD, _, e3, { E = Num (n2) }) -> simplify (binSUB (subNum n1 n2) e3) (* SUB - Num, Num - SUB *) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), Num (n3) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), Num (n3) -> simplify (binSUB (subNum n1 n3) e2) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), Num (n3) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }), Num (n3) -> simplify (binSUB e1 (addNum n2 n3)) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3, _) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, { E = Num (n2) }, e3) -> simplify (binADD e3 (subNum n1 n2)) - | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }, _) + | BinOpType.SUB, Num (n1), BinOp (BinOpType.SUB, _, e2, { E = Num (n3) }) -> simplify (binSUB (addNum n1 n3) e2) (* ADD - SUB, SUB - ADD *) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4, _) -> + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), + BinOp (BinOpType.SUB, _, { E = Num (n3) }, e4) -> simplify (binADD (subNum n1 n3) (binSUB e2 e4)) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) - | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }, _), - BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }, _) -> + | BinOpType.SUB, BinOp (BinOpType.ADD, _, { E = Num (n1) }, e2), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }) + | BinOpType.SUB, BinOp (BinOpType.ADD, _, e2, { E = Num (n1) }), + BinOp (BinOpType.SUB, _, e3, { E = Num (n4) }) -> simplify (binADD (addNum n1 n4) (binSUB e2 e3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, e1, { E = Num (n2) }), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) -> simplify (binSUB (binSUB e1 e4) (addNum n2 n3)) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4, _) - | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2, _), - BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }, _) -> + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, { E = Num (n3) }, e4) + | BinOpType.SUB, BinOp (BinOpType.SUB, _, { E = Num (n1) }, e2), + BinOp (BinOpType.ADD, _, e4, { E = Num (n3) }) -> simplify (binSUB (subNum n1 n3) (binADD e2 e4)) | BinOpType.SUB, _, _ when e1 = e2 -> zeroNum ty | BinOpType.MUL, _, _ when isOne e1 -> simplify e2 @@ -230,5 +230,5 @@ and simplifyBinOp op ty e1 e2 = and simplifyCast kind ty e1 = match kind, e1.E with - | CastKind.ZeroExt, Num n -> BitVector.zext n ty |> AST.num + | CastKind.ZeroExt, Num n -> BitVector.ZExt (n, ty) |> AST.num | _, _ -> AST.cast kind ty <| simplify e1 diff --git a/src/RearEnd/ROP/State.fs b/src/RearEnd/ROP/State.fs index 001ee3d9..172a572f 100644 --- a/src/RearEnd/ROP/State.fs +++ b/src/RearEnd/ROP/State.fs @@ -49,17 +49,17 @@ type Value (expr) = module Value = let toLinear (value: Value) = match value.GetExpr().E with - | Var (32, _, reg, _) -> Some (reg, 0u) + | Var (32, _, reg) -> Some (reg, 0u) | BinOp (BinOpType.ADD, _, - { E = Var (32, _, reg, _) }, { E = Num n }, _) + { E = Var (32, _, reg) }, { E = Num n }) | BinOp (BinOpType.ADD, _, - { E = Num n }, { E = Var (32, _, reg, _) }, _) -> - Some (reg, BitVector.toUInt32 n) + { E = Num n }, { E = Var (32, _, reg) }) -> + Some (reg, BitVector.ToUInt32 n) | BinOp (BinOpType.SUB, _, - { E = Var (32, _, reg, _) }, { E = Num n }, _) + { E = Var (32, _, reg) }, { E = Num n }) | BinOp (BinOpType.SUB, _, - { E = Num n }, { E = Var (32, _, reg, _) }, _) -> - Some (reg, BitVector.neg n |> BitVector.toUInt32) + { E = Num n }, { E = Var (32, _, reg) }) -> + Some (reg, BitVector.Neg n |> BitVector.ToUInt32) | _ -> None type State = { @@ -96,18 +96,18 @@ module State = let rec evalExpr state e = match e.E with - | Var (_, _, name, _) -> getReg state name e + | Var (_, _, name) -> getReg state name e | TempVar (_, name) -> getTempReg state name - | UnOp (op, expr, _) -> AST.unop op (getEvalExpr state expr) |> Value - | BinOp (op, ty, lExpr, rExpr, _) -> + | UnOp (op, expr) -> AST.unop op (getEvalExpr state expr) |> Value + | BinOp (op, ty, lExpr, rExpr) -> AST.binop op (getEvalExpr state lExpr) (getEvalExpr state rExpr) |> Value - | RelOp (op, lExpr, rExpr, _) -> + | RelOp (op, lExpr, rExpr) -> AST.relop op (getEvalExpr state lExpr) (getEvalExpr state rExpr) |> Value - | Load (endian, ty, expr, _) -> evalLoad state endian ty expr - | Ite (cExpr, tExpr, fExpr, _) -> + | Load (endian, ty, expr) -> evalLoad state endian ty expr + | Ite (cExpr, tExpr, fExpr) -> AST.ite (getEvalExpr state cExpr) (getEvalExpr state tExpr) (getEvalExpr state fExpr) |> Value - | Cast (kind, ty, expr, _) -> + | Cast (kind, ty, expr) -> AST.cast kind ty <| getEvalExpr state expr |> Value | _ -> Value e // Num, Name, PCVar @@ -162,7 +162,7 @@ module State = let evalStmt state stmt = match stmt.S with | ISMark _ | IEMark _ | LMark _ -> state - | Put ({ E = Var (_, _, reg, _) }, value) -> evalPutVar state reg value + | Put ({ E = Var (_, _, reg) }, value) -> evalPutVar state reg value | Put ({ E = TempVar (_, reg) }, value) -> evalPutTemp state reg value | Store (endian, addr, value) -> evalStore state endian addr value | CJmp (condE, trueE, falseE) -> evalCJmp state condE trueE falseE diff --git a/src/RearEnd/ROP/Summary.fs b/src/RearEnd/ROP/Summary.fs index 0e43f823..1cf54091 100644 --- a/src/RearEnd/ROP/Summary.fs +++ b/src/RearEnd/ROP/Summary.fs @@ -27,7 +27,7 @@ namespace B2R2.RearEnd.ROP open B2R2 open B2R2.BinIR open B2R2.BinIR.LowUIR -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.FrontEnd.BinLifter.Intel type Summary = { @@ -44,12 +44,11 @@ module Summary = let private emptyInput = (Set.empty, Set.empty) - // FIXME - let private ESP = + let private esp = let regID = Register.toRegID Register.ESP - AST.var 32 regID "ESP" (IntelRegisterSet.singleton regID) + AST.var 32 regID "ESP" - let private REGS = + let private regs = [| "EIP"; "ESP"; "EBP"; "EAX"; "EBX"; "ECX"; "EDX"; "ESI"; "EDI" |] let private syscallOutRegs = @@ -58,17 +57,17 @@ module Summary = let getInput (state: State) e = let rec getInput e = match e.E with - | Var (_, _, n, _) -> (Set.empty.Add (n), Set.empty) + | Var (_, _, n) -> (Set.empty.Add (n), Set.empty) | TempVar (_, n) -> getInput <| (Map.find n state.TempRegs).GetExpr () - | UnOp (_, expr, _) -> getInput expr - | BinOp (_, _, lExpr, rExpr, _) | RelOp (_, lExpr, rExpr, _) -> + | UnOp (_, expr) -> getInput expr + | BinOp (_, _, lExpr, rExpr) | RelOp (_, lExpr, rExpr) -> mergeInput (getInput lExpr) (getInput rExpr) - | Load (_, _, expr, _) -> + | Load (_, _, expr) -> mergeInput (getInput expr) (Set.empty, Set.empty.Add (Value expr)) - | Ite (cExpr, tExpr, fExpr, _) -> + | Ite (cExpr, tExpr, fExpr) -> mergeInput (getInput cExpr) (getInput tExpr) |> mergeInput (getInput fExpr) - | Cast (_, _, expr, _) | Extract (expr, _, _, _) -> getInput expr + | Cast (_, _, expr) | Extract (expr, _, _) -> getInput expr | _ -> emptyInput // Num, Name, PCVar getInput e @@ -94,17 +93,17 @@ module Summary = let private getEspOff e = match e.E with - | _ when e = ESP -> Some 0 - | BinOp (BinOpType.ADD, 32, var, { E = Num (n) }, _) - | BinOp (BinOpType.ADD, 32, { E = Num (n) }, var, _) when var = ESP -> - calcOffset (BitVector.toInt32 n) - | BinOp (BinOpType.SUB, 32, var, { E = Num (n) }, _) when var = ESP -> - calcOffset (- (BitVector.toInt32 n)) + | _ when e = esp -> Some 0 + | BinOp (BinOpType.ADD, 32, var, { E = Num (n) }) + | BinOp (BinOpType.ADD, 32, { E = Num (n) }, var) when var = esp -> + calcOffset (BitVector.ToInt32 n) + | BinOp (BinOpType.SUB, 32, var, { E = Num (n) }) when var = esp -> + calcOffset (- (BitVector.ToInt32 n)) | _ -> None let private getStackOff (v: Value) = match v.GetExpr().E with - | Load (_, 32, expr, _) -> getEspOff expr + | Load (_, 32, expr) -> getEspOff expr | _ -> None let private getRegStackOff reg regs = @@ -117,7 +116,7 @@ module Summary = match getRegStackOff reg sum.OutRegs with | Some v -> Map.add reg v acc | None -> acc - Array.fold folder Map.empty REGS + Array.fold folder Map.empty regs let private isStackMem (addr: Value) = match getEspOff (addr.GetExpr ()) with @@ -128,17 +127,17 @@ module Summary = let private isLinearExpr e = match e.E with - | Var (32, _, reg, _) -> Some (reg, 0u) + | Var (32, _, reg) -> Some (reg, 0u) | BinOp (BinOpType.ADD, _, - { E = Var (32, _, reg, _) }, { E = Num n }, _) + { E = Var (32, _, reg) }, { E = Num n }) | BinOp (BinOpType.ADD, _, - { E = Num n }, { E = Var (32, _, reg, _) }, _) -> - Some (reg, BitVector.toUInt32 n) + { E = Num n }, { E = Var (32, _, reg) }) -> + Some (reg, BitVector.ToUInt32 n) | BinOp (BinOpType.SUB, _, - { E = Var (32, _, reg, _) }, { E = Num n }, _) + { E = Var (32, _, reg) }, { E = Num n }) | BinOp (BinOpType.SUB, _, - { E = Num n }, { E = Var (32, _, reg, _) }, _) -> - Some (reg, BitVector.neg n |> BitVector.toUInt32) + { E = Num n }, { E = Var (32, _, reg) }) -> + Some (reg, BitVector.Neg n |> BitVector.ToUInt32) | _ -> None let private isLinear (value: Value) = value.GetExpr () |> isLinearExpr @@ -176,7 +175,7 @@ module Summary = let inline containKeys keys map = Set.forall (fun k -> Map.containsKey k map) keys - let private isReg reg = Array.exists (fun x -> x = reg) REGS + let private isReg reg = Array.exists (fun x -> x = reg) regs let private getRegs regMap = let folder acc reg _ = @@ -193,7 +192,7 @@ module Summary = match Map.tryFind reg sum.OutRegs with | Some value -> match value.GetExpr().E with - | Load (_, _, addr, _) -> isLinearExpr addr + | Load (_, _, addr) -> isLinearExpr addr | _ -> None | _ -> None @@ -236,20 +235,20 @@ module Summary = let private checkRegs (sum: Summary) regs = let checker (reg, v) = match Map.tryFind reg sum.OutRegs with - | Some x when x = (BitVector.ofUInt32 v 32 |> AST.num |> Value) -> + | Some x when x = (BitVector.OfUInt32 v 32 |> AST.num |> Value) -> true | _ -> false Array.forall checker regs let private addNum32 (ptr: Value) num = - BitVector.ofInt32 num 32 + BitVector.OfInt32 num 32 |> AST.num |> Simplify.simplifyBinOp BinOpType.ADD 32 (ptr.GetExpr ()) |> Value let private toBytes (value: Value) = match value.GetExpr().E with - | Num n -> (BitVector.getValue n).ToByteArray () |> Some + | Num n -> (BitVector.GetValue n).ToByteArray () |> Some | _ -> None let private readMemStr (sum: Summary) ptr = @@ -296,9 +295,9 @@ module Summary = s.OutMems printfn "-----------------------------------" - let summary hdl gadget = + let summary (hdl: BinHandle) gadget = gadget.Instrs - |> List.map (BinHandle.LiftInstr hdl) + |> List.map hdl.LiftInstr |> Array.concat |> Array.fold (State.evalStmt) State.initState |> getSummary diff --git a/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj b/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj index 1f66341c..17927616 100644 --- a/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj +++ b/src/RearEnd/Repl/B2R2.RearEnd.Repl.fsproj @@ -14,14 +14,14 @@ - + - - + + diff --git a/src/RearEnd/Repl/Program.fs b/src/RearEnd/Repl/Program.fs index a2e45c92..df554f7b 100644 --- a/src/RearEnd/Repl/Program.fs +++ b/src/RearEnd/Repl/Program.fs @@ -25,7 +25,7 @@ module B2R2.RearEnd.Repl.Program open B2R2 -open B2R2.FrontEnd.BinInterface +open B2R2.FrontEnd open B2R2.Peripheral.Assembly let cmds = @@ -66,8 +66,8 @@ let rec run showTemporary (state: ReplState) asm = run showTemporary state asm let runRepl _args (opts: ReplOpts) = - let binhandler = BinHandle.Init (opts.ISA) - let state = ReplState (opts.ISA, binhandler.RegisterBay, not opts.Verbose) + let binhandler = BinHandle ("", opts.ISA) + let state = ReplState (opts.ISA, binhandler.RegisterFactory, not opts.Verbose) let asm = AsmInterface (opts.ISA, 0UL) Display.printBlue "Welcome to B2R2 REPL\n" state.ConsolePrompt |> console.UpdatePrompt diff --git a/src/RearEnd/Repl/ReplState.fs b/src/RearEnd/Repl/ReplState.fs index 5acfc59b..f221f6a1 100644 --- a/src/RearEnd/Repl/ReplState.fs +++ b/src/RearEnd/Repl/ReplState.fs @@ -33,21 +33,24 @@ type ParserState = | LowUIRParser | BinParser of Architecture -type ReplState (isa: ISA, regbay: RegisterBay, doFiltering) = +type ReplState (isa: ISA, regFactory: RegisterFactory, doFiltering) = let rstate = EvalState () let mutable parser = BinParser isa.Arch do - regbay.GetAllRegExprs () + rstate.SideEffectEventHandler <- + (fun e st -> printfn $"[*] Unhandled side-effect ({e}) encountered" + st.IsInstrTerminated <- true) + regFactory.GetAllRegExprs () |> List.map (fun r -> - (regbay.RegIDFromRegExpr r, BitVector.ofInt32 0 (TypeCheck.typeOf r))) + (regFactory.RegIDFromRegExpr r, BitVector.OfInt32 0 (TypeCheck.typeOf r))) |> rstate.InitializeContext 0UL let mutable prevReg = rstate.Registers.ToArray () |> Array.map (fun (i, v) -> RegisterID.create i, v) let mutable prevTmp = rstate.Temporaries.ToArray () let generalRegs = - regbay.GetGeneralRegExprs () - |> List.map regbay.RegIDFromRegExpr + regFactory.GetGeneralRegExprs () + |> List.map regFactory.RegIDFromRegExpr |> Set.ofList member private __.EvaluateStmts (stmts: Stmt []) = @@ -85,13 +88,13 @@ type ReplState (isa: ISA, regbay: RegisterBay, doFiltering) = |> Seq.toList |> __.Filter |> List.map (fun (r, v) -> - let regStr = regbay.RegIDToString r + let regStr = regFactory.RegIDToString r let regVal = v.ToString () regStr + ": " + regVal, Set.contains r set) /// Gets a temporary register name and EvalValue string representation. member private __.TempRegString (n: int) v = - "T_" + string (n) + ": " + v.ToString () + "T_" + string (n) + ": " + (if isNull v then "n/a" else v.ToString ()) member __.GetAllTempValString delta = let set = Set.ofList delta diff --git a/src/RearEnd/Transformer/B2R2.RearEnd.Transformer.fsproj b/src/RearEnd/Transformer/B2R2.RearEnd.Transformer.fsproj new file mode 100644 index 00000000..06f5cd96 --- /dev/null +++ b/src/RearEnd/Transformer/B2R2.RearEnd.Transformer.fsproj @@ -0,0 +1,46 @@ + + + + Exe + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/RearEnd/Transformer/CFGAction.fs b/src/RearEnd/Transformer/CFGAction.fs new file mode 100644 index 00000000..57022a82 --- /dev/null +++ b/src/RearEnd/Transformer/CFGAction.fs @@ -0,0 +1,69 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open B2R2 +open B2R2.MiddleEnd.BinEssence +open B2R2.MiddleEnd.ControlFlowAnalysis + +/// The `cfg` action. +type CFGAction () = + let output (fn: RegularFunction) = function + | Ok () -> + CFG.Init fn.MinAddr fn.IRCFG |> box + | Error e -> + ConsolePrinter.PrintErrorToConsole $"Failed to recover CFG: {e}" + NoCFG <| e.ToString () |> box + + let getCFG (input: obj) = + match input with + | :? Binary as bin -> + let hdl = Binary.Handle bin + let ess = BinEssence.empty hdl + let ep = hdl.File.EntryPoint |> Option.defaultValue 0UL + let fn = ess.CodeManager.FunctionMaintainer.GetOrAddFunction ep + let eAddr = uint64 hdl.File.Length - 1UL + let mode = hdl.Parser.OperationMode + let builder = CFGBuilder (hdl, ess.CodeManager, ess.JumpTables) + let evts = CFGEvents.empty + ess.CodeManager.ParseSequence hdl mode ep eAddr fn evts + |> Result.bind (fun evts -> + (builder :> ICFGBuildable).Update (evts, true) + |> Result.mapError (fun _ -> ErrorCase.FailedToRecoverCFG)) + |> output fn + | _ -> invalidArg (nameof input) "Invalid argument." + + interface IAction with + member __.ActionID with get() = "cfg" + member __.Signature with get() = "Binary -> CFG" + member __.Description with get() = """ + Take in a Binary as input and returns an IR-level Control Flow Graph (CFG) + as output. This action assumes that the given binary is well-formed, meaning + that it has no bad instructions, and the control does not flow in the middle + of an instruction. Any indirect branches will be simply ignored, i.e., it + does not perform any of the heavy analyses in our middle-end. +""" + member __.Transform _args collection = + { Values = collection.Values |> Array.map getCFG } diff --git a/src/RearEnd/Transformer/CountAction.fs b/src/RearEnd/Transformer/CountAction.fs new file mode 100644 index 00000000..e1f7b395 --- /dev/null +++ b/src/RearEnd/Transformer/CountAction.fs @@ -0,0 +1,56 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open B2R2 + +/// The `count` action. +type CountAction () = + let rec count (o: obj) = + let typ = o.GetType () + if typ.IsArray then countArrayResult o + elif typ = typeof then countBinary o + else Utils.futureFeature () + + and countArrayResult (o: obj) = + let arr = o :?> _[] + if Array.isEmpty arr then 0 else 1 + + and countBinary (o: obj) = + let bin = o :?> Binary + let hdl = Binary.Handle bin + hdl.File.Length + + interface IAction with + member __.ActionID with get() = "count" + member __.Signature with get() = "ObjCollection -> int" + member __.Description with get() = """ + Take in ObjCollection as input and returns how many objects are valid. This + action is useful when counting the number of results obtained from grep + action. +""" + member __.Transform _args collection = + { Values = [| collection.Values + |> Array.fold (fun acc v -> acc + count v) 0 |] } diff --git a/src/RearEnd/Transformer/DbscanAction.fs b/src/RearEnd/Transformer/DbscanAction.fs new file mode 100644 index 00000000..5e390130 --- /dev/null +++ b/src/RearEnd/Transformer/DbscanAction.fs @@ -0,0 +1,123 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open System.Collections.Generic + +[] +type DbscanStatus = + | Unvisited + | Visited + | Noise + +/// DBSCAN element. +type DbscanElement = { + mutable Status: DbscanStatus + Fingerprint: HashSet + ElementName: string +} +with + static member Init (fp: Fingerprint) = + { Status = Unvisited + Fingerprint = fp.Patterns |> List.map fst |> HashSet + ElementName = fp.Annotation } + +/// The `dbscan` action. +type DbscanAction () = + let buildDistanceCache (elms: DbscanElement[]) = + let cache = Array2D.zeroCreate elms.Length elms.Length + for i = 0 to elms.Length - 1 do + for j = i + 1 to elms.Length - 1 do + let e1, e2 = elms[i], elms[j] + let fp = HashSet e1.Fingerprint + fp.IntersectWith e2.Fingerprint + let overlap = (* overlap coefficient *) + float fp.Count / float (min e1.Fingerprint.Count e2.Fingerprint.Count) + let dist = 1.0 - overlap + cache.[i, j] <- dist + cache.[j, i] <- dist + cache + + let dist (cache: float[,]) i j = cache[i, j] + + let findNeighbors (cache: float[,]) i eps = + let neighbors = List () + for j = 0 to Array2D.length1 cache - 1 do + if dist cache i j <= eps then + neighbors.Add j |> ignore + else () + neighbors + + let cluster eps minpts (fingerprints: Fingerprint[]) = + let elms = fingerprints |> Array.map DbscanElement.Init + let cache = buildDistanceCache elms + let clusters = List () (* List> *) + for i in 0 .. (elms.Length - 1) do + if elms[i].Status <> Unvisited then () + else + let neighbors = findNeighbors cache i eps + if neighbors.Count < minpts then elms[i].Status <- Noise + else + let cluster = List () (* List *) + elms[i].Status <- Visited + cluster.Add elms[i].ElementName |> ignore + neighbors.Remove i |> ignore + while neighbors.Count > 0 do + let n = neighbors[0] + neighbors.RemoveAt 0 + if elms[n].Status = Noise then + elms[n].Status <- Visited + cluster.Add elms[n].ElementName |> ignore + elif elms[n].Status <> Unvisited then () + else + elms[n].Status <- Visited + cluster.Add elms[n].ElementName |> ignore + let newNeighbors = findNeighbors cache n eps + if newNeighbors.Count >= minpts then + neighbors.AddRange newNeighbors + else () + clusters.Add (cluster.ToArray ()) |> ignore + [| box { Clusters = clusters.ToArray () } |] + + interface IAction with + member __.ActionID with get() = "dbscan" + member __.Signature + with get() = "Fingerprint collection * [eps] * [minPts] -> Cluster array" + member __.Description with get() = """ + Take in an array of fingerprints and return an array of clustered + fingerprints. User may specify and as arguments. If not, we + use a default value of = 0.2 and = 3. +""" + member __.Transform args collection = + let eps, minPts = + match args with + | eps :: minPts :: [] -> Convert.ToDouble eps, Convert.ToInt32 minPts + | eps :: [] -> Convert.ToDouble eps, 3 + | [] -> 0.2, 3 + | _ -> invalidArg (nameof args) "Too many arguments given." + { Values = collection.Values + |> Array.map unbox + |> cluster eps minPts } \ No newline at end of file diff --git a/src/RearEnd/Transformer/DetectAction.fs b/src/RearEnd/Transformer/DetectAction.fs new file mode 100644 index 00000000..5e037b4b --- /dev/null +++ b/src/RearEnd/Transformer/DetectAction.fs @@ -0,0 +1,79 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open System.IO +open B2R2 + +/// The `detect` action. +type DetectAction () = + let resultToString (path: string, matchRate: float) = + [ (NoColor, $"{path}: {matchRate:F}") ] + |> OutputColored + |> box + + let detectFile fp path = + let bs = File.ReadAllBytes path + let span = ReadOnlySpan bs + let ngram = + Utils.buildNgram [] fp.NGramSize span 0 + |> Array.map fst + |> Set + let matchCnt = + fp.Patterns + |> List.fold (fun cnt pattern -> + let hash, _ = pattern + if ngram.Contains hash then cnt + 1 else cnt) 0 + path, (float matchCnt / float fp.Patterns.Length) + + let detectDir fp path = + Directory.GetFiles path + |> Array.map (detectFile fp) + |> Array.sortByDescending snd + |> Array.map resultToString + |> box + + let detect path input = + let fp = unbox input + if File.Exists path then detectFile fp path |> resultToString + elif Directory.Exists path then detectDir fp path + else invalidArg (nameof path) "File not found." + + interface IAction with + member __.ActionID with get() = "detect" + member __.Signature with get() = "Fingerprint * -> OutString" + member __.Description with get() = """ + Take in a fingerprint and a path as input, and analyze file(s) in the given + path to detect the fingerprint. This action will eventually return a match + score as output. If the is a directory, it analyzes every file in the + directory. If the is a file, it only analyzes the file. +""" + member __.Transform args collection = + let fps = collection.Values + match args with + | [ path ] -> { Values = fps |> Array.map (detect path) } + | [] -> invalidArg (nameof args) "A path should be given." + | _ -> invalidArg (nameof args) "Too many paths are given." diff --git a/src/RearEnd/Transformer/DiffAction.fs b/src/RearEnd/Transformer/DiffAction.fs new file mode 100755 index 00000000..be884d83 --- /dev/null +++ b/src/RearEnd/Transformer/DiffAction.fs @@ -0,0 +1,325 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open System.Collections.Generic +open B2R2 +open B2R2.RearEnd.Transformer.Utils + +type KVecDim = { + XOffsets: int[] + IdxForward: int + IdxBackward: int +} + +type OverlappedPosition = { + X: int + Y: int +} + +type Box = { + XOff: int + XLim: int + YOff: int + YLim: int +} + +type DiffData = { + LineNo: int[] + LineID: int[] + ChangedLineNumbers: bool[] + Len: int +} + +/// The `diff` action. +type DiffAction () = + let rec findUniqId lineNum cnt lines (dict: Dictionary<_, int>) = + if lineNum = Array.length lines then dict + else + let found, _ = dict.TryGetValue lines[lineNum] + if not found then + dict.Add (lines[lineNum], cnt) + findUniqId (lineNum + 1) (cnt + 1) lines dict + else + findUniqId (lineNum + 1) cnt lines dict + + let rec findChangedLines lineNum rchg lineToId (lines: _[]) = + if lineNum = -1 then + Array.ofList rchg + else + let found, _ = (lineToId: Dictionary<_, _>).TryGetValue lines[lineNum] + if found then + findChangedLines (lineNum - 1) (false :: rchg) lineToId lines + else + findChangedLines (lineNum - 1) (true :: rchg) lineToId lines + + let rec matchIndices n lineID rindex + (rchg: bool[]) (lineToId: Dictionary<_,int>) lines = + if n = Array.length lines then + lineID, rindex + elif rchg[n] then + matchIndices (n + 1) lineID rindex rchg lineToId lines + else + let lineID' = Array.append lineID [| lineToId[lines[n]] |] + let rindex' = Array.append rindex [| n |] + matchIndices (n + 1) lineID' rindex' rchg lineToId lines + + let rec findDiffstart n idA idB = + if n >= min (Array.length idA) (Array.length idB) then 0 + elif idA[n] <> idB[n] then n + else findDiffstart (n + 1) idA idB + + let rec findDiffend n idA idB = + if n >= min (Array.length idA) (Array.length idB) then 1 + elif idA[(Array.length idA - 1) - n] <> idB[(Array.length idB - 1) - n] then + n + else findDiffend (n + 1) idA idB + + let trim idA idB (lnumA: int[]) (lnumB: int[]) = + let diffStart = findDiffstart 0 idA idB + let diffEnd = findDiffend 0 idA idB + let idA' = idA[diffStart .. (Array.length idA - 1) - diffEnd] + let idB' = idB[diffStart .. (Array.length idB - 1) - diffEnd] + let lnumA' = lnumA[diffStart .. (Array.length lnumA - 1) - diffEnd] + let lnumB' = lnumB[diffStart .. (Array.length lnumB - 1) - diffEnd] + idA', idB', lnumA', lnumB' + + let prepareMyers linesA linesB = + let lineToIdA = Dictionary<_, int> () |> findUniqId 0 0 linesA + let lineToIdB = Dictionary<_, int> () |> findUniqId 0 0 linesB + let clnumA = findChangedLines (Array.length linesA - 1) [] lineToIdB linesA + let clnumB = findChangedLines (Array.length linesB - 1) [] lineToIdA linesB + let idA, lnumA = matchIndices 0 [||] [||] clnumA lineToIdA linesA + let idB, lnumB = matchIndices 0 [||] [||] clnumB lineToIdA linesB + let idA, idB, lnumA, lnumB = trim idA idB lnumA lnumB + { LineNo = lnumA + LineID = idA + ChangedLineNumbers = clnumA + Len = Array.length lnumA }, + { LineNo = lnumB + LineID = idB + ChangedLineNumbers = clnumB + Len = Array.length lnumB } + + /// Initialize the external K value + let adjustMin kvd idx min dmin value = + if min > dmin then + kvd.XOffsets[idx + (min - 1) - 1] <- value + min - 1 + else + min + 1 + + /// Initialize the external K value + let adjustMax kvd idx max dmax value = + if max < dmax then + kvd.XOffsets[idx + (max + 1) + 1] <- value + max + 1 + else + max - 1 + + let adjustBoundaryForward kvd min max dmin dmax = + let min' = adjustMin kvd kvd.IdxForward min dmin -1 + let max' = adjustMax kvd kvd.IdxForward max dmax -1 + min', max' + + let adjustBoundaryBackward kvd min max dmin dmax = + let min' = adjustMin kvd kvd.IdxBackward min dmin Int32.MaxValue + let max' = adjustMax kvd kvd.IdxBackward max dmax Int32.MaxValue + min', max' + + let rec takeSnakeForward x y boundX boundY (idA: int[]) (idB: int[]) = + if x < boundX && y < boundY && idA[x] = idB[y] then + takeSnakeForward (x + 1) (y + 1) boundX boundY idA idB + else x + + let rec takeSnakeBackward x y boundX boundY (idA: int[]) (idB: int[]) = + if x > boundX && y > boundY && idA[x - 1] = idB[y - 1] then + takeSnakeBackward (x - 1) (y - 1) boundX boundY idA idB + else x + + let rec traverseForward d fmin kvd idA idB box bmin bmax isOdd = + if d < fmin then None + else + let x = + if kvd.XOffsets[kvd.IdxForward + d - 1] + >= kvd.XOffsets[kvd.IdxForward + d + 1] then + kvd.XOffsets[kvd.IdxForward + d - 1] + 1 + else + kvd.XOffsets[kvd.IdxForward + d + 1] + let x = takeSnakeForward x (x - d) box.XLim box.YLim idA idB + kvd.XOffsets[kvd.IdxForward + d] <- x + if isOdd && bmin <= d && d <= bmax + && kvd.XOffsets[kvd.IdxBackward + d] <= x + then + Some { X = x; Y = x - d } + else + traverseForward (d - 2) fmin kvd idA idB box bmin bmax isOdd + + let rec traverseBackward d bmin kvd idA idB box fmin fmax isOdd = + if d < bmin then None + else + let x = + if kvd.XOffsets[kvd.IdxBackward + d - 1] + < kvd.XOffsets[kvd.IdxBackward + d + 1] + then + kvd.XOffsets[kvd.IdxBackward + d - 1] + else + kvd.XOffsets[kvd.IdxBackward + d + 1] - 1 + let x = takeSnakeBackward x (x - d) box.XOff box.YOff idA idB + kvd.XOffsets[kvd.IdxBackward + d] <- x + if not isOdd && fmin <= d && d <= fmax + && x <= kvd.XOffsets[kvd.IdxForward + d] then + Some { X = x; Y = x - d } + else + traverseBackward (d - 2) bmin kvd idA idB box fmin fmax isOdd + + let rec splitBox kvd idA idB box fmin fmax bmin bmax isOdd = + let dmin = box.XOff - box.YLim + let dmax = box.XLim - box.YOff + (* Forward *) + let fmin, fmax = adjustBoundaryForward kvd fmin fmax dmin dmax + let overlap1 = traverseForward fmax fmin kvd idA idB box bmin bmax isOdd + (* Backward *) + let bmin, bmax = adjustBoundaryBackward kvd bmin bmax dmin dmax + let overlap2 = traverseBackward bmax bmin kvd idA idB box fmin fmax isOdd + match (overlap1, overlap2) with + | (Some ov1, _) -> ov1 + | (_, Some ov2) -> ov2 + | (_, _) -> splitBox kvd idA idB box fmin fmax bmin bmax isOdd + + /// Shrink the box by walking through SW diagonal snake. + let rec walkThroughDiagonalSW (idA: int[]) (idB: int[]) off1 lim1 off2 lim2 = + if off1 < lim1 && off2 < lim2 && idA[off1] = idB[off2] then + walkThroughDiagonalSW idA idB (off1 + 1) lim1 (off2 + 1) lim2 + else + { XOff = off1; XLim = lim1; YOff = off2; YLim = lim2 } + + /// Shrink the box by walking through NE diagonal snake. + let rec walkThroughDiagonalNE (idA: int[]) (idB: int[]) off1 lim1 off2 lim2 = + if off1 < lim1 && off2 < lim2 && idA[lim1 - 1] = idB[lim2 - 1] then + walkThroughDiagonalNE idA idB off1 (lim1 - 1) off2 (lim2 - 1) + else + { XOff = off1; XLim = lim1; YOff = off2; YLim = lim2 } + + let rec markChangedLines dd off lim = + if off < lim then + dd.ChangedLineNumbers[dd.LineNo[off]] <- true + markChangedLines dd (off + 1) lim + else () + + let shrinkBox idA idB box = + let box' = walkThroughDiagonalSW idA idB box.XOff box.XLim box.YOff box.YLim + walkThroughDiagonalNE idA idB box'.XOff box'.XLim box'.YOff box'.YLim + + let rec cmpChangedLines kvd dd1 dd2 box = + (* Shrink the box by walking through each diagonal snake (SW and NE). *) + let box = shrinkBox dd1.LineID dd2.LineID box + if box.XOff = box.XLim then + markChangedLines dd2 box.YOff box.YLim + elif box.YOff = box.YLim then + markChangedLines dd1 box.XOff box.XLim + else + (* Divide *) + let fmid, bmid = box.XOff - box.YOff, box.XLim - box.YLim + let isOdd = (fmid - bmid) % 2 <> 0 + kvd.XOffsets[kvd.IdxForward + fmid] <- box.XOff + kvd.XOffsets[kvd.IdxBackward + bmid] <- box.XLim + let spl = splitBox kvd dd1.LineID dd2.LineID box fmid fmid bmid bmid isOdd + (* Conquer *) + { XOff = box.XOff; XLim = spl.X; YOff = box.YOff; YLim = spl.Y } + |> cmpChangedLines kvd dd1 dd2 + { XOff = spl.X; XLim = box.XLim; YOff = spl.Y; YLim = box.YLim } + |> cmpChangedLines kvd dd1 dd2 + + let myersDiff dd1 dd2 = + let nDiags = dd1.Len + dd2.Len + 3 + let kvd = + { XOffsets = Array.zeroCreate (2 * nDiags + 2); + IdxForward = dd2.Len + 1 + IdxBackward = dd2.Len + 1 + nDiags } + { XOff = 0; XLim = dd1.Len; YOff = 0; YLim = dd2.Len } + |> cmpChangedLines kvd dd1 dd2 + dd1.ChangedLineNumbers, dd2.ChangedLineNumbers + + let [] NumBytesPerLine = 16 + + let padSpace (arr: _[]) = + let len = arr.Length + let padLen = NumBytesPerLine - len % NumBytesPerLine + Array.concat [| arr + (Array.replicate (padLen - 1) (NoColor, " ")) + [| (NoColor, " ") |] |] + + let colorResult bs color res = + let hex = byteArrayToHexStringArray bs + Array.mapi2 (fun idx hex needColor -> + (if needColor then color else NoColor), + (if idx = bs.Length - 1 then hex else hex + " ") + ) hex res + |> padSpace + |> Array.chunkBySize NumBytesPerLine + + let equalizeLines lines1 lines2 = + let maxlines = max (Array.length lines1) (Array.length lines2) + let dummyLine = padSpace [| (NoColor, " ") |] + Array.append lines1 (Array.replicate (maxlines - lines1.Length) dummyLine), + Array.append lines2 (Array.replicate (maxlines - lines2.Length) dummyLine) + + let diff bin1 bin2 = + let hdl1, hdl2 = Binary.Handle bin1, Binary.Handle bin2 + let bs1, bs2 = hdl1.File.RawBytes, hdl2.File.RawBytes + let dd1, dd2 = prepareMyers bs1 bs2 + let res1, res2 = myersDiff dd1 dd2 + let res1, res2 = colorResult bs1 Red res1, colorResult bs2 Green res2 + let res1, res2 = equalizeLines res1 res2 + Array.mapi2 (fun lnum line1 line2 -> + let offsetStr = (lnum * NumBytesPerLine).ToString("x").PadLeft 8 + Array.concat [| [| (NoColor, offsetStr + " | ") |] + line1 + [| (NoColor, "| ") |] + line2 + [| (NoColor, Environment.NewLine) |] |]) res1 res2 + |> Array.concat + |> Array.toList + |> ColoredString.compile + |> OutputColored + + interface IAction with + member __.ActionID with get() = "diff" + member __.Signature with get() = "Binary collection -> OutString" + member __.Description with get() = """ + Take in two binaries as input and return a diff string as output. +""" + member __.Transform args collection = + let bins = collection.Values + if bins.Length <> 2 then + invalidArg (nameof DiffAction) "Can only diff extractly two binaries." + else + match args with + | [] -> + let outstr = diff (unbox bins[0]) (unbox bins[1]) + { Values = [| box outstr |] } + | _ -> invalidArg (nameof DiffAction) "Invalid input to diff" diff --git a/src/RearEnd/Transformer/DisasmAction.fs b/src/RearEnd/Transformer/DisasmAction.fs new file mode 100644 index 00000000..88ac2059 --- /dev/null +++ b/src/RearEnd/Transformer/DisasmAction.fs @@ -0,0 +1,66 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open B2R2 +open B2R2.FrontEnd +open B2R2.FrontEnd.BinFile + +/// The `disasm` action. +type DisasmAction () = + let rec disasm acc (hdl: BinHandle) ptr = + if BinFilePointer.IsValid ptr then + match hdl.TryParseInstr (ptr) with + | Ok instr -> + let insLen = int instr.Length + let insBytes = hdl.File.Slice(ptr.Addr, insLen).ToArray() + let ptr = BinFilePointer.Advance ptr insLen + let acc = ValidInstruction (instr, insBytes) :: acc + disasm acc hdl ptr + | Error _ -> + let badbyte = [| hdl.File.ReadByte ptr.Offset |] + let acc = BadInstruction (ptr.Addr, badbyte) :: acc + let ptr = BinFilePointer.Advance ptr 1 + disasm acc hdl ptr + else + List.rev acc |> List.toArray + + let disasmByteArray _args (o: obj) = + let bin = unbox o + let hdl = Binary.Handle bin + let baddr = hdl.File.BaseAddress + let ptr = BinFilePointer (baddr, 0, hdl.File.Length - 1) + disasm [] hdl ptr + |> box + + interface IAction with + member __.ActionID with get() = "disasm" + member __.Signature with get() = "Binary -> Instruction array" + member __.Description with get() = """ + Take in a binary and linearly disassemble the binary to return a list of + instructions along with its corresponding bytes. +""" + member __.Transform args collection = + { Values = collection.Values |> Array.map (disasmByteArray args) } diff --git a/src/MiddleEnd/ControlFlowGraph/DisasmCFG.fs b/src/RearEnd/Transformer/DotAction.fs similarity index 57% rename from src/MiddleEnd/ControlFlowGraph/DisasmCFG.fs rename to src/RearEnd/Transformer/DotAction.fs index 07bdb670..5a22fc7d 100644 --- a/src/MiddleEnd/ControlFlowGraph/DisasmCFG.fs +++ b/src/RearEnd/Transformer/DotAction.fs @@ -22,30 +22,35 @@ SOFTWARE. *) -namespace B2R2.MiddleEnd.ControlFlowGraph +namespace B2R2.RearEnd.Transformer +open B2R2 open B2R2.MiddleEnd.BinGraph open B2R2.MiddleEnd.ControlFlowGraph -/// Disassembly-based CFG, where each node contains disassembly code. -type DisasmCFG = ControlFlowGraph - -[] -module DisasmCFG = - let private initializer core = - DisasmCFG (core) :> DiGraph - - let private initImperative () = - ImperativeCore (initializer, UnknownEdge) - |> DisasmCFG - :> DiGraph - - let private initPersistent () = - PersistentCore (initializer, UnknownEdge) - |> DisasmCFG - :> DiGraph - - /// Initialize IRCFG based on the implementation type. - let init = function - | ImperativeGraph -> initImperative () - | PersistentGraph -> initPersistent () +/// The `dot` action. +type DOTAction () = + let vToStr (v: IVertex) = + let id = v.VData.FirstLifted.BBLAddr.ToString "x" + let instrs = + v.VData.ToArray () + |> Array.map (fun ins -> ins.Disasm (true, null)) + |> String.concat "\\l" + $"n_{id}", $"[label=\"{instrs}\\l\"]" + + let toDOT o = + match unbox o with + | CFG (addr, cfg) -> + let name = Addr.toFuncName addr + cfg.ToDOTStr (name, vToStr, (fun _ -> "")) + | NoCFG e -> $"Failed to construct CFG: {e}" + + interface IAction with + member __.ActionID with get() = "dot" + member __.Signature with get() = "CFG -> string" + member __.Description with get() = """ + Take in a CFG as input, and returns a string representation of the CFG in + DOT format. +""" + member __.Transform _args collection = + { Values = [| collection.Values |> Array.map toDOT |] } diff --git a/src/RearEnd/Transformer/EditAction.fs b/src/RearEnd/Transformer/EditAction.fs new file mode 100644 index 00000000..fd3438ed --- /dev/null +++ b/src/RearEnd/Transformer/EditAction.fs @@ -0,0 +1,129 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open B2R2 +open B2R2.FrontEnd + +/// The `edit` action. +type EditAction () = + let makeBinary bin (hdl: BinHandle) newbs = + let mode = hdl.Parser.OperationMode + let hdl' = lazy BinHandle (newbs, hdl.File.ISA, mode, None, false) + let annot = Binary.MakeAnnotation "Editted from " bin + Binary.Init annot hdl' + |> box + + let parseEndOffset soff (eoff: string) = + if eoff.StartsWith "+" then soff + Convert.ToInt32 eoff[1..] - 1 + else Convert.ToInt32 eoff + + let insert off (snip: byte[]) o = + let bin = unbox o + let hdl = Binary.Handle bin + let bs = hdl.File.RawBytes + let newbs = Array.zeroCreate (bs.Length + snip.Length) + if off > bs.Length then invalidArg (nameof off) "Offset is too large." + elif off = 0 then + Array.blit snip 0 newbs 0 snip.Length + Array.blit bs 0 newbs snip.Length bs.Length + else + Array.blit bs 0 newbs 0 off + Array.blit snip 0 newbs off snip.Length + Array.blit bs off newbs (off + snip.Length) (bs.Length - off) + makeBinary bin hdl newbs + + let delete soff eoff o = + let bin = unbox o + let hdl = Binary.Handle bin + let bs = hdl.File.RawBytes + let rmlen = eoff - soff + 1 + let newbs = Array.zeroCreate (bs.Length - rmlen) + if rmlen > bs.Length || eoff >= bs.Length || soff >= bs.Length || soff < 0 + then invalidArg (nameof soff) "Wrong offset(s) given." + elif soff = 0 then + Array.blit bs rmlen newbs 0 (bs.Length - rmlen) + else + Array.blit bs 0 newbs 0 soff + Array.blit bs (soff + rmlen) newbs soff (bs.Length - soff - rmlen) + makeBinary bin hdl newbs + + let replace soff eoff newbs o = + let bin = unbox o + let hdl = Binary.Handle bin + let bs = hdl.File.RawBytes + Array.blit newbs 0 bs soff (eoff - soff + 1) + makeBinary bin hdl newbs + + interface IAction with + member __.ActionID with get() = "edit" + member __.Signature + with get() = "Binary * -> Binary" + member __.Description with get() = """ + Take in a binary as well as edit action as input and return a modified + binary as output. There are following supported edit actions. + + - `insert` + Insert bytes, given as , at offset . This will increase + the size of the resulting binary by the size of the given hexstring. + + - `delete` + Remove bytes of size (m - n + 1) in the given binary located at . The + resulting binary will have the size less than the original one. + + - `delete` + + Remove bytes of size `sz` in the given binary located at . The + resulting binary will have the size less than the original one. + + - `replace` + Replace bytes at offset from to with the given . The + size of the hexstring should be equal to "m - n + 1" where m > n. + + - `replace` + + Replace bytes at offset from n to (n + sz - 1) with the given + . The size of the hexstring should be equal to sz. +""" + member __.Transform args collection = + match args with + | "insert" :: off :: hexstr :: [] -> + let off = Convert.ToInt32 off + let bs = ByteArray.ofHexString hexstr + { Values = collection.Values + |> Array.map (insert off bs) } + | "delete" :: soff :: eoff :: [] -> + let soff = Convert.ToInt32 soff + let eoff = parseEndOffset soff eoff + if eoff >= soff then + { Values = collection.Values |> Array.map (delete soff eoff) } + else invalidArg (nameof args) "Invalid offsets." + | "replace" :: soff :: eoff :: hexstr :: [] -> + let soff = Convert.ToInt32 soff + let eoff = parseEndOffset soff eoff + let newbs = ByteArray.ofHexString hexstr + if eoff >= soff && (eoff - soff + 1) = newbs.Length then + { Values = collection.Values |> Array.map (replace soff eoff newbs) } + else invalidArg (nameof args) "Invalid offsets or hexstring." + | _ -> invalidArg (nameof args) "Invalid edit action." diff --git a/src/RearEnd/Transformer/GrepAction.fs b/src/RearEnd/Transformer/GrepAction.fs new file mode 100755 index 00000000..7eea62ca --- /dev/null +++ b/src/RearEnd/Transformer/GrepAction.fs @@ -0,0 +1,93 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open System.Text.RegularExpressions +open B2R2 +open B2R2.FrontEnd +open B2R2.RearEnd.Transformer.Utils + +/// The `grep` action. +type GrepAction () = + let grepFromBinary (pattern: string) bytesBefore bytesAfter bin = + let hdl = Binary.Handle bin + let bs = hdl.File.RawBytes + let hs = byteArrayToHexStringArray bs |> String.concat "" + let regex = Regex (pattern.ToLowerInvariant ()) + regex.Matches hs + |> Seq.choose (fun m -> + if m.Index % 2 = 0 then Some (m.Index / 2, m.Length / 2) + else None) + |> Seq.toArray + |> Array.map (fun (i, len) -> + let soff = if (i - bytesBefore) < 0 then 0 else i - bytesBefore + let eoff = i + len - 1 + let eoff = if (eoff + bytesAfter) >= bs.Length then bs.Length - 1 + else eoff + bytesAfter + let isa, mode = hdl.File.ISA, hdl.Parser.OperationMode + lazy BinHandle (bs[soff .. eoff], isa, mode, Some (uint64 soff), false) + |> Binary.Init (Binary.MakeAnnotation "Greped from " bin)) + |> box + + let grep pattern bytesBefore bytesAfter (input: obj) = + match input with + | :? Binary as bin -> grepFromBinary pattern bytesBefore bytesAfter bin + | _ -> invalidArg (nameof input) "Invalid object is given." + + interface IAction with + member __.ActionID with get() = "grep" + member __.Signature + with get() = + "'a array * * [bytes before] * [bytes after] -> 'a array" + member __.Description with get() = """ + Take in an array as input and return one or more matched items from the + array as in the `grep` command. The represents a binary pattern + using a regular expression with hexstrings. For example, the pattern + "3031.." will match a three-byte sequence {{ 0x30, 0x31, * }}, where * means + any byte. Note that '.' means any 4-bit value in our regular expression. + Similarly, the pattern "(30)+" means a sequence of 0x30s of any length, + e.g., {{ 0x30, 0x30, 0x30, 0x30, 0x30 }} will match the pattern. + + Two optional arguments [bytes before] and [bytes after] can be given to get + the context of the matched items. For example, if [bytes before] is 2 and + [bytes after] is 1, then the matched items will be surrounded by two bytes + before and one line after. If the matched items are at the beginning or end + of the array, the context will be truncated accordingly. +""" + member __.Transform args collection = + match args with + | pattern :: bytesBefore :: bytesAfter :: [] -> + let bytesBefore = Convert.ToInt32 bytesBefore + let bytesAfter = Convert.ToInt32 bytesAfter + { Values = collection.Values + |> Array.map (grep pattern bytesBefore bytesAfter) } + | pattern :: bytesBefore :: [] -> + let bytesBefore = Convert.ToInt32 bytesBefore + { Values = collection.Values + |> Array.map (grep pattern bytesBefore 0) } + | [ pattern ] -> + { Values = collection.Values |> Array.map (grep pattern 0 0) } + | _ -> invalidArg (nameof args) "Single pattern should be given." diff --git a/src/FrontEnd/BinLifter/ARM32/ARM32.fs b/src/RearEnd/Transformer/HexdumpAction.fs similarity index 55% rename from src/FrontEnd/BinLifter/ARM32/ARM32.fs rename to src/RearEnd/Transformer/HexdumpAction.fs index 4cc92c73..a014db1a 100644 --- a/src/FrontEnd/BinLifter/ARM32/ARM32.fs +++ b/src/RearEnd/Transformer/HexdumpAction.fs @@ -22,28 +22,34 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.ARM32 +namespace B2R2.RearEnd.Transformer open B2R2 -open B2R2.FrontEnd.BinLifter - -/// Translation context for 32-bit ARM instructions (ARMv7 and ARMv8 AARCH32). -type ARM32TranslationContext internal (isa, regexprs) = - inherit TranslationContext (isa) - member val private RegExprs: RegExprs = regexprs - override __.GetRegVar id = Register.ofRegID id |> __.RegExprs.GetRegVar - override __.GetPseudoRegVar _id _pos = Utils.futureFeature () - -module Basis = - let init isa = - let regexprs = RegExprs () - struct ( - ARM32TranslationContext (isa, regexprs) :> TranslationContext, - ARM32RegisterBay (regexprs) :> RegisterBay - ) - - let initRegBay () = - let regexprs = RegExprs () - ARM32RegisterBay (regexprs) :> RegisterBay - -// vim: set tw=80 sts=2 sw=2: +open B2R2.RearEnd + +/// The `hexdump` action. +type HexdumpAction () = + let rec hexdump (o: obj) = + let typ = o.GetType () + if typ = typeof then hexdumpBinary o + else invalidArg (nameof o) "Invalid input type." + + and hexdumpBinary o = + let bin = unbox o + let hdl = Binary.Handle bin + let bs = hdl.File.RawBytes + let baseAddr = hdl.File.BaseAddress + HexDumper.dump 16 hdl.File.ISA.WordSize true baseAddr bs + |> box + + interface IAction with + member __.ActionID with get() = "hexdump" + member __.Signature with get() = "Binary -> string" + member __.Description with get() = """ + Take in a binary and convert it to a hexdump string. +""" + member __.Transform args collection = + match args with + | [] -> + { Values = collection.Values |> Array.map hexdump } + | _ -> invalidArg (nameof args) "Invalid argument given." diff --git a/src/RearEnd/Transformer/IAction.fs b/src/RearEnd/Transformer/IAction.fs new file mode 100644 index 00000000..2932e121 --- /dev/null +++ b/src/RearEnd/Transformer/IAction.fs @@ -0,0 +1,39 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +/// The interface for a transforming action. +type IAction = + /// Action command ID. + abstract member ActionID: string + + /// Signature string. + abstract member Signature: string + + /// Description about this action. + abstract member Description: string + + /// Transform the input object collection to the output object collction. + abstract member Transform: string list -> ObjCollection -> ObjCollection \ No newline at end of file diff --git a/src/RearEnd/Transformer/JaccardAction.fs b/src/RearEnd/Transformer/JaccardAction.fs new file mode 100644 index 00000000..597cd947 --- /dev/null +++ b/src/RearEnd/Transformer/JaccardAction.fs @@ -0,0 +1,48 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +/// The `jaccard` action. +type JaccardAction () = + let jaccard fp0 fp1 = + match unbox fp0, unbox fp1 with + | fp0, fp1 -> + let s0 = List.fold (fun s (v, _) -> Set.add v s) Set.empty fp0.Patterns + let s1 = List.fold (fun s (v, _) -> Set.add v s) Set.empty fp1.Patterns + float (Set.intersect s0 s1 |> Set.count) + / float (Set.union s0 s1 |> Set.count) + + interface IAction with + member __.ActionID with get() = "jaccard" + member __.Signature with get() = "Fingerprint collection -> int" + member __.Description with get() = """ + Take in two fingerprints and returns the jaccard index between them. +""" + member __.Transform args collection = + if args.Length <> 0 then + invalidArg (nameof args) "No arguments should be given." + elif collection.Values.Length = 2 then + { Values = [| jaccard collection.Values[0] collection.Values[1] |] } + else invalidArg (nameof collection) "Two fingerprints should be given." diff --git a/src/RearEnd/Transformer/LLVMAction.fs b/src/RearEnd/Transformer/LLVMAction.fs new file mode 100644 index 00000000..2ac433b2 --- /dev/null +++ b/src/RearEnd/Transformer/LLVMAction.fs @@ -0,0 +1,76 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open B2R2 +open B2R2.MiddleEnd.BinEssence +open B2R2.MiddleEnd.ControlFlowAnalysis +open B2R2.MiddleEnd.LLVM + +/// The `llvm` action. +type LLVMAction () = + let printOut hdl (fn: RegularFunction) = function + | Ok () -> + let builder = LLVMTranslator.createBuilder hdl fn.MinAddr + fn.IRCFG.IterVertex (fun bbl -> + let succs = + fn.IRCFG.GetSuccs bbl + |> Seq.toList + |> List.map (fun s -> s.VData.PPoint.Address) + let bblAddr = bbl.VData.PPoint.Address + bbl.VData.IRStatements + |> Array.concat + |> LLVMTranslator.translate builder bblAddr succs + ) + builder.ToString () + | Error e -> e.ToString () + + let translate (o: obj) = + let bin = unbox o + let hdl = Binary.Handle bin + let ess = BinEssence.empty hdl + let ep = hdl.File.EntryPoint |> Option.defaultValue 0UL + let fn = ess.CodeManager.FunctionMaintainer.GetOrAddFunction ep + let eAddr = uint64 hdl.File.Length - 1UL + let mode = hdl.Parser.OperationMode + let builder = CFGBuilder (hdl, ess.CodeManager, ess.JumpTables) + let evts = CFGEvents.empty + ess.CodeManager.ParseSequence hdl mode ep eAddr fn evts + |> Result.bind (fun evts -> + (builder :> ICFGBuildable).Update (evts, true) + |> Result.mapError (fun _ -> ErrorCase.FailedToRecoverCFG)) + |> printOut hdl fn + + interface IAction with + member __.ActionID with get() = "llvm" + member __.Signature with get() = "Binary -> string" + member __.Description with get() = """ + Take in a parsed binary and lift it to an LLVM function, and then dump the + lifted function to a string. +""" + member __.Transform args collection = + match args with + | [] -> { Values = [| collection.Values |> Array.map translate |] } + | _ -> invalidArg (nameof args) "Invalid argument." diff --git a/src/RearEnd/Transformer/LiftAction.fs b/src/RearEnd/Transformer/LiftAction.fs new file mode 100644 index 00000000..2216e021 --- /dev/null +++ b/src/RearEnd/Transformer/LiftAction.fs @@ -0,0 +1,63 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System.Text +open B2R2 +open B2R2.BinIR.LowUIR +open B2R2.FrontEnd +open B2R2.FrontEnd.BinFile + +/// The `lift` action. +type LiftAction () = + let rec lift (sb: StringBuilder) (hdl: BinHandle) ptr = + if BinFilePointer.IsValid ptr then + match hdl.TryParseInstr (ptr) with + | Ok instr -> + let s = instr.Translate hdl.TranslationContext |> Pp.stmtsToString + let ptr = BinFilePointer.Advance ptr (int instr.Length) + lift (sb.Append s) hdl ptr + | Error _ -> "Bad instruction found" + else + sb.ToString () + + let liftByteArray (o: obj) = + let bin = unbox o + let hdl = Binary.Handle bin + let baddr = hdl.File.BaseAddress + let ptr = BinFilePointer (baddr, 0, hdl.File.Length - 1) + let sb = StringBuilder () + lift sb hdl ptr + |> box + + interface IAction with + member __.ActionID with get() = "lift" + member __.Signature with get() = "Binary -> string" + member __.Description with get() = """ + Take in a binary and linearly disassemble the binary and lift it to a + sequence of LowUIR statements, and dump the result to a string. +""" + member __.Transform args collection = + { Values = collection.Values |> Array.map liftByteArray } diff --git a/src/RearEnd/Transformer/ListAction.fs b/src/RearEnd/Transformer/ListAction.fs new file mode 100644 index 00000000..17b3ca94 --- /dev/null +++ b/src/RearEnd/Transformer/ListAction.fs @@ -0,0 +1,52 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open B2R2.FrontEnd + +/// The `list` action. +type ListAction () = + let listSections (input: obj) = + let bin = unbox input + let hdl = Binary.Handle bin + hdl.File.GetSections () + |> Seq.toArray + |> box + + interface IAction with + member __.ActionID with get() = "list" + member __.Signature with get() = "Binary * [cmd] -> unit" + member __.Description with get() = """ + Take in a parsed binary and return a list of elements such as functions, + sections, etc. The output type is determined by the extra [cmd] argument. + Currently, we support the following [cmd]: + + - `sections` (sects|ss): returns a list of sections. +""" + member __.Transform args collection = + match args with + | [ "sections" ] | [ "sects" ] | [ "ss" ] -> + { Values = collection.Values |> Array.map listSections } + | _ -> invalidArg (nameof args) "Invalid argument." diff --git a/src/RearEnd/Transformer/LoadAction.fs b/src/RearEnd/Transformer/LoadAction.fs new file mode 100644 index 00000000..00e2816a --- /dev/null +++ b/src/RearEnd/Transformer/LoadAction.fs @@ -0,0 +1,82 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System.IO +open B2R2 +open B2R2.FrontEnd + +/// The `load` action. +type LoadAction () = + let load isa mode parseFileFormat s = + if File.Exists (path=s) then + lazy BinHandle (s, isa, mode, None) + |> Binary.PlainInit + |> box + |> Array.singleton + elif Directory.Exists (path=s) then + Directory.GetFiles s + |> Array.map (fun f -> + lazy BinHandle (f, isa, mode, None) + |> Binary.PlainInit |> box) + else + lazy BinHandle (ByteArray.ofHexString s, isa, mode, None, false) + |> Binary.PlainInit + |> box + |> Array.singleton + + interface IAction with + member __.ActionID with get() = "load" + member __.Signature + with get() = "unit * * [isa] * [mode]: string -> Binary" + member __.Description with get() = """ + Take in a string and return a binary object. The given input string + can either represent a file path or a hexstring. If the given string + represents a valid file path, then the raw file content will be loaded. + If the given string is a valid directory path, then every file in the + directory will be loaded in bulk. Otherwise, we consider the input string as + a hexstring, and return the corresponding binary. + + - [isa] : parse the binary for the given ISA. + - [mode]: parse the binary for the given operation mode. +""" + member __.Transform args collection = + if collection.Values |> Array.forall isNull then () + else invalidArg (nameof collection) "Invalid argument type." + match args with + | s :: isa :: mode :: "raw" :: [] -> + let isa = ISA.OfString isa + let mode = ArchOperationMode.ofString mode + { Values = load isa mode false s } + | s :: isa :: mode :: [] -> + let isa = ISA.OfString isa + let mode = ArchOperationMode.ofString mode + { Values = load isa mode true s } + | s :: isa :: [] -> + let isa = ISA.OfString isa + { Values = load isa ArchOperationMode.NoMode true s } + | s :: [] -> + { Values = load ISA.DefaultISA ArchOperationMode.NoMode true s } + | _ -> invalidArg (nameof args) "Invalid arguments given." diff --git a/src/RearEnd/Transformer/PrintAction.fs b/src/RearEnd/Transformer/PrintAction.fs new file mode 100644 index 00000000..e17c911b --- /dev/null +++ b/src/RearEnd/Transformer/PrintAction.fs @@ -0,0 +1,72 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open FSharp.Reflection +open B2R2 + +/// The `print` action. +type PrintAction () = + let rec print (o: obj) = + let typ = o.GetType () + if typ = typeof then printObjCollection o + elif typ = typeof then printClusterResult o + elif typ.IsArray then printArray o + elif FSharpType.IsUnion typ + && typ.BaseType = typeof then printOutString o + else Printer.PrintToConsoleLine (o.ToString ()) + + and printObjCollection (o: obj) = + let res = o :?> ObjCollection + res.Values + |> Array.iteri (fun idx v -> + Printer.PrintToConsoleLine $"[*] result({idx})" + print v) + + and printClusterResult (o: obj) = + let res = o :?> ClusterResult + res.Clusters + |> Array.iteri (fun idx cluster -> + cluster + |> Array.iter (fun elem -> + Printer.PrintToConsoleLine $" - Cluster({idx}): {elem}")) + + and printArray (o: obj) = + let arr = o :?> _[] + arr |> Array.iter print + + and printOutString (o: obj) = + let os = o :?> OutString + Printer.PrintToConsoleLine os + + interface IAction with + member __.ActionID with get() = "print" + member __.Signature with get() = "'a -> unit" + member __.Description with get() = """ + Take in an input object and print out its value. +""" + member __.Transform _args o = + print (box o) + { Values = [||] } \ No newline at end of file diff --git a/src/RearEnd/Transformer/Program.fs b/src/RearEnd/Transformer/Program.fs new file mode 100644 index 00000000..a2b09b53 --- /dev/null +++ b/src/RearEnd/Transformer/Program.fs @@ -0,0 +1,197 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +module B2R2.RearEnd.Transformer.Program + +open System +open System.IO +open System.Reflection +open B2R2 +open B2R2.RearEnd + +let [] private Usage = """[Usage] + +b2r2 transformer [-d file] [action] (-- [action] ...) + +Transformer runs a chain of transforming actions (IAction). An action takes in a +collection of objects as input and returns another collection of objects as +output. Any number of actions can be chained together as long as their types +match. Users can define their own action(s) by implementing the IAction +interface. + +[Options] + +-d : Load a dll file defining custom actions. + +[Actions] +""" + +/// The `help` action. +type private HelpAction (map: Map) = + interface IAction with + member __.ActionID with get() = "help" + member __.Signature with get() = "'a -> 'b" + member __.Description with get() = "" + member __.Transform _args _ = + Printer.PrintToConsoleLine () + CmdOpts.WriteIntro () + Printer.PrintToConsoleLine Usage + map |> Map.iter (fun id act -> + Printer.PrintToConsoleLine $"- {id}: {act.Signature}" + Printer.PrintToConsoleLine $"{act.Description}") + exit 0 + +let private accumulateActions map actions = + actions + |> Array.fold (fun map t -> + let act = Activator.CreateInstance t :?> IAction + if Map.containsKey act.ActionID map then + invalidOp $"Duplicate action ID: {act.ActionID}" + else + Map.add act.ActionID act map) map + +let inline private filterIActionType types = + (types: System.Type[]) + |> Array.filter (fun t -> + t.IsPublic + && (t.GetInterface (nameof IAction) |> isNull |> not)) + +let private loadUserDLL dllPath = + if File.Exists dllPath then + let dllPath = Path.GetFullPath dllPath + let dll = Assembly.LoadFile dllPath + dll.GetExportedTypes () + |> filterIActionType + |> accumulateActions Map.empty + else invalidOp $"File not found: {dllPath}" + +let private retrieveActionMap map = + let actionType = typeof + let map = + actionType.Assembly.GetExportedTypes () + |> filterIActionType + |> accumulateActions map + let helpAction = HelpAction map :> IAction + Map.add helpAction.ActionID helpAction map + +let private splitBySpecialSeparators (args: string list) = + args + |> List.collect (fun arg -> + arg.Replace("--", " -- ") + .Replace(",", " , ") + .Split (' ', StringSplitOptions.RemoveEmptyEntries) |> Array.toList) + +let rec private breakCommandByComma cmds cmd = function + | [] -> List.rev (List.rev cmd :: cmds) + | "," :: rest -> + let cmds = if List.isEmpty cmd then cmds else (List.rev cmd) :: cmds + breakCommandByComma cmds [] rest + | arg :: rest -> breakCommandByComma cmds (arg :: cmd) rest + +let private accumulateIfNotEmpty grp acc = + if List.isEmpty grp then acc + else List.rev grp :: acc + +let rec private parseActionCommands grps grp = function + | [] -> List.rev (accumulateIfNotEmpty grp grps) + | "--" :: rest -> + let grps = + if List.isEmpty grp then grps else accumulateIfNotEmpty grp grps + parseActionCommands grps [] rest + | arg :: rest -> parseActionCommands grps (arg :: grp) rest + +let private checkValidityOfCommandGroup cmdgrp = + let actionIDs = cmdgrp |> List.map List.tryHead + let fstActionID = List.head actionIDs + if actionIDs |> List.forall (fun actionID -> actionID = fstActionID) then () + else + Printer.PrintErrorToConsole "different actions in the same group." + exit 1 + +let private runCommand actionMap input (cmd: string list) = + let actionID = List.head cmd + let args = List.tail cmd + let action: IAction = + match Map.tryFind (actionID.ToLowerInvariant ()) actionMap with + | Some act -> act + | None -> + Printer.PrintErrorToConsole $"({actionID}) is not a valid action." + exit 1 +#if DEBUG + if actionID <> "help" then Printer.PrintToConsoleLine $"[*] {actionID}" + else () +#endif + try + action.Transform args input + with + | :? InvalidCastException -> + Printer.PrintErrorToConsole $"({actionID}) action type mismatch." + exit 1 + | :? NullReferenceException -> + Printer.PrintErrorToConsole $"({actionID}) action should follow another." + exit 1 + | :? ArgumentException as e -> + Printer.PrintErrorToConsole $"{e.Message}" + exit 1 + | e -> + Printer.PrintErrorToConsole $"({actionID}): {e}" + exit 1 + +let inline private unwrap (c: ObjCollection) = c.Values + +let autoPrint actionMap collection = + if collection.Values.Length = 0 then () + else runCommand actionMap collection [ "print" ] |> ignore + +let private parseActions args actionMap = + args + |> splitBySpecialSeparators + |> parseActionCommands [] [] + |> List.map (breakCommandByComma [] []) + |> List.fold (fun input cmdgrp -> + checkValidityOfCommandGroup cmdgrp + { Values = + cmdgrp + |> List.map (fun cmd -> runCommand actionMap input cmd |> unwrap) + |> Array.concat } + ) { Values = [| () |] } + |> autoPrint actionMap + +[] +let main argv = + match List.ofArray argv with + | [] -> + retrieveActionMap Map.empty + |> parseActions [ "help" ] + |> ignore + | "-d" :: file :: args -> + loadUserDLL file + |> retrieveActionMap + |> parseActions args + |> ignore + | args -> + retrieveActionMap Map.empty + |> parseActions args + |> ignore + 0 \ No newline at end of file diff --git a/src/RearEnd/Transformer/SliceAction.fs b/src/RearEnd/Transformer/SliceAction.fs new file mode 100644 index 00000000..68a27394 --- /dev/null +++ b/src/RearEnd/Transformer/SliceAction.fs @@ -0,0 +1,88 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open B2R2 +open B2R2.FrontEnd + +/// The `slice` action. +type SliceAction () = + let sliceByAddrRange bin a1 a2 = + let hdl = Binary.Handle bin + if a1 > a2 then invalidArg (nameof bin) "Invalid address range." + elif not (hdl.File.IsInFileAddr a1) + || not (hdl.File.IsInFileAddr a2) then + invalidArg (nameof hdl) "Address out of range." + else + let bs = hdl.File.Slice(a1, int (a2 - a1 + 1UL)).ToArray () + let isa, mode = hdl.File.ISA, hdl.Parser.OperationMode + lazy BinHandle (bs, isa, mode, None, false) + |> Binary.Init (Binary.MakeAnnotation "Sliced from " bin) + + let sliceBySectionName bin secName = + let hdl = Binary.Handle bin + let sec = hdl.File.GetSections (name=secName) |> Seq.exactlyOne + let a1 = sec.Address + let a2 = a1 + uint64 sec.Size - 1UL + sliceByAddrRange bin a1 a2 + + let parseTwoArgs (a1: string) (a2: string) = + let a1 = Convert.ToUInt64 (a1, 16) + let a2 = + if a2.StartsWith '+' then + let numBase = if a2.StartsWith "+0x" then 16 else 10 + a1 + Convert.ToUInt64 (a2[1..], numBase) - 1UL + else Convert.ToUInt64 (a2, 16) + a1, a2 + + let sliceBin args bin = + match args with + | a1 :: a2 :: [] -> + let a1, a2 = parseTwoArgs a1 a2 + sliceByAddrRange bin a1 a2 |> box + | secName :: [] -> + sliceBySectionName bin secName |> box + | _ -> invalidArg (nameof args) "Invalid argument." + + let slice args (input: obj) = + match input with + | :? Binary as bin -> sliceBin args bin + | _ -> invalidArg (nameof input) "Invalid input type." + + interface IAction with + member __.ActionID with get() = "slice" + member __.Signature with get() = "Binary * [optional arg(s)] -> Binary" + member __.Description with get() = """ + Take in a byte array or a BinHandle and return a byte array of a part of the + binary along with its starting address. Users can specify a specific address + range or a section name as argument(s), which are listed below. + + - : returns a slice of the bianry from to . + - +: returns a slice of the bianry from to . + - : returns a slice of the binary of the section . +""" + member __.Transform args collection = + { Values = collection.Values |> Array.map (slice args) } diff --git a/src/RearEnd/Transformer/Types.fs b/src/RearEnd/Transformer/Types.fs new file mode 100644 index 00000000..33c0ec47 --- /dev/null +++ b/src/RearEnd/Transformer/Types.fs @@ -0,0 +1,123 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open System.Text +open B2R2 +open B2R2.FrontEnd +open B2R2.MiddleEnd.ControlFlowGraph +open type FileFormat + +/// Binary is the main data object representing a byte sequence tagged with +/// some useful information. +type Binary = Binary of Lazy * annotation: string +with + static member Init annot hdl = Binary (hdl, annot) + + static member PlainInit hdl = Binary (hdl, "") + + static member Handle bin = + match bin with + | Binary (hdl, _) -> hdl.Value + + static member Annotation bin = + match bin with + | Binary (_, annot) -> annot + + static member MakeAnnotation prefix bin = + match bin with + | Binary (hdl, annot) -> + let path = hdl.Value.File.Path + if String.IsNullOrEmpty path then annot + else $"{prefix}{path}" + + override __.ToString () = + match __ with + | Binary (hdl, annot) when hdl.Value.File.Format = RawBinary -> + let hdl = hdl.Value + let s = Utils.makeByteArraySummary hdl.File.RawBytes + if String.IsNullOrEmpty annot then + $"Binary(Raw) | 0x{hdl.File.BaseAddress:x8} | {s}" + else + $"Binary(Raw) | 0x{hdl.File.BaseAddress:x8} | {s} | {annot}" + | Binary (hdl, annot) -> + let hdl = hdl.Value + let file = hdl.File + let s = Utils.makeByteArraySummary file.RawBytes + let fmt = FileFormat.toString hdl.File.Format + let path = file.Path + let finfo = if String.IsNullOrEmpty path then "" else $", {path}" + if String.IsNullOrEmpty annot then + $"Binary({fmt}{finfo}) | 0x{file.BaseAddress:x8} | {s}" + else + $"Binary({fmt}{finfo}) | 0x{file.BaseAddress:x8} | {s} | {annot}" + +/// Instruction tagged with its corresponding bytes. +type Instruction = + | ValidInstruction of FrontEnd.BinLifter.Instruction * byte[] + | BadInstruction of Addr * byte[] +with + override __.ToString () = + match __ with + | ValidInstruction (ins, bs) -> + let bs = Utils.makeByteArraySummary bs + $"{ins.Address:x16} | {bs.PadRight 48} | {ins.Disasm ()}" + | BadInstruction (addr, bs) -> + let bs = Utils.makeByteArraySummary bs + $"{addr:x16} | {bs.PadRight 32} | (bad)" + +/// Fingerprint of a binary, which is a list of (hash * byte position) tuple. +type Fingerprint = { + Patterns: (int * int) list + NGramSize: int + WindowSize: int + Annotation: string +} +with + override __.ToString () = + let sb = StringBuilder () + sb.Append $"({__.Annotation}){Environment.NewLine}" |> ignore + __.Patterns + |> List.iter (fun (b, p) -> + sb.Append $"{b:x2}@{p}{Environment.NewLine}" |> ignore) + sb.ToString () + +/// CFG of a function. +type CFG = + | CFG of addr: Addr * ir: IRCFG + | NoCFG of err: string (* Error message describing the reason for failure. *) +with + static member Init addr ir = CFG (addr, ir) + +/// Collection of objects. +type ObjCollection = { + Values: obj array +} + +/// Clustering result. +type ClusterResult = { + Clusters: string array array +} diff --git a/src/FrontEnd/BinLifter/CIL/CILRegisterSet.fs b/src/RearEnd/Transformer/Utils.fs similarity index 59% rename from src/FrontEnd/BinLifter/CIL/CILRegisterSet.fs rename to src/RearEnd/Transformer/Utils.fs index 5de63c6f..5c2a1b53 100644 --- a/src/FrontEnd/BinLifter/CIL/CILRegisterSet.fs +++ b/src/RearEnd/Transformer/Utils.fs @@ -22,31 +22,35 @@ SOFTWARE. *) -namespace B2R2.FrontEnd.BinLifter.CIL +module B2R2.RearEnd.Transformer.Utils +open System +open System.IO.Hashing open B2R2 -type CILRegisterSet (bitArray: uint64 [], s: Set) = - inherit NonEmptyRegisterSet (bitArray, s) - - new () = CILRegisterSet (RegisterSet.MakeInternalBitArray 2, Set.empty) - - override __.Tag = RegisterSetTag.CIL - - override __.ArrSize = 2 - - override __.New arr s = new CILRegisterSet (arr, s) :> RegisterSet - - override __.RegIDToIndex rid = - Register.ofRegID rid |> int - - override __.IndexToRegID index = - LanguagePrimitives.Int32WithMeasure index - - override __.ToString () = - sprintf "CILReisterSet<%x, %x>" __.BitArray[0] __.BitArray[1] - -[] -module CILRegisterSet = - let singleton rid = CILRegisterSet().Add(rid) - let empty = CILRegisterSet () :> RegisterSet +let [] MaxByteShow = 14 + +let byteArrayToHexStringArray (bs: byte[]) = + bs |> Array.map (sprintf "%02x") + +let makeSpanSummary (bs: ByteSpan) = + if bs.Length > MaxByteShow then + let s = + bs.Slice(0, MaxByteShow).ToArray () + |> Array.map (sprintf "%02x") + |> String.concat " " + s + " ..." + else + bs.ToArray () + |> Array.map (sprintf "%02x") + |> String.concat " " + +let makeByteArraySummary (bs: byte[]) = + makeSpanSummary (ReadOnlySpan bs) + +let rec buildNgram acc n (span: ByteSpan) idx = + if idx <= span.Length - n then + let bs = span.Slice(idx, n).ToArray () + let h = XxHash32.Hash bs |> BitConverter.ToInt32 + buildNgram ((h, idx) :: acc) n span (idx + 1) + else List.rev acc |> List.toArray diff --git a/src/RearEnd/Transformer/WinnowingAction.fs b/src/RearEnd/Transformer/WinnowingAction.fs new file mode 100644 index 00000000..56951361 --- /dev/null +++ b/src/RearEnd/Transformer/WinnowingAction.fs @@ -0,0 +1,83 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System +open B2R2 + +/// The `winnowing` action. +type WinnowingAction () = + let rec min (span: Span) (minHash, minPos) idx = + if idx < span.Length then + let curHash, curPos = span[idx] + let minHash, minPos = + if minHash > curHash then curHash, curPos + elif minHash = curHash && minPos < curPos then curHash, curPos + else minHash, minPos + min span (minHash, minPos) (idx + 1) + else (minHash, minPos) + + let rec computeFingerprint acc annot prev n wsz idx (ngrams: (int * int)[]) = + if idx <= ngrams.Length - wsz then + let span = ngrams.AsSpan (idx, wsz) + let m = min span (Int32.MaxValue, Int32.MaxValue) 0 + if fst prev = fst m then + computeFingerprint acc annot prev n wsz (idx + 1) ngrams + else + computeFingerprint (m :: acc) annot m n wsz (idx + 1) ngrams + else { Patterns = List.rev acc + NGramSize = n + WindowSize = wsz + Annotation = annot } + + let winnowing n wsz input = + let bin = unbox input + let hdl = Binary.Handle bin + let annot = Binary.MakeAnnotation "Winnowing from " bin + let span = ReadOnlySpan hdl.File.RawBytes + if span.Length < n + wsz then + invalidArg (nameof input) "The input binary is too small." + else + Utils.buildNgram [] n span 0 + |> computeFingerprint [] annot (0, 0) n wsz 0 + |> box + + interface IAction with + member __.ActionID with get() = "winnowing" + member __.Signature with get() = "Binary * [n] * [wsz] -> Fingerprint" + member __.Description with get() = """ + Take in an input binary and returns its fingerprint, which is essentially a + list of (hash * byte position) tuples. + + - [n] : Size of n-gram. The default is 4. + - [w] : Window size. The default is 4. +""" + member __.Transform args collection = + let n, wsz = + match args with + | [] -> 4, 4 + | n :: w :: [] -> Convert.ToInt32 n, Convert.ToInt32 w + | _ -> invalidArg (nameof args) "Two many arguments given." + { Values = collection.Values |> Array.map (winnowing n wsz) } diff --git a/src/RearEnd/Transformer/WriteAction.fs b/src/RearEnd/Transformer/WriteAction.fs new file mode 100644 index 00000000..ac3fbcf1 --- /dev/null +++ b/src/RearEnd/Transformer/WriteAction.fs @@ -0,0 +1,62 @@ +(* + B2R2 - the Next-Generation Reversing Platform + + Copyright (c) SoftSec Lab. @ KAIST, since 2016 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*) + +namespace B2R2.RearEnd.Transformer + +open System.IO +open B2R2 + +/// The `write` action. +type WriteAction () = + let rec write fname (o: obj) = + match o with + | :? Binary as bin -> writeBinary fname bin + | :? OutString as os -> writeOutString fname os + | _ -> File.WriteAllText (fname, o.ToString ()) + + and writeBinary fname bin = + let hdl = Binary.Handle bin + File.WriteAllBytes (fname, hdl.File.RawBytes) + + and writeOutString fname os = + File.WriteAllText (fname, OutString.toString os) + + interface IAction with + member __.ActionID with get() = "write" + member __.Signature + with get() = "'a * -> unit" + member __.Description with get() = """ + Take in an input object and write out its content to the . +""" + member __.Transform args collection = + if args.Length = collection.Values.Length then + let args = List.toArray args + Array.iter2 write args collection.Values + { Values = [||] } + elif args.Length = 1 then + let fname = List.head args + let fnames = collection.Values |> Array.mapi (fun i _ -> $"{fname}.{i}") + Array.iter2 write fnames collection.Values + { Values = [||] } + else invalidArg (nameof args) "Input lengths mismatch." diff --git a/src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj b/src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj index 8c72b69f..f9265431 100644 --- a/src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj +++ b/src/RearEnd/Visualization/B2R2.RearEnd.Visualization.fsproj @@ -21,7 +21,7 @@ - + diff --git a/src/RearEnd/Visualization/CoordAssignment.fs b/src/RearEnd/Visualization/CoordAssignment.fs index 1390161f..2f5211a0 100644 --- a/src/RearEnd/Visualization/CoordAssignment.fs +++ b/src/RearEnd/Visualization/CoordAssignment.fs @@ -36,8 +36,8 @@ type HDirection = | Leftmost | Rightmost -type VertexMap = Dictionary, Vertex> -type FloatMap = Dictionary, float> +type VertexMap = Dictionary, IVertex> +type FloatMap = Dictionary, float> /// The horizontal interval of two consecutive blocks. [] @@ -48,28 +48,28 @@ let private BlockIntervalX = 50.0 let private BlockIntervalY = 100.0 /// Inner segment is an edge between two dummy nodes -let findIncidentInnerSegmentNode vGraph (v: Vertex) = +let findIncidentInnerSegmentNode vGraph (v: IVertex) = if v.VData.IsDummy then - VisGraph.getPreds vGraph v |> List.tryFind (fun v -> v.VData.IsDummy) + VisGraph.getPreds vGraph v |> Seq.tryFind (fun v -> v.VData.IsDummy) else None -let pairID (u: Vertex) (v: Vertex) = +let pairID (u: IVertex) (v: IVertex) = if u.VData.Layer > v.VData.Layer then u, v else v, u -let addConflict (u: Vertex) (v: Vertex) conflicts = +let addConflict (u: IVertex) (v: IVertex) conflicts = Set.add (pairID u v) conflicts -let checkConflict (u: Vertex) (v: Vertex) conflicts = +let checkConflict (u: IVertex) (v: IVertex) conflicts = Set.contains (pairID u v) conflicts /// Type1 conflict means inner segment and non-inner segment are crossing -let markTypeOneConflict vGraph k0 k1 conflicts (v: Vertex<_>) = +let markTypeOneConflict vGraph k0 k1 conflicts (v: IVertex<_>) = let mark conflicts u = let k = VisGraph.getIndex u if k < k0 || k1 < k then addConflict u v conflicts else conflicts - List.fold mark conflicts <| VisGraph.getPreds vGraph v + Seq.fold mark conflicts <| VisGraph.getPreds vGraph v let rec findTypeOneConflictLoop vGraph upperLen vertices conflicts l k0 l1 = if l1 = Array.length vertices then conflicts @@ -81,11 +81,12 @@ let rec findTypeOneConflictLoop vGraph upperLen vertices conflicts l k0 l1 = let conflicts = vertices[l .. l1] |> Array.fold (markTypeOneConflict vGraph k0 k1) conflicts - findTypeOneConflictLoop vGraph upperLen vertices conflicts (l1 + 1) k1 (l1 + 1) + findTypeOneConflictLoop + vGraph upperLen vertices conflicts (l1 + 1) k1 (l1 + 1) else findTypeOneConflictLoop vGraph upperLen vertices conflicts l k0 (l1 + 1) -let findTypeOneConflictAux vGraph (vLayout: _ [][]) conflicts (layer, vertices) = +let findTypeOneConflictAux vGraph (vLayout: _[][]) conflicts (layer, vertices) = if layer > 0 && layer < Array.length vLayout - 1 then let nUpperVertices = Array.length vLayout[layer - 1] findTypeOneConflictLoop vGraph nUpperVertices vertices conflicts 0 -1 0 @@ -96,11 +97,11 @@ let findTypeOneConflict vGraph vLayout = Array.mapi (fun layer vertices -> layer, vertices) vLayout |> Array.fold (findTypeOneConflictAux vGraph vLayout) Set.empty -let getLayerByDirection (vLayout: Vertex<_> [][]) idx = function +let getLayerByDirection (vLayout: IVertex<_>[][]) idx = function | Leftmost -> vLayout[idx] | Rightmost -> Array.rev vLayout[idx] -let getMedianNeighbors (sortedNeighbors: Vertex []) hDir = +let getMedianNeighbors (sortedNeighbors: IVertex[]) hDir = let middle = float (sortedNeighbors.Length - 1) / 2.0 let a = int (floor middle) let b = int (ceil middle) @@ -114,13 +115,11 @@ let isBefore a b = function | Rightmost -> a > b /// Alg 2 of Brandes et al. -let vAlign vGraph vLayout maxLayer conflicts vDir hDir = +let vAlign (vGraph: IGraph<_, _>) vLayout maxLayer conflicts vDir hDir = let layers, neighborFn = match vDir with - | Topmost -> - [0 .. (maxLayer - 1)], (fun v -> DiGraph.getPreds vGraph v) - | Bottommost -> - [(maxLayer - 1) .. -1 .. 0], (fun v -> DiGraph.getSuccs vGraph v) + | Topmost -> [0 .. (maxLayer - 1)], vGraph.GetPreds + | Bottommost -> [(maxLayer - 1) .. -1 .. 0], vGraph.GetSuccs let root = VertexMap () let align = VertexMap () (vGraph: VisGraph).IterVertex (fun v -> root[v] <- v; align[v] <- v) @@ -133,9 +132,9 @@ let vAlign vGraph vLayout maxLayer conflicts vDir hDir = | Rightmost -> Int32.MaxValue for v in vertices do let neighbors = neighborFn v - if List.isEmpty neighbors then () + if neighbors.Count = 0 then () else - let neighbors = Array.ofList neighbors |> Array.sortBy VisGraph.getIndex + let neighbors = Seq.toArray neighbors |> Array.sortBy VisGraph.getIndex let medians = getMedianNeighbors neighbors hDir for m in medians do let w = neighbors[m] @@ -152,29 +151,37 @@ let vAlign vGraph vLayout maxLayer conflicts vDir hDir = done) root, align -let inBound (v: Vertex) counts = function +let inBound (v: IVertex) counts = function | Leftmost -> v.VData.Index > 0 | Rightmost -> v.VData.Index < counts - 1 -let getPred (vertices: Vertex []) idx = function +let getPred (vertices: IVertex[]) idx = function | Leftmost -> vertices[idx - 1] | Rightmost -> vertices[idx + 1] let fixShift (xs: FloatMap) (shift: FloatMap) (sink: VertexMap) u v = function | Leftmost -> shift[sink[u]] <- - min (shift[sink[u]]) (xs[v] - xs[u] - u.VData.Width - BlockIntervalX) + min (shift[sink[u]]) + (xs[v] - xs[u] - u.VData.Width - BlockIntervalX) | Rightmost -> shift[sink[u]] <- - max (shift[sink[u]]) (xs[v] - xs[u] + v.VData.Width + BlockIntervalX) + max (shift[sink[u]]) + (xs[v] - xs[u] + v.VData.Width + BlockIntervalX) let adjustX (xs: FloatMap) u v = function | Leftmost -> xs[v] <- - max xs[v] (xs[u] + u.VData.Width + v.VData.Width / 2.0 + BlockIntervalX) + max xs[v] + (xs[u] + u.VData.Width + + v.VData.Width / 2.0 + + BlockIntervalX) | Rightmost -> xs[v] <- - min xs[v] (xs[u] - v.VData.Width - u.VData.Width / 2.0 - BlockIntervalX) + min xs[v] + (xs[u] - v.VData.Width + - u.VData.Width / 2.0 + - BlockIntervalX) let rec placeBlock vLayout hDir root align sink shift (xs: FloatMap) v = if not (Double.IsNaN xs[v]) then () @@ -187,7 +194,7 @@ let rec placeBlock vLayout hDir root align sink shift (xs: FloatMap) v = updateBlock vLayout hDir root align sink shift xs v w w <- align[w] and updateBlock vLayout hDir root (align: VertexMap) sink shift xs v w = - let vertices = (vLayout: Vertex<_> [][])[VisGraph.getLayer w] + let vertices = (vLayout: IVertex<_>[][])[VisGraph.getLayer w] if inBound w vertices.Length hDir then let idx = Array.findIndex (fun v -> v = w) vertices let u = (root: VertexMap)[getPred vertices idx hDir] @@ -228,7 +235,7 @@ let alignAndCompact vGraph vLayout maxLayer conflicts vDir hDir = let getBound vLayout (xs: FloatMap, hDir) = vLayout - |> Array.fold (fun (minWidth, bound) (vertices: Vertex<_> []) -> + |> Array.fold (fun (minWidth, bound) (vertices: IVertex<_>[]) -> let left = xs[vertices[0]] let last = vertices[vertices.Length - 1] let right = xs[last] + last.VData.Width @@ -256,16 +263,15 @@ let collectX xPerV (xs: FloatMap) = | Some (acc) -> Map.add v (xs[v] :: acc) xPerV | None -> Map.add v [xs[v]] xPerV) xPerV -let setXPos (v: Vertex) x = - let vData = v.VData - vData.Coordinate.X <- x +let setXPos (v: IVertex) x = + v.VData.Coordinate.X <- x let averageMedian (xAlignments: FloatMap list) = let xPerV = List.fold collectX Map.empty xAlignments let xPerV = Map.map (fun v xs -> List.toArray xs) xPerV let xPerV = Map.map (fun v xs -> Array.sort xs) xPerV let medians = - Map.map (fun v (xs: float []) -> (xs[1] + xs[2]) / 2.0) xPerV + Map.map (fun v (xs: float[]) -> (xs[1] + xs[2]) / 2.0) xPerV let xs = Map.fold (fun xs _ x -> x :: xs) [] medians let minX = List.min xs let maxX = List.max xs @@ -286,9 +292,8 @@ let assignXCoordinates (vGraph: VisGraph) vLayout = |> averageMedian let assignYCoordinate y vertices = - Array.iter (fun (v: Vertex) -> - let vData = v.VData - vData.Coordinate.Y <- y) vertices + Array.iter (fun (v: IVertex) -> + v.VData.Coordinate.Y <- y) vertices let maxHeight = Array.map VisGraph.getHeight vertices |> Array.max y + maxHeight + BlockIntervalY @@ -297,23 +302,23 @@ let assignYCoordinates vLayout = List.map (fun layer -> vLayout[layer]) [ 0 .. maxLayer ] |> List.fold assignYCoordinate 0.0 |> ignore -let adjustXCoordinate (v: Vertex) = +let adjustXCoordinate (v: IVertex) = let coord = v.VData.Coordinate coord.X <- coord.X - v.VData.Width / 2.0 -let getLeftCoordinate xs (v: Vertex) = - let vData = v.VData - if vData.IsDummy then xs - else vData.Coordinate.X :: xs +let getLeftCoordinate xs (v: IVertex) = + let blk = v.VData + if blk.IsDummy then xs + else blk.Coordinate.X :: xs -let getRightCoordinate xs (v: Vertex) = - let vData = v.VData - if vData.IsDummy then xs - else (vData.Coordinate.X + vData.Width) :: xs +let getRightCoordinate xs (v: IVertex) = + let blk = v.VData + if blk.IsDummy then xs + else (blk.Coordinate.X + blk.Width) :: xs -let shiftXCoordinate shift (v: Vertex) = - let vData = v.VData - vData.Coordinate.X <- vData.Coordinate.X - shift +let shiftXCoordinate shift (v: IVertex) = + let blk = v.VData + blk.Coordinate.X <- blk.Coordinate.X - shift let adjustCoordinates (vGraph: VisGraph) = vGraph.IterVertex adjustXCoordinate diff --git a/src/RearEnd/Visualization/CrossMinimization.fs b/src/RearEnd/Visualization/CrossMinimization.fs index 06206380..4db2f0b3 100644 --- a/src/RearEnd/Visualization/CrossMinimization.fs +++ b/src/RearEnd/Visualization/CrossMinimization.fs @@ -26,7 +26,7 @@ module internal B2R2.RearEnd.Visualization.CrossMinimization open B2R2.MiddleEnd.BinGraph -type VLayout = Vertex [][] +type VLayout = IVertex[][] /// The maximum number of iterations. let [] private MaxCnt = 128 @@ -39,7 +39,7 @@ let private computeMaxLayer (vGraph: VisGraph) = let private generateVPerLayer vGraph = let maxLayer = computeMaxLayer vGraph let vPerLayer = Array.create (maxLayer + 1) [] - let folder (vPerLayer: Vertex list []) v = + let folder (vPerLayer: IVertex list []) v = let layer = VisGraph.getLayer v vPerLayer[layer] <- v :: vPerLayer[layer] vPerLayer @@ -47,22 +47,22 @@ let private generateVPerLayer vGraph = let private alignVertices vertices = let arr = Array.zeroCreate (List.length vertices) - List.fold (fun i (v: Vertex) -> + List.fold (fun i (v: IVertex) -> Array.set arr i v; v.VData.Index <- i; i + 1) 0 vertices |> ignore arr let private generateVLayout vPerLayer = - Array.map (fun vertices -> alignVertices vertices) vPerLayer + Array.map alignVertices vPerLayer -let private baryCenter vGraph isDown (v: Vertex) = +let private baryCenter (vGraph: IGraph<_, _>) isDown (v: IVertex) = let neighbor = - if isDown then DiGraph.getPreds vGraph v - else DiGraph.getSuccs vGraph v - if List.isEmpty neighbor then System.Double.MaxValue, v + if isDown then vGraph.GetPreds v + else vGraph.GetSuccs v + if neighbor.Count = 0 then System.Double.MaxValue, v else - let xs = neighbor |> List.fold (fun acc v -> acc + v.VData.Index) 0 - float xs / float (List.length neighbor), v + let xs = neighbor |> Seq.fold (fun acc v -> acc + v.VData.Index) 0 + float xs / float neighbor.Count, v let private bcReorderOneLayer vGraph (vLayout: VLayout) isDown layer = let vertices = vLayout[layer] @@ -80,7 +80,7 @@ let private phase1 vGraph vLayout isDown from maxLayer = let rec private calcFirstIndex idx wlen = if idx < wlen then calcFirstIndex (idx * 2) wlen else idx -let rec private countLoop (tree: int []) southseq cnt index = +let rec private countLoop (tree: int[]) southseq cnt index = if index > 0 then let cnt = if index % 2 <> 0 then cnt + tree[index + 1] else cnt let index = (index - 1) / 2 @@ -94,7 +94,7 @@ let private countCross southseq wlen = let firstIndex = firstIndex - 1 let tree = Array.zeroCreate (treeSize) let cnt, _ = - List.fold (fun (cnt, (tree: int [])) item -> + List.fold (fun (cnt, (tree: int[])) item -> let index = firstIndex + item tree[index] <- tree[index] + 1 countLoop tree southseq cnt index) (0, tree) southseq @@ -104,14 +104,14 @@ let private bilayerCount vGraph (vLayout: VLayout) isDown layer = let myLayer = vLayout[layer] let pairs, _ = if isDown then - Array.fold (fun (acc, i) (v: Vertex) -> - DiGraph.getSuccs vGraph v - |> List.fold (fun acc w -> (i, w.VData.Index) :: acc) acc, + Array.fold (fun (acc, i) (v: IVertex) -> + (vGraph: IGraph<_, _>).GetSuccs v + |> Seq.fold (fun acc w -> (i, w.VData.Index) :: acc) acc, i + 1) ([], 0) vLayout[layer - 1] else - Array.fold (fun (acc, i) (v: Vertex) -> - DiGraph.getPreds vGraph v - |> List.fold (fun acc w -> (i, w.VData.Index) :: acc) acc, + Array.fold (fun (acc, i) (v: IVertex) -> + vGraph.GetPreds v + |> Seq.fold (fun acc w -> (i, w.VData.Index) :: acc) acc, i + 1) ([], 0) vLayout[layer + 1] let pairs = List.sort pairs let southseq = List.map snd pairs @@ -122,8 +122,9 @@ let private collectBaryCenters bcByValues (bc, v) = | Some (vs) -> Map.add bc (v :: vs) bcByValues | None -> Map.add bc [v] bcByValues -let private reorderVertices (vertices: Vertex []) idx (_, vs) = - List.fold (fun i v -> vertices[i] <- v; v.VData.Index <- i; i + 1) idx vs +let private reorderVertices (vertices: IVertex[]) idx (_, vs) = + List.fold (fun i v -> + vertices[i] <- v; v.VData.Index <- i; i + 1) idx vs let private reverseOneLayer vGraph vLayout isDown maxLayer layer = let count = bilayerCount vGraph vLayout isDown layer diff --git a/src/RearEnd/Visualization/CycleRemoval.fs b/src/RearEnd/Visualization/CycleRemoval.fs index 07176c0e..6449aaa7 100644 --- a/src/RearEnd/Visualization/CycleRemoval.fs +++ b/src/RearEnd/Visualization/CycleRemoval.fs @@ -26,33 +26,35 @@ module internal B2R2.RearEnd.Visualization.CycleRemoval open B2R2.MiddleEnd.BinGraph -let private collectSelfCycle backEdgeList src dst edge = - if VisGraph.getID src = VisGraph.getID dst then (* Definition of self cycle *) - (edge: VisEdge).IsBackEdge <- true - (src, dst, edge, false) :: backEdgeList - else backEdgeList - -let private collectBackEdge (vGraph: VisGraph) order backEdgeList src dst edge = +let private collectBackEdge vGraph order backEdgeList (edge: Edge<_, VisEdge>) = + let src, dst = edge.First, edge.Second if Map.find src order > Map.find dst order then (* BackEdge *) - (edge: VisEdge).IsBackEdge <- true - match vGraph.TryFindEdgeData dst src with + edge.Label.IsBackEdge <- true + match (vGraph: VisGraph).TryFindEdge (dst, src) with | Some _ -> (src, dst, edge, false) :: backEdgeList | None -> (src, dst, edge, true) :: backEdgeList else backEdgeList -let removeBackEdge (vGraph: VisGraph) src dst edge needToAddReverse = - vGraph.RemoveEdge src dst |> ignore - if needToAddReverse then vGraph.AddEdge dst src edge |> ignore - let private dfsCollectBackEdges vGraph roots backEdgeList = let _, orderMap = Traversal.foldTopologically vGraph roots (fun (cnt, map) v -> cnt + 1, Map.add v cnt map) (0, Map.empty) vGraph.FoldEdge (collectBackEdge vGraph orderMap) backEdgeList +let private collectSelfCycle backEdgeList (edge: Edge<_, VisEdge>) = + let src, dst = edge.First, edge.Second + if VisGraph.getID src = VisGraph.getID dst then (* Definition of self cycle *) + edge.Label.IsBackEdge <- true + (src, dst, edge, false) :: backEdgeList + else backEdgeList + +let removeBackEdge (vGraph: VisGraph) src dst edge needToAddReverse = + vGraph.RemoveEdge (src, dst) |> ignore + if needToAddReverse then vGraph.AddEdge (dst, src, edge) |> ignore + let removeCycles (vGraph: VisGraph) roots = vGraph.FoldEdge collectSelfCycle [] |> dfsCollectBackEdges vGraph roots |> List.map (fun (src, dst, edge, needToAddReverse) -> - removeBackEdge vGraph src dst edge needToAddReverse - (src, dst, edge)) + removeBackEdge vGraph src dst edge.Label needToAddReverse + (src, dst, edge.Label)) diff --git a/src/RearEnd/Visualization/EdgeDrawing.fs b/src/RearEnd/Visualization/EdgeDrawing.fs index a5315f97..34fa7a2b 100644 --- a/src/RearEnd/Visualization/EdgeDrawing.fs +++ b/src/RearEnd/Visualization/EdgeDrawing.fs @@ -81,34 +81,37 @@ let [] private FitErrorMargin = 1.0 /// then we expand the layer's height. let [] private LayerHeightExpansionThreshold = 15 -let inline private isDummy (v: Vertex) = v.VData.IsDummy +let inline private isDummy (v: IVertex) = v.VData.IsDummy let private restoreBackEdge (g: VisGraph) (src, dst, edge: VisEdge) = - match g.TryFindEdgeData dst src with - | Some eData when eData.IsBackEdge -> g.RemoveEdge dst src |> ignore + match g.TryFindEdge (dst, src) with + | Some e when e.Label.IsBackEdge -> g.RemoveEdge (dst, src) |> ignore | _ -> () - g.AddEdge src dst edge |> ignore + g.AddEdge (src, dst, edge) |> ignore let private restoreBackEdges g backEdgeList = List.iter (restoreBackEdge g) backEdgeList /// Compute the original destination vertex, given dummy source node src. -let rec private getOriginalDst (v: Vertex) = - if isDummy v then getOriginalDst (List.head v.Succs) +let rec private getOriginalDst (g: IGraph<_, _>) (v: IVertex) = + if isDummy v then + let succs = g.GetSuccs v + getOriginalDst g (Seq.head succs) else v /// Given src is original, add original edge to acc. -let private accOriginalEdge acc src dst (edge: VisEdge) = +let private accOriginalEdge g acc (edge: Edge<_, VisEdge>) = + let src, dst = edge.First, edge.Second if isDummy src then acc - elif isDummy dst then (src, getOriginalDst dst, edge ) :: acc - else (src, dst, edge) :: acc + elif isDummy dst then (src, getOriginalDst g dst, edge.Label) :: acc + else (src, dst, edge.Label) :: acc /// Sort vertices by the x-coordinates. let private sortLayers vLayout = vLayout |> Array.map (fun layer -> Array.sortBy (fun v -> (VisGraph.getXPos v)) layer) -let private countDegree edges (getter: 'a -> Vertex) v = +let private countDegree edges (getter: _ -> IVertex) v = edges |> List.fold (fun cnt e -> if getter e = v then cnt + 1 else cnt) 0 @@ -118,10 +121,10 @@ let private getMaxDegree edges getter layer = |> Array.max let private downShiftLayers layers degree = - Array.iter (Array.iter (fun (v: Vertex) -> - let vData = v.VData - let newY = vData.Coordinate.Y + EdgeOffsetY * float degree - vData.Coordinate.Y <- newY)) layers + Array.iter (Array.iter (fun (v: IVertex) -> + let blk = v.VData + let newY = blk.Coordinate.Y + EdgeOffsetY * float degree + blk.Coordinate.Y <- newY)) layers let rec private adjustLayers isIncoming layerNum vLayout = function | [] -> () @@ -138,17 +141,17 @@ let rec private adjustLayers isIncoming layerNum vLayout = function /// edges. let private adjustLayerYPositions edges vLayout = let maxIncomingDegrees = - vLayout |> Array.map (getMaxDegree edges Utils.tripleSnd) |> Array.toList + vLayout |> Array.map (getMaxDegree edges Utils.sndOfTriple) |> Array.toList let maxOutgoingDegrees = - vLayout |> Array.map (getMaxDegree edges Utils.tripleFst) |> Array.toList + vLayout |> Array.map (getMaxDegree edges Utils.fstOfTriple) |> Array.toList adjustLayers true 0 vLayout maxIncomingDegrees adjustLayers false 0 vLayout maxOutgoingDegrees -let private getEntryPoint (v: Vertex) = +let private getEntryPoint (v: IVertex) = let x, y = VisGraph.getXPos v, VisGraph.getYPos v (x + VisGraph.getWidth v / 2.0), (y + VisGraph.getHeight v) -let private getExitPoint (v: Vertex) = +let private getExitPoint (v: IVertex) = let x, y = VisGraph.getXPos v, VisGraph.getYPos v (x + VisGraph.getWidth v / 2.0), y @@ -164,7 +167,7 @@ let private makeBox left right top bottom isVirtual = let private makeDummyBox () = makeBox 0.0 0.0 0.0 0.0 true /// Convert a Vertex into a Box. -let private vertexToBox (v: Vertex): Box = +let private vertexToBox (v: IVertex): Box = let left = VisGraph.getXPos v - if (isDummy v) then 0.0 else NodeBoxOffset let right = (VisGraph.getXPos v + VisGraph.getWidth v @@ -208,7 +211,7 @@ let private getIntersectingLines boxes = | _ -> Utils.impossible () let private getBasicComponents (vLayout: _[][]) (boxes: _[][]) v = - let layer = VisGraph.getLayer (v: Vertex) + let layer = VisGraph.getLayer (v: IVertex) let nth = Array.findIndex ((=) v) vLayout[layer] let boxarr = boxes[layer] let box: Box = boxes[layer][nth] @@ -255,7 +258,7 @@ let private computeWidthLine boxes = leftmost, rightmost /// Return a list of layers between q (qLayer) and r (rLayer). -let getLayersBetween (dummies: Vertex list) qLayer rLayer = +let getLayersBetween (dummies: IVertex list) qLayer rLayer = if dummies.IsEmpty then [ (min qLayer rLayer) ] else [ (min qLayer rLayer) .. (max qLayer rLayer) - 1 ] @@ -312,7 +315,7 @@ let private virtualNodeBox boxes widthLine (yPositions: _ []) shrinkBox dummy = if shrinkBox then makeBox (left + delta) (right - delta) top bottom true else makeBox left right top bottom true -let private nodeIsLeft (q: Vertex) (r: Vertex) = +let private nodeIsLeft (q: IVertex) (r: IVertex) = let qx, rx = VisGraph.getXPos q, VisGraph.getXPos r qx + 1.5 * (VisGraph.getWidth q) < rx @@ -359,9 +362,9 @@ let rec private computePList (interLines: Line array) q r = let private computeRegularEdgePoints isBackEdge dummies boxes q r qBox rBox = let intersectingLines = getIntersectingLines boxes let tailQ, headR = getEntryPoint q, getExitPoint r (* Key points *) - let q1 = makeVisPos (fst tailQ, snd tailQ) + let q1 = makeVisPos tailQ let q2 = { q1 with Y = q1.Y + NodeBoxOffset } - let r1 = makeVisPos (fst headR, snd headR) + let r1 = makeVisPos headR let r2 = { r1 with Y = r1.Y - NodeBoxOffset } let qWidth = VisGraph.getWidth q if isBackEdge then @@ -404,24 +407,24 @@ let private drawRegular g vLayout boxes dummyMap (q, r, edge: VisEdge) = ((List.fold2 (fun acc v i -> i :: v :: acc) [interLayerBoxes.Head] virtualNodeBoxes interLayerBoxes.Tail) |> List.rev) let points = computeRegularEdgePoints isBackEdge dummies boxes q r qBox rBox - match (g: VisGraph).TryFindEdgeData q r with + match (g: VisGraph).TryFindEdge (q, r) with | None -> (* Imaginary edges for display purposes only *) let newEdge = VisEdge (edge.Type) newEdge.IsBackEdge <- isBackEdge newEdge.Points <- points - g.AddEdge q r newEdge |> ignore - | Some e -> e.Points <- points + g.AddEdge (q, r, newEdge) |> ignore + | Some e -> e.Label.Points <- points -let private drawSelfLoop g (v: Vertex) = +let private drawSelfLoop g (v: IVertex) = let nodeWidth = VisGraph.getWidth v - let eData = (g: VisGraph).FindEdgeData v v + let e = (g: VisGraph).FindEdge (v, v) let startP, endP = getEntryPoint v, getExitPoint v let p1 = (fst startP), (snd startP + LastSegLen) let p2 = ((fst p1) + nodeWidth / 2.0 + BackEdgeMargin), (snd p1) let p3 = (fst p2), (snd endP) - LastSegLen let p4 = (fst endP), snd p3 let points = [ startP; p1; p2; p3; p4; endP ] |> List.map makeVisPos - eData.Points <- points + e.Label.Points <- points let private drawBoxes g vLayout boxes dummyMap (src, dst, edge) = if isDummy src || isDummy dst then () @@ -430,13 +433,13 @@ let private drawBoxes g vLayout boxes dummyMap (src, dst, edge) = let rec private removeDummyLoop (g: VisGraph) src dst points = function | dummy :: rest -> - let eData = g.FindEdgeData src dummy - g.RemoveEdge src dummy |> ignore - removeDummyLoop g dummy dst (points @ eData.Points) rest + let e = g.FindEdge (src, dummy) + g.RemoveEdge (src, dummy) |> ignore + removeDummyLoop g dummy dst (points @ e.Label.Points) rest | [] -> - let eData = g.FindEdgeData src dst - g.RemoveEdge src dst |> ignore - points @ eData.Points + let e = g.FindEdge (src, dst) + g.RemoveEdge (src, dst) |> ignore + points @ e.Label.Points let private makeSmooth isBack points = let rec loop acc prev = function @@ -458,10 +461,11 @@ let private removeDummy g (src, dst) ((edge: VisEdge), dummies) = let newEdge = VisEdge (edge.Type) newEdge.IsBackEdge <- edge.IsBackEdge newEdge.Points <- pts - g.AddEdge src dst newEdge |> ignore - dummies |> List.iter (fun (v: Vertex<_>) -> g.RemoveVertex v |> ignore) + g.AddEdge (src, dst, newEdge) |> ignore + dummies |> List.iter (g.RemoveVertex >> ignore) -let private categorizeEdge isHeadPort acc (q, r, edge: VisEdge) = +let private categorizeEdge isHeadPort acc (q, r, edge: Edge<_, VisEdge>) = + let edge = edge.Label let points = edge.Points |> Array.ofList let n = Array.length points if n < 4 then acc @@ -559,14 +563,16 @@ let rec private shiftVertically isHeadPort offset = function shiftVertically isHeadPort offset rest /// Give some offsets to each neighboring edge of v. -let private giveOffsets (g: VisGraph) (v: Vertex) = - let incoming = v.Preds |> List.map (fun p -> p, v, g.FindEdgeData p v) - let outgoing = v.Succs |> List.map (fun s -> v, s, g.FindEdgeData v s) +let private giveOffsets (g: VisGraph) (v: IVertex) = + let preds = g.GetPreds v |> Seq.toArray + let succs = g.GetSuccs v |> Seq.toArray + let incoming = preds |> Array.map (fun p -> p, v, g.FindEdge (p, v)) + let outgoing = succs |> Array.map (fun s -> v, s, g.FindEdge (v, s)) let ins = - List.fold (categorizeEdge true) emptyPartitionedEdges incoming + Array.fold (categorizeEdge true) emptyPartitionedEdges incoming |> sortPartitions true true let outs = - List.fold (categorizeEdge false) emptyPartitionedEdges outgoing + Array.fold (categorizeEdge false) emptyPartitionedEdges outgoing |> sortPartitions false false shiftHorizontally true ins.BackEdgesFromLeft 0.0 shiftHorizontally true outs.BackEdgesFromLeft 0.0 @@ -595,7 +601,7 @@ let private giveOffsets (g: VisGraph) (v: Vertex) = let drawEdges (g: VisGraph) vLayout backEdgeList dummyMap = restoreBackEdges g backEdgeList - let originalEdgeList = g.FoldEdge accOriginalEdge [] + let originalEdgeList = g.FoldEdge (accOriginalEdge g) [] let vLayoutSorted = sortLayers vLayout adjustLayerYPositions originalEdgeList vLayoutSorted let boxes = verticesToBoxes2D vLayoutSorted diff --git a/src/RearEnd/Visualization/JSONExport.fs b/src/RearEnd/Visualization/JSONExport.fs index fba134fa..ef8136b5 100644 --- a/src/RearEnd/Visualization/JSONExport.fs +++ b/src/RearEnd/Visualization/JSONExport.fs @@ -60,7 +60,7 @@ module JSONExport = let private getJSONTerms (visualBlock: VisualBlock) = visualBlock |> Array.map (Array.map AsmWord.ToStringTuple) - let private ofVisGraph (g: VisGraph) (roots: Vertex<#BasicBlock> list) = + let private ofVisGraph (g: VisGraph) (roots: IVertex<#BasicBlock> list) = let roots = roots |> List.map (fun r -> r.VData.PPoint.Address) let nodes = g.FoldVertex (fun acc v -> @@ -71,7 +71,8 @@ module JSONExport = Coordinate = { X = v.VData.Coordinate.X Y = v.VData.Coordinate.Y } } :: acc) [] let edges = - g.FoldEdge (fun acc _ _ e -> + g.FoldEdge (fun acc e -> + let e = e.Label { Type = e.Type Points = e.Points |> List.map (fun p -> { X = p.X; Y = p.Y }) IsBackEdge = e.IsBackEdge } :: acc) [] diff --git a/src/RearEnd/Visualization/LayerAssignment.fs b/src/RearEnd/Visualization/LayerAssignment.fs index 8133d8ff..54304fc0 100644 --- a/src/RearEnd/Visualization/LayerAssignment.fs +++ b/src/RearEnd/Visualization/LayerAssignment.fs @@ -29,11 +29,10 @@ open B2R2.MiddleEnd.BinGraph let assignLayerFromPred (vGraph: VisGraph) vData = let v = vGraph.FindVertexByData vData let preds = VisGraph.getPreds vGraph v - match preds with - | [] -> VisGraph.setLayer v 0 - | preds -> - let predLayers = List.map VisGraph.getLayer preds - VisGraph.setLayer v <| List.max predLayers + 1 + if preds.Count = 0 then VisGraph.setLayer v 0 + else + let maxLayer = (Seq.maxBy VisGraph.getLayer preds).VData.Layer + VisGraph.setLayer v <| maxLayer + 1 let kahnAssignLayers (vGraph: VisGraph) = Traversal.foldTopologically vGraph [] (fun acc v -> v.VData :: acc) [] @@ -44,43 +43,48 @@ let rec addDummy (g: VisGraph) (backEdges, dummies) k src dst (e: VisEdge) cnt = if cnt = 0 then let edge = VisEdge (e.Type) edge.IsBackEdge <- e.IsBackEdge - g.AddEdge src dst edge |> ignore + g.AddEdge (src, dst, edge) |> ignore let backEdges = - if edge.IsBackEdge then (dst, src, edge) :: backEdges else backEdges + if edge.IsBackEdge then (dst, src, edge) :: backEdges + else backEdges backEdges, dummies else let vNode = VisBBlock (src.VData, true) - let dummy, _ = g.AddVertex (vNode) + let dummy, _ = g.AddVertex vNode VisGraph.setLayer dummy <| VisGraph.getLayer src + 1 let edge = VisEdge (e.Type) edge.IsBackEdge <- e.IsBackEdge - g.AddEdge src dummy edge |> ignore + g.AddEdge (src, dummy, edge) |> ignore let backEdges = - if edge.IsBackEdge then (dummy, src, edge) :: backEdges else backEdges + if edge.IsBackEdge then (dummy, src, edge) :: backEdges + else backEdges let eData, vertices = Map.find k dummies let dummies = Map.add k (eData, dummy :: vertices) dummies addDummy g (backEdges, dummies) k dummy dst e (cnt - 1) -let siftBackEdgesAndPickLongEdges (backEdges, longEdges) src dst edge = +let siftBackEdgesAndPickLongEdges (backEdges, longEdges) edge = + let src, dst = (edge: Edge<_, VisEdge>).First, edge.Second let delta = VisGraph.getLayer dst - VisGraph.getLayer src if delta > 1 then (* Backedge in forward direction = Extra edge added in the cycle removal. *) let backEdges = - if (edge: VisEdge).IsBackEdge then - List.filter (fun (_, _, e) -> e <> edge) backEdges + if edge.Label.IsBackEdge then + List.filter (fun (_, _, e) -> e <> edge.Label) backEdges else backEdges let longEdges = (src, dst, edge, delta) :: longEdges backEdges, longEdges else backEdges, longEdges let addDummyNodes vGraph (backEdges, dummies) (src, dst, edge, delta) = - (vGraph: VisGraph).RemoveEdge src dst |> ignore - let k = if (edge: VisEdge).IsBackEdge then dst, src else src, dst - let dummies = Map.add k (edge, []) dummies + (vGraph: VisGraph).RemoveEdge (src, dst) |> ignore + let k = + if (edge: Edge<_, VisEdge>).Label.IsBackEdge then dst, src + else src, dst + let dummies = Map.add k (edge.Label, []) dummies let backEdges, dummies = - addDummy vGraph (backEdges, dummies) k src dst edge (delta - 1) + addDummy vGraph (backEdges, dummies) k src dst edge.Label (delta - 1) let dummies = - if not edge.IsBackEdge then + if not edge.Label.IsBackEdge then let eData, vertices = Map.find k dummies Map.add k (eData, List.rev vertices) dummies else dummies diff --git a/src/RearEnd/Visualization/VisDebug.fs b/src/RearEnd/Visualization/VisDebug.fs index 20c5a832..2f1d4d21 100644 --- a/src/RearEnd/Visualization/VisDebug.fs +++ b/src/RearEnd/Visualization/VisDebug.fs @@ -40,18 +40,18 @@ module VisDebug = fs.Write (bytes, 0, bytes.Length) fs.Flush () - let private ppNode vGraph (vNode: Vertex) = + let private ppNode (vGraph: IGraph<_, _>) (vNode: IVertex) = logn "Node {" - sprintf "\tID: %d" (vNode.GetID ()) |> logn + sprintf "\tID: %d" vNode.ID |> logn sprintf "\tAddr: (%s)" (vNode.VData.PPoint.ToString ()) |> logn sprintf "\tLayer: %d" vNode.VData.Layer |> logn logn "\tPreds: [" - List.iter (fun (v: Vertex) -> - sprintf "%d, " (v.GetID ()) |> logn) <| DiGraph.getPreds vGraph vNode + Seq.iter (fun (v: IVertex) -> + sprintf "%d, " v.ID |> logn) <| vGraph.GetPreds vNode logn "]" logn "\tSuccss: [" - List.iter (fun (v: Vertex) -> - sprintf "%d, " (v.GetID ()) |> logn) <| DiGraph.getSuccs vGraph vNode + Seq.iter (fun (v: IVertex) -> + sprintf "%d, " v.ID |> logn) <| vGraph.GetSuccs vNode logn "]" logn "}" diff --git a/src/RearEnd/Visualization/VisGraph.fs b/src/RearEnd/Visualization/VisGraph.fs index 69d065d3..79163055 100644 --- a/src/RearEnd/Visualization/VisGraph.fs +++ b/src/RearEnd/Visualization/VisGraph.fs @@ -29,54 +29,51 @@ open B2R2.MiddleEnd.ControlFlowGraph open System.Collections.Generic /// The main graph type for visualization. -type VisGraph = ControlFlowGraph +type VisGraph = IGraph module VisGraph = - let private initializer core = VisGraph (core) :> DiGraph - let init () = - ImperativeCore (initializer, VisEdge UnknownEdge) - |> VisGraph + ImperativeDiGraph () + :> VisGraph let ofCFG g roots = let newGraph = init () - let visited = Dictionary> () - let getVisBBlock (oldV: Vertex<#BasicBlock>) = - match visited.TryGetValue (oldV.GetID ()) with + let visited = Dictionary> () + let getVisBBlock (oldV: IVertex<#BasicBlock>) = + match visited.TryGetValue oldV.ID with | false, _ -> let blk = VisBBlock (oldV.VData :> BasicBlock, false) let v, _ = newGraph.AddVertex blk - visited[oldV.GetID ()] <- v + visited[oldV.ID] <- v v | true, v -> v (* In case there is no edge in the graph. *) let roots = roots |> List.map (getVisBBlock) - DiGraph.iterEdge g (fun src dst e -> - let srcV = getVisBBlock src - let dstV = getVisBBlock dst - let edge = VisEdge (e) - newGraph.AddEdge srcV dstV edge |> ignore) + (g: IGraph<_, _>).IterEdge (fun e -> + let srcV = getVisBBlock e.First + let dstV = getVisBBlock e.Second + let edge = VisEdge e.Label + newGraph.AddEdge (srcV, dstV, edge) |> ignore) newGraph, roots - let getID v = Vertex.GetID v - - let getPreds vGraph (v: Vertex) = DiGraph.getPreds vGraph v + let getID (v: IVertex<_>) = v.ID - let getSuccs vGraph (v: Vertex) = DiGraph.getSuccs vGraph v + let getPreds (vGraph: IGraph<_, _>) (v: IVertex<_>) = vGraph.GetPreds v - let getVData (v: Vertex) = v.VData + let getSuccs (vGraph: IGraph<_, _>) (v: IVertex<_>) = vGraph.GetSuccs v - let getIndex (v: Vertex) = v.VData.Index + let getVData (v: IVertex<_>) = v.VData - let getLayer (v: Vertex) = v.VData.Layer + let getIndex (v: IVertex) = v.VData.Index - let setLayer (v: Vertex) layer = v.VData.Layer <- layer + let getLayer (v: IVertex) = v.VData.Layer - let getWidth (v: Vertex) = v.VData.Width + let setLayer (v: IVertex) layer = v.VData.Layer <- layer - let getHeight (v: Vertex) = v.VData.Height + let getWidth (v: IVertex) = v.VData.Width - let getXPos (v: Vertex) = v.VData.Coordinate.X + let getHeight (v: IVertex) = v.VData.Height - let getYPos (v: Vertex) = v.VData.Coordinate.Y + let getXPos (v: IVertex) = v.VData.Coordinate.X + let getYPos (v: IVertex) = v.VData.Coordinate.Y