aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instruction
diff options
context:
space:
mode:
authorAlex Barney <thealexbarney@gmail.com>2018-10-30 19:43:02 -0600
committergdkchan <gab.dark.100@gmail.com>2018-10-30 22:43:02 -0300
commit9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d (patch)
tree0c97425aeb311c142bc92a6fcc503cb2c07d4376 /ChocolArm64/Instruction
parent5a87e58183578f5b84ca8d01cbb76aed11820f78 (diff)
Adjust naming conventions for Ryujinx and ChocolArm64 projects (#484)
* Change naming convention for Ryujinx project * Change naming convention for ChocolArm64 project * Fix NaN * Remove unneeded this. from Ryujinx project * Adjust naming from new PRs * Name changes based on feedback * How did this get removed? * Rebasing fix * Change FP enum case * Remove prefix from ChocolArm64 classes - Part 1 * Remove prefix from ChocolArm64 classes - Part 2 * Fix alignment from last commit's renaming * Rename namespaces * Rename stragglers * Fix alignment * Rename OpCode class * Missed a few * Adjust alignment
Diffstat (limited to 'ChocolArm64/Instruction')
-rw-r--r--ChocolArm64/Instruction/ACryptoHelper.cs328
-rw-r--r--ChocolArm64/Instruction/AInst.cs20
-rw-r--r--ChocolArm64/Instruction/AInstEmitAlu.cs402
-rw-r--r--ChocolArm64/Instruction/AInstEmitAluHelper.cs212
-rw-r--r--ChocolArm64/Instruction/AInstEmitBfm.cs208
-rw-r--r--ChocolArm64/Instruction/AInstEmitCcmp.cs81
-rw-r--r--ChocolArm64/Instruction/AInstEmitCsel.cs58
-rw-r--r--ChocolArm64/Instruction/AInstEmitException.cs86
-rw-r--r--ChocolArm64/Instruction/AInstEmitFlow.cs189
-rw-r--r--ChocolArm64/Instruction/AInstEmitHash.cs115
-rw-r--r--ChocolArm64/Instruction/AInstEmitMemory.cs252
-rw-r--r--ChocolArm64/Instruction/AInstEmitMemoryEx.cs192
-rw-r--r--ChocolArm64/Instruction/AInstEmitMemoryHelper.cs138
-rw-r--r--ChocolArm64/Instruction/AInstEmitMove.cs41
-rw-r--r--ChocolArm64/Instruction/AInstEmitMul.cs80
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs2387
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdCmp.cs526
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdCrypto.cs54
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdCvt.cs697
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdHash.cs140
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdHelper.cs1495
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdLogical.cs311
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdMemory.cs185
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdMove.cs562
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdShift.cs865
-rw-r--r--ChocolArm64/Instruction/AInstEmitSystem.cs138
-rw-r--r--ChocolArm64/Instruction/AInstEmitter.cs6
-rw-r--r--ChocolArm64/Instruction/AInstInterpreter.cs8
-rw-r--r--ChocolArm64/Instruction/ASoftFallback.cs922
-rw-r--r--ChocolArm64/Instruction/ASoftFloat.cs2127
-rw-r--r--ChocolArm64/Instruction/AVectorHelper.cs790
31 files changed, 0 insertions, 13615 deletions
diff --git a/ChocolArm64/Instruction/ACryptoHelper.cs b/ChocolArm64/Instruction/ACryptoHelper.cs
deleted file mode 100644
index 2dc65972..00000000
--- a/ChocolArm64/Instruction/ACryptoHelper.cs
+++ /dev/null
@@ -1,328 +0,0 @@
-// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
-
-using System;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-namespace ChocolArm64.Instruction
-{
- static class ACryptoHelper
- {
-#region "LookUp Tables"
- private static byte[] SBox =
- {
- 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
- 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
- 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
- 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
- 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
- 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
- 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
- 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
- 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
- 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
- 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
- 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
- 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
- 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
- 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
- };
-
- private static byte[] InvSBox =
- {
- 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
- 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
- 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
- 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
- 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
- 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
- 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
- 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
- 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
- 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
- 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
- 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
- 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
- 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
- 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
- };
-
- private static byte[] GFMul_02 =
- {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
- 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
- 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
- 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
- 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
- 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
- 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
- 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
- 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
- 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
- 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
- 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
- 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
- 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
- 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
- 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
- };
-
- private static byte[] GFMul_03 =
- {
- 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
- 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
- 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
- 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
- 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
- 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
- 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
- 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
- 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
- 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
- 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
- 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
- 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
- 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
- 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
- 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
- };
-
- private static byte[] GFMul_09 =
- {
- 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
- 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
- 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
- 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
- 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
- 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
- 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
- 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
- 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
- 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
- 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
- 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
- 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
- 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
- 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
- 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
- };
-
- private static byte[] GFMul_0B =
- {
- 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
- 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
- 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
- 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
- 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
- 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
- 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
- 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
- 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
- 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
- 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
- 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
- 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
- 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
- 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
- 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
- };
-
- private static byte[] GFMul_0D =
- {
- 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
- 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
- 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
- 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
- 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
- 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
- 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
- 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
- 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
- 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
- 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
- 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
- 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
- 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
- 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
- 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
- };
-
- private static byte[] GFMul_0E =
- {
- 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
- 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
- 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
- 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
- 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
- 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
- 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
- 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
- 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
- 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
- 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
- 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
- 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
- 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
- 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
- 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
- };
-
- private static byte[] SRPerm = { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 };
-
- private static byte[] ISRPerm = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 };
-#endregion
-
- public static Vector128<float> AESInvMixColumns(Vector128<float> op)
- {
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
-
- FromVectorToByteArray(InState, ref op);
-
- for (int Columns = 0; Columns <= 3; Columns++)
- {
- int Idx = Columns << 2;
-
- byte Row0 = InState[Idx + 0]; // A, E, I, M: [Row0, Col0-Col3]
- byte Row1 = InState[Idx + 1]; // B, F, J, N: [Row1, Col0-Col3]
- byte Row2 = InState[Idx + 2]; // C, G, K, O: [Row2, Col0-Col3]
- byte Row3 = InState[Idx + 3]; // D, H, L, P: [Row3, Col0-Col3]
-
- OutState[Idx + 0] = (byte)((uint)GFMul_0E[Row0] ^ GFMul_0B[Row1] ^ GFMul_0D[Row2] ^ GFMul_09[Row3]);
- OutState[Idx + 1] = (byte)((uint)GFMul_09[Row0] ^ GFMul_0E[Row1] ^ GFMul_0B[Row2] ^ GFMul_0D[Row3]);
- OutState[Idx + 2] = (byte)((uint)GFMul_0D[Row0] ^ GFMul_09[Row1] ^ GFMul_0E[Row2] ^ GFMul_0B[Row3]);
- OutState[Idx + 3] = (byte)((uint)GFMul_0B[Row0] ^ GFMul_0D[Row1] ^ GFMul_09[Row2] ^ GFMul_0E[Row3]);
- }
-
- FromByteArrayToVector(OutState, ref op);
-
- return op;
- }
-
- public static Vector128<float> AESInvShiftRows(Vector128<float> op)
- {
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
-
- FromVectorToByteArray(InState, ref op);
-
- for (int Idx = 0; Idx <= 15; Idx++)
- {
- OutState[ISRPerm[Idx]] = InState[Idx];
- }
-
- FromByteArrayToVector(OutState, ref op);
-
- return op;
- }
-
- public static Vector128<float> AESInvSubBytes(Vector128<float> op)
- {
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
-
- FromVectorToByteArray(InState, ref op);
-
- for (int Idx = 0; Idx <= 15; Idx++)
- {
- OutState[Idx] = InvSBox[InState[Idx]];
- }
-
- FromByteArrayToVector(OutState, ref op);
-
- return op;
- }
-
- public static Vector128<float> AESMixColumns(Vector128<float> op)
- {
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
-
- FromVectorToByteArray(InState, ref op);
-
- for (int Columns = 0; Columns <= 3; Columns++)
- {
- int Idx = Columns << 2;
-
- byte Row0 = InState[Idx + 0]; // A, E, I, M: [Row0, Col0-Col3]
- byte Row1 = InState[Idx + 1]; // B, F, J, N: [Row1, Col0-Col3]
- byte Row2 = InState[Idx + 2]; // C, G, K, O: [Row2, Col0-Col3]
- byte Row3 = InState[Idx + 3]; // D, H, L, P: [Row3, Col0-Col3]
-
- OutState[Idx + 0] = (byte)((uint)GFMul_02[Row0] ^ GFMul_03[Row1] ^ Row2 ^ Row3);
- OutState[Idx + 1] = (byte)((uint)Row0 ^ GFMul_02[Row1] ^ GFMul_03[Row2] ^ Row3);
- OutState[Idx + 2] = (byte)((uint)Row0 ^ Row1 ^ GFMul_02[Row2] ^ GFMul_03[Row3]);
- OutState[Idx + 3] = (byte)((uint)GFMul_03[Row0] ^ Row1 ^ Row2 ^ GFMul_02[Row3]);
- }
-
- FromByteArrayToVector(OutState, ref op);
-
- return op;
- }
-
- public static Vector128<float> AESShiftRows(Vector128<float> op)
- {
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
-
- FromVectorToByteArray(InState, ref op);
-
- for (int Idx = 0; Idx <= 15; Idx++)
- {
- OutState[SRPerm[Idx]] = InState[Idx];
- }
-
- FromByteArrayToVector(OutState, ref op);
-
- return op;
- }
-
- public static Vector128<float> AESSubBytes(Vector128<float> op)
- {
- byte[] InState = new byte[16];
- byte[] OutState = new byte[16];
-
- FromVectorToByteArray(InState, ref op);
-
- for (int Idx = 0; Idx <= 15; Idx++)
- {
- OutState[Idx] = SBox[InState[Idx]];
- }
-
- FromByteArrayToVector(OutState, ref op);
-
- return op;
- }
-
- private static void FromVectorToByteArray(byte[] State, ref Vector128<float> op)
- {
- ulong ULongLow = AVectorHelper.VectorExtractIntZx((op), (byte)0, 3);
- ulong ULongHigh = AVectorHelper.VectorExtractIntZx((op), (byte)1, 3);
-
- for (int Idx = 0; Idx <= 7; Idx++)
- {
- State[Idx + 0] = (byte)(ULongLow & 0xFFUL);
- State[Idx + 8] = (byte)(ULongHigh & 0xFFUL);
-
- ULongLow >>= 8;
- ULongHigh >>= 8;
- }
- }
-
- private static void FromByteArrayToVector(byte[] State, ref Vector128<float> op)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- op = Sse.StaticCast<byte, float>(Sse2.SetVector128(
- State[15], State[14], State[13], State[12],
- State[11], State[10], State[9], State[8],
- State[7], State[6], State[5], State[4],
- State[3], State[2], State[1], State[0]));
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInst.cs b/ChocolArm64/Instruction/AInst.cs
deleted file mode 100644
index 74093536..00000000
--- a/ChocolArm64/Instruction/AInst.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-
-namespace ChocolArm64.Instruction
-{
- struct AInst
- {
- public AInstInterpreter Interpreter { get; private set; }
- public AInstEmitter Emitter { get; private set; }
- public Type Type { get; private set; }
-
- public static AInst Undefined => new AInst(null, AInstEmit.Und, null);
-
- public AInst(AInstInterpreter Interpreter, AInstEmitter Emitter, Type Type)
- {
- this.Interpreter = Interpreter;
- this.Emitter = Emitter;
- this.Type = Type;
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs
deleted file mode 100644
index 4551346b..00000000
--- a/ChocolArm64/Instruction/AInstEmitAlu.cs
+++ /dev/null
@@ -1,402 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitAluHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Adc(AILEmitterCtx Context) => EmitAdc(Context, false);
- public static void Adcs(AILEmitterCtx Context) => EmitAdc(Context, true);
-
- private static void EmitAdc(AILEmitterCtx Context, bool SetFlags)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Type[] MthdTypes = new Type[] { typeof(bool) };
-
- MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes);
-
- Context.EmitCall(MthdInfo);
-
- if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.Emit(OpCodes.Add);
-
- if (SetFlags)
- {
- Context.EmitZNFlagCheck();
-
- EmitAdcsCCheck(Context);
- EmitAddsVCheck(Context);
- }
-
- EmitDataStore(Context);
- }
-
- public static void Add(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Add);
-
- public static void Adds(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitZNFlagCheck();
-
- EmitAddsCCheck(Context);
- EmitAddsVCheck(Context);
- EmitDataStoreS(Context);
- }
-
- public static void And(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.And);
-
- public static void Ands(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.And);
-
- EmitZeroCVFlags(Context);
-
- Context.EmitZNFlagCheck();
-
- EmitDataStoreS(Context);
- }
-
- public static void Asrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr);
-
- public static void Bic(AILEmitterCtx Context) => EmitBic(Context, false);
- public static void Bics(AILEmitterCtx Context) => EmitBic(Context, true);
-
- private static void EmitBic(AILEmitterCtx Context, bool SetFlags)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
-
- if (SetFlags)
- {
- EmitZeroCVFlags(Context);
-
- Context.EmitZNFlagCheck();
- }
-
- EmitDataStore(Context, SetFlags);
- }
-
- public static void Cls(AILEmitterCtx Context)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitLdc_I4(Op.RegisterSize == ARegisterSize.Int32 ? 32 : 64);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingSigns));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Clz(AILEmitterCtx Context)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Lzcnt.IsSupported)
- {
- Type TValue = Op.RegisterSize == ARegisterSize.Int32 ? typeof(uint) : typeof(ulong);
-
- Context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { TValue }));
- }
- else
- {
- Context.EmitLdc_I4(Op.RegisterSize == ARegisterSize.Int32 ? 32 : 64);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingZeros));
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Eon(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.Xor);
-
- EmitDataStore(Context);
- }
-
- public static void Eor(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Xor);
-
- public static void Extr(AILEmitterCtx Context)
- {
- //TODO: Ensure that the Shift is valid for the Is64Bits.
- AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rm);
-
- if (Op.Shift > 0)
- {
- Context.EmitLdc_I4(Op.Shift);
-
- Context.Emit(OpCodes.Shr_Un);
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdc_I4(Op.GetBitsCount() - Op.Shift);
-
- Context.Emit(OpCodes.Shl);
- Context.Emit(OpCodes.Or);
- }
-
- EmitDataStore(Context);
- }
-
- public static void Lslv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shl);
- public static void Lsrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr_Un);
-
- public static void Sbc(AILEmitterCtx Context) => EmitSbc(Context, false);
- public static void Sbcs(AILEmitterCtx Context) => EmitSbc(Context, true);
-
- private static void EmitSbc(AILEmitterCtx Context, bool SetFlags)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Sub);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Type[] MthdTypes = new Type[] { typeof(bool) };
-
- MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes);
-
- Context.EmitCall(MthdInfo);
-
- Context.EmitLdc_I4(1);
-
- Context.Emit(OpCodes.Xor);
-
- if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.Emit(OpCodes.Sub);
-
- if (SetFlags)
- {
- Context.EmitZNFlagCheck();
-
- EmitSbcsCCheck(Context);
- EmitSubsVCheck(Context);
- }
-
- EmitDataStore(Context);
- }
-
- public static void Sub(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Sub);
-
- public static void Subs(AILEmitterCtx Context)
- {
- Context.TryOptMarkCondWithoutCmp();
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Sub);
-
- Context.EmitZNFlagCheck();
-
- EmitSubsCCheck(Context);
- EmitSubsVCheck(Context);
- EmitDataStoreS(Context);
- }
-
- public static void Orn(AILEmitterCtx Context)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.Or);
-
- EmitDataStore(Context);
- }
-
- public static void Orr(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Or);
-
- public static void Rbit(AILEmitterCtx Context) => EmitFallback32_64(Context,
- nameof(ASoftFallback.ReverseBits32),
- nameof(ASoftFallback.ReverseBits64));
-
- public static void Rev16(AILEmitterCtx Context) => EmitFallback32_64(Context,
- nameof(ASoftFallback.ReverseBytes16_32),
- nameof(ASoftFallback.ReverseBytes16_64));
-
- public static void Rev32(AILEmitterCtx Context) => EmitFallback32_64(Context,
- nameof(ASoftFallback.ReverseBytes32_32),
- nameof(ASoftFallback.ReverseBytes32_64));
-
- private static void EmitFallback32_64(AILEmitterCtx Context, string Name32, string Name64)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Op.RegisterSize == ARegisterSize.Int32)
- {
- ASoftFallback.EmitCall(Context, Name32);
- }
- else
- {
- ASoftFallback.EmitCall(Context, Name64);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Rev64(AILEmitterCtx Context)
- {
- AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBytes64));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Rorv(AILEmitterCtx Context)
- {
- EmitDataLoadRn(Context);
- EmitDataLoadShift(Context);
-
- Context.Emit(OpCodes.Shr_Un);
-
- EmitDataLoadRn(Context);
-
- Context.EmitLdc_I4(Context.CurrOp.GetBitsCount());
-
- EmitDataLoadShift(Context);
-
- Context.Emit(OpCodes.Sub);
- Context.Emit(OpCodes.Shl);
- Context.Emit(OpCodes.Or);
-
- EmitDataStore(Context);
- }
-
- public static void Sdiv(AILEmitterCtx Context) => EmitDiv(Context, OpCodes.Div);
- public static void Udiv(AILEmitterCtx Context) => EmitDiv(Context, OpCodes.Div_Un);
-
- private static void EmitDiv(AILEmitterCtx Context, OpCode ILOp)
- {
- //If Rm == 0, Rd = 0 (division by zero).
- Context.EmitLdc_I(0);
-
- EmitDataLoadRm(Context);
-
- Context.EmitLdc_I(0);
-
- AILLabel BadDiv = new AILLabel();
-
- Context.Emit(OpCodes.Beq_S, BadDiv);
- Context.Emit(OpCodes.Pop);
-
- if (ILOp == OpCodes.Div)
- {
- //If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow).
- long IntMin = 1L << (Context.CurrOp.GetBitsCount() - 1);
-
- Context.EmitLdc_I(IntMin);
-
- EmitDataLoadRn(Context);
-
- Context.EmitLdc_I(IntMin);
-
- Context.Emit(OpCodes.Ceq);
-
- EmitDataLoadRm(Context);
-
- Context.EmitLdc_I(-1);
-
- Context.Emit(OpCodes.Ceq);
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Brtrue_S, BadDiv);
- Context.Emit(OpCodes.Pop);
- }
-
- EmitDataLoadRn(Context);
- EmitDataLoadRm(Context);
-
- Context.Emit(ILOp);
-
- Context.MarkLabel(BadDiv);
-
- EmitDataStore(Context);
- }
-
- private static void EmitDataOp(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitDataLoadOpers(Context);
-
- Context.Emit(ILOp);
-
- EmitDataStore(Context);
- }
-
- private static void EmitDataOpShift(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitDataLoadRn(Context);
- EmitDataLoadShift(Context);
-
- Context.Emit(ILOp);
-
- EmitDataStore(Context);
- }
-
- private static void EmitDataLoadShift(AILEmitterCtx Context)
- {
- EmitDataLoadRm(Context);
-
- Context.EmitLdc_I(Context.CurrOp.GetBitsCount() - 1);
-
- Context.Emit(OpCodes.And);
-
- //Note: Only 32-bits shift values are valid, so when the value is 64-bits
- //we need to cast it to a 32-bits integer. This is fine because we
- //AND the value and only keep the lower 5 or 6 bits anyway -- it
- //could very well fit on a byte.
- if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_I4);
- }
- }
-
- private static void EmitZeroCVFlags(AILEmitterCtx Context)
- {
- Context.EmitLdc_I4(0);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4(0);
-
- Context.EmitStflg((int)APState.CBit);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitAluHelper.cs b/ChocolArm64/Instruction/AInstEmitAluHelper.cs
deleted file mode 100644
index ef9dd7a7..00000000
--- a/ChocolArm64/Instruction/AInstEmitAluHelper.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static class AInstEmitAluHelper
- {
- public static void EmitAdcsCCheck(AILEmitterCtx Context)
- {
- //C = (Rd == Rn && CIn) || Rd < Rn
- Context.EmitSttmp();
- Context.EmitLdtmp();
- Context.EmitLdtmp();
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Ceq);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Context.Emit(OpCodes.And);
-
- Context.EmitLdtmp();
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Clt_Un);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitAddsCCheck(AILEmitterCtx Context)
- {
- //C = Rd < Rn
- Context.Emit(OpCodes.Dup);
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Clt_Un);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitAddsVCheck(AILEmitterCtx Context)
- {
- //V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0
- Context.Emit(OpCodes.Dup);
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Xor);
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Xor);
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I(0);
-
- Context.Emit(OpCodes.Clt);
-
- Context.EmitStflg((int)APState.VBit);
- }
-
- public static void EmitSbcsCCheck(AILEmitterCtx Context)
- {
- //C = (Rn == Rm && CIn) || Rn > Rm
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Ceq);
-
- Context.EmitLdflg((int)APState.CBit);
-
- Context.Emit(OpCodes.And);
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Cgt_Un);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitSubsCCheck(AILEmitterCtx Context)
- {
- //C = Rn == Rm || Rn > Rm = !(Rn < Rm)
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Clt_Un);
-
- Context.EmitLdc_I4(1);
-
- Context.Emit(OpCodes.Xor);
-
- Context.EmitStflg((int)APState.CBit);
- }
-
- public static void EmitSubsVCheck(AILEmitterCtx Context)
- {
- //V = (Rd ^ Rn) & (Rn ^ Rm) < 0
- Context.Emit(OpCodes.Dup);
-
- EmitDataLoadRn(Context);
-
- Context.Emit(OpCodes.Xor);
-
- EmitDataLoadOpers(Context);
-
- Context.Emit(OpCodes.Xor);
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I(0);
-
- Context.Emit(OpCodes.Clt);
-
- Context.EmitStflg((int)APState.VBit);
- }
-
- public static void EmitDataLoadRm(AILEmitterCtx Context)
- {
- Context.EmitLdintzr(((IAOpCodeAluRs)Context.CurrOp).Rm);
- }
-
- public static void EmitDataLoadOpers(AILEmitterCtx Context)
- {
- EmitDataLoadRn(Context);
- EmitDataLoadOper2(Context);
- }
-
- public static void EmitDataLoadRn(AILEmitterCtx Context)
- {
- IAOpCodeAlu Op = (IAOpCodeAlu)Context.CurrOp;
-
- if (Op.DataOp == ADataOp.Logical || Op is IAOpCodeAluRs)
- {
- Context.EmitLdintzr(Op.Rn);
- }
- else
- {
- Context.EmitLdint(Op.Rn);
- }
- }
-
- public static void EmitDataLoadOper2(AILEmitterCtx Context)
- {
- switch (Context.CurrOp)
- {
- case IAOpCodeAluImm Op:
- Context.EmitLdc_I(Op.Imm);
- break;
-
- case IAOpCodeAluRs Op:
- Context.EmitLdintzr(Op.Rm);
-
- switch (Op.ShiftType)
- {
- case AShiftType.Lsl: Context.EmitLsl(Op.Shift); break;
- case AShiftType.Lsr: Context.EmitLsr(Op.Shift); break;
- case AShiftType.Asr: Context.EmitAsr(Op.Shift); break;
- case AShiftType.Ror: Context.EmitRor(Op.Shift); break;
- }
- break;
-
- case IAOpCodeAluRx Op:
- Context.EmitLdintzr(Op.Rm);
- Context.EmitCast(Op.IntType);
- Context.EmitLsl(Op.Shift);
- break;
- }
- }
-
- public static void EmitDataStore(AILEmitterCtx Context) => EmitDataStore(Context, false);
- public static void EmitDataStoreS(AILEmitterCtx Context) => EmitDataStore(Context, true);
-
- public static void EmitDataStore(AILEmitterCtx Context, bool SetFlags)
- {
- IAOpCodeAlu Op = (IAOpCodeAlu)Context.CurrOp;
-
- if (SetFlags || Op is IAOpCodeAluRs)
- {
- Context.EmitStintzr(Op.Rd);
- }
- else
- {
- Context.EmitStint(Op.Rd);
- }
- }
-
- public static void EmitSetNZCV(AILEmitterCtx Context, int NZCV)
- {
- Context.EmitLdc_I4((NZCV >> 0) & 1);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4((NZCV >> 1) & 1);
-
- Context.EmitStflg((int)APState.CBit);
-
- Context.EmitLdc_I4((NZCV >> 2) & 1);
-
- Context.EmitStflg((int)APState.ZBit);
-
- Context.EmitLdc_I4((NZCV >> 3) & 1);
-
- Context.EmitStflg((int)APState.NBit);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitBfm.cs b/ChocolArm64/Instruction/AInstEmitBfm.cs
deleted file mode 100644
index 2e8f2508..00000000
--- a/ChocolArm64/Instruction/AInstEmitBfm.cs
+++ /dev/null
@@ -1,208 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Bfm(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- EmitBfmLoadRn(Context);
-
- Context.EmitLdintzr(Op.Rd);
- Context.EmitLdc_I(~Op.WMask & Op.TMask);
-
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Or);
-
- Context.EmitLdintzr(Op.Rd);
- Context.EmitLdc_I(~Op.TMask);
-
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Sbfm(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- int BitsCount = Op.GetBitsCount();
-
- if (Op.Pos + 1 == BitsCount)
- {
- EmitSbfmShift(Context);
- }
- else if (Op.Pos < Op.Shift)
- {
- EmitSbfiz(Context);
- }
- else if (Op.Pos == 7 && Op.Shift == 0)
- {
- EmitSbfmCast(Context, OpCodes.Conv_I1);
- }
- else if (Op.Pos == 15 && Op.Shift == 0)
- {
- EmitSbfmCast(Context, OpCodes.Conv_I2);
- }
- else if (Op.Pos == 31 && Op.Shift == 0)
- {
- EmitSbfmCast(Context, OpCodes.Conv_I4);
- }
- else
- {
- EmitBfmLoadRn(Context);
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitLsl(BitsCount - 1 - Op.Pos);
- Context.EmitAsr(BitsCount - 1);
-
- Context.EmitLdc_I(~Op.TMask);
-
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-
- public static void Ubfm(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- if (Op.Pos + 1 == Op.GetBitsCount())
- {
- EmitUbfmShift(Context);
- }
- else if (Op.Pos < Op.Shift)
- {
- EmitUbfiz(Context);
- }
- else if (Op.Pos + 1 == Op.Shift)
- {
- EmitBfmLsl(Context);
- }
- else if (Op.Pos == 7 && Op.Shift == 0)
- {
- EmitUbfmCast(Context, OpCodes.Conv_U1);
- }
- else if (Op.Pos == 15 && Op.Shift == 0)
- {
- EmitUbfmCast(Context, OpCodes.Conv_U2);
- }
- else
- {
- EmitBfmLoadRn(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-
- private static void EmitSbfiz(AILEmitterCtx Context) => EmitBfiz(Context, true);
- private static void EmitUbfiz(AILEmitterCtx Context) => EmitBfiz(Context, false);
-
- private static void EmitBfiz(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- int Width = Op.Pos + 1;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitLsl(Op.GetBitsCount() - Width);
-
- if (Signed)
- {
- Context.EmitAsr(Op.Shift - Width);
- }
- else
- {
- Context.EmitLsr(Op.Shift - Width);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitSbfmCast(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitBfmCast(Context, ILOp, true);
- }
-
- private static void EmitUbfmCast(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitBfmCast(Context, ILOp, false);
- }
-
- private static void EmitBfmCast(AILEmitterCtx Context, OpCode ILOp, bool Signed)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(ILOp);
-
- if (Op.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(Signed
- ? OpCodes.Conv_I8
- : OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitSbfmShift(AILEmitterCtx Context)
- {
- EmitBfmShift(Context, true);
- }
-
- private static void EmitUbfmShift(AILEmitterCtx Context)
- {
- EmitBfmShift(Context, false);
- }
-
- private static void EmitBfmShift(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdc_I4(Op.Shift);
-
- Context.Emit(Signed
- ? OpCodes.Shr
- : OpCodes.Shr_Un);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitBfmLsl(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitLsl(Op.GetBitsCount() - Op.Shift);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitBfmLoadRn(AILEmitterCtx Context)
- {
- AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.EmitRor(Op.Shift);
-
- Context.EmitLdc_I(Op.WMask & Op.TMask);
-
- Context.Emit(OpCodes.And);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitCcmp.cs b/ChocolArm64/Instruction/AInstEmitCcmp.cs
deleted file mode 100644
index 7153a6a0..00000000
--- a/ChocolArm64/Instruction/AInstEmitCcmp.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-using static ChocolArm64.Instruction.AInstEmitAluHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- private enum CcmpOp
- {
- Cmp,
- Cmn
- }
-
- public static void Ccmn(AILEmitterCtx Context) => EmitCcmp(Context, CcmpOp.Cmn);
- public static void Ccmp(AILEmitterCtx Context) => EmitCcmp(Context, CcmpOp.Cmp);
-
- private static void EmitCcmp(AILEmitterCtx Context, CcmpOp CmpOp)
- {
- AOpCodeCcmp Op = (AOpCodeCcmp)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.EmitCondBranch(LblTrue, Op.Cond);
-
- Context.EmitLdc_I4((Op.NZCV >> 0) & 1);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 1) & 1);
-
- Context.EmitStflg((int)APState.CBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 2) & 1);
-
- Context.EmitStflg((int)APState.ZBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 3) & 1);
-
- Context.EmitStflg((int)APState.NBit);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- EmitDataLoadOpers(Context);
-
- if (CmpOp == CcmpOp.Cmp)
- {
- Context.Emit(OpCodes.Sub);
-
- Context.EmitZNFlagCheck();
-
- EmitSubsCCheck(Context);
- EmitSubsVCheck(Context);
- }
- else if (CmpOp == CcmpOp.Cmn)
- {
- Context.Emit(OpCodes.Add);
-
- Context.EmitZNFlagCheck();
-
- EmitAddsCCheck(Context);
- EmitAddsVCheck(Context);
- }
- else
- {
- throw new ArgumentException(nameof(CmpOp));
- }
-
- Context.Emit(OpCodes.Pop);
-
- Context.MarkLabel(LblEnd);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitCsel.cs b/ChocolArm64/Instruction/AInstEmitCsel.cs
deleted file mode 100644
index 21876752..00000000
--- a/ChocolArm64/Instruction/AInstEmitCsel.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- private enum CselOperation
- {
- None,
- Increment,
- Invert,
- Negate
- }
-
- public static void Csel(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.None);
- public static void Csinc(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.Increment);
- public static void Csinv(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.Invert);
- public static void Csneg(AILEmitterCtx Context) => EmitCsel(Context, CselOperation.Negate);
-
- private static void EmitCsel(AILEmitterCtx Context, CselOperation CselOp)
- {
- AOpCodeCsel Op = (AOpCodeCsel)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.EmitCondBranch(LblTrue, Op.Cond);
- Context.EmitLdintzr(Op.Rm);
-
- if (CselOp == CselOperation.Increment)
- {
- Context.EmitLdc_I(1);
-
- Context.Emit(OpCodes.Add);
- }
- else if (CselOp == CselOperation.Invert)
- {
- Context.Emit(OpCodes.Not);
- }
- else if (CselOp == CselOperation.Negate)
- {
- Context.Emit(OpCodes.Neg);
- }
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- Context.EmitLdintzr(Op.Rn);
-
- Context.MarkLabel(LblEnd);
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitException.cs b/ChocolArm64/Instruction/AInstEmitException.cs
deleted file mode 100644
index 73d20967..00000000
--- a/ChocolArm64/Instruction/AInstEmitException.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Brk(AILEmitterCtx Context)
- {
- EmitExceptionCall(Context, nameof(AThreadState.OnBreak));
- }
-
- public static void Svc(AILEmitterCtx Context)
- {
- EmitExceptionCall(Context, nameof(AThreadState.OnSvcCall));
- }
-
- private static void EmitExceptionCall(AILEmitterCtx Context, string MthdName)
- {
- AOpCodeException Op = (AOpCodeException)Context.CurrOp;
-
- Context.EmitStoreState();
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitLdc_I8(Op.Position);
- Context.EmitLdc_I4(Op.Id);
-
- Context.EmitPrivateCall(typeof(AThreadState), MthdName);
-
- //Check if the thread should still be running, if it isn't then we return 0
- //to force a return to the dispatcher and then exit the thread.
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Running));
-
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(OpCodes.Brtrue_S, LblEnd);
-
- Context.EmitLdc_I8(0);
-
- Context.Emit(OpCodes.Ret);
-
- Context.MarkLabel(LblEnd);
-
- if (Context.CurrBlock.Next != null)
- {
- Context.EmitLoadState(Context.CurrBlock.Next);
- }
- else
- {
- Context.EmitLdc_I8(Op.Position + 4);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- public static void Und(AILEmitterCtx Context)
- {
- AOpCode Op = Context.CurrOp;
-
- Context.EmitStoreState();
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitLdc_I8(Op.Position);
- Context.EmitLdc_I4(Op.RawOpCode);
-
- Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.OnUndefined));
-
- if (Context.CurrBlock.Next != null)
- {
- Context.EmitLoadState(Context.CurrBlock.Next);
- }
- else
- {
- Context.EmitLdc_I8(Op.Position + 4);
-
- Context.Emit(OpCodes.Ret);
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitFlow.cs b/ChocolArm64/Instruction/AInstEmitFlow.cs
deleted file mode 100644
index 91262834..00000000
--- a/ChocolArm64/Instruction/AInstEmitFlow.cs
+++ /dev/null
@@ -1,189 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void B(AILEmitterCtx Context)
- {
- AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
-
- if (Context.CurrBlock.Branch != null)
- {
- Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm));
- }
- else
- {
- Context.EmitStoreState();
- Context.EmitLdc_I8(Op.Imm);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- public static void B_Cond(AILEmitterCtx Context)
- {
- AOpCodeBImmCond Op = (AOpCodeBImmCond)Context.CurrOp;
-
- EmitBranch(Context, Op.Cond);
- }
-
- public static void Bl(AILEmitterCtx Context)
- {
- AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Position + 4);
- Context.EmitStint(AThreadState.LRIndex);
- Context.EmitStoreState();
-
- if (Context.TryOptEmitSubroutineCall())
- {
- //Note: the return value of the called method will be placed
- //at the Stack, the return value is always a Int64 with the
- //return address of the function. We check if the address is
- //correct, if it isn't we keep returning until we reach the dispatcher.
- Context.Emit(OpCodes.Dup);
-
- Context.EmitLdc_I8(Op.Position + 4);
-
- AILLabel LblContinue = new AILLabel();
-
- Context.Emit(OpCodes.Beq_S, LblContinue);
- Context.Emit(OpCodes.Ret);
-
- Context.MarkLabel(LblContinue);
-
- Context.Emit(OpCodes.Pop);
-
- Context.EmitLoadState(Context.CurrBlock.Next);
- }
- else
- {
- Context.EmitLdc_I8(Op.Imm);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- public static void Blr(AILEmitterCtx Context)
- {
- AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Position + 4);
- Context.EmitStint(AThreadState.LRIndex);
- Context.EmitStoreState();
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(OpCodes.Ret);
- }
-
- public static void Br(AILEmitterCtx Context)
- {
- AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
-
- Context.EmitStoreState();
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(OpCodes.Ret);
- }
-
- public static void Cbnz(AILEmitterCtx Context) => EmitCb(Context, OpCodes.Bne_Un);
- public static void Cbz(AILEmitterCtx Context) => EmitCb(Context, OpCodes.Beq);
-
- private static void EmitCb(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rt);
- Context.EmitLdc_I(0);
-
- EmitBranch(Context, ILOp);
- }
-
- public static void Ret(AILEmitterCtx Context)
- {
- Context.EmitStoreState();
- Context.EmitLdint(AThreadState.LRIndex);
-
- Context.Emit(OpCodes.Ret);
- }
-
- public static void Tbnz(AILEmitterCtx Context) => EmitTb(Context, OpCodes.Bne_Un);
- public static void Tbz(AILEmitterCtx Context) => EmitTb(Context, OpCodes.Beq);
-
- private static void EmitTb(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeBImmTest Op = (AOpCodeBImmTest)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rt);
- Context.EmitLdc_I(1L << Op.Pos);
-
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I(0);
-
- EmitBranch(Context, ILOp);
- }
-
- private static void EmitBranch(AILEmitterCtx Context, ACond Cond)
- {
- AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
-
- if (Context.CurrBlock.Next != null &&
- Context.CurrBlock.Branch != null)
- {
- Context.EmitCondBranch(Context.GetLabel(Op.Imm), Cond);
- }
- else
- {
- Context.EmitStoreState();
-
- AILLabel LblTaken = new AILLabel();
-
- Context.EmitCondBranch(LblTaken, Cond);
-
- Context.EmitLdc_I8(Op.Position + 4);
-
- Context.Emit(OpCodes.Ret);
-
- Context.MarkLabel(LblTaken);
-
- Context.EmitLdc_I8(Op.Imm);
-
- Context.Emit(OpCodes.Ret);
- }
- }
-
- private static void EmitBranch(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
-
- if (Context.CurrBlock.Next != null &&
- Context.CurrBlock.Branch != null)
- {
- Context.Emit(ILOp, Context.GetLabel(Op.Imm));
- }
- else
- {
- Context.EmitStoreState();
-
- AILLabel LblTaken = new AILLabel();
-
- Context.Emit(ILOp, LblTaken);
-
- Context.EmitLdc_I8(Op.Position + 4);
-
- Context.Emit(OpCodes.Ret);
-
- Context.MarkLabel(LblTaken);
-
- Context.EmitLdc_I8(Op.Imm);
-
- Context.Emit(OpCodes.Ret);
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitHash.cs b/ChocolArm64/Instruction/AInstEmitHash.cs
deleted file mode 100644
index 69bdbc48..00000000
--- a/ChocolArm64/Instruction/AInstEmitHash.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Crc32b(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32b));
- }
-
- public static void Crc32h(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32h));
- }
-
- public static void Crc32w(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32w));
- }
-
- public static void Crc32x(AILEmitterCtx Context)
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32x));
- }
-
- public static void Crc32cb(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(uint), typeof(byte));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32cb));
- }
- }
-
- public static void Crc32ch(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(uint), typeof(ushort));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32ch));
- }
- }
-
- public static void Crc32cw(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(uint), typeof(uint));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32cw));
- }
- }
-
- public static void Crc32cx(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse42)
- {
- EmitSse42Crc32(Context, typeof(ulong), typeof(ulong));
- }
- else
- {
- EmitCrc32(Context, nameof(ASoftFallback.Crc32cx));
- }
- }
-
- private static void EmitSse42Crc32(AILEmitterCtx Context, Type TCrc, Type TData)
- {
- AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
-
- Context.EmitCall(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { TCrc, TData }));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitCrc32(AILEmitterCtx Context, string Name)
- {
- AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Op.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- Context.EmitLdintzr(Op.Rm);
-
- ASoftFallback.EmitCall(Context, Name);
-
- if (Op.RegisterSize != ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitMemory.cs b/ChocolArm64/Instruction/AInstEmitMemory.cs
deleted file mode 100644
index 67653ed0..00000000
--- a/ChocolArm64/Instruction/AInstEmitMemory.cs
+++ /dev/null
@@ -1,252 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Adr(AILEmitterCtx Context)
- {
- AOpCodeAdr Op = (AOpCodeAdr)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Position + Op.Imm);
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Adrp(AILEmitterCtx Context)
- {
- AOpCodeAdr Op = (AOpCodeAdr)Context.CurrOp;
-
- Context.EmitLdc_I((Op.Position & ~0xfffL) + (Op.Imm << 12));
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Ldr(AILEmitterCtx Context) => EmitLdr(Context, false);
- public static void Ldrs(AILEmitterCtx Context) => EmitLdr(Context, true);
-
- private static void EmitLdr(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeMem Op = (AOpCodeMem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- if (Signed && Op.Extend64)
- {
- EmitReadSx64Call(Context, Op.Size);
- }
- else if (Signed)
- {
- EmitReadSx32Call(Context, Op.Size);
- }
- else
- {
- EmitReadZxCall(Context, Op.Size);
- }
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitStvec(Op.Rt);
- }
- else
- {
- Context.EmitStintzr(Op.Rt);
- }
-
- EmitWBackIfNeeded(Context);
- }
-
- public static void LdrLit(AILEmitterCtx Context)
- {
- IAOpCodeLit Op = (IAOpCodeLit)Context.CurrOp;
-
- if (Op.Prefetch)
- {
- return;
- }
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdc_I8(Op.Imm);
-
- if (Op.Signed)
- {
- EmitReadSx64Call(Context, Op.Size);
- }
- else
- {
- EmitReadZxCall(Context, Op.Size);
- }
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitStvec(Op.Rt);
- }
- else
- {
- Context.EmitStint(Op.Rt);
- }
- }
-
- public static void Ldp(AILEmitterCtx Context)
- {
- AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;
-
- void EmitReadAndStore(int Rt)
- {
- if (Op.Extend64)
- {
- EmitReadSx64Call(Context, Op.Size);
- }
- else
- {
- EmitReadZxCall(Context, Op.Size);
- }
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitStvec(Rt);
- }
- else
- {
- Context.EmitStintzr(Rt);
- }
- }
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- EmitReadAndStore(Op.Rt);
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- EmitReadAndStore(Op.Rt2);
-
- EmitWBackIfNeeded(Context);
- }
-
- public static void Str(AILEmitterCtx Context)
- {
- AOpCodeMem Op = (AOpCodeMem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitLdvec(Op.Rt);
- }
- else
- {
- Context.EmitLdintzr(Op.Rt);
- }
-
- EmitWriteCall(Context, Op.Size);
-
- EmitWBackIfNeeded(Context);
- }
-
- public static void Stp(AILEmitterCtx Context)
- {
- AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
-
- EmitLoadAddress(Context);
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitLdvec(Op.Rt);
- }
- else
- {
- Context.EmitLdintzr(Op.Rt);
- }
-
- EmitWriteCall(Context, Op.Size);
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- if (Op is IAOpCodeSimd)
- {
- Context.EmitLdvec(Op.Rt2);
- }
- else
- {
- Context.EmitLdintzr(Op.Rt2);
- }
-
- EmitWriteCall(Context, Op.Size);
-
- EmitWBackIfNeeded(Context);
- }
-
- private static void EmitLoadAddress(AILEmitterCtx Context)
- {
- switch (Context.CurrOp)
- {
- case AOpCodeMemImm Op:
- Context.EmitLdint(Op.Rn);
-
- if (!Op.PostIdx)
- {
- //Pre-indexing.
- Context.EmitLdc_I(Op.Imm);
-
- Context.Emit(OpCodes.Add);
- }
- break;
-
- case AOpCodeMemReg Op:
- Context.EmitLdint(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
- Context.EmitCast(Op.IntType);
-
- if (Op.Shift)
- {
- Context.EmitLsl(Op.Size);
- }
-
- Context.Emit(OpCodes.Add);
- break;
- }
-
- //Save address to Scratch var since the register value may change.
- Context.Emit(OpCodes.Dup);
-
- Context.EmitSttmp();
- }
-
- private static void EmitWBackIfNeeded(AILEmitterCtx Context)
- {
- //Check whenever the current OpCode has post-indexed write back, if so write it.
- //Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both.
- if (Context.CurrOp is AOpCodeMemImm Op && Op.WBack)
- {
- Context.EmitLdtmp();
-
- if (Op.PostIdx)
- {
- Context.EmitLdc_I(Op.Imm);
-
- Context.Emit(OpCodes.Add);
- }
-
- Context.EmitStint(Op.Rn);
- }
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMemoryEx.cs b/ChocolArm64/Instruction/AInstEmitMemoryEx.cs
deleted file mode 100644
index cf19b4a1..00000000
--- a/ChocolArm64/Instruction/AInstEmitMemoryEx.cs
+++ /dev/null
@@ -1,192 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Threading;
-
-using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- [Flags]
- private enum AccessType
- {
- None = 0,
- Ordered = 1,
- Exclusive = 2,
- OrderedEx = Ordered | Exclusive
- }
-
- public static void Clrex(AILEmitterCtx Context)
- {
- EmitMemoryCall(Context, nameof(AMemory.ClearExclusive));
- }
-
- public static void Dmb(AILEmitterCtx Context) => EmitBarrier(Context);
- public static void Dsb(AILEmitterCtx Context) => EmitBarrier(Context);
-
- public static void Ldar(AILEmitterCtx Context) => EmitLdr(Context, AccessType.Ordered);
- public static void Ldaxr(AILEmitterCtx Context) => EmitLdr(Context, AccessType.OrderedEx);
- public static void Ldxr(AILEmitterCtx Context) => EmitLdr(Context, AccessType.Exclusive);
- public static void Ldxp(AILEmitterCtx Context) => EmitLdp(Context, AccessType.Exclusive);
- public static void Ldaxp(AILEmitterCtx Context) => EmitLdp(Context, AccessType.OrderedEx);
-
- private static void EmitLdr(AILEmitterCtx Context, AccessType AccType)
- {
- EmitLoad(Context, AccType, false);
- }
-
- private static void EmitLdp(AILEmitterCtx Context, AccessType AccType)
- {
- EmitLoad(Context, AccType, true);
- }
-
- private static void EmitLoad(AILEmitterCtx Context, AccessType AccType, bool Pair)
- {
- AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;
-
- bool Ordered = (AccType & AccessType.Ordered) != 0;
- bool Exclusive = (AccType & AccessType.Exclusive) != 0;
-
- if (Ordered)
- {
- EmitBarrier(Context);
- }
-
- if (Exclusive)
- {
- EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn);
- }
-
- Context.EmitLdint(Op.Rn);
- Context.EmitSttmp();
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
-
- EmitReadZxCall(Context, Op.Size);
-
- Context.EmitStintzr(Op.Rt);
-
- if (Pair)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdtmp();
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- EmitReadZxCall(Context, Op.Size);
-
- Context.EmitStintzr(Op.Rt2);
- }
- }
-
- public static void Pfrm(AILEmitterCtx Context)
- {
- //Memory Prefetch, execute as no-op.
- }
-
- public static void Stlr(AILEmitterCtx Context) => EmitStr(Context, AccessType.Ordered);
- public static void Stlxr(AILEmitterCtx Context) => EmitStr(Context, AccessType.OrderedEx);
- public static void Stxr(AILEmitterCtx Context) => EmitStr(Context, AccessType.Exclusive);
- public static void Stxp(AILEmitterCtx Context) => EmitStp(Context, AccessType.Exclusive);
- public static void Stlxp(AILEmitterCtx Context) => EmitStp(Context, AccessType.OrderedEx);
-
- private static void EmitStr(AILEmitterCtx Context, AccessType AccType)
- {
- EmitStore(Context, AccType, false);
- }
-
- private static void EmitStp(AILEmitterCtx Context, AccessType AccType)
- {
- EmitStore(Context, AccType, true);
- }
-
- private static void EmitStore(AILEmitterCtx Context, AccessType AccType, bool Pair)
- {
- AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;
-
- bool Ordered = (AccType & AccessType.Ordered) != 0;
- bool Exclusive = (AccType & AccessType.Exclusive) != 0;
-
- if (Ordered)
- {
- EmitBarrier(Context);
- }
-
- AILLabel LblEx = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- if (Exclusive)
- {
- EmitMemoryCall(Context, nameof(AMemory.TestExclusive), Op.Rn);
-
- Context.Emit(OpCodes.Brtrue_S, LblEx);
-
- Context.EmitLdc_I8(1);
- Context.EmitStintzr(Op.Rs);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
- }
-
- Context.MarkLabel(LblEx);
-
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdintzr(Op.Rt);
-
- EmitWriteCall(Context, Op.Size);
-
- if (Pair)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(1 << Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitLdintzr(Op.Rt2);
-
- EmitWriteCall(Context, Op.Size);
- }
-
- if (Exclusive)
- {
- Context.EmitLdc_I8(0);
- Context.EmitStintzr(Op.Rs);
-
- EmitMemoryCall(Context, nameof(AMemory.ClearExclusiveForStore));
- }
-
- Context.MarkLabel(LblEnd);
- }
-
- private static void EmitMemoryCall(AILEmitterCtx Context, string Name, int Rn = -1)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Core));
-
- if (Rn != -1)
- {
- Context.EmitLdint(Rn);
- }
-
- Context.EmitCall(typeof(AMemory), Name);
- }
-
- private static void EmitBarrier(AILEmitterCtx Context)
- {
- //Note: This barrier is most likely not necessary, and probably
- //doesn't make any difference since we need to do a ton of stuff
- //(software MMU emulation) to read or write anything anyway.
- Context.EmitCall(typeof(Thread), nameof(Thread.MemoryBarrier));
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
deleted file mode 100644
index b10551fe..00000000
--- a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Memory;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static class AInstEmitMemoryHelper
- {
- private enum Extension
- {
- Zx,
- Sx32,
- Sx64
- }
-
- public static void EmitReadZxCall(AILEmitterCtx Context, int Size)
- {
- EmitReadCall(Context, Extension.Zx, Size);
- }
-
- public static void EmitReadSx32Call(AILEmitterCtx Context, int Size)
- {
- EmitReadCall(Context, Extension.Sx32, Size);
- }
-
- public static void EmitReadSx64Call(AILEmitterCtx Context, int Size)
- {
- EmitReadCall(Context, Extension.Sx64, Size);
- }
-
- private static void EmitReadCall(AILEmitterCtx Context, Extension Ext, int Size)
- {
- bool IsSimd = GetIsSimd(Context);
-
- string Name = null;
-
- if (Size < 0 || Size > (IsSimd ? 4 : 3))
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- if (IsSimd)
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.ReadVector8); break;
- case 1: Name = nameof(AMemory.ReadVector16); break;
- case 2: Name = nameof(AMemory.ReadVector32); break;
- case 3: Name = nameof(AMemory.ReadVector64); break;
- case 4: Name = nameof(AMemory.ReadVector128); break;
- }
- }
- else
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.ReadByte); break;
- case 1: Name = nameof(AMemory.ReadUInt16); break;
- case 2: Name = nameof(AMemory.ReadUInt32); break;
- case 3: Name = nameof(AMemory.ReadUInt64); break;
- }
- }
-
- Context.EmitCall(typeof(AMemory), Name);
-
- if (!IsSimd)
- {
- if (Ext == Extension.Sx32 ||
- Ext == Extension.Sx64)
- {
- switch (Size)
- {
- case 0: Context.Emit(OpCodes.Conv_I1); break;
- case 1: Context.Emit(OpCodes.Conv_I2); break;
- case 2: Context.Emit(OpCodes.Conv_I4); break;
- }
- }
-
- if (Size < 3)
- {
- Context.Emit(Ext == Extension.Sx64
- ? OpCodes.Conv_I8
- : OpCodes.Conv_U8);
- }
- }
- }
-
- public static void EmitWriteCall(AILEmitterCtx Context, int Size)
- {
- bool IsSimd = GetIsSimd(Context);
-
- string Name = null;
-
- if (Size < 0 || Size > (IsSimd ? 4 : 3))
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- if (Size < 3 && !IsSimd)
- {
- Context.Emit(OpCodes.Conv_I4);
- }
-
- if (IsSimd)
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.WriteVector8); break;
- case 1: Name = nameof(AMemory.WriteVector16); break;
- case 2: Name = nameof(AMemory.WriteVector32); break;
- case 3: Name = nameof(AMemory.WriteVector64); break;
- case 4: Name = nameof(AMemory.WriteVector128); break;
- }
- }
- else
- {
- switch (Size)
- {
- case 0: Name = nameof(AMemory.WriteByte); break;
- case 1: Name = nameof(AMemory.WriteUInt16); break;
- case 2: Name = nameof(AMemory.WriteUInt32); break;
- case 3: Name = nameof(AMemory.WriteUInt64); break;
- }
- }
-
- Context.EmitCall(typeof(AMemory), Name);
- }
-
- private static bool GetIsSimd(AILEmitterCtx Context)
- {
- return Context.CurrOp is IAOpCodeSimd &&
- !(Context.CurrOp is AOpCodeSimdMemMs ||
- Context.CurrOp is AOpCodeSimdMemSs);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMove.cs b/ChocolArm64/Instruction/AInstEmitMove.cs
deleted file mode 100644
index 719b53d5..00000000
--- a/ChocolArm64/Instruction/AInstEmitMove.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Movk(AILEmitterCtx Context)
- {
- AOpCodeMov Op = (AOpCodeMov)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rd);
- Context.EmitLdc_I(~(0xffffL << Op.Pos));
-
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I(Op.Imm);
-
- Context.Emit(OpCodes.Or);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Movn(AILEmitterCtx Context)
- {
- AOpCodeMov Op = (AOpCodeMov)Context.CurrOp;
-
- Context.EmitLdc_I(~Op.Imm);
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Movz(AILEmitterCtx Context)
- {
- AOpCodeMov Op = (AOpCodeMov)Context.CurrOp;
-
- Context.EmitLdc_I(Op.Imm);
- Context.EmitStintzr(Op.Rd);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMul.cs b/ChocolArm64/Instruction/AInstEmitMul.cs
deleted file mode 100644
index 3713c81f..00000000
--- a/ChocolArm64/Instruction/AInstEmitMul.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Madd(AILEmitterCtx Context) => EmitMul(Context, OpCodes.Add);
- public static void Msub(AILEmitterCtx Context) => EmitMul(Context, OpCodes.Sub);
-
- private static void EmitMul(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Ra);
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
-
- Context.Emit(OpCodes.Mul);
- Context.Emit(ILOp);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Smaddl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Add, true);
- public static void Smsubl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Sub, true);
- public static void Umaddl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Add, false);
- public static void Umsubl(AILEmitterCtx Context) => EmitMull(Context, OpCodes.Sub, false);
-
- private static void EmitMull(AILEmitterCtx Context, OpCode AddSubOp, bool Signed)
- {
- AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;
-
- OpCode CastOp = Signed
- ? OpCodes.Conv_I8
- : OpCodes.Conv_U8;
-
- Context.EmitLdintzr(Op.Ra);
- Context.EmitLdintzr(Op.Rn);
-
- Context.Emit(OpCodes.Conv_I4);
- Context.Emit(CastOp);
-
- Context.EmitLdintzr(Op.Rm);
-
- Context.Emit(OpCodes.Conv_I4);
- Context.Emit(CastOp);
- Context.Emit(OpCodes.Mul);
-
- Context.Emit(AddSubOp);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Smulh(AILEmitterCtx Context)
- {
- AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SMulHi128));
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Umulh(AILEmitterCtx Context)
- {
- AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdintzr(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UMulHi128));
-
- Context.EmitStintzr(Op.Rd);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
deleted file mode 100644
index 1bd48364..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
+++ /dev/null
@@ -1,2387 +0,0 @@
-// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h
-
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Abs_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Abs_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Add_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Add_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Add));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
- }
-
- public static void Addhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Add), Round: false);
- }
-
- public static void Addp_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
- EmitVectorExtractZx(Context, Op.Rn, 1, Op.Size);
-
- Context.Emit(OpCodes.Add);
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void Addp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Addv_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
-
- for (int Index = 1; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void Cls_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- int ESize = 8 << Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.EmitLdc_I4(ESize);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingSigns));
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Clz_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- int ESize = 8 << Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- if (Lzcnt.IsSupported && ESize == 32)
- {
- Context.Emit(OpCodes.Conv_U4);
-
- Context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { typeof(uint) }));
-
- Context.Emit(OpCodes.Conv_U8);
- }
- else
- {
- Context.EmitLdc_I4(ESize);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingZeros));
- }
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Cnt_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, 0);
-
- if (Popcnt.IsSupported)
- {
- Context.EmitCall(typeof(Popcnt).GetMethod(nameof(Popcnt.PopCount), new Type[] { typeof(ulong) }));
- }
- else
- {
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountSetBits8));
- }
-
- EmitVectorInsert(Context, Op.Rd, Index, 0);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Fabd_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
-
- EmitUnaryMathCall(Context, nameof(Math.Abs));
- });
- }
-
- public static void Fabs_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Abs));
- });
- }
-
- public static void Fabs_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Abs));
- });
- }
-
- public static void Fadd_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.AddScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPAdd));
- });
- }
- }
-
- public static void Fadd_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Add));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPAdd));
- });
- }
- }
-
- public static void Faddp_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
- EmitVectorExtractF(Context, Op.Rn, 1, SizeF);
-
- Context.Emit(OpCodes.Add);
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void Faddp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpF(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Fdiv_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.DivideScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPDiv));
- });
- }
- }
-
- public static void Fdiv_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Divide));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPDiv));
- });
- }
- }
-
- public static void Fmadd_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (Op.Size == 0)
- {
- Type[] TypesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdvec(Op.Ra);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulAdd));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AddScalar), TypesMulAdd));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (Op.Size == 1) */
- {
- Type[] TypesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- EmitLdvecWithCastToDouble(Context, Op.Ra);
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulAdd));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AddScalar), TypesMulAdd));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarTernaryRaOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulAdd));
- });
- }
- }
-
- public static void Fmax_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.MaxScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax));
- });
- }
- }
-
- public static void Fmax_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Max));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax));
- });
- }
- }
-
- public static void Fmaxnm_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMaxNum));
- });
- }
-
- public static void Fmaxnm_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMaxNum));
- });
- }
-
- public static void Fmaxp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax));
- });
- }
-
- public static void Fmin_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.MinScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin));
- });
- }
- }
-
- public static void Fmin_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Min));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin));
- });
- }
- }
-
- public static void Fminnm_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMinNum));
- });
- }
-
- public static void Fminnm_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMinNum));
- });
- }
-
- public static void Fminp_V(AILEmitterCtx Context)
- {
- EmitVectorPairwiseOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin));
- });
- }
-
- public static void Fmla_Se(AILEmitterCtx Context)
- {
- EmitScalarTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Fmla_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Fmla_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Fmls_Se(AILEmitterCtx Context)
- {
- EmitScalarTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Fmls_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Fmls_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Fmsub_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (Op.Size == 0)
- {
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdvec(Op.Ra);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (Op.Size == 1) */
- {
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- EmitLdvecWithCastToDouble(Context, Op.Ra);
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarTernaryRaOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulSub));
- });
- }
- }
-
- public static void Fmul_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.MultiplyScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMul));
- });
- }
- }
-
- public static void Fmul_Se(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Fmul_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Multiply));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMul));
- });
- }
- }
-
- public static void Fmul_Ve(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Fmulx_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fmulx_Se(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpByElemF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fmulx_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fmulx_Ve(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpByElemF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX));
- });
- }
-
- public static void Fneg_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Fneg_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Fnmadd_S(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
-
- Context.Emit(OpCodes.Neg);
-
- EmitVectorExtractF(Context, Op.Rm, 0, SizeF);
-
- Context.Emit(OpCodes.Mul);
-
- EmitVectorExtractF(Context, Op.Ra, 0, SizeF);
-
- Context.Emit(OpCodes.Sub);
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void Fnmsub_S(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
- EmitVectorExtractF(Context, Op.Rm, 0, SizeF);
-
- Context.Emit(OpCodes.Mul);
-
- EmitVectorExtractF(Context, Op.Ra, 0, SizeF);
-
- Context.Emit(OpCodes.Sub);
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void Fnmul_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Neg);
- });
- }
-
- public static void Frecpe_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.RecipEstimate));
- });
- }
-
- public static void Frecpe_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.RecipEstimate));
- });
- }
-
- public static void Frecps_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSsv = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(2f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), TypesSsv));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSsv = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(2d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), TypesSsv));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecipStepFused));
- });
- }
- }
-
- public static void Frecps_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSav = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(2f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), TypesSav));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSav = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(2d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecipStepFused));
- });
- }
- }
-
- public static void Frecpx_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecpX));
- });
- }
-
- public static void Frinta_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Frinta_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
- });
- }
-
- public static void Frinti_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitScalarUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (Op.Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (Op.Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frinti_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- EmitVectorUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (SizeF == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frintm_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Floor));
- });
- }
-
- public static void Frintm_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Floor));
- });
- }
-
- public static void Frintn_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitRoundMathCall(Context, MidpointRounding.ToEven);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Frintn_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitRoundMathCall(Context, MidpointRounding.ToEven);
- });
- }
-
- public static void Frintp_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Ceiling));
- });
- }
-
- public static void Frintp_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnaryMathCall(Context, nameof(Math.Ceiling));
- });
- }
-
- public static void Frintx_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitScalarUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (Op.Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (Op.Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frintx_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorUnaryOpF(Context, () =>
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (Op.Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
- }
- else if (Op.Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
- }
- else
- {
- throw new InvalidOperationException();
- }
- });
- }
-
- public static void Frsqrte_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.InvSqrtEstimate));
- });
- }
-
- public static void Frsqrte_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.InvSqrtEstimate));
- });
- }
-
- public static void Frsqrts_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSsv = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(0.5f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), TypesSsv));
-
- Context.EmitLdc_R4(3f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), TypesSsv));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSsv = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(0.5d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), TypesSsv));
-
- Context.EmitLdc_R8(3d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), TypesSsv));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused));
- });
- }
- }
-
- public static void Frsqrts_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (SizeF == 0)
- {
- Type[] TypesSav = new Type[] { typeof(float) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
-
- Context.EmitLdc_R4(0.5f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), TypesSav));
-
- Context.EmitLdc_R4(3f);
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), TypesSav));
-
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), TypesMulSub));
- Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), TypesMulSub));
-
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else /* if (SizeF == 1) */
- {
- Type[] TypesSav = new Type[] { typeof(double) };
- Type[] TypesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
-
- Context.EmitLdc_R8(0.5d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- Context.EmitLdc_R8(3d);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
- EmitLdvecWithCastToDouble(Context, Op.Rm);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), TypesMulSub));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused));
- });
- }
- }
-
- public static void Fsqrt_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.SqrtScalar));
- }
- else
- {
- EmitScalarUnaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt));
- });
- }
- }
-
- public static void Fsqrt_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Sqrt));
- }
- else
- {
- EmitVectorUnaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt));
- });
- }
- }
-
- public static void Fsub_S(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.SubtractScalar));
- }
- else
- {
- EmitScalarBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSub));
- });
- }
- }
-
- public static void Fsub_V(AILEmitterCtx Context)
- {
- if (AOptimizations.FastFP && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.Subtract));
- }
- else
- {
- EmitVectorBinaryOpF(Context, () =>
- {
- EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSub));
- });
- }
- }
-
- public static void Mla_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Mla_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Mls_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Mls_Ve(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpByElemZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
-
- public static void Mul_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Mul_Ve(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpByElemZx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Neg_S(AILEmitterCtx Context)
- {
- EmitScalarUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Neg_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Raddhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Add), Round: true);
- }
-
- public static void Rsubhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Sub), Round: true);
- }
-
- public static void Saba_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Sabal_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Sabd_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Sabdl_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Sadalp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: true, Accumulate: true);
- }
-
- public static void Saddl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Type[] TypesSrl = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size + 1],
- VectorIntTypesPerSizeLog2[Op.Size + 1] };
-
- string[] NamesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16),
- nameof(Sse41.ConvertToVector128Int32),
- nameof(Sse41.ConvertToVector128Int64) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
- }
- }
-
- public static void Saddlp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: true, Accumulate: false);
- }
-
- public static void Saddw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Shadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAndXorAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], VectorIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), TypesAndXorAdd));
-
- Context.EmitLdvectmp();
- Context.EmitLdvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), TypesAndXorAdd));
-
- Context.EmitLdc_I4(1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAndXorAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Add);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Shr);
- });
- }
- }
-
- public static void Shsub_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size < 2)
- {
- Type[] TypesSav = new Type[] { IntTypesPerSizeLog2[Op.Size] };
- Type[] TypesAddSub = new Type[] { VectorIntTypesPerSizeLog2 [Op.Size], VectorIntTypesPerSizeLog2 [Op.Size] };
- Type[] TypesAvg = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- Context.EmitLdc_I4(Op.Size == 0 ? sbyte.MinValue : short.MinValue);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- Context.EmitStvectmp();
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
- Context.EmitLdvectmp();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAddSub));
-
- Context.Emit(OpCodes.Dup);
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
- Context.EmitLdvectmp();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAddSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), TypesAvg));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesAddSub));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Shr);
- });
- }
- }
-
- public static void Smax_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(long), typeof(long) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
-
- EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Smaxp_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(long), typeof(long) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
-
- EmitVectorPairwiseOpSx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Smin_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(long), typeof(long) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
-
- EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Sminp_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(long), typeof(long) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
-
- EmitVectorPairwiseOpSx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Smlal_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse41 && Op.Size < 2)
- {
- Type[] TypesSrl = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesMulAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size + 1],
- VectorIntTypesPerSizeLog2[Op.Size + 1] };
-
- Type TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulAdd));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesMulAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
- }
-
- public static void Smlsl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse41 && Op.Size < 2)
- {
- Type[] TypesSrl = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesMulSub = new Type[] { VectorIntTypesPerSizeLog2[Op.Size + 1],
- VectorIntTypesPerSizeLog2[Op.Size + 1] };
-
- Type TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
- }
-
- public static void Smull_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Sqabs_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Sqabs_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingUnaryOpSx(Context, () => EmitAbs(Context));
- }
-
- public static void Sqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Add);
- }
-
- public static void Sqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Add);
- }
-
- public static void Sqdmulh_S(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: false), SaturatingFlags.ScalarSx);
- }
-
- public static void Sqdmulh_V(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: false), SaturatingFlags.VectorSx);
- }
-
- public static void Sqneg_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Sqneg_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
- }
-
- public static void Sqrdmulh_S(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: true), SaturatingFlags.ScalarSx);
- }
-
- public static void Sqrdmulh_V(AILEmitterCtx Context)
- {
- EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: true), SaturatingFlags.VectorSx);
- }
-
- public static void Sqsub_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Sub);
- }
-
- public static void Sqsub_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Sub);
- }
-
- public static void Sqxtn_S(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarSxSx);
- }
-
- public static void Sqxtn_V(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorSxSx);
- }
-
- public static void Sqxtun_S(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarSxZx);
- }
-
- public static void Sqxtun_V(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorSxZx);
- }
-
- public static void Srhadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size < 2)
- {
- Type[] TypesSav = new Type[] { IntTypesPerSizeLog2[Op.Size] };
- Type[] TypesSubAdd = new Type[] { VectorIntTypesPerSizeLog2 [Op.Size], VectorIntTypesPerSizeLog2 [Op.Size] };
- Type[] TypesAvg = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- Context.EmitLdc_I4(Op.Size == 0 ? sbyte.MinValue : short.MinValue);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), TypesSav));
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
- Context.EmitLdvectmp();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesSubAdd));
-
- EmitLdvecWithSignedCast(Context, Op.Rm, Op.Size);
- Context.EmitLdvectmp();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesSubAdd));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), TypesAvg));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesSubAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpSx(Context, () =>
- {
- Context.Emit(OpCodes.Add);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Add);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Shr);
- });
- }
- }
-
- public static void Ssubl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Type[] TypesSrl = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesSub = new Type[] { VectorIntTypesPerSizeLog2[Op.Size + 1],
- VectorIntTypesPerSizeLog2[Op.Size + 1] };
-
- string[] NamesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16),
- nameof(Sse41.ConvertToVector128Int32),
- nameof(Sse41.ConvertToVector128Int64) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesSub));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Sub));
- }
- }
-
- public static void Ssubw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Sub));
- }
-
- public static void Sub_S(AILEmitterCtx Context)
- {
- EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
-
- public static void Sub_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Subtract));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
- }
-
- public static void Subhn_V(AILEmitterCtx Context)
- {
- EmitHighNarrow(Context, () => Context.Emit(OpCodes.Sub), Round: false);
- }
-
- public static void Suqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Suqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Uaba_V(AILEmitterCtx Context)
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Uabal_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
-
- Context.Emit(OpCodes.Add);
- });
- }
-
- public static void Uabd_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Uabdl_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
- EmitAbs(Context);
- });
- }
-
- public static void Uadalp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: false, Accumulate: true);
- }
-
- public static void Uaddl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size + 1],
- VectorUIntTypesPerSizeLog2[Op.Size + 1] };
-
- string[] NamesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16),
- nameof(Sse41.ConvertToVector128Int32),
- nameof(Sse41.ConvertToVector128Int64) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
- }
-
- public static void Uaddlp_V(AILEmitterCtx Context)
- {
- EmitAddLongPairwise(Context, Signed: false, Accumulate: false);
- }
-
- public static void Uaddlv_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
-
- for (int Index = 1; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitScalarSet(Context, Op.Rd, Op.Size + 1);
- }
-
- public static void Uaddw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
- }
-
- public static void Uhadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAndXorAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), TypesAndXorAdd));
-
- Context.EmitLdvectmp();
- Context.EmitLdvectmp2();
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), TypesAndXorAdd));
-
- Context.EmitLdc_I4(1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAndXorAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Add);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Shr_Un);
- });
- }
- }
-
- public static void Uhsub_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size < 2)
- {
- Type[] TypesAvgSub = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- Context.Emit(OpCodes.Dup);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), TypesAvgSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesAvgSub));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Sub);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Shr_Un);
- });
- }
- }
-
- public static void Umax_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(ulong), typeof(ulong) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
-
- EmitVectorBinaryOpZx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Umaxp_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(ulong), typeof(ulong) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
-
- EmitVectorPairwiseOpZx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Umin_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(ulong), typeof(ulong) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
-
- EmitVectorBinaryOpZx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Uminp_V(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(ulong), typeof(ulong) };
-
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
-
- EmitVectorPairwiseOpZx(Context, () => Context.EmitCall(MthdInfo));
- }
-
- public static void Umlal_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse41 && Op.Size < 2)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesMulAdd = new Type[] { VectorIntTypesPerSizeLog2 [Op.Size + 1],
- VectorIntTypesPerSizeLog2 [Op.Size + 1] };
-
- Type TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulAdd));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesMulAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
- }
-
- public static void Umlsl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse41 && Op.Size < 2)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesMulSub = new Type[] { VectorIntTypesPerSizeLog2 [Op.Size + 1],
- VectorIntTypesPerSizeLog2 [Op.Size + 1] };
-
- Type TypeMul = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- string NameCvt = Op.Size == 0
- ? nameof(Sse41.ConvertToVector128Int16)
- : nameof(Sse41.ConvertToVector128Int32);
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NameCvt, TypesCvt));
-
- Context.EmitCall(TypeMul.GetMethod(nameof(Sse2.MultiplyLow), TypesMulSub));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesMulSub));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmTernaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Sub);
- });
- }
- }
-
- public static void Umull_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
- }
-
- public static void Uqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpZx(Context, SaturatingFlags.Add);
- }
-
- public static void Uqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpZx(Context, SaturatingFlags.Add);
- }
-
- public static void Uqsub_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpZx(Context, SaturatingFlags.Sub);
- }
-
- public static void Uqsub_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpZx(Context, SaturatingFlags.Sub);
- }
-
- public static void Uqxtn_S(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarZxZx);
- }
-
- public static void Uqxtn_V(AILEmitterCtx Context)
- {
- EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorZxZx);
- }
-
- public static void Urhadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size < 2)
- {
- Type[] TypesAvg = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), TypesAvg));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Add);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Add);
-
- Context.Emit(OpCodes.Ldc_I4_1);
- Context.Emit(OpCodes.Shr_Un);
- });
- }
- }
-
- public static void Usqadd_S(AILEmitterCtx Context)
- {
- EmitScalarSaturatingBinaryOpZx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Usqadd_V(AILEmitterCtx Context)
- {
- EmitVectorSaturatingBinaryOpZx(Context, SaturatingFlags.Accumulate);
- }
-
- public static void Usubl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse41)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesCvt = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size] };
- Type[] TypesSub = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size + 1],
- VectorUIntTypesPerSizeLog2[Op.Size + 1] };
-
- string[] NamesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16),
- nameof(Sse41.ConvertToVector128Int32),
- nameof(Sse41.ConvertToVector128Int64) };
-
- int NumBytes = Op.RegisterSize == ARegisterSize.SIMD128 ? 8 : 0;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitLdc_I4(NumBytes);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), TypesSrl));
-
- Context.EmitCall(typeof(Sse41).GetMethod(NamesCvt[Op.Size], TypesCvt));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), TypesSub));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size + 1);
- }
- else
- {
- EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
- }
-
- public static void Usubw_V(AILEmitterCtx Context)
- {
- EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
- }
-
- private static void EmitAbs(AILEmitterCtx Context)
- {
- AILLabel LblTrue = new AILLabel();
-
- Context.Emit(OpCodes.Dup);
- Context.Emit(OpCodes.Ldc_I4_0);
- Context.Emit(OpCodes.Bge_S, LblTrue);
-
- Context.Emit(OpCodes.Neg);
-
- Context.MarkLabel(LblTrue);
- }
-
- private static void EmitAddLongPairwise(AILEmitterCtx Context, bool Signed, bool Accumulate)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Words = Op.GetBitsCount() >> 4;
- int Pairs = Words >> Op.Size;
-
- for (int Index = 0; Index < Pairs; Index++)
- {
- int Idx = Index << 1;
-
- EmitVectorExtract(Context, Op.Rn, Idx, Op.Size, Signed);
- EmitVectorExtract(Context, Op.Rn, Idx + 1, Op.Size, Signed);
-
- Context.Emit(OpCodes.Add);
-
- if (Accumulate)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size + 1, Signed);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size + 1);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitDoublingMultiplyHighHalf(AILEmitterCtx Context, bool Round)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int ESize = 8 << Op.Size;
-
- Context.Emit(OpCodes.Mul);
-
- if (!Round)
- {
- Context.EmitAsr(ESize - 1);
- }
- else
- {
- long RoundConst = 1L << (ESize - 1);
-
- AILLabel LblTrue = new AILLabel();
-
- Context.EmitLsl(1);
-
- Context.EmitLdc_I8(RoundConst);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitAsr(ESize);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitLdc_I8((long)int.MinValue);
- Context.Emit(OpCodes.Bne_Un_S, LblTrue);
-
- Context.Emit(OpCodes.Neg);
-
- Context.MarkLabel(LblTrue);
- }
- }
-
- private static void EmitHighNarrow(AILEmitterCtx Context, Action Emit, bool Round)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int ESize = 8 << Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- long RoundConst = 1L << (ESize - 1);
-
- if (Part != 0)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1);
- EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size + 1);
-
- Emit();
-
- if (Round)
- {
- Context.EmitLdc_I8(RoundConst);
-
- Context.Emit(OpCodes.Add);
- }
-
- Context.EmitLsr(ESize);
-
- EmitVectorInsertTmp(Context, Part + Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
deleted file mode 100644
index cd3480e6..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
+++ /dev/null
@@ -1,526 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitAluHelper;
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Cmeq_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Beq_S, Scalar: true);
- }
-
- public static void Cmeq_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg Op)
- {
- if (Op.Size < 3 && AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.CompareEqual));
- }
- else if (Op.Size == 3 && AOptimizations.UseSse41)
- {
- EmitSse41Op(Context, nameof(Sse41.CompareEqual));
- }
- else
- {
- EmitCmp(Context, OpCodes.Beq_S, Scalar: false);
- }
- }
- else
- {
- EmitCmp(Context, OpCodes.Beq_S, Scalar: false);
- }
- }
-
- public static void Cmge_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_S, Scalar: true);
- }
-
- public static void Cmge_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_S, Scalar: false);
- }
-
- public static void Cmgt_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bgt_S, Scalar: true);
- }
-
- public static void Cmgt_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg Op)
- {
- if (Op.Size < 3 && AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.CompareGreaterThan));
- }
- else if (Op.Size == 3 && AOptimizations.UseSse42)
- {
- EmitSse42Op(Context, nameof(Sse42.CompareGreaterThan));
- }
- else
- {
- EmitCmp(Context, OpCodes.Bgt_S, Scalar: false);
- }
- }
- else
- {
- EmitCmp(Context, OpCodes.Bgt_S, Scalar: false);
- }
- }
-
- public static void Cmhi_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bgt_Un_S, Scalar: true);
- }
-
- public static void Cmhi_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bgt_Un_S, Scalar: false);
- }
-
- public static void Cmhs_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_Un_S, Scalar: true);
- }
-
- public static void Cmhs_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Bge_Un_S, Scalar: false);
- }
-
- public static void Cmle_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Ble_S, Scalar: true);
- }
-
- public static void Cmle_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Ble_S, Scalar: false);
- }
-
- public static void Cmlt_S(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Blt_S, Scalar: true);
- }
-
- public static void Cmlt_V(AILEmitterCtx Context)
- {
- EmitCmp(Context, OpCodes.Blt_S, Scalar: false);
- }
-
- public static void Cmtst_S(AILEmitterCtx Context)
- {
- EmitCmtst(Context, Scalar: true);
- }
-
- public static void Cmtst_V(AILEmitterCtx Context)
- {
- EmitCmtst(Context, Scalar: false);
- }
-
- public static void Fccmp_S(AILEmitterCtx Context)
- {
- AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.EmitCondBranch(LblTrue, Op.Cond);
-
- EmitSetNZCV(Context, Op.NZCV);
-
- Context.Emit(OpCodes.Br, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- Fcmp_S(Context);
-
- Context.MarkLabel(LblEnd);
- }
-
- public static void Fccmpe_S(AILEmitterCtx Context)
- {
- Fccmp_S(Context);
- }
-
- public static void Fcmeq_S(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.CompareEqualScalar));
- }
- else
- {
- EmitScalarFcmp(Context, OpCodes.Beq_S);
- }
- }
-
- public static void Fcmeq_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.CompareEqual));
- }
- else
- {
- EmitVectorFcmp(Context, OpCodes.Beq_S);
- }
- }
-
- public static void Fcmge_S(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThanOrEqualScalar));
- }
- else
- {
- EmitScalarFcmp(Context, OpCodes.Bge_S);
- }
- }
-
- public static void Fcmge_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThanOrEqual));
- }
- else
- {
- EmitVectorFcmp(Context, OpCodes.Bge_S);
- }
- }
-
- public static void Fcmgt_S(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitScalarSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThanScalar));
- }
- else
- {
- EmitScalarFcmp(Context, OpCodes.Bgt_S);
- }
- }
-
- public static void Fcmgt_V(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
- && AOptimizations.UseSse2)
- {
- EmitVectorSseOrSse2OpF(Context, nameof(Sse.CompareGreaterThan));
- }
- else
- {
- EmitVectorFcmp(Context, OpCodes.Bgt_S);
- }
- }
-
- public static void Fcmle_S(AILEmitterCtx Context)
- {
- EmitScalarFcmp(Context, OpCodes.Ble_S);
- }
-
- public static void Fcmle_V(AILEmitterCtx Context)
- {
- EmitVectorFcmp(Context, OpCodes.Ble_S);
- }
-
- public static void Fcmlt_S(AILEmitterCtx Context)
- {
- EmitScalarFcmp(Context, OpCodes.Blt_S);
- }
-
- public static void Fcmlt_V(AILEmitterCtx Context)
- {
- EmitVectorFcmp(Context, OpCodes.Blt_S);
- }
-
- public static void Fcmp_S(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
-
- //Handle NaN case.
- //If any number is NaN, then NZCV = 0011.
- if (CmpWithZero)
- {
- EmitNaNCheck(Context, Op.Rn);
- }
- else
- {
- EmitNaNCheck(Context, Op.Rn);
- EmitNaNCheck(Context, Op.Rm);
-
- Context.Emit(OpCodes.Or);
- }
-
- AILLabel LblNaN = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(OpCodes.Brtrue_S, LblNaN);
-
- void EmitLoadOpers()
- {
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- if (CmpWithZero)
- {
- if (Op.Size == 0)
- {
- Context.EmitLdc_R4(0f);
- }
- else /* if (Op.Size == 1) */
- {
- Context.EmitLdc_R8(0d);
- }
- }
- else
- {
- EmitVectorExtractF(Context, Op.Rm, 0, Op.Size);
- }
- }
-
- //Z = Rn == Rm
- EmitLoadOpers();
-
- Context.Emit(OpCodes.Ceq);
- Context.Emit(OpCodes.Dup);
-
- Context.EmitStflg((int)APState.ZBit);
-
- //C = Rn >= Rm
- EmitLoadOpers();
-
- Context.Emit(OpCodes.Cgt);
- Context.Emit(OpCodes.Or);
-
- Context.EmitStflg((int)APState.CBit);
-
- //N = Rn < Rm
- EmitLoadOpers();
-
- Context.Emit(OpCodes.Clt);
-
- Context.EmitStflg((int)APState.NBit);
-
- //V = 0
- Context.EmitLdc_I4(0);
-
- Context.EmitStflg((int)APState.VBit);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblNaN);
-
- EmitSetNZCV(Context, 0b0011);
-
- Context.MarkLabel(LblEnd);
- }
-
- public static void Fcmpe_S(AILEmitterCtx Context)
- {
- Fcmp_S(Context);
- }
-
- private static void EmitNaNCheck(AILEmitterCtx Context, int Reg)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Reg, 0, Op.Size);
-
- if (Op.Size == 0)
- {
- Context.EmitCall(typeof(float), nameof(float.IsNaN));
- }
- else if (Op.Size == 1)
- {
- Context.EmitCall(typeof(double), nameof(double.IsNaN));
- }
- else
- {
- throw new InvalidOperationException();
- }
- }
-
- private static void EmitCmp(AILEmitterCtx Context, OpCode ILOp, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> Op.Size : 1;
-
- ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractSx(Context, Op.Rn, Index, Op.Size);
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- EmitVectorExtractSx(Context, BinOp.Rm, Index, Op.Size);
- }
- else
- {
- Context.EmitLdc_I8(0L);
- }
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(ILOp, LblTrue);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask);
-
- Context.MarkLabel(LblEnd);
- }
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitCmtst(AILEmitterCtx Context, bool Scalar)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> Op.Size : 1;
-
- ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
- EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size);
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(OpCodes.And);
-
- Context.EmitLdc_I8(0L);
-
- Context.Emit(OpCodes.Bne_Un_S, LblTrue);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask);
-
- Context.MarkLabel(LblEnd);
- }
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitScalarFcmp(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitFcmp(Context, ILOp, 0, Scalar: true);
- }
-
- private static void EmitVectorFcmp(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> SizeF + 2;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitFcmp(Context, ILOp, Index, Scalar: false);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- ulong SzMask = ulong.MaxValue >> (64 - (32 << SizeF));
-
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- EmitVectorExtractF(Context, BinOp.Rm, Index, SizeF);
- }
- else if (SizeF == 0)
- {
- Context.EmitLdc_R4(0f);
- }
- else /* if (SizeF == 1) */
- {
- Context.EmitLdc_R8(0d);
- }
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.Emit(ILOp, LblTrue);
-
- if (Scalar)
- {
- EmitVectorZeroAll(Context, Op.Rd);
- }
- else
- {
- EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0);
- }
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- if (Scalar)
- {
- EmitVectorInsert(Context, Op.Rd, Index, 3, (long)SzMask);
-
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- else
- {
- EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask);
- }
-
- Context.MarkLabel(LblEnd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCrypto.cs b/ChocolArm64/Instruction/AInstEmitSimdCrypto.cs
deleted file mode 100644
index b2680a58..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdCrypto.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Aesd_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Decrypt));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Aese_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Encrypt));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Aesimc_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InverseMixColumns));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Aesmc_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MixColumns));
-
- Context.EmitStvec(Op.Rd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs
deleted file mode 100644
index f277069b..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs
+++ /dev/null
@@ -1,697 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Fcvt_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- if (Op.Size == 1 && Op.Opc == 0)
- {
- //Double -> Single.
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleZero));
-
- EmitLdvecWithCastToDouble(Context, Op.Rn);
-
- Type[] Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<double>) };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), Types));
-
- Context.EmitStvec(Op.Rd);
- }
- else if (Op.Size == 0 && Op.Opc == 1)
- {
- //Single -> Double.
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleZero));
-
- Context.EmitLdvec(Op.Rn);
-
- Type[] Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<float>) };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), Types));
-
- EmitStvecWithCastFromDouble(Context, Op.Rd);
- }
- else
- {
- //Invalid encoding.
- throw new InvalidOperationException();
- }
- }
- else
- {
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitFloatCast(Context, Op.Opc);
-
- EmitScalarSetF(Context, Op.Rd, Op.Opc);
- }
- }
-
- public static void Fcvtas_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero));
- }
-
- public static void Fcvtau_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero));
- }
-
- public static void Fcvtl_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Elems = 4 >> SizeF;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (SizeF == 0)
- {
- EmitVectorExtractZx(Context, Op.Rn, Part + Index, 1);
- Context.Emit(OpCodes.Conv_U2);
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCall(typeof(ASoftFloat16_32), nameof(ASoftFloat16_32.FPConvert));
- }
- else /* if (SizeF == 1) */
- {
- EmitVectorExtractF(Context, Op.Rn, Part + Index, 0);
-
- Context.Emit(OpCodes.Conv_R8);
- }
-
- EmitVectorInsertTmpF(Context, Index, SizeF);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Fcvtms_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor)));
- }
-
- public static void Fcvtmu_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor)));
- }
-
- public static void Fcvtn_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Elems = 4 >> SizeF;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- if (Part != 0)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- if (SizeF == 0)
- {
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCall(typeof(ASoftFloat32_16), nameof(ASoftFloat32_16.FPConvert));
-
- Context.Emit(OpCodes.Conv_U8);
- EmitVectorInsertTmp(Context, Part + Index, 1);
- }
- else /* if (SizeF == 1) */
- {
- Context.Emit(OpCodes.Conv_R4);
-
- EmitVectorInsertTmpF(Context, Part + Index, 0);
- }
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Fcvtns_S(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: true, Scalar: true);
- }
-
- public static void Fcvtns_V(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: true, Scalar: false);
- }
-
- public static void Fcvtnu_S(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: false, Scalar: true);
- }
-
- public static void Fcvtnu_V(AILEmitterCtx Context)
- {
- EmitFcvtn(Context, Signed: false, Scalar: false);
- }
-
- public static void Fcvtps_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling)));
- }
-
- public static void Fcvtpu_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling)));
- }
-
- public static void Fcvtzs_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_s_Gp(Context, () => { });
- }
-
- public static void Fcvtzs_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtzs_Gp_Fix(Context);
- }
-
- public static void Fcvtzs_S(AILEmitterCtx Context)
- {
- EmitScalarFcvtzs(Context);
- }
-
- public static void Fcvtzs_V(AILEmitterCtx Context)
- {
- EmitVectorFcvtzs(Context);
- }
-
- public static void Fcvtzu_Gp(AILEmitterCtx Context)
- {
- EmitFcvt_u_Gp(Context, () => { });
- }
-
- public static void Fcvtzu_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtzu_Gp_Fix(Context);
- }
-
- public static void Fcvtzu_S(AILEmitterCtx Context)
- {
- EmitScalarFcvtzu(Context);
- }
-
- public static void Fcvtzu_V(AILEmitterCtx Context)
- {
- EmitVectorFcvtzu(Context);
- }
-
- public static void Scvtf_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Scvtf_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size + 2);
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Scvtf_V(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, Signed: true);
- }
-
- public static void Ucvtf_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- Context.Emit(OpCodes.Conv_R_Un);
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Ucvtf_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size + 2);
-
- Context.Emit(OpCodes.Conv_R_Un);
-
- EmitFloatCast(Context, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Ucvtf_V(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, Signed: false);
- }
-
- private static int GetFBits(AILEmitterCtx Context)
- {
- if (Context.CurrOp is AOpCodeSimdShImm Op)
- {
- return GetImmShr(Op);
- }
-
- return 0;
- }
-
- private static void EmitFloatCast(AILEmitterCtx Context, int Size)
- {
- if (Size == 0)
- {
- Context.Emit(OpCodes.Conv_R4);
- }
- else if (Size == 1)
- {
- Context.Emit(OpCodes.Conv_R8);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- private static void EmitFcvtn(AILEmitterCtx Context, bool Signed, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
- int SizeI = SizeF + 2;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> SizeI : 1;
-
- if (Scalar && (SizeF == 0))
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- EmitRoundMathCall(Context, MidpointRounding.ToEven);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF32ToS32)
- : nameof(AVectorHelper.SatF32ToU32));
-
- Context.Emit(OpCodes.Conv_U8);
- }
- else /* if (SizeF == 1) */
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF64ToS64)
- : nameof(AVectorHelper.SatF64ToU64));
- }
-
- EmitVectorInsertTmp(Context, Index, SizeI);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitFcvt_s_Gp(AILEmitterCtx Context, Action Emit)
- {
- EmitFcvt___Gp(Context, Emit, true);
- }
-
- private static void EmitFcvt_u_Gp(AILEmitterCtx Context, Action Emit)
- {
- EmitFcvt___Gp(Context, Emit, false);
- }
-
- private static void EmitFcvt___Gp(AILEmitterCtx Context, Action Emit, bool Signed)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- Emit();
-
- if (Signed)
- {
- EmitScalarFcvts(Context, Op.Size, 0);
- }
- else
- {
- EmitScalarFcvtu(Context, Op.Size, 0);
- }
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitFcvtzs_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtz__Gp_Fix(Context, true);
- }
-
- private static void EmitFcvtzu_Gp_Fix(AILEmitterCtx Context)
- {
- EmitFcvtz__Gp_Fix(Context, false);
- }
-
- private static void EmitFcvtz__Gp_Fix(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- if (Signed)
- {
- EmitScalarFcvts(Context, Op.Size, Op.FBits);
- }
- else
- {
- EmitScalarFcvtu(Context, Op.Size, Op.FBits);
- }
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rd);
- }
-
- private static void EmitVectorScvtf(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, true);
- }
-
- private static void EmitVectorUcvtf(AILEmitterCtx Context)
- {
- EmitVectorCvtf(Context, false);
- }
-
- private static void EmitVectorCvtf(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
- int SizeI = SizeF + 2;
-
- int FBits = GetFBits(Context);
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> SizeI;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, SizeI, Signed);
-
- if (!Signed)
- {
- Context.Emit(OpCodes.Conv_R_Un);
- }
-
- Context.Emit(SizeF == 0
- ? OpCodes.Conv_R4
- : OpCodes.Conv_R8);
-
- EmitI2fFBitsMul(Context, SizeF, FBits);
-
- EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitScalarFcvtzs(AILEmitterCtx Context)
- {
- EmitScalarFcvtz(Context, true);
- }
-
- private static void EmitScalarFcvtzu(AILEmitterCtx Context)
- {
- EmitScalarFcvtz(Context, false);
- }
-
- private static void EmitScalarFcvtz(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
- int SizeI = SizeF + 2;
-
- int FBits = GetFBits(Context);
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
-
- EmitF2iFBitsMul(Context, SizeF, FBits);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF32ToS32)
- : nameof(AVectorHelper.SatF32ToU32));
- }
- else /* if (SizeF == 1) */
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF64ToS64)
- : nameof(AVectorHelper.SatF64ToU64));
- }
-
- if (SizeF == 0)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- EmitScalarSet(Context, Op.Rd, SizeI);
- }
-
- private static void EmitVectorFcvtzs(AILEmitterCtx Context)
- {
- EmitVectorFcvtz(Context, true);
- }
-
- private static void EmitVectorFcvtzu(AILEmitterCtx Context)
- {
- EmitVectorFcvtz(Context, false);
- }
-
- private static void EmitVectorFcvtz(AILEmitterCtx Context, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
- int SizeI = SizeF + 2;
-
- int FBits = GetFBits(Context);
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> SizeI;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
-
- EmitF2iFBitsMul(Context, SizeF, FBits);
-
- if (SizeF == 0)
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF32ToS32)
- : nameof(AVectorHelper.SatF32ToU32));
- }
- else /* if (SizeF == 1) */
- {
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.SatF64ToS64)
- : nameof(AVectorHelper.SatF64ToU64));
- }
-
- if (SizeF == 0)
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- EmitVectorInsert(Context, Op.Rd, Index, SizeI);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitScalarFcvts(AILEmitterCtx Context, int Size, int FBits)
- {
- if (Size < 0 || Size > 1)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- EmitF2iFBitsMul(Context, Size, FBits);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToS32));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToS32));
- }
- }
- else
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToS64));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToS64));
- }
- }
- }
-
- private static void EmitScalarFcvtu(AILEmitterCtx Context, int Size, int FBits)
- {
- if (Size < 0 || Size > 1)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- EmitF2iFBitsMul(Context, Size, FBits);
-
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToU32));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToU32));
- }
- }
- else
- {
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToU64));
- }
- else /* if (Size == 1) */
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToU64));
- }
- }
- }
-
- private static void EmitF2iFBitsMul(AILEmitterCtx Context, int Size, int FBits)
- {
- if (FBits != 0)
- {
- if (Size == 0)
- {
- Context.EmitLdc_R4(MathF.Pow(2f, FBits));
- }
- else if (Size == 1)
- {
- Context.EmitLdc_R8(Math.Pow(2d, FBits));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.Emit(OpCodes.Mul);
- }
- }
-
- private static void EmitI2fFBitsMul(AILEmitterCtx Context, int Size, int FBits)
- {
- if (FBits != 0)
- {
- if (Size == 0)
- {
- Context.EmitLdc_R4(1f / MathF.Pow(2f, FBits));
- }
- else if (Size == 1)
- {
- Context.EmitLdc_R8(1d / Math.Pow(2d, FBits));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.Emit(OpCodes.Mul);
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdHash.cs b/ChocolArm64/Instruction/AInstEmitSimdHash.cs
deleted file mode 100644
index 5a59e779..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdHash.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Translation;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
-#region "Sha1"
- public static void Sha1c_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashChoose));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1h_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.FixedRotate));
-
- EmitScalarSet(Context, Op.Rd, 2);
- }
-
- public static void Sha1m_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashMajority));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1p_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- EmitVectorExtractZx(Context, Op.Rn, 0, 2);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashParity));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1su0_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha1SchedulePart1));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha1su1_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha1SchedulePart2));
-
- Context.EmitStvec(Op.Rd);
- }
-#endregion
-
-#region "Sha256"
- public static void Sha256h_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashLower));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha256h2_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.HashUpper));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha256su0_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha256SchedulePart1));
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Sha256su1_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Sha256SchedulePart2));
-
- Context.EmitStvec(Op.Rd);
- }
-#endregion
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
deleted file mode 100644
index ff082831..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
+++ /dev/null
@@ -1,1495 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-namespace ChocolArm64.Instruction
-{
- static class AInstEmitSimdHelper
- {
- public static readonly Type[] IntTypesPerSizeLog2 = new Type[]
- {
- typeof(sbyte),
- typeof(short),
- typeof(int),
- typeof(long)
- };
-
- public static readonly Type[] UIntTypesPerSizeLog2 = new Type[]
- {
- typeof(byte),
- typeof(ushort),
- typeof(uint),
- typeof(ulong)
- };
-
- public static readonly Type[] VectorIntTypesPerSizeLog2 = new Type[]
- {
- typeof(Vector128<sbyte>),
- typeof(Vector128<short>),
- typeof(Vector128<int>),
- typeof(Vector128<long>)
- };
-
- public static readonly Type[] VectorUIntTypesPerSizeLog2 = new Type[]
- {
- typeof(Vector128<byte>),
- typeof(Vector128<ushort>),
- typeof(Vector128<uint>),
- typeof(Vector128<ulong>)
- };
-
- [Flags]
- public enum OperFlags
- {
- Rd = 1 << 0,
- Rn = 1 << 1,
- Rm = 1 << 2,
- Ra = 1 << 3,
-
- RnRm = Rn | Rm,
- RdRn = Rd | Rn,
- RaRnRm = Ra | Rn | Rm,
- RdRnRm = Rd | Rn | Rm
- }
-
- public static int GetImmShl(AOpCodeSimdShImm Op)
- {
- return Op.Imm - (8 << Op.Size);
- }
-
- public static int GetImmShr(AOpCodeSimdShImm Op)
- {
- return (8 << (Op.Size + 1)) - Op.Imm;
- }
-
- public static void EmitSse2Op(AILEmitterCtx Context, string Name)
- {
- EmitSseOp(Context, Name, typeof(Sse2));
- }
-
- public static void EmitSse41Op(AILEmitterCtx Context, string Name)
- {
- EmitSseOp(Context, Name, typeof(Sse41));
- }
-
- public static void EmitSse42Op(AILEmitterCtx Context, string Name)
- {
- EmitSseOp(Context, Name, typeof(Sse42));
- }
-
- private static void EmitSseOp(AILEmitterCtx Context, string Name, Type Type)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Type BaseType = VectorIntTypesPerSizeLog2[Op.Size];
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- EmitLdvecWithSignedCast(Context, BinOp.Rm, Op.Size);
-
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType, BaseType }));
- }
- else
- {
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType }));
- }
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitLdvecWithSignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- Context.EmitLdvec(Reg);
-
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToSByte)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToInt16)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToInt32)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToInt64)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- public static void EmitLdvecWithCastToDouble(AILEmitterCtx Context, int Reg)
- {
- Context.EmitLdvec(Reg);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToDouble));
- }
-
- public static void EmitStvecWithCastFromDouble(AILEmitterCtx Context, int Reg)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleToSingle));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitLdvecWithUnsignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- Context.EmitLdvec(Reg);
-
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToByte)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToUInt16)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToUInt32)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToUInt64)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- public static void EmitStvecWithSignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSByteToSingle)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt16ToSingle)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt32ToSingle)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt64ToSingle)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitStvecWithUnsignedCast(AILEmitterCtx Context, int Reg, int Size)
- {
- switch (Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorByteToSingle)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorUInt16ToSingle)); break;
- case 2: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorUInt32ToSingle)); break;
- case 3: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorUInt64ToSingle)); break;
-
- default: throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitScalarSseOrSse2OpF(AILEmitterCtx Context, string Name)
- {
- EmitSseOrSse2OpF(Context, Name, true);
- }
-
- public static void EmitVectorSseOrSse2OpF(AILEmitterCtx Context, string Name)
- {
- EmitSseOrSse2OpF(Context, Name, false);
- }
-
- public static void EmitSseOrSse2OpF(AILEmitterCtx Context, string Name, bool Scalar)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- void Ldvec(int Reg)
- {
- Context.EmitLdvec(Reg);
-
- if (SizeF == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleToDouble));
- }
- }
-
- Ldvec(Op.Rn);
-
- Type Type;
- Type BaseType;
-
- if (SizeF == 0)
- {
- Type = typeof(Sse);
- BaseType = typeof(Vector128<float>);
- }
- else /* if (SizeF == 1) */
- {
- Type = typeof(Sse2);
- BaseType = typeof(Vector128<double>);
- }
-
- if (Op is AOpCodeSimdReg BinOp)
- {
- Ldvec(BinOp.Rm);
-
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType, BaseType }));
- }
- else
- {
- Context.EmitCall(Type.GetMethod(Name, new Type[] { BaseType }));
- }
-
- if (SizeF == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleToSingle));
- }
-
- Context.EmitStvec(Op.Rd);
-
- if (Scalar)
- {
- if (SizeF == 0)
- {
- EmitVectorZero32_128(Context, Op.Rd);
- }
- else /* if (SizeF == 1) */
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitUnaryMathCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- MethodInfo MthdInfo;
-
- if (SizeF == 0)
- {
- MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float) });
- }
- else /* if (SizeF == 1) */
- {
- MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double) });
- }
-
- Context.EmitCall(MthdInfo);
- }
-
- public static void EmitBinaryMathCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- MethodInfo MthdInfo;
-
- if (SizeF == 0)
- {
- MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float), typeof(float) });
- }
- else /* if (SizeF == 1) */
- {
- MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double), typeof(double) });
- }
-
- Context.EmitCall(MthdInfo);
- }
-
- public static void EmitRoundMathCall(AILEmitterCtx Context, MidpointRounding RoundMode)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- MethodInfo MthdInfo;
-
- if (SizeF == 0)
- {
- MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) });
- }
- else /* if (SizeF == 1) */
- {
- MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) });
- }
-
- Context.EmitLdc_I4((int)RoundMode);
-
- Context.EmitCall(MthdInfo);
- }
-
- public static void EmitUnarySoftFloatCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- MethodInfo MthdInfo;
-
- if (SizeF == 0)
- {
- MthdInfo = typeof(ASoftFloat).GetMethod(Name, new Type[] { typeof(float) });
- }
- else /* if (SizeF == 1) */
- {
- MthdInfo = typeof(ASoftFloat).GetMethod(Name, new Type[] { typeof(double) });
- }
-
- Context.EmitCall(MthdInfo);
- }
-
- public static void EmitSoftFloatCall(AILEmitterCtx Context, string Name)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
-
- Type Type = (Op.Size & 1) == 0
- ? typeof(ASoftFloat_32)
- : typeof(ASoftFloat_64);
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitCall(Type, Name);
- }
-
- public static void EmitScalarBinaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitScalarOpByElemF(Context, Emit, Op.Index, Ternary: false);
- }
-
- public static void EmitScalarTernaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitScalarOpByElemF(Context, Emit, Op.Index, Ternary: true);
- }
-
- public static void EmitScalarOpByElemF(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- if (Ternary)
- {
- EmitVectorExtractF(Context, Op.Rd, 0, SizeF);
- }
-
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
- EmitVectorExtractF(Context, Op.Rm, Elem, SizeF);
-
- Emit();
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void EmitScalarUnaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.Rn, true);
- }
-
- public static void EmitScalarBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.RnRm, true);
- }
-
- public static void EmitScalarUnaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.Rn, false);
- }
-
- public static void EmitScalarBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.RnRm, false);
- }
-
- public static void EmitScalarTernaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOp(Context, Emit, OperFlags.RdRnRm, false);
- }
-
- public static void EmitScalarOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- bool Rd = (Opers & OperFlags.Rd) != 0;
- bool Rn = (Opers & OperFlags.Rn) != 0;
- bool Rm = (Opers & OperFlags.Rm) != 0;
-
- if (Rd)
- {
- EmitVectorExtract(Context, Op.Rd, 0, Op.Size, Signed);
- }
-
- if (Rn)
- {
- EmitVectorExtract(Context, Op.Rn, 0, Op.Size, Signed);
- }
-
- if (Rm)
- {
- EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, 0, Op.Size, Signed);
- }
-
- Emit();
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void EmitScalarUnaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOpF(Context, Emit, OperFlags.Rn);
- }
-
- public static void EmitScalarBinaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOpF(Context, Emit, OperFlags.RnRm);
- }
-
- public static void EmitScalarTernaryRaOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitScalarOpF(Context, Emit, OperFlags.RaRnRm);
- }
-
- public static void EmitScalarOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- bool Ra = (Opers & OperFlags.Ra) != 0;
- bool Rn = (Opers & OperFlags.Rn) != 0;
- bool Rm = (Opers & OperFlags.Rm) != 0;
-
- if (Ra)
- {
- EmitVectorExtractF(Context, ((AOpCodeSimdReg)Op).Ra, 0, SizeF);
- }
-
- if (Rn)
- {
- EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
- }
-
- if (Rm)
- {
- EmitVectorExtractF(Context, ((AOpCodeSimdReg)Op).Rm, 0, SizeF);
- }
-
- Emit();
-
- EmitScalarSetF(Context, Op.Rd, SizeF);
- }
-
- public static void EmitVectorUnaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOpF(Context, Emit, OperFlags.Rn);
- }
-
- public static void EmitVectorBinaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOpF(Context, Emit, OperFlags.RnRm);
- }
-
- public static void EmitVectorTernaryOpF(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOpF(Context, Emit, OperFlags.RdRnRm);
- }
-
- public static void EmitVectorOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> SizeF + 2;
-
- bool Rd = (Opers & OperFlags.Rd) != 0;
- bool Rn = (Opers & OperFlags.Rn) != 0;
- bool Rm = (Opers & OperFlags.Rm) != 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (Rd)
- {
- EmitVectorExtractF(Context, Op.Rd, Index, SizeF);
- }
-
- if (Rn)
- {
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
- }
-
- if (Rm)
- {
- EmitVectorExtractF(Context, ((AOpCodeSimdReg)Op).Rm, Index, SizeF);
- }
-
- Emit();
-
- EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorBinaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: false);
- }
-
- public static void EmitVectorTernaryOpByElemF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp;
-
- EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: true);
- }
-
- public static void EmitVectorOpByElemF(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> SizeF + 2;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (Ternary)
- {
- EmitVectorExtractF(Context, Op.Rd, Index, SizeF);
- }
-
- EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
- EmitVectorExtractF(Context, Op.Rm, Elem, SizeF);
-
- Emit();
-
- EmitVectorInsertTmpF(Context, Index, SizeF);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorUnaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.Rn, true);
- }
-
- public static void EmitVectorBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RnRm, true);
- }
-
- public static void EmitVectorTernaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RdRnRm, true);
- }
-
- public static void EmitVectorUnaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.Rn, false);
- }
-
- public static void EmitVectorBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RnRm, false);
- }
-
- public static void EmitVectorTernaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, OperFlags.RdRnRm, false);
- }
-
- public static void EmitVectorOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- bool Rd = (Opers & OperFlags.Rd) != 0;
- bool Rn = (Opers & OperFlags.Rn) != 0;
- bool Rm = (Opers & OperFlags.Rm) != 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (Rd)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
- }
-
- if (Rn)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
- }
-
- if (Rm)
- {
- EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
- }
-
- Emit();
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorBinaryOpByElemSx(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
-
- EmitVectorOpByElem(Context, Emit, Op.Index, false, true);
- }
-
- public static void EmitVectorBinaryOpByElemZx(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
-
- EmitVectorOpByElem(Context, Emit, Op.Index, false, false);
- }
-
- public static void EmitVectorTernaryOpByElemZx(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
-
- EmitVectorOpByElem(Context, Emit, Op.Index, true, false);
- }
-
- public static void EmitVectorOpByElem(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- EmitVectorExtract(Context, Op.Rm, Elem, Op.Size, Signed);
- Context.EmitSttmp();
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (Ternary)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
- }
-
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
- Context.EmitLdtmp();
-
- Emit();
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorImmUnaryOp(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorImmOp(Context, Emit, false);
- }
-
- public static void EmitVectorImmBinaryOp(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorImmOp(Context, Emit, true);
- }
-
- public static void EmitVectorImmOp(AILEmitterCtx Context, Action Emit, bool Binary)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (Binary)
- {
- EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
- }
-
- Context.EmitLdc_I8(Op.Imm);
-
- Emit();
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorWidenRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRmBinaryOp(Context, Emit, true);
- }
-
- public static void EmitVectorWidenRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRmBinaryOp(Context, Emit, false);
- }
-
- public static void EmitVectorWidenRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed);
- EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed);
-
- Emit();
-
- EmitVectorInsertTmp(Context, Index, Op.Size + 1);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
- }
-
- public static void EmitVectorWidenRnRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, false, true);
- }
-
- public static void EmitVectorWidenRnRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, false, false);
- }
-
- public static void EmitVectorWidenRnRmTernaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, true, true);
- }
-
- public static void EmitVectorWidenRnRmTernaryOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorWidenRnRmOp(Context, Emit, true, false);
- }
-
- public static void EmitVectorWidenRnRmOp(AILEmitterCtx Context, Action Emit, bool Ternary, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- if (Ternary)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size + 1, Signed);
- }
-
- EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed);
- EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed);
-
- Emit();
-
- EmitVectorInsertTmp(Context, Index, Op.Size + 1);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
- }
-
- public static void EmitVectorPairwiseOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorPairwiseOp(Context, Emit, true);
- }
-
- public static void EmitVectorPairwiseOpZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorPairwiseOp(Context, Emit, false);
- }
-
- public static void EmitVectorPairwiseOp(AILEmitterCtx Context, Action Emit, bool Signed)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Words = Op.GetBitsCount() >> 4;
- int Pairs = Words >> Op.Size;
-
- for (int Index = 0; Index < Pairs; Index++)
- {
- int Idx = Index << 1;
-
- EmitVectorExtract(Context, Op.Rn, Idx, Op.Size, Signed);
- EmitVectorExtract(Context, Op.Rn, Idx + 1, Op.Size, Signed);
-
- Emit();
-
- EmitVectorExtract(Context, Op.Rm, Idx, Op.Size, Signed);
- EmitVectorExtract(Context, Op.Rm, Idx + 1, Op.Size, Signed);
-
- Emit();
-
- EmitVectorInsertTmp(Context, Pairs + Index, Op.Size);
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitVectorPairwiseOpF(AILEmitterCtx Context, Action Emit)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int SizeF = Op.Size & 1;
-
- int Words = Op.GetBitsCount() >> 4;
- int Pairs = Words >> SizeF + 2;
-
- for (int Index = 0; Index < Pairs; Index++)
- {
- int Idx = Index << 1;
-
- EmitVectorExtractF(Context, Op.Rn, Idx, SizeF);
- EmitVectorExtractF(Context, Op.Rn, Idx + 1, SizeF);
-
- Emit();
-
- EmitVectorExtractF(Context, Op.Rm, Idx, SizeF);
- EmitVectorExtractF(Context, Op.Rm, Idx + 1, SizeF);
-
- Emit();
-
- EmitVectorInsertTmpF(Context, Pairs + Index, SizeF);
- EmitVectorInsertTmpF(Context, Index, SizeF);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- [Flags]
- public enum SaturatingFlags
- {
- Scalar = 1 << 0,
- Signed = 1 << 1,
-
- Add = 1 << 2,
- Sub = 1 << 3,
-
- Accumulate = 1 << 4,
-
- ScalarSx = Scalar | Signed,
- ScalarZx = Scalar,
-
- VectorSx = Signed,
- VectorZx = 0
- }
-
- public static void EmitScalarSaturatingUnaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitSaturatingUnaryOpSx(Context, Emit, SaturatingFlags.ScalarSx);
- }
-
- public static void EmitVectorSaturatingUnaryOpSx(AILEmitterCtx Context, Action Emit)
- {
- EmitSaturatingUnaryOpSx(Context, Emit, SaturatingFlags.VectorSx);
- }
-
- public static void EmitSaturatingUnaryOpSx(AILEmitterCtx Context, Action Emit, SaturatingFlags Flags)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- bool Scalar = (Flags & SaturatingFlags.Scalar) != 0;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> Op.Size : 1;
-
- if (Scalar)
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractSx(Context, Op.Rn, Index, Op.Size);
-
- Emit();
-
- if (Op.Size <= 2)
- {
- EmitSatQ(Context, Op.Size, true, true);
- }
- else /* if (Op.Size == 3) */
- {
- EmitUnarySignedSatQAbsOrNeg(Context);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void EmitScalarSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.ScalarSx | Flags);
- }
-
- public static void EmitScalarSaturatingBinaryOpZx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.ScalarZx | Flags);
- }
-
- public static void EmitVectorSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.VectorSx | Flags);
- }
-
- public static void EmitVectorSaturatingBinaryOpZx(AILEmitterCtx Context, SaturatingFlags Flags)
- {
- EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.VectorZx | Flags);
- }
-
- public static void EmitSaturatingBinaryOp(AILEmitterCtx Context, Action Emit, SaturatingFlags Flags)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- bool Scalar = (Flags & SaturatingFlags.Scalar) != 0;
- bool Signed = (Flags & SaturatingFlags.Signed) != 0;
-
- bool Add = (Flags & SaturatingFlags.Add) != 0;
- bool Sub = (Flags & SaturatingFlags.Sub) != 0;
-
- bool Accumulate = (Flags & SaturatingFlags.Accumulate) != 0;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> Op.Size : 1;
-
- if (Scalar)
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- if (Add || Sub)
- {
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
- EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
-
- if (Op.Size <= 2)
- {
- Context.Emit(Add ? OpCodes.Add : OpCodes.Sub);
-
- EmitSatQ(Context, Op.Size, true, Signed);
- }
- else /* if (Op.Size == 3) */
- {
- if (Add)
- {
- EmitBinarySatQAdd(Context, Signed);
- }
- else /* if (Sub) */
- {
- EmitBinarySatQSub(Context, Signed);
- }
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
- }
- else if (Accumulate)
- {
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, !Signed);
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
-
- if (Op.Size <= 2)
- {
- Context.Emit(OpCodes.Add);
-
- EmitSatQ(Context, Op.Size, true, Signed);
- }
- else /* if (Op.Size == 3) */
- {
- EmitBinarySatQAccumulate(Context, Signed);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
- }
- else
- {
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
- EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
-
- Emit();
-
- EmitSatQ(Context, Op.Size, true, Signed);
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- [Flags]
- public enum SaturatingNarrowFlags
- {
- Scalar = 1 << 0,
- SignedSrc = 1 << 1,
- SignedDst = 1 << 2,
-
- ScalarSxSx = Scalar | SignedSrc | SignedDst,
- ScalarSxZx = Scalar | SignedSrc,
- ScalarZxZx = Scalar,
-
- VectorSxSx = SignedSrc | SignedDst,
- VectorSxZx = SignedSrc,
- VectorZxZx = 0
- }
-
- public static void EmitSaturatingNarrowOp(AILEmitterCtx Context, SaturatingNarrowFlags Flags)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- bool Scalar = (Flags & SaturatingNarrowFlags.Scalar) != 0;
- bool SignedSrc = (Flags & SaturatingNarrowFlags.SignedSrc) != 0;
- bool SignedDst = (Flags & SaturatingNarrowFlags.SignedDst) != 0;
-
- int Elems = !Scalar ? 8 >> Op.Size : 1;
-
- int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0;
-
- if (Scalar)
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- if (Part != 0)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc);
-
- EmitSatQ(Context, Op.Size, SignedSrc, SignedDst);
-
- EmitVectorInsertTmp(Context, Part + Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
- public static void EmitSatQ(
- AILEmitterCtx Context,
- int SizeDst,
- bool SignedSrc,
- bool SignedDst)
- {
- if (SizeDst > 2)
- {
- throw new ArgumentOutOfRangeException(nameof(SizeDst));
- }
-
- Context.EmitLdc_I4(SizeDst);
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- if (SignedSrc)
- {
- ASoftFallback.EmitCall(Context, SignedDst
- ? nameof(ASoftFallback.SignedSrcSignedDstSatQ)
- : nameof(ASoftFallback.SignedSrcUnsignedDstSatQ));
- }
- else
- {
- ASoftFallback.EmitCall(Context, SignedDst
- ? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ)
- : nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ));
- }
- }
-
- // TSrc (64bit) == TDst (64bit); signed.
- public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx Context)
- {
- if (((AOpCodeSimd)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UnarySignedSatQAbsOrNeg));
- }
-
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQAdd(AILEmitterCtx Context, bool Signed)
- {
- if (((AOpCodeSimdReg)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.BinarySignedSatQAdd)
- : nameof(ASoftFallback.BinaryUnsignedSatQAdd));
- }
-
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQSub(AILEmitterCtx Context, bool Signed)
- {
- if (((AOpCodeSimdReg)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.BinarySignedSatQSub)
- : nameof(ASoftFallback.BinaryUnsignedSatQSub));
- }
-
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQAccumulate(AILEmitterCtx Context, bool Signed)
- {
- if (((AOpCodeSimd)Context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.BinarySignedSatQAcc)
- : nameof(ASoftFallback.BinaryUnsignedSatQAcc));
- }
-
- public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
- {
- EmitVectorZeroAll(Context, Reg);
- EmitVectorInsert(Context, Reg, 0, Size);
- }
-
- public static void EmitScalarSetF(AILEmitterCtx Context, int Reg, int Size)
- {
- if (AOptimizations.UseSse41 && Size == 0)
- {
- //If the type is float, we can perform insertion and
- //zero the upper bits with a single instruction (INSERTPS);
- Context.EmitLdvec(Reg);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Sse41VectorInsertScalarSingle));
-
- Context.EmitStvec(Reg);
- }
- else
- {
- EmitVectorZeroAll(Context, Reg);
- EmitVectorInsertF(Context, Reg, 0, Size);
- }
- }
-
- public static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- EmitVectorExtract(Context, Reg, Index, Size, true);
- }
-
- public static void EmitVectorExtractZx(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- EmitVectorExtract(Context, Reg, Index, Size, false);
- }
-
- public static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, Signed
- ? nameof(AVectorHelper.VectorExtractIntSx)
- : nameof(AVectorHelper.VectorExtractIntZx));
- }
-
- public static void EmitVectorExtractF(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- ThrowIfInvalidF(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
-
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorExtractSingle));
- }
- else if (Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorExtractDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- public static void EmitVectorZeroAll(AILEmitterCtx Context, int Rd)
- {
- if (AOptimizations.UseSse2)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleZero));
-
- Context.EmitStvec(Rd);
- }
- else
- {
- EmitVectorZeroLower(Context, Rd);
- EmitVectorZeroUpper(Context, Rd);
- }
- }
-
- public static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
- {
- EmitVectorInsert(Context, Rd, 0, 3, 0);
- }
-
- public static void EmitVectorZeroLowerTmp(AILEmitterCtx Context)
- {
- EmitVectorInsertTmp(Context, 0, 3, 0);
- }
-
- public static void EmitVectorZeroUpper(AILEmitterCtx Context, int Reg)
- {
- if (AOptimizations.UseSse2)
- {
- //TODO: Use MoveScalar once it is fixed, as of the
- //time of writing it just crashes the JIT.
- EmitLdvecWithUnsignedCast(Context, Reg, 3);
-
- Type[] Types = new Type[] { typeof(Vector128<ulong>), typeof(byte) };
-
- //Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), Types));
-
- Context.EmitLdc_I4(8);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical128BitLane), Types));
-
- Context.EmitLdc_I4(8);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), Types));
-
- EmitStvecWithUnsignedCast(Context, Reg, 3);
- }
- else
- {
- EmitVectorInsert(Context, Reg, 1, 3, 0);
- }
- }
-
- public static void EmitVectorZero32_128(AILEmitterCtx Context, int Reg)
- {
- Context.EmitLdvec(Reg);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorZero32_128));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdvectmp();
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvectmp();
- }
-
- public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdc_I8(Value);
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size, long Value)
- {
- ThrowIfInvalid(Index, Size);
-
- Context.EmitLdc_I8(Value);
- Context.EmitLdvectmp();
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
-
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));
-
- Context.EmitStvectmp();
- }
-
- public static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size)
- {
- ThrowIfInvalidF(Index, Size);
-
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
-
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertSingle));
- }
- else if (Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvec(Reg);
- }
-
- public static void EmitVectorInsertTmpF(AILEmitterCtx Context, int Index, int Size)
- {
- ThrowIfInvalidF(Index, Size);
-
- Context.EmitLdvectmp();
- Context.EmitLdc_I4(Index);
-
- if (Size == 0)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertSingle));
- }
- else if (Size == 1)
- {
- AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- Context.EmitStvectmp();
- }
-
- private static void ThrowIfInvalid(int Index, int Size)
- {
- if ((uint)Size > 3u)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- if ((uint)Index >= 16u >> Size)
- {
- throw new ArgumentOutOfRangeException(nameof(Index));
- }
- }
-
- private static void ThrowIfInvalidF(int Index, int Size)
- {
- if ((uint)Size > 1u)
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
-
- if ((uint)Index >= 4u >> Size)
- {
- throw new ArgumentOutOfRangeException(nameof(Index));
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
deleted file mode 100644
index 1aa8981f..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
+++ /dev/null
@@ -1,311 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void And_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.And));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.And));
- }
- }
-
- public static void Bic_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
- });
- }
- }
-
- public static void Bic_Vi(AILEmitterCtx Context)
- {
- EmitVectorImmBinaryOp(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
- });
- }
-
- public static void Bif_V(AILEmitterCtx Context)
- {
- EmitBitBif(Context, true);
- }
-
- public static void Bit_V(AILEmitterCtx Context)
- {
- EmitBitBif(Context, false);
- }
-
- private static void EmitBitBif(AILEmitterCtx Context, bool NotRm)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- string Name = NotRm ? nameof(Sse2.AndNot) : nameof(Sse2.And);
-
- Context.EmitCall(typeof(Sse2).GetMethod(Name, Types));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.Emit(OpCodes.Xor);
-
- EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size);
-
- if (NotRm)
- {
- Context.Emit(OpCodes.Not);
- }
-
- Context.Emit(OpCodes.And);
-
- EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
-
- Context.Emit(OpCodes.Xor);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-
- public static void Bsl_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), Types));
-
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorTernaryOpZx(Context, () =>
- {
- Context.EmitSttmp();
- Context.EmitLdtmp();
-
- Context.Emit(OpCodes.Xor);
- Context.Emit(OpCodes.And);
-
- Context.EmitLdtmp();
-
- Context.Emit(OpCodes.Xor);
- });
- }
- }
-
- public static void Eor_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Xor));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Xor));
- }
- }
-
- public static void Not_V(AILEmitterCtx Context)
- {
- EmitVectorUnaryOpZx(Context, () => Context.Emit(OpCodes.Not));
- }
-
- public static void Orn_V(AILEmitterCtx Context)
- {
- EmitVectorBinaryOpZx(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.Or);
- });
- }
-
- public static void Orr_V(AILEmitterCtx Context)
- {
- if (AOptimizations.UseSse2)
- {
- EmitSse2Op(Context, nameof(Sse2.Or));
- }
- else
- {
- EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Or));
- }
- }
-
- public static void Orr_Vi(AILEmitterCtx Context)
- {
- EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or));
- }
-
- public static void Rbit_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, 0);
-
- Context.Emit(OpCodes.Conv_U4);
-
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBits8));
-
- Context.Emit(OpCodes.Conv_U8);
-
- EmitVectorInsert(Context, Op.Rd, Index, 0);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Rev16_V(AILEmitterCtx Context)
- {
- EmitRev_V(Context, ContainerSize: 1);
- }
-
- public static void Rev32_V(AILEmitterCtx Context)
- {
- EmitRev_V(Context, ContainerSize: 2);
- }
-
- public static void Rev64_V(AILEmitterCtx Context)
- {
- EmitRev_V(Context, ContainerSize: 3);
- }
-
- private static void EmitRev_V(AILEmitterCtx Context, int ContainerSize)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- if (Op.Size >= ContainerSize)
- {
- throw new InvalidOperationException();
- }
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- int RevIndex = Index ^ ContainerMask;
-
- EmitVectorExtractZx(Context, Op.Rn, RevIndex, Op.Size);
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdMemory.cs b/ChocolArm64/Instruction/AInstEmitSimdMemory.cs
deleted file mode 100644
index 368b014f..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdMemory.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-
-using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Ld__Vms(AILEmitterCtx Context)
- {
- EmitSimdMemMs(Context, IsLoad: true);
- }
-
- public static void Ld__Vss(AILEmitterCtx Context)
- {
- EmitSimdMemSs(Context, IsLoad: true);
- }
-
- public static void St__Vms(AILEmitterCtx Context)
- {
- EmitSimdMemMs(Context, IsLoad: false);
- }
-
- public static void St__Vss(AILEmitterCtx Context)
- {
- EmitSimdMemSs(Context, IsLoad: false);
- }
-
- private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
- {
- AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)Context.CurrOp;
-
- int Offset = 0;
-
- for (int Rep = 0; Rep < Op.Reps; Rep++)
- for (int Elem = 0; Elem < Op.Elems; Elem++)
- for (int SElem = 0; SElem < Op.SElems; SElem++)
- {
- int Rtt = (Op.Rt + Rep + SElem) & 0x1f;
-
- if (IsLoad)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(Offset);
-
- Context.Emit(OpCodes.Add);
-
- EmitReadZxCall(Context, Op.Size);
-
- EmitVectorInsert(Context, Rtt, Elem, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64 && Elem == Op.Elems - 1)
- {
- EmitVectorZeroUpper(Context, Rtt);
- }
- }
- else
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(Offset);
-
- Context.Emit(OpCodes.Add);
-
- EmitVectorExtractZx(Context, Rtt, Elem, Op.Size);
-
- EmitWriteCall(Context, Op.Size);
- }
-
- Offset += 1 << Op.Size;
- }
-
- if (Op.WBack)
- {
- EmitSimdMemWBack(Context, Offset);
- }
- }
-
- private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
- {
- AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;
-
- int Offset = 0;
-
- void EmitMemAddress()
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(Offset);
-
- Context.Emit(OpCodes.Add);
- }
-
- if (Op.Replicate)
- {
- //Only loads uses the replicate mode.
- if (!IsLoad)
- {
- throw new InvalidOperationException();
- }
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- for (int SElem = 0; SElem < Op.SElems; SElem++)
- {
- int Rt = (Op.Rt + SElem) & 0x1f;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitMemAddress();
-
- EmitReadZxCall(Context, Op.Size);
-
- EmitVectorInsert(Context, Rt, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Rt);
- }
-
- Offset += 1 << Op.Size;
- }
- }
- else
- {
- for (int SElem = 0; SElem < Op.SElems; SElem++)
- {
- int Rt = (Op.Rt + SElem) & 0x1f;
-
- if (IsLoad)
- {
- EmitMemAddress();
-
- EmitReadZxCall(Context, Op.Size);
-
- EmitVectorInsert(Context, Rt, Op.Index, Op.Size);
- }
- else
- {
- EmitMemAddress();
-
- EmitVectorExtractZx(Context, Rt, Op.Index, Op.Size);
-
- EmitWriteCall(Context, Op.Size);
- }
-
- Offset += 1 << Op.Size;
- }
- }
-
- if (Op.WBack)
- {
- EmitSimdMemWBack(Context, Offset);
- }
- }
-
- private static void EmitSimdMemWBack(AILEmitterCtx Context, int Offset)
- {
- AOpCodeMemReg Op = (AOpCodeMemReg)Context.CurrOp;
-
- Context.EmitLdint(Op.Rn);
-
- if (Op.Rm != AThreadState.ZRIndex)
- {
- Context.EmitLdint(Op.Rm);
- }
- else
- {
- Context.EmitLdc_I8(Offset);
- }
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitStint(Op.Rn);
- }
- }
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitSimdMove.cs b/ChocolArm64/Instruction/AInstEmitSimdMove.cs
deleted file mode 100644
index 6001f48c..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdMove.cs
+++ /dev/null
@@ -1,562 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Dup_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- Context.EmitLdintzr(Op.Rn);
-
- switch (Op.Size)
- {
- case 0: Context.Emit(OpCodes.Conv_U1); break;
- case 1: Context.Emit(OpCodes.Conv_U2); break;
- case 2: Context.Emit(OpCodes.Conv_U4); break;
- }
-
- Type[] Types = new Type[] { UIntTypesPerSizeLog2[Op.Size] };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- Context.EmitLdintzr(Op.Rn);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-
- public static void Dup_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- EmitScalarSet(Context, Op.Rd, Op.Size);
- }
-
- public static void Dup_V(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Ext_V(AILEmitterCtx Context)
- {
- AOpCodeSimdExt Op = (AOpCodeSimdExt)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
-
- int Bytes = Op.GetBitsCount() >> 3;
-
- int Position = Op.Imm4;
-
- for (int Index = 0; Index < Bytes; Index++)
- {
- int Reg = Op.Imm4 + Index < Bytes ? Op.Rn : Op.Rm;
-
- if (Position == Bytes)
- {
- Position = 0;
- }
-
- EmitVectorExtractZx(Context, Reg, Position++, 0);
- EmitVectorInsertTmp(Context, Index, 0);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Fcsel_S(AILEmitterCtx Context)
- {
- AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;
-
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- Context.EmitCondBranch(LblTrue, Op.Cond);
-
- EmitVectorExtractF(Context, Op.Rm, 0, Op.Size);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
-
- Context.MarkLabel(LblTrue);
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- Context.MarkLabel(LblEnd);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Fmov_Ftoi(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 0, 3);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Fmov_Ftoi1(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, 1, 3);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Fmov_Itof(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- EmitScalarSet(Context, Op.Rd, 3);
- }
-
- public static void Fmov_Itof1(AILEmitterCtx Context)
- {
- AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- EmitVectorInsert(Context, Op.Rd, 1, 3);
- }
-
- public static void Fmov_S(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
- EmitScalarSetF(Context, Op.Rd, Op.Size);
- }
-
- public static void Fmov_Si(AILEmitterCtx Context)
- {
- AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp;
-
- Context.EmitLdc_I8(Op.Imm);
-
- EmitScalarSet(Context, Op.Rd, Op.Size + 2);
- }
-
- public static void Fmov_V(AILEmitterCtx Context)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
-
- int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 4 : 2;
-
- for (int Index = 0; Index < (Elems >> Op.Size); Index++)
- {
- Context.EmitLdc_I8(Op.Imm);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size + 2);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Ins_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- Context.EmitLdintzr(Op.Rn);
-
- EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
- }
-
- public static void Ins_V(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, Op.SrcIndex, Op.Size);
-
- EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
- }
-
- public static void Movi_V(AILEmitterCtx Context)
- {
- EmitVectorImmUnaryOp(Context, () => { });
- }
-
- public static void Mvni_V(AILEmitterCtx Context)
- {
- EmitVectorImmUnaryOp(Context, () => Context.Emit(OpCodes.Not));
- }
-
- public static void Smov_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractSx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- EmitIntZeroUpperIfNeeded(Context);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Tbl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdTbl Op = (AOpCodeSimdTbl)Context.CurrOp;
-
- Context.EmitLdvec(Op.Rm);
-
- for (int Index = 0; Index < Op.Size; Index++)
- {
- Context.EmitLdvec((Op.Rn + Index) & 0x1f);
- }
-
- switch (Op.Size)
- {
- case 1: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl1_V64),
- nameof(AVectorHelper.Tbl1_V128)); break;
-
- case 2: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl2_V64),
- nameof(AVectorHelper.Tbl2_V128)); break;
-
- case 3: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl3_V64),
- nameof(AVectorHelper.Tbl3_V128)); break;
-
- case 4: AVectorHelper.EmitCall(Context,
- nameof(AVectorHelper.Tbl4_V64),
- nameof(AVectorHelper.Tbl4_V128)); break;
-
- default: throw new InvalidOperationException();
- }
-
- Context.EmitStvec(Op.Rd);
- }
-
- public static void Trn1_V(AILEmitterCtx Context)
- {
- EmitVectorTranspose(Context, Part: 0);
- }
-
- public static void Trn2_V(AILEmitterCtx Context)
- {
- EmitVectorTranspose(Context, Part: 1);
- }
-
- public static void Umov_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
-
- EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
-
- Context.EmitStintzr(Op.Rd);
- }
-
- public static void Uzp1_V(AILEmitterCtx Context)
- {
- EmitVectorUnzip(Context, Part: 0);
- }
-
- public static void Uzp2_V(AILEmitterCtx Context)
- {
- EmitVectorUnzip(Context, Part: 1);
- }
-
- public static void Xtn_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- if (AOptimizations.UseSse41 && Op.Size < 2)
- {
- void EmitZeroVector()
- {
- switch (Op.Size)
- {
- case 0: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt16Zero)); break;
- case 1: AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInt32Zero)); break;
- }
- }
-
- //For XTN, first operand is source, second operand is 0.
- //For XTN2, first operand is 0, second operand is source.
- if (Part != 0)
- {
- EmitZeroVector();
- }
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size + 1);
-
- //Set mask to discard the upper half of the wide elements.
- switch (Op.Size)
- {
- case 0: Context.EmitLdc_I4(0x00ff); break;
- case 1: Context.EmitLdc_I4(0x0000ffff); break;
- }
-
- Type WideType = IntTypesPerSizeLog2[Op.Size + 1];
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), new Type[] { WideType }));
-
- WideType = VectorIntTypesPerSizeLog2[Op.Size + 1];
-
- Type[] WideTypes = new Type[] { WideType, WideType };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), WideTypes));
-
- if (Part == 0)
- {
- EmitZeroVector();
- }
-
- //Pack values with signed saturation, the signed saturation shouldn't
- //saturate anything since the upper bits were masked off.
- Type SseType = Op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- Context.EmitCall(SseType.GetMethod(nameof(Sse2.PackUnsignedSaturate), WideTypes));
-
- if (Part != 0)
- {
- //For XTN2, we additionally need to discard the upper bits
- //of the target register and OR the result with it.
- EmitVectorZeroUpper(Context, Op.Rd);
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- Type NarrowType = VectorUIntTypesPerSizeLog2[Op.Size];
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), new Type[] { NarrowType, NarrowType }));
- }
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- }
- else
- {
- if (Part != 0)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1);
-
- EmitVectorInsertTmp(Context, Part + Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
-
- public static void Zip1_V(AILEmitterCtx Context)
- {
- EmitVectorZip(Context, Part: 0);
- }
-
- public static void Zip2_V(AILEmitterCtx Context)
- {
- EmitVectorZip(Context, Part: 1);
- }
-
- private static void EmitIntZeroUpperIfNeeded(AILEmitterCtx Context)
- {
- if (Context.CurrOp.RegisterSize == ARegisterSize.Int32 ||
- Context.CurrOp.RegisterSize == ARegisterSize.SIMD64)
- {
- Context.Emit(OpCodes.Conv_U4);
- Context.Emit(OpCodes.Conv_U8);
- }
- }
-
- private static void EmitVectorTranspose(AILEmitterCtx Context, int Part)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Words = Op.GetBitsCount() >> 4;
- int Pairs = Words >> Op.Size;
-
- for (int Index = 0; Index < Pairs; Index++)
- {
- int Idx = Index << 1;
-
- EmitVectorExtractZx(Context, Op.Rn, Idx + Part, Op.Size);
- EmitVectorExtractZx(Context, Op.Rm, Idx + Part, Op.Size);
-
- EmitVectorInsertTmp(Context, Idx + 1, Op.Size);
- EmitVectorInsertTmp(Context, Idx, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitVectorUnzip(AILEmitterCtx Context, int Part)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- int Words = Op.GetBitsCount() >> 4;
- int Pairs = Words >> Op.Size;
-
- for (int Index = 0; Index < Pairs; Index++)
- {
- int Idx = Index << 1;
-
- EmitVectorExtractZx(Context, Op.Rn, Idx + Part, Op.Size);
- EmitVectorExtractZx(Context, Op.Rm, Idx + Part, Op.Size);
-
- EmitVectorInsertTmp(Context, Pairs + Index, Op.Size);
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitVectorZip(AILEmitterCtx Context, int Part)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
-
- if (AOptimizations.UseSse2)
- {
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size);
-
- Type[] Types = new Type[]
- {
- VectorUIntTypesPerSizeLog2[Op.Size],
- VectorUIntTypesPerSizeLog2[Op.Size]
- };
-
- string Name = Part == 0 || (Part != 0 && Op.RegisterSize == ARegisterSize.SIMD64)
- ? nameof(Sse2.UnpackLow)
- : nameof(Sse2.UnpackHigh);
-
- Context.EmitCall(typeof(Sse2).GetMethod(Name, Types));
-
- if (Op.RegisterSize == ARegisterSize.SIMD64 && Part != 0)
- {
- Context.EmitLdc_I4(8);
-
- Type[] ShTypes = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), ShTypes));
- }
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64 && Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- int Words = Op.GetBitsCount() >> 4;
- int Pairs = Words >> Op.Size;
-
- int Base = Part != 0 ? Pairs : 0;
-
- for (int Index = 0; Index < Pairs; Index++)
- {
- int Idx = Index << 1;
-
- EmitVectorExtractZx(Context, Op.Rn, Base + Index, Op.Size);
- EmitVectorExtractZx(Context, Op.Rm, Base + Index, Op.Size);
-
- EmitVectorInsertTmp(Context, Idx + 1, Op.Size);
- EmitVectorInsertTmp(Context, Idx, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs
deleted file mode 100644
index 4f828cf8..00000000
--- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs
+++ /dev/null
@@ -1,865 +0,0 @@
-// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h
-
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection.Emit;
-using System.Runtime.Intrinsics.X86;
-
-using static ChocolArm64.Instruction.AInstEmitSimdHelper;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Rshrn_V(AILEmitterCtx Context)
- {
- EmitVectorShrImmNarrowOpZx(Context, Round: true);
- }
-
- public static void Shl_S(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- EmitScalarUnaryOpZx(Context, () =>
- {
- Context.EmitLdc_I4(GetImmShl(Op));
-
- Context.Emit(OpCodes.Shl);
- });
- }
-
- public static void Shl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSll = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShl(Op));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesSll));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorUnaryOpZx(Context, () =>
- {
- Context.EmitLdc_I4(GetImmShl(Op));
-
- Context.Emit(OpCodes.Shl);
- });
- }
- }
-
- public static void Shll_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Shift = 8 << Op.Size;
-
- EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
- }
-
- public static void Shrn_V(AILEmitterCtx Context)
- {
- EmitVectorShrImmNarrowOpZx(Context, Round: false);
- }
-
- public static void Sli_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = Bytes >> Op.Size;
-
- int Shift = GetImmShl(Op);
-
- ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
-
- Context.EmitLdc_I4(Shift);
-
- Context.Emit(OpCodes.Shl);
-
- EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
-
- Context.EmitLdc_I8((long)Mask);
-
- Context.Emit(OpCodes.And);
- Context.Emit(OpCodes.Or);
-
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
- }
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- public static void Sqrshrn_S(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
- }
-
- public static void Sqrshrn_V(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxSx);
- }
-
- public static void Sqrshrun_S(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
- }
-
- public static void Sqrshrun_V(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxZx);
- }
-
- public static void Sqshrn_S(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
- }
-
- public static void Sqshrn_V(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxSx);
- }
-
- public static void Sqshrun_S(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
- }
-
- public static void Sqshrun_V(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxZx);
- }
-
- public static void Srshr_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpSx(Context, ShrImmFlags.Round);
- }
-
- public static void Srshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0
- && Op.Size < 3)
- {
- Type[] TypesShs = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], VectorIntTypesPerSizeLog2[Op.Size] };
-
- int Shift = GetImmShr(Op);
- int ESize = 8 << Op.Size;
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- Context.EmitLdc_I4(ESize - Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesShs));
-
- Context.EmitLdc_I4(ESize - 1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitLdvectmp();
-
- Context.EmitLdc_I4(Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesShs));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpSx(Context, ShrImmFlags.Round);
- }
- }
-
- public static void Srsra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpSx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
-
- public static void Srsra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0
- && Op.Size < 3)
- {
- Type[] TypesShs = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], VectorIntTypesPerSizeLog2[Op.Size] };
-
- int Shift = GetImmShr(Op);
- int ESize = 8 << Op.Size;
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- Context.EmitLdc_I4(ESize - Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesShs));
-
- Context.EmitLdc_I4(ESize - 1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitLdvectmp();
-
- Context.EmitLdc_I4(Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesShs));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpSx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
- }
-
- public static void Sshl_V(AILEmitterCtx Context)
- {
- EmitVectorShl(Context, Signed: true);
- }
-
- public static void Sshll_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- EmitVectorShImmWidenBinarySx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
- }
-
- public static void Sshr_S(AILEmitterCtx Context)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarSx);
- }
-
- public static void Sshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0
- && Op.Size < 3)
- {
- Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorSx);
- }
- }
-
- public static void Ssra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpSx(Context, ShrImmFlags.Accumulate);
- }
-
- public static void Ssra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0
- && Op.Size < 3)
- {
- Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], VectorIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpSx(Context, ShrImmFlags.Accumulate);
- }
- }
-
- public static void Uqrshrn_S(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
- }
-
- public static void Uqrshrn_V(AILEmitterCtx Context)
- {
- EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorZxZx);
- }
-
- public static void Uqshrn_S(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
- }
-
- public static void Uqshrn_V(AILEmitterCtx Context)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorZxZx);
- }
-
- public static void Urshr_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpZx(Context, ShrImmFlags.Round);
- }
-
- public static void Urshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesShs = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- int Shift = GetImmShr(Op);
- int ESize = 8 << Op.Size;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- Context.EmitLdc_I4(ESize - Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesShs));
-
- Context.EmitLdc_I4(ESize - 1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitLdvectmp();
-
- Context.EmitLdc_I4(Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpZx(Context, ShrImmFlags.Round);
- }
- }
-
- public static void Ursra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpZx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
-
- public static void Ursra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesShs = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- int Shift = GetImmShr(Op);
- int ESize = 8 << Op.Size;
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.Emit(OpCodes.Dup);
- Context.EmitStvectmp();
-
- Context.EmitLdc_I4(ESize - Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesShs));
-
- Context.EmitLdc_I4(ESize - 1);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitLdvectmp();
-
- Context.EmitLdc_I4(Shift);
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpZx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
- }
- }
-
- public static void Ushl_V(AILEmitterCtx Context)
- {
- EmitVectorShl(Context, Signed: false);
- }
-
- public static void Ushll_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
- }
-
- public static void Ushr_S(AILEmitterCtx Context)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarZx);
- }
-
- public static void Ushr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorZx);
- }
- }
-
- public static void Usra_S(AILEmitterCtx Context)
- {
- EmitScalarShrImmOpZx(Context, ShrImmFlags.Accumulate);
- }
-
- public static void Usra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- if (AOptimizations.UseSse2 && Op.Size > 0)
- {
- Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
- Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };
-
- EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
- EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);
-
- Context.EmitLdc_I4(GetImmShr(Op));
-
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
- Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
-
- EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);
-
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- else
- {
- EmitVectorShrImmOpZx(Context, ShrImmFlags.Accumulate);
- }
- }
-
- private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
- {
- //This instruction shifts the value on vector A by the number of bits
- //specified on the signed, lower 8 bits of vector B. If the shift value
- //is greater or equal to the data size of each lane, then the result is zero.
- //Additionally, negative shifts produces right shifts by the negated shift value.
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int MaxShift = 8 << Op.Size;
-
- Action Emit = () =>
- {
- AILLabel LblShl = new AILLabel();
- AILLabel LblZero = new AILLabel();
- AILLabel LblEnd = new AILLabel();
-
- void EmitShift(OpCode ILOp)
- {
- Context.Emit(OpCodes.Dup);
-
- Context.EmitLdc_I4(MaxShift);
-
- Context.Emit(OpCodes.Bge_S, LblZero);
- Context.Emit(ILOp);
- Context.Emit(OpCodes.Br_S, LblEnd);
- }
-
- Context.Emit(OpCodes.Conv_I1);
- Context.Emit(OpCodes.Dup);
-
- Context.EmitLdc_I4(0);
-
- Context.Emit(OpCodes.Bge_S, LblShl);
- Context.Emit(OpCodes.Neg);
-
- EmitShift(Signed
- ? OpCodes.Shr
- : OpCodes.Shr_Un);
-
- Context.MarkLabel(LblShl);
-
- EmitShift(OpCodes.Shl);
-
- Context.MarkLabel(LblZero);
-
- Context.Emit(OpCodes.Pop);
- Context.Emit(OpCodes.Pop);
-
- Context.EmitLdc_I8(0);
-
- Context.MarkLabel(LblEnd);
- };
-
- if (Signed)
- {
- EmitVectorBinaryOpSx(Context, Emit);
- }
- else
- {
- EmitVectorBinaryOpZx(Context, Emit);
- }
- }
-
- [Flags]
- private enum ShrImmFlags
- {
- Scalar = 1 << 0,
- Signed = 1 << 1,
-
- Round = 1 << 2,
- Accumulate = 1 << 3,
-
- ScalarSx = Scalar | Signed,
- ScalarZx = Scalar,
-
- VectorSx = Signed,
- VectorZx = 0
- }
-
- private static void EmitScalarShrImmOpSx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarSx | Flags);
- }
-
- private static void EmitScalarShrImmOpZx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.ScalarZx | Flags);
- }
-
- private static void EmitVectorShrImmOpSx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorSx | Flags);
- }
-
- private static void EmitVectorShrImmOpZx(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- EmitShrImmOp(Context, ShrImmFlags.VectorZx | Flags);
- }
-
- private static void EmitShrImmOp(AILEmitterCtx Context, ShrImmFlags Flags)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- bool Scalar = (Flags & ShrImmFlags.Scalar) != 0;
- bool Signed = (Flags & ShrImmFlags.Signed) != 0;
- bool Round = (Flags & ShrImmFlags.Round) != 0;
- bool Accumulate = (Flags & ShrImmFlags.Accumulate) != 0;
-
- int Shift = GetImmShr(Op);
-
- long RoundConst = 1L << (Shift - 1);
-
- int Bytes = Op.GetBitsCount() >> 3;
- int Elems = !Scalar ? Bytes >> Op.Size : 1;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
-
- if (Op.Size <= 2)
- {
- if (Round)
- {
- Context.EmitLdc_I8(RoundConst);
-
- Context.Emit(OpCodes.Add);
- }
-
- Context.EmitLdc_I4(Shift);
-
- Context.Emit(Signed ? OpCodes.Shr : OpCodes.Shr_Un);
- }
- else /* if (Op.Size == 3) */
- {
- EmitShrImm_64(Context, Signed, Round ? RoundConst : 0L, Shift);
- }
-
- if (Accumulate)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
-
- Context.Emit(OpCodes.Add);
- }
-
- EmitVectorInsertTmp(Context, Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- private static void EmitVectorShrImmNarrowOpZx(AILEmitterCtx Context, bool Round)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- int Shift = GetImmShr(Op);
-
- long RoundConst = 1L << (Shift - 1);
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- if (Part != 0)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1);
-
- if (Round)
- {
- Context.EmitLdc_I8(RoundConst);
-
- Context.Emit(OpCodes.Add);
- }
-
- Context.EmitLdc_I4(Shift);
-
- Context.Emit(OpCodes.Shr_Un);
-
- EmitVectorInsertTmp(Context, Part + Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- [Flags]
- private enum ShrImmSaturatingNarrowFlags
- {
- Scalar = 1 << 0,
- SignedSrc = 1 << 1,
- SignedDst = 1 << 2,
-
- Round = 1 << 3,
-
- ScalarSxSx = Scalar | SignedSrc | SignedDst,
- ScalarSxZx = Scalar | SignedSrc,
- ScalarZxZx = Scalar,
-
- VectorSxSx = SignedSrc | SignedDst,
- VectorSxZx = SignedSrc,
- VectorZxZx = 0
- }
-
- private static void EmitRoundShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags)
- {
- EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.Round | Flags);
- }
-
- private static void EmitShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- bool Scalar = (Flags & ShrImmSaturatingNarrowFlags.Scalar) != 0;
- bool SignedSrc = (Flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0;
- bool SignedDst = (Flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0;
- bool Round = (Flags & ShrImmSaturatingNarrowFlags.Round) != 0;
-
- int Shift = GetImmShr(Op);
-
- long RoundConst = 1L << (Shift - 1);
-
- int Elems = !Scalar ? 8 >> Op.Size : 1;
-
- int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0;
-
- if (Scalar)
- {
- EmitVectorZeroLowerTmp(Context);
- }
-
- if (Part != 0)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitStvectmp();
- }
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc);
-
- if (Op.Size <= 1 || !Round)
- {
- if (Round)
- {
- Context.EmitLdc_I8(RoundConst);
-
- Context.Emit(OpCodes.Add);
- }
-
- Context.EmitLdc_I4(Shift);
-
- Context.Emit(SignedSrc ? OpCodes.Shr : OpCodes.Shr_Un);
- }
- else /* if (Op.Size == 2 && Round) */
- {
- EmitShrImm_64(Context, SignedSrc, RoundConst, Shift); // Shift <= 32
- }
-
- EmitSatQ(Context, Op.Size, SignedSrc, SignedDst);
-
- EmitVectorInsertTmp(Context, Part + Index, Op.Size);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
-
- if (Part == 0)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
-
- // Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift;
- private static void EmitShrImm_64(
- AILEmitterCtx Context,
- bool Signed,
- long RoundConst,
- int Shift)
- {
- Context.EmitLdc_I8(RoundConst);
- Context.EmitLdc_I4(Shift);
-
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.SignedShrImm_64)
- : nameof(ASoftFallback.UnsignedShrImm_64));
- }
-
- private static void EmitVectorShImmWidenBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
- {
- EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, true);
- }
-
- private static void EmitVectorShImmWidenBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
- {
- EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, false);
- }
-
- private static void EmitVectorShImmWidenBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
- int Elems = 8 >> Op.Size;
-
- int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
-
- for (int Index = 0; Index < Elems; Index++)
- {
- EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed);
-
- Context.EmitLdc_I4(Imm);
-
- Emit();
-
- EmitVectorInsertTmp(Context, Index, Op.Size + 1);
- }
-
- Context.EmitLdvectmp();
- Context.EmitStvec(Op.Rd);
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs
deleted file mode 100644
index a365398f..00000000
--- a/ChocolArm64/Instruction/AInstEmitSystem.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Reflection;
-using System.Reflection.Emit;
-
-namespace ChocolArm64.Instruction
-{
- static partial class AInstEmit
- {
- public static void Hint(AILEmitterCtx Context)
- {
- //Execute as no-op.
- }
-
- public static void Isb(AILEmitterCtx Context)
- {
- //Execute as no-op.
- }
-
- public static void Mrs(AILEmitterCtx Context)
- {
- AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- string PropName;
-
- switch (GetPackedId(Op))
- {
- case 0b11_011_0000_0000_001: PropName = nameof(AThreadState.CtrEl0); break;
- case 0b11_011_0000_0000_111: PropName = nameof(AThreadState.DczidEl0); break;
- case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break;
- case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break;
- case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;
- case 0b11_011_1101_0000_011: PropName = nameof(AThreadState.Tpidr); break;
- case 0b11_011_1110_0000_000: PropName = nameof(AThreadState.CntfrqEl0); break;
- case 0b11_011_1110_0000_001: PropName = nameof(AThreadState.CntpctEl0); break;
-
- default: throw new NotImplementedException($"Unknown MRS at {Op.Position:x16}");
- }
-
- Context.EmitCallPropGet(typeof(AThreadState), PropName);
-
- PropertyInfo PropInfo = typeof(AThreadState).GetProperty(PropName);
-
- if (PropInfo.PropertyType != typeof(long) &&
- PropInfo.PropertyType != typeof(ulong))
- {
- Context.Emit(OpCodes.Conv_U8);
- }
-
- Context.EmitStintzr(Op.Rt);
- }
-
- public static void Msr(AILEmitterCtx Context)
- {
- AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
- Context.EmitLdintzr(Op.Rt);
-
- string PropName;
-
- switch (GetPackedId(Op))
- {
- case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break;
- case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break;
- case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;
-
- default: throw new NotImplementedException($"Unknown MSR at {Op.Position:x16}");
- }
-
- PropertyInfo PropInfo = typeof(AThreadState).GetProperty(PropName);
-
- if (PropInfo.PropertyType != typeof(long) &&
- PropInfo.PropertyType != typeof(ulong))
- {
- Context.Emit(OpCodes.Conv_U4);
- }
-
- Context.EmitCallPropSet(typeof(AThreadState), PropName);
- }
-
- public static void Nop(AILEmitterCtx Context)
- {
- //Do nothing.
- }
-
- public static void Sys(AILEmitterCtx Context)
- {
- //This instruction is used to do some operations on the CPU like cache invalidation,
- //address translation and the like.
- //We treat it as no-op here since we don't have any cache being emulated anyway.
- AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
-
- switch (GetPackedId(Op))
- {
- case 0b11_011_0111_0100_001:
- {
- //DC ZVA
- for (int Offs = 0; Offs < (4 << AThreadState.DczSizeLog2); Offs += 8)
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdintzr(Op.Rt);
- Context.EmitLdc_I(Offs);
-
- Context.Emit(OpCodes.Add);
-
- Context.EmitLdc_I8(0);
-
- AInstEmitMemoryHelper.EmitWriteCall(Context, 3);
- }
-
- break;
- }
-
- //No-op
- case 0b11_011_0111_1110_001: //DC CIVAC
- break;
- }
- }
-
- private static int GetPackedId(AOpCodeSystem Op)
- {
- int Id;
-
- Id = Op.Op2 << 0;
- Id |= Op.CRm << 3;
- Id |= Op.CRn << 7;
- Id |= Op.Op1 << 11;
- Id |= Op.Op0 << 14;
-
- return Id;
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AInstEmitter.cs b/ChocolArm64/Instruction/AInstEmitter.cs
deleted file mode 100644
index 8712a736..00000000
--- a/ChocolArm64/Instruction/AInstEmitter.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using ChocolArm64.Translation;
-
-namespace ChocolArm64.Instruction
-{
- delegate void AInstEmitter(AILEmitterCtx Context);
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstInterpreter.cs b/ChocolArm64/Instruction/AInstInterpreter.cs
deleted file mode 100644
index 6a855aec..00000000
--- a/ChocolArm64/Instruction/AInstInterpreter.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using ChocolArm64.Decoder;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-
-namespace ChocolArm64.Instruction
-{
- delegate void AInstInterpreter(AThreadState State, AMemory Memory, AOpCode OpCode);
-} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs
deleted file mode 100644
index d643fb6f..00000000
--- a/ChocolArm64/Instruction/ASoftFallback.cs
+++ /dev/null
@@ -1,922 +0,0 @@
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-namespace ChocolArm64.Instruction
-{
- using static AVectorHelper;
-
- static class ASoftFallback
- {
- public static void EmitCall(AILEmitterCtx Context, string MthdName)
- {
- Context.EmitCall(typeof(ASoftFallback), MthdName);
- }
-
-#region "ShrImm_64"
- public static long SignedShrImm_64(long Value, long RoundConst, int Shift)
- {
- if (RoundConst == 0L)
- {
- if (Shift <= 63)
- {
- return Value >> Shift;
- }
- else /* if (Shift == 64) */
- {
- if (Value < 0L)
- {
- return -1L;
- }
- else
- {
- return 0L;
- }
- }
- }
- else /* if (RoundConst == 1L << (Shift - 1)) */
- {
- if (Shift <= 63)
- {
- long Add = Value + RoundConst;
-
- if ((~Value & (Value ^ Add)) < 0L)
- {
- return (long)((ulong)Add >> Shift);
- }
- else
- {
- return Add >> Shift;
- }
- }
- else /* if (Shift == 64) */
- {
- return 0L;
- }
- }
- }
-
- public static ulong UnsignedShrImm_64(ulong Value, long RoundConst, int Shift)
- {
- if (RoundConst == 0L)
- {
- if (Shift <= 63)
- {
- return Value >> Shift;
- }
- else /* if (Shift == 64) */
- {
- return 0UL;
- }
- }
- else /* if (RoundConst == 1L << (Shift - 1)) */
- {
- ulong Add = Value + (ulong)RoundConst;
-
- if ((Add < Value) && (Add < (ulong)RoundConst))
- {
- if (Shift <= 63)
- {
- return (Add >> Shift) | (0x8000000000000000UL >> (Shift - 1));
- }
- else /* if (Shift == 64) */
- {
- return 1UL;
- }
- }
- else
- {
- if (Shift <= 63)
- {
- return Add >> Shift;
- }
- else /* if (Shift == 64) */
- {
- return 0UL;
- }
- }
- }
- }
-#endregion
-
-#region "Saturating"
- public static long SignedSrcSignedDstSatQ(long Op, int Size, AThreadState State)
- {
- int ESize = 8 << Size;
-
- long TMaxValue = (1L << (ESize - 1)) - 1L;
- long TMinValue = -(1L << (ESize - 1));
-
- if (Op > TMaxValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return TMaxValue;
- }
- else if (Op < TMinValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return TMinValue;
- }
- else
- {
- return Op;
- }
- }
-
- public static ulong SignedSrcUnsignedDstSatQ(long Op, int Size, AThreadState State)
- {
- int ESize = 8 << Size;
-
- ulong TMaxValue = (1UL << ESize) - 1UL;
- ulong TMinValue = 0UL;
-
- if (Op > (long)TMaxValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return TMaxValue;
- }
- else if (Op < (long)TMinValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return TMinValue;
- }
- else
- {
- return (ulong)Op;
- }
- }
-
- public static long UnsignedSrcSignedDstSatQ(ulong Op, int Size, AThreadState State)
- {
- int ESize = 8 << Size;
-
- long TMaxValue = (1L << (ESize - 1)) - 1L;
-
- if (Op > (ulong)TMaxValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return TMaxValue;
- }
- else
- {
- return (long)Op;
- }
- }
-
- public static ulong UnsignedSrcUnsignedDstSatQ(ulong Op, int Size, AThreadState State)
- {
- int ESize = 8 << Size;
-
- ulong TMaxValue = (1UL << ESize) - 1UL;
-
- if (Op > TMaxValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return TMaxValue;
- }
- else
- {
- return Op;
- }
- }
-
- public static long UnarySignedSatQAbsOrNeg(long Op, AThreadState State)
- {
- if (Op == long.MinValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return long.MaxValue;
- }
- else
- {
- return Op;
- }
- }
-
- public static long BinarySignedSatQAdd(long Op1, long Op2, AThreadState State)
- {
- long Add = Op1 + Op2;
-
- if ((~(Op1 ^ Op2) & (Op1 ^ Add)) < 0L)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- if (Op1 < 0L)
- {
- return long.MinValue;
- }
- else
- {
- return long.MaxValue;
- }
- }
- else
- {
- return Add;
- }
- }
-
- public static ulong BinaryUnsignedSatQAdd(ulong Op1, ulong Op2, AThreadState State)
- {
- ulong Add = Op1 + Op2;
-
- if ((Add < Op1) && (Add < Op2))
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return ulong.MaxValue;
- }
- else
- {
- return Add;
- }
- }
-
- public static long BinarySignedSatQSub(long Op1, long Op2, AThreadState State)
- {
- long Sub = Op1 - Op2;
-
- if (((Op1 ^ Op2) & (Op1 ^ Sub)) < 0L)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- if (Op1 < 0L)
- {
- return long.MinValue;
- }
- else
- {
- return long.MaxValue;
- }
- }
- else
- {
- return Sub;
- }
- }
-
- public static ulong BinaryUnsignedSatQSub(ulong Op1, ulong Op2, AThreadState State)
- {
- ulong Sub = Op1 - Op2;
-
- if (Op1 < Op2)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return ulong.MinValue;
- }
- else
- {
- return Sub;
- }
- }
-
- public static long BinarySignedSatQAcc(ulong Op1, long Op2, AThreadState State)
- {
- if (Op1 <= (ulong)long.MaxValue)
- {
- // Op1 from ulong.MinValue to (ulong)long.MaxValue
- // Op2 from long.MinValue to long.MaxValue
-
- long Add = (long)Op1 + Op2;
-
- if ((~Op2 & Add) < 0L)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return long.MaxValue;
- }
- else
- {
- return Add;
- }
- }
- else if (Op2 >= 0L)
- {
- // Op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
- // Op2 from (long)ulong.MinValue to long.MaxValue
-
- State.SetFpsrFlag(FPSR.QC);
-
- return long.MaxValue;
- }
- else
- {
- // Op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
- // Op2 from long.MinValue to (long)ulong.MinValue - 1L
-
- ulong Add = Op1 + (ulong)Op2;
-
- if (Add > (ulong)long.MaxValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return long.MaxValue;
- }
- else
- {
- return (long)Add;
- }
- }
- }
-
- public static ulong BinaryUnsignedSatQAcc(long Op1, ulong Op2, AThreadState State)
- {
- if (Op1 >= 0L)
- {
- // Op1 from (long)ulong.MinValue to long.MaxValue
- // Op2 from ulong.MinValue to ulong.MaxValue
-
- ulong Add = (ulong)Op1 + Op2;
-
- if ((Add < (ulong)Op1) && (Add < Op2))
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return ulong.MaxValue;
- }
- else
- {
- return Add;
- }
- }
- else if (Op2 > (ulong)long.MaxValue)
- {
- // Op1 from long.MinValue to (long)ulong.MinValue - 1L
- // Op2 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
-
- return (ulong)Op1 + Op2;
- }
- else
- {
- // Op1 from long.MinValue to (long)ulong.MinValue - 1L
- // Op2 from ulong.MinValue to (ulong)long.MaxValue
-
- long Add = Op1 + (long)Op2;
-
- if (Add < (long)ulong.MinValue)
- {
- State.SetFpsrFlag(FPSR.QC);
-
- return ulong.MinValue;
- }
- else
- {
- return (ulong)Add;
- }
- }
- }
-#endregion
-
-#region "Count"
- public static ulong CountLeadingSigns(ulong Value, int Size) // Size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
- {
- Value ^= Value >> 1;
-
- int HighBit = Size - 2;
-
- for (int Bit = HighBit; Bit >= 0; Bit--)
- {
- if (((Value >> Bit) & 0b1) != 0)
- {
- return (ulong)(HighBit - Bit);
- }
- }
-
- return (ulong)(Size - 1);
- }
-
- private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- public static ulong CountLeadingZeros(ulong Value, int Size) // Size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
- {
- if (Value == 0ul)
- {
- return (ulong)Size;
- }
-
- int NibbleIdx = Size;
- int PreCount, Count = 0;
-
- do
- {
- NibbleIdx -= 4;
- PreCount = ClzNibbleTbl[(Value >> NibbleIdx) & 0b1111];
- Count += PreCount;
- }
- while (PreCount == 4);
-
- return (ulong)Count;
- }
-
- public static ulong CountSetBits8(ulong Value) // "Size" is 8 (SIMD&FP Inst.).
- {
- if (Value == 0xfful)
- {
- return 8ul;
- }
-
- Value = ((Value >> 1) & 0x55ul) + (Value & 0x55ul);
- Value = ((Value >> 2) & 0x33ul) + (Value & 0x33ul);
-
- return (Value >> 4) + (Value & 0x0ful);
- }
-#endregion
-
-#region "Crc32"
- private const uint Crc32RevPoly = 0xedb88320;
- private const uint Crc32cRevPoly = 0x82f63b78;
-
- public static uint Crc32b(uint Crc, byte Val) => Crc32 (Crc, Crc32RevPoly, Val);
- public static uint Crc32h(uint Crc, ushort Val) => Crc32h(Crc, Crc32RevPoly, Val);
- public static uint Crc32w(uint Crc, uint Val) => Crc32w(Crc, Crc32RevPoly, Val);
- public static uint Crc32x(uint Crc, ulong Val) => Crc32x(Crc, Crc32RevPoly, Val);
-
- public static uint Crc32cb(uint Crc, byte Val) => Crc32 (Crc, Crc32cRevPoly, Val);
- public static uint Crc32ch(uint Crc, ushort Val) => Crc32h(Crc, Crc32cRevPoly, Val);
- public static uint Crc32cw(uint Crc, uint Val) => Crc32w(Crc, Crc32cRevPoly, Val);
- public static uint Crc32cx(uint Crc, ulong Val) => Crc32x(Crc, Crc32cRevPoly, Val);
-
- private static uint Crc32h(uint Crc, uint Poly, ushort Val)
- {
- Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
-
- return Crc;
- }
-
- private static uint Crc32w(uint Crc, uint Poly, uint Val)
- {
- Crc = Crc32(Crc, Poly, (byte)(Val >> 0 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 8 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
-
- return Crc;
- }
-
- private static uint Crc32x(uint Crc, uint Poly, ulong Val)
- {
- Crc = Crc32(Crc, Poly, (byte)(Val >> 0 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 8 ));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 32));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 40));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 48));
- Crc = Crc32(Crc, Poly, (byte)(Val >> 56));
-
- return Crc;
- }
-
- private static uint Crc32(uint Crc, uint Poly, byte Val)
- {
- Crc ^= Val;
-
- for (int Bit = 7; Bit >= 0; Bit--)
- {
- uint Mask = (uint)(-(int)(Crc & 1));
-
- Crc = (Crc >> 1) ^ (Poly & Mask);
- }
-
- return Crc;
- }
-#endregion
-
-#region "Aes"
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> Decrypt(Vector128<float> value, Vector128<float> roundKey)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- return ACryptoHelper.AESInvSubBytes(ACryptoHelper.AESInvShiftRows(Sse.Xor(value, roundKey)));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> Encrypt(Vector128<float> value, Vector128<float> roundKey)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- return ACryptoHelper.AESSubBytes(ACryptoHelper.AESShiftRows(Sse.Xor(value, roundKey)));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> InverseMixColumns(Vector128<float> value)
- {
- return ACryptoHelper.AESInvMixColumns(value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> MixColumns(Vector128<float> value)
- {
- return ACryptoHelper.AESMixColumns(value);
- }
-#endregion
-
-#region "Sha1"
- public static Vector128<float> HashChoose(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint t = SHAchoose((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2));
-
- hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t;
- hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2);
-
- t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30);
- hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2);
-
- Rol32_160(ref hash_e, ref hash_abcd);
- }
-
- return hash_abcd;
- }
-
- public static uint FixedRotate(uint hash_e)
- {
- return hash_e.Rol(30);
- }
-
- public static Vector128<float> HashMajority(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint t = SHAmajority((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2));
-
- hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t;
- hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2);
-
- t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30);
- hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2);
-
- Rol32_160(ref hash_e, ref hash_abcd);
- }
-
- return hash_abcd;
- }
-
- public static Vector128<float> HashParity(Vector128<float> hash_abcd, uint hash_e, Vector128<float> wk)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint t = SHAparity((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)2, 2),
- (uint)VectorExtractIntZx(hash_abcd, (byte)3, 2));
-
- hash_e += Rol((uint)VectorExtractIntZx(hash_abcd, (byte)0, 2), 5) + t;
- hash_e += (uint)VectorExtractIntZx(wk, (byte)e, 2);
-
- t = Rol((uint)VectorExtractIntZx(hash_abcd, (byte)1, 2), 30);
- hash_abcd = VectorInsertInt((ulong)t, hash_abcd, (byte)1, 2);
-
- Rol32_160(ref hash_e, ref hash_abcd);
- }
-
- return hash_abcd;
- }
-
- public static Vector128<float> Sha1SchedulePart1(Vector128<float> w0_3, Vector128<float> w4_7, Vector128<float> w8_11)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- Vector128<float> result = new Vector128<float>();
-
- ulong t2 = VectorExtractIntZx(w4_7, (byte)0, 3);
- ulong t1 = VectorExtractIntZx(w0_3, (byte)1, 3);
-
- result = VectorInsertInt((ulong)t1, result, (byte)0, 3);
- result = VectorInsertInt((ulong)t2, result, (byte)1, 3);
-
- return Sse.Xor(result, Sse.Xor(w0_3, w8_11));
- }
-
- public static Vector128<float> Sha1SchedulePart2(Vector128<float> tw0_3, Vector128<float> w12_15)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- Vector128<float> result = new Vector128<float>();
-
- Vector128<float> T = Sse.Xor(tw0_3, Sse.StaticCast<uint, float>(
- Sse2.ShiftRightLogical128BitLane(Sse.StaticCast<float, uint>(w12_15), (byte)4)));
-
- uint tE0 = (uint)VectorExtractIntZx(T, (byte)0, 2);
- uint tE1 = (uint)VectorExtractIntZx(T, (byte)1, 2);
- uint tE2 = (uint)VectorExtractIntZx(T, (byte)2, 2);
- uint tE3 = (uint)VectorExtractIntZx(T, (byte)3, 2);
-
- result = VectorInsertInt((ulong)tE0.Rol(1), result, (byte)0, 2);
- result = VectorInsertInt((ulong)tE1.Rol(1), result, (byte)1, 2);
- result = VectorInsertInt((ulong)tE2.Rol(1), result, (byte)2, 2);
-
- return VectorInsertInt((ulong)(tE3.Rol(1) ^ tE0.Rol(2)), result, (byte)3, 2);
- }
-
- private static void Rol32_160(ref uint y, ref Vector128<float> X)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- uint xE3 = (uint)VectorExtractIntZx(X, (byte)3, 2);
-
- X = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(X), (byte)4));
- X = VectorInsertInt((ulong)y, X, (byte)0, 2);
-
- y = xE3;
- }
-
- private static uint SHAchoose(uint x, uint y, uint z)
- {
- return ((y ^ z) & x) ^ z;
- }
-
- private static uint SHAmajority(uint x, uint y, uint z)
- {
- return (x & y) | ((x | y) & z);
- }
-
- private static uint SHAparity(uint x, uint y, uint z)
- {
- return x ^ y ^ z;
- }
-
- private static uint Rol(this uint value, int count)
- {
- return (value << count) | (value >> (32 - count));
- }
-#endregion
-
-#region "Sha256"
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> HashLower(Vector128<float> hash_abcd, Vector128<float> hash_efgh, Vector128<float> wk)
- {
- return SHA256hash(hash_abcd, hash_efgh, wk, true);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> HashUpper(Vector128<float> hash_efgh, Vector128<float> hash_abcd, Vector128<float> wk)
- {
- return SHA256hash(hash_abcd, hash_efgh, wk, false);
- }
-
- public static Vector128<float> Sha256SchedulePart1(Vector128<float> w0_3, Vector128<float> w4_7)
- {
- Vector128<float> result = new Vector128<float>();
-
- for (int e = 0; e <= 3; e++)
- {
- uint elt = (uint)VectorExtractIntZx(e <= 2 ? w0_3 : w4_7, (byte)(e <= 2 ? e + 1 : 0), 2);
-
- elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
-
- elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2);
-
- result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
- }
-
- return result;
- }
-
- public static Vector128<float> Sha256SchedulePart2(Vector128<float> w0_3, Vector128<float> w8_11, Vector128<float> w12_15)
- {
- Vector128<float> result = new Vector128<float>();
-
- ulong T1 = VectorExtractIntZx(w12_15, (byte)1, 3);
-
- for (int e = 0; e <= 1; e++)
- {
- uint elt = T1.ULongPart(e);
-
- elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
-
- elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2);
- elt += (uint)VectorExtractIntZx(w8_11, (byte)(e + 1), 2);
-
- result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
- }
-
- T1 = VectorExtractIntZx(result, (byte)0, 3);
-
- for (int e = 2; e <= 3; e++)
- {
- uint elt = T1.ULongPart(e - 2);
-
- elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
-
- elt += (uint)VectorExtractIntZx(w0_3, (byte)e, 2);
- elt += (uint)VectorExtractIntZx(e == 2 ? w8_11 : w12_15, (byte)(e == 2 ? 3 : 0), 2);
-
- result = VectorInsertInt((ulong)elt, result, (byte)e, 2);
- }
-
- return result;
- }
-
- private static Vector128<float> SHA256hash(Vector128<float> X, Vector128<float> Y, Vector128<float> W, bool part1)
- {
- for (int e = 0; e <= 3; e++)
- {
- uint chs = SHAchoose((uint)VectorExtractIntZx(Y, (byte)0, 2),
- (uint)VectorExtractIntZx(Y, (byte)1, 2),
- (uint)VectorExtractIntZx(Y, (byte)2, 2));
-
- uint maj = SHAmajority((uint)VectorExtractIntZx(X, (byte)0, 2),
- (uint)VectorExtractIntZx(X, (byte)1, 2),
- (uint)VectorExtractIntZx(X, (byte)2, 2));
-
- uint t1 = (uint)VectorExtractIntZx(Y, (byte)3, 2);
- t1 += SHAhashSIGMA1((uint)VectorExtractIntZx(Y, (byte)0, 2)) + chs;
- t1 += (uint)VectorExtractIntZx(W, (byte)e, 2);
-
- uint t2 = t1 + (uint)VectorExtractIntZx(X, (byte)3, 2);
- X = VectorInsertInt((ulong)t2, X, (byte)3, 2);
- t2 = t1 + SHAhashSIGMA0((uint)VectorExtractIntZx(X, (byte)0, 2)) + maj;
- Y = VectorInsertInt((ulong)t2, Y, (byte)3, 2);
-
- Rol32_256(ref Y, ref X);
- }
-
- return part1 ? X : Y;
- }
-
- private static void Rol32_256(ref Vector128<float> Y, ref Vector128<float> X)
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- uint yE3 = (uint)VectorExtractIntZx(Y, (byte)3, 2);
- uint xE3 = (uint)VectorExtractIntZx(X, (byte)3, 2);
-
- Y = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(Y), (byte)4));
- X = Sse.StaticCast<uint, float>(Sse2.ShiftLeftLogical128BitLane(Sse.StaticCast<float, uint>(X), (byte)4));
-
- Y = VectorInsertInt((ulong)xE3, Y, (byte)0, 2);
- X = VectorInsertInt((ulong)yE3, X, (byte)0, 2);
- }
-
- private static uint SHAhashSIGMA0(uint x)
- {
- return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
- }
-
- private static uint SHAhashSIGMA1(uint x)
- {
- return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
- }
-
- private static uint Ror(this uint value, int count)
- {
- return (value >> count) | (value << (32 - count));
- }
-
- private static uint Lsr(this uint value, int count)
- {
- return value >> count;
- }
-
- private static uint ULongPart(this ulong value, int part)
- {
- return part == 0
- ? (uint)(value & 0xFFFFFFFFUL)
- : (uint)(value >> 32);
- }
-#endregion
-
-#region "Reverse"
- public static uint ReverseBits8(uint Value)
- {
- Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1);
- Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2);
-
- return (Value >> 4) | ((Value & 0x0f) << 4);
- }
-
- public static uint ReverseBits32(uint Value)
- {
- Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1);
- Value = ((Value & 0xcccccccc) >> 2) | ((Value & 0x33333333) << 2);
- Value = ((Value & 0xf0f0f0f0) >> 4) | ((Value & 0x0f0f0f0f) << 4);
- Value = ((Value & 0xff00ff00) >> 8) | ((Value & 0x00ff00ff) << 8);
-
- return (Value >> 16) | (Value << 16);
- }
-
- public static ulong ReverseBits64(ulong Value)
- {
- Value = ((Value & 0xaaaaaaaaaaaaaaaa) >> 1 ) | ((Value & 0x5555555555555555) << 1 );
- Value = ((Value & 0xcccccccccccccccc) >> 2 ) | ((Value & 0x3333333333333333) << 2 );
- Value = ((Value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((Value & 0x0f0f0f0f0f0f0f0f) << 4 );
- Value = ((Value & 0xff00ff00ff00ff00) >> 8 ) | ((Value & 0x00ff00ff00ff00ff) << 8 );
- Value = ((Value & 0xffff0000ffff0000) >> 16) | ((Value & 0x0000ffff0000ffff) << 16);
-
- return (Value >> 32) | (Value << 32);
- }
-
- public static uint ReverseBytes16_32(uint Value) => (uint)ReverseBytes16_64(Value);
- public static uint ReverseBytes32_32(uint Value) => (uint)ReverseBytes32_64(Value);
-
- public static ulong ReverseBytes16_64(ulong Value) => ReverseBytes(Value, RevSize.Rev16);
- public static ulong ReverseBytes32_64(ulong Value) => ReverseBytes(Value, RevSize.Rev32);
- public static ulong ReverseBytes64(ulong Value) => ReverseBytes(Value, RevSize.Rev64);
-
- private enum RevSize
- {
- Rev16,
- Rev32,
- Rev64
- }
-
- private static ulong ReverseBytes(ulong Value, RevSize Size)
- {
- Value = ((Value & 0xff00ff00ff00ff00) >> 8) | ((Value & 0x00ff00ff00ff00ff) << 8);
-
- if (Size == RevSize.Rev16)
- {
- return Value;
- }
-
- Value = ((Value & 0xffff0000ffff0000) >> 16) | ((Value & 0x0000ffff0000ffff) << 16);
-
- if (Size == RevSize.Rev32)
- {
- return Value;
- }
-
- Value = ((Value & 0xffffffff00000000) >> 32) | ((Value & 0x00000000ffffffff) << 32);
-
- if (Size == RevSize.Rev64)
- {
- return Value;
- }
-
- throw new ArgumentException(nameof(Size));
- }
-#endregion
-
-#region "MultiplyHigh"
- public static long SMulHi128(long Left, long Right)
- {
- long Result = (long)UMulHi128((ulong)Left, (ulong)Right);
-
- if (Left < 0)
- {
- Result -= Right;
- }
-
- if (Right < 0)
- {
- Result -= Left;
- }
-
- return Result;
- }
-
- public static ulong UMulHi128(ulong Left, ulong Right)
- {
- ulong LHigh = Left >> 32;
- ulong LLow = Left & 0xFFFFFFFF;
- ulong RHigh = Right >> 32;
- ulong RLow = Right & 0xFFFFFFFF;
-
- ulong Z2 = LLow * RLow;
- ulong T = LHigh * RLow + (Z2 >> 32);
- ulong Z1 = T & 0xFFFFFFFF;
- ulong Z0 = T >> 32;
-
- Z1 += LLow * RHigh;
-
- return LHigh * RHigh + Z0 + (Z1 >> 32);
- }
-#endregion
- }
-}
diff --git a/ChocolArm64/Instruction/ASoftFloat.cs b/ChocolArm64/Instruction/ASoftFloat.cs
deleted file mode 100644
index 0912257a..00000000
--- a/ChocolArm64/Instruction/ASoftFloat.cs
+++ /dev/null
@@ -1,2127 +0,0 @@
-using ChocolArm64.State;
-using System;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace ChocolArm64.Instruction
-{
- static class ASoftFloat
- {
- static ASoftFloat()
- {
- RecipEstimateTable = BuildRecipEstimateTable();
- InvSqrtEstimateTable = BuildInvSqrtEstimateTable();
- }
-
- private static readonly byte[] RecipEstimateTable;
- private static readonly byte[] InvSqrtEstimateTable;
-
- private static byte[] BuildRecipEstimateTable()
- {
- byte[] Table = new byte[256];
- for (ulong index = 0; index < 256; index++)
- {
- ulong a = index | 0x100;
-
- a = (a << 1) + 1;
- ulong b = 0x80000 / a;
- b = (b + 1) >> 1;
-
- Table[index] = (byte)(b & 0xFF);
- }
- return Table;
- }
-
- private static byte[] BuildInvSqrtEstimateTable()
- {
- byte[] Table = new byte[512];
- for (ulong index = 128; index < 512; index++)
- {
- ulong a = index;
- if (a < 256)
- {
- a = (a << 1) + 1;
- }
- else
- {
- a = (a | 1) << 1;
- }
-
- ulong b = 256;
- while (a * (b + 1) * (b + 1) < (1ul << 28))
- {
- b++;
- }
- b = (b + 1) >> 1;
-
- Table[index] = (byte)(b & 0xFF);
- }
- return Table;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float RecipEstimate(float x)
- {
- return (float)RecipEstimate((double)x);
- }
-
- public static double RecipEstimate(double x)
- {
- ulong x_bits = (ulong)BitConverter.DoubleToInt64Bits(x);
- ulong x_sign = x_bits & 0x8000000000000000;
- ulong x_exp = (x_bits >> 52) & 0x7FF;
- ulong scaled = x_bits & ((1ul << 52) - 1);
-
- if (x_exp >= 2045)
- {
- if (x_exp == 0x7ff && scaled != 0)
- {
- // NaN
- return BitConverter.Int64BitsToDouble((long)(x_bits | 0x0008000000000000));
- }
-
- // Infinity, or Out of range -> Zero
- return BitConverter.Int64BitsToDouble((long)x_sign);
- }
-
- if (x_exp == 0)
- {
- if (scaled == 0)
- {
- // Zero -> Infinity
- return BitConverter.Int64BitsToDouble((long)(x_sign | 0x7FF0000000000000));
- }
-
- // Denormal
- if ((scaled & (1ul << 51)) == 0)
- {
- x_exp = ~0ul;
- scaled <<= 2;
- }
- else
- {
- scaled <<= 1;
- }
- }
-
- scaled >>= 44;
- scaled &= 0xFF;
-
- ulong result_exp = (2045 - x_exp) & 0x7FF;
- ulong estimate = (ulong)RecipEstimateTable[scaled];
- ulong fraction = estimate << 44;
-
- if (result_exp == 0)
- {
- fraction >>= 1;
- fraction |= 1ul << 51;
- }
- else if (result_exp == 0x7FF)
- {
- result_exp = 0;
- fraction >>= 2;
- fraction |= 1ul << 50;
- }
-
- ulong result = x_sign | (result_exp << 52) | fraction;
- return BitConverter.Int64BitsToDouble((long)result);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float InvSqrtEstimate(float x)
- {
- return (float)InvSqrtEstimate((double)x);
- }
-
- public static double InvSqrtEstimate(double x)
- {
- ulong x_bits = (ulong)BitConverter.DoubleToInt64Bits(x);
- ulong x_sign = x_bits & 0x8000000000000000;
- long x_exp = (long)((x_bits >> 52) & 0x7FF);
- ulong scaled = x_bits & ((1ul << 52) - 1);
-
- if (x_exp == 0x7FF && scaled != 0)
- {
- // NaN
- return BitConverter.Int64BitsToDouble((long)(x_bits | 0x0008000000000000));
- }
-
- if (x_exp == 0)
- {
- if (scaled == 0)
- {
- // Zero -> Infinity
- return BitConverter.Int64BitsToDouble((long)(x_sign | 0x7FF0000000000000));
- }
-
- // Denormal
- while ((scaled & (1 << 51)) == 0)
- {
- scaled <<= 1;
- x_exp--;
- }
- scaled <<= 1;
- }
-
- if (x_sign != 0)
- {
- // Negative -> NaN
- return BitConverter.Int64BitsToDouble((long)0x7FF8000000000000);
- }
-
- if (x_exp == 0x7ff && scaled == 0)
- {
- // Infinity -> Zero
- return BitConverter.Int64BitsToDouble((long)x_sign);
- }
-
- if (((ulong)x_exp & 1) == 1)
- {
- scaled >>= 45;
- scaled &= 0xFF;
- scaled |= 0x80;
- }
- else
- {
- scaled >>= 44;
- scaled &= 0xFF;
- scaled |= 0x100;
- }
-
- ulong result_exp = ((ulong)(3068 - x_exp) / 2) & 0x7FF;
- ulong estimate = (ulong)InvSqrtEstimateTable[scaled];
- ulong fraction = estimate << 44;
-
- ulong result = x_sign | (result_exp << 52) | fraction;
- return BitConverter.Int64BitsToDouble((long)result);
- }
- }
-
- static class ASoftFloat16_32
- {
- public static float FPConvert(ushort ValueBits, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat16_32.FPConvert: State.Fpcr = 0x{State.Fpcr:X8}");
-
- double Real = ValueBits.FPUnpackCV(out FPType Type, out bool Sign, State);
-
- float Result;
-
- if (Type == FPType.SNaN || Type == FPType.QNaN)
- {
- if (State.GetFpcrFlag(FPCR.DN))
- {
- Result = FPDefaultNaN();
- }
- else
- {
- Result = FPConvertNaN(ValueBits);
- }
-
- if (Type == FPType.SNaN)
- {
- FPProcessException(FPExc.InvalidOp, State);
- }
- }
- else if (Type == FPType.Infinity)
- {
- Result = FPInfinity(Sign);
- }
- else if (Type == FPType.Zero)
- {
- Result = FPZero(Sign);
- }
- else
- {
- Result = FPRoundCV(Real, State);
- }
-
- return Result;
- }
-
- private static float FPDefaultNaN()
- {
- return -float.NaN;
- }
-
- private static float FPInfinity(bool Sign)
- {
- return Sign ? float.NegativeInfinity : float.PositiveInfinity;
- }
-
- private static float FPZero(bool Sign)
- {
- return Sign ? -0f : +0f;
- }
-
- private static float FPMaxNormal(bool Sign)
- {
- return Sign ? float.MinValue : float.MaxValue;
- }
-
- private static double FPUnpackCV(this ushort ValueBits, out FPType Type, out bool Sign, AThreadState State)
- {
- Sign = (~(uint)ValueBits & 0x8000u) == 0u;
-
- uint Exp16 = ((uint)ValueBits & 0x7C00u) >> 10;
- uint Frac16 = (uint)ValueBits & 0x03FFu;
-
- double Real;
-
- if (Exp16 == 0u)
- {
- if (Frac16 == 0u)
- {
- Type = FPType.Zero;
- Real = 0d;
- }
- else
- {
- Type = FPType.Nonzero; // Subnormal.
- Real = Math.Pow(2d, -14) * ((double)Frac16 * Math.Pow(2d, -10));
- }
- }
- else if (Exp16 == 0x1Fu && !State.GetFpcrFlag(FPCR.AHP))
- {
- if (Frac16 == 0u)
- {
- Type = FPType.Infinity;
- Real = Math.Pow(2d, 1000);
- }
- else
- {
- Type = (~Frac16 & 0x0200u) == 0u ? FPType.QNaN : FPType.SNaN;
- Real = 0d;
- }
- }
- else
- {
- Type = FPType.Nonzero; // Normal.
- Real = Math.Pow(2d, (int)Exp16 - 15) * (1d + (double)Frac16 * Math.Pow(2d, -10));
- }
-
- return Sign ? -Real : Real;
- }
-
- private static float FPRoundCV(double Real, AThreadState State)
- {
- const int MinimumExp = -126;
-
- const int E = 8;
- const int F = 23;
-
- bool Sign;
- double Mantissa;
-
- if (Real < 0d)
- {
- Sign = true;
- Mantissa = -Real;
- }
- else
- {
- Sign = false;
- Mantissa = Real;
- }
-
- int Exponent = 0;
-
- while (Mantissa < 1d)
- {
- Mantissa *= 2d;
- Exponent--;
- }
-
- while (Mantissa >= 2d)
- {
- Mantissa /= 2d;
- Exponent++;
- }
-
- if (State.GetFpcrFlag(FPCR.FZ) && Exponent < MinimumExp)
- {
- State.SetFpsrFlag(FPSR.UFC);
-
- return FPZero(Sign);
- }
-
- uint BiasedExp = (uint)Math.Max(Exponent - MinimumExp + 1, 0);
-
- if (BiasedExp == 0u)
- {
- Mantissa /= Math.Pow(2d, MinimumExp - Exponent);
- }
-
- uint IntMant = (uint)Math.Floor(Mantissa * Math.Pow(2d, F));
- double Error = Mantissa * Math.Pow(2d, F) - (double)IntMant;
-
- if (BiasedExp == 0u && (Error != 0d || State.GetFpcrFlag(FPCR.UFE)))
- {
- FPProcessException(FPExc.Underflow, State);
- }
-
- bool OverflowToInf;
- bool RoundUp;
-
- switch (State.FPRoundingMode())
- {
- default:
- case ARoundMode.ToNearest:
- RoundUp = (Error > 0.5d || (Error == 0.5d && (IntMant & 1u) == 1u));
- OverflowToInf = true;
- break;
-
- case ARoundMode.TowardsPlusInfinity:
- RoundUp = (Error != 0d && !Sign);
- OverflowToInf = !Sign;
- break;
-
- case ARoundMode.TowardsMinusInfinity:
- RoundUp = (Error != 0d && Sign);
- OverflowToInf = Sign;
- break;
-
- case ARoundMode.TowardsZero:
- RoundUp = false;
- OverflowToInf = false;
- break;
- }
-
- if (RoundUp)
- {
- IntMant++;
-
- if (IntMant == (uint)Math.Pow(2d, F))
- {
- BiasedExp = 1u;
- }
-
- if (IntMant == (uint)Math.Pow(2d, F + 1))
- {
- BiasedExp++;
- IntMant >>= 1;
- }
- }
-
- float Result;
-
- if (BiasedExp >= (uint)Math.Pow(2d, E) - 1u)
- {
- Result = OverflowToInf ? FPInfinity(Sign) : FPMaxNormal(Sign);
-
- FPProcessException(FPExc.Overflow, State);
-
- Error = 1d;
- }
- else
- {
- Result = BitConverter.Int32BitsToSingle(
- (int)((Sign ? 1u : 0u) << 31 | (BiasedExp & 0xFFu) << 23 | (IntMant & 0x007FFFFFu)));
- }
-
- if (Error != 0d)
- {
- FPProcessException(FPExc.Inexact, State);
- }
-
- return Result;
- }
-
- private static float FPConvertNaN(ushort ValueBits)
- {
- return BitConverter.Int32BitsToSingle(
- (int)(((uint)ValueBits & 0x8000u) << 16 | 0x7FC00000u | ((uint)ValueBits & 0x01FFu) << 13));
- }
-
- private static void FPProcessException(FPExc Exc, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-
- static class ASoftFloat32_16
- {
- public static ushort FPConvert(float Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat32_16.FPConvert: State.Fpcr = 0x{State.Fpcr:X8}");
-
- double Real = Value.FPUnpackCV(out FPType Type, out bool Sign, State, out uint ValueBits);
-
- bool AltHp = State.GetFpcrFlag(FPCR.AHP);
-
- ushort ResultBits;
-
- if (Type == FPType.SNaN || Type == FPType.QNaN)
- {
- if (AltHp)
- {
- ResultBits = FPZero(Sign);
- }
- else if (State.GetFpcrFlag(FPCR.DN))
- {
- ResultBits = FPDefaultNaN();
- }
- else
- {
- ResultBits = FPConvertNaN(ValueBits);
- }
-
- if (Type == FPType.SNaN || AltHp)
- {
- FPProcessException(FPExc.InvalidOp, State);
- }
- }
- else if (Type == FPType.Infinity)
- {
- if (AltHp)
- {
- ResultBits = (ushort)((Sign ? 1u : 0u) << 15 | 0x7FFFu);
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else
- {
- ResultBits = FPInfinity(Sign);
- }
- }
- else if (Type == FPType.Zero)
- {
- ResultBits = FPZero(Sign);
- }
- else
- {
- ResultBits = FPRoundCV(Real, State);
- }
-
- return ResultBits;
- }
-
- private static ushort FPDefaultNaN()
- {
- return (ushort)0x7E00u;
- }
-
- private static ushort FPInfinity(bool Sign)
- {
- return Sign ? (ushort)0xFC00u : (ushort)0x7C00u;
- }
-
- private static ushort FPZero(bool Sign)
- {
- return Sign ? (ushort)0x8000u : (ushort)0x0000u;
- }
-
- private static ushort FPMaxNormal(bool Sign)
- {
- return Sign ? (ushort)0xFBFFu : (ushort)0x7BFFu;
- }
-
- private static double FPUnpackCV(this float Value, out FPType Type, out bool Sign, AThreadState State, out uint ValueBits)
- {
- ValueBits = (uint)BitConverter.SingleToInt32Bits(Value);
-
- Sign = (~ValueBits & 0x80000000u) == 0u;
-
- uint Exp32 = (ValueBits & 0x7F800000u) >> 23;
- uint Frac32 = ValueBits & 0x007FFFFFu;
-
- double Real;
-
- if (Exp32 == 0u)
- {
- if (Frac32 == 0u || State.GetFpcrFlag(FPCR.FZ))
- {
- Type = FPType.Zero;
- Real = 0d;
-
- if (Frac32 != 0u) FPProcessException(FPExc.InputDenorm, State);
- }
- else
- {
- Type = FPType.Nonzero; // Subnormal.
- Real = Math.Pow(2d, -126) * ((double)Frac32 * Math.Pow(2d, -23));
- }
- }
- else if (Exp32 == 0xFFu)
- {
- if (Frac32 == 0u)
- {
- Type = FPType.Infinity;
- Real = Math.Pow(2d, 1000);
- }
- else
- {
- Type = (~Frac32 & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
- Real = 0d;
- }
- }
- else
- {
- Type = FPType.Nonzero; // Normal.
- Real = Math.Pow(2d, (int)Exp32 - 127) * (1d + (double)Frac32 * Math.Pow(2d, -23));
- }
-
- return Sign ? -Real : Real;
- }
-
- private static ushort FPRoundCV(double Real, AThreadState State)
- {
- const int MinimumExp = -14;
-
- const int E = 5;
- const int F = 10;
-
- bool Sign;
- double Mantissa;
-
- if (Real < 0d)
- {
- Sign = true;
- Mantissa = -Real;
- }
- else
- {
- Sign = false;
- Mantissa = Real;
- }
-
- int Exponent = 0;
-
- while (Mantissa < 1d)
- {
- Mantissa *= 2d;
- Exponent--;
- }
-
- while (Mantissa >= 2d)
- {
- Mantissa /= 2d;
- Exponent++;
- }
-
- uint BiasedExp = (uint)Math.Max(Exponent - MinimumExp + 1, 0);
-
- if (BiasedExp == 0u)
- {
- Mantissa /= Math.Pow(2d, MinimumExp - Exponent);
- }
-
- uint IntMant = (uint)Math.Floor(Mantissa * Math.Pow(2d, F));
- double Error = Mantissa * Math.Pow(2d, F) - (double)IntMant;
-
- if (BiasedExp == 0u && (Error != 0d || State.GetFpcrFlag(FPCR.UFE)))
- {
- FPProcessException(FPExc.Underflow, State);
- }
-
- bool OverflowToInf;
- bool RoundUp;
-
- switch (State.FPRoundingMode())
- {
- default:
- case ARoundMode.ToNearest:
- RoundUp = (Error > 0.5d || (Error == 0.5d && (IntMant & 1u) == 1u));
- OverflowToInf = true;
- break;
-
- case ARoundMode.TowardsPlusInfinity:
- RoundUp = (Error != 0d && !Sign);
- OverflowToInf = !Sign;
- break;
-
- case ARoundMode.TowardsMinusInfinity:
- RoundUp = (Error != 0d && Sign);
- OverflowToInf = Sign;
- break;
-
- case ARoundMode.TowardsZero:
- RoundUp = false;
- OverflowToInf = false;
- break;
- }
-
- if (RoundUp)
- {
- IntMant++;
-
- if (IntMant == (uint)Math.Pow(2d, F))
- {
- BiasedExp = 1u;
- }
-
- if (IntMant == (uint)Math.Pow(2d, F + 1))
- {
- BiasedExp++;
- IntMant >>= 1;
- }
- }
-
- ushort ResultBits;
-
- if (!State.GetFpcrFlag(FPCR.AHP))
- {
- if (BiasedExp >= (uint)Math.Pow(2d, E) - 1u)
- {
- ResultBits = OverflowToInf ? FPInfinity(Sign) : FPMaxNormal(Sign);
-
- FPProcessException(FPExc.Overflow, State);
-
- Error = 1d;
- }
- else
- {
- ResultBits = (ushort)((Sign ? 1u : 0u) << 15 | (BiasedExp & 0x1Fu) << 10 | (IntMant & 0x03FFu));
- }
- }
- else
- {
- if (BiasedExp >= (uint)Math.Pow(2d, E))
- {
- ResultBits = (ushort)((Sign ? 1u : 0u) << 15 | 0x7FFFu);
-
- FPProcessException(FPExc.InvalidOp, State);
-
- Error = 0d;
- }
- else
- {
- ResultBits = (ushort)((Sign ? 1u : 0u) << 15 | (BiasedExp & 0x1Fu) << 10 | (IntMant & 0x03FFu));
- }
- }
-
- if (Error != 0d)
- {
- FPProcessException(FPExc.Inexact, State);
- }
-
- return ResultBits;
- }
-
- private static ushort FPConvertNaN(uint ValueBits)
- {
- return (ushort)((ValueBits & 0x80000000u) >> 16 | 0x7E00u | (ValueBits & 0x003FE000u) >> 13);
- }
-
- private static void FPProcessException(FPExc Exc, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-
- static class ASoftFloat_32
- {
- public static float FPAdd(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if (Inf1 && Inf2 && Sign1 == !Sign2)
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if ((Inf1 && !Sign1) || (Inf2 && !Sign2))
- {
- Result = FPInfinity(false);
- }
- else if ((Inf1 && Sign1) || (Inf2 && Sign2))
- {
- Result = FPInfinity(true);
- }
- else if (Zero1 && Zero2 && Sign1 == Sign2)
- {
- Result = FPZero(Sign1);
- }
- else
- {
- Result = Value1 + Value2;
- }
- }
-
- return Result;
- }
-
- public static float FPDiv(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPDiv: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Inf2) || (Zero1 && Zero2))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if (Inf1 || Zero2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
-
- if (!Inf1) FPProcessException(FPExc.DivideByZero, State);
- }
- else if (Zero1 || Inf2)
- {
- Result = FPZero(Sign1 ^ Sign2);
- }
- else
- {
- Result = Value1 / Value2;
- }
- }
-
- return Result;
- }
-
- public static float FPMax(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMax: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- if (Value1 > Value2)
- {
- if (Type1 == FPType.Infinity)
- {
- Result = FPInfinity(Sign1);
- }
- else if (Type1 == FPType.Zero)
- {
- Result = FPZero(Sign1 && Sign2);
- }
- else
- {
- Result = Value1;
- }
- }
- else
- {
- if (Type2 == FPType.Infinity)
- {
- Result = FPInfinity(Sign2);
- }
- else if (Type2 == FPType.Zero)
- {
- Result = FPZero(Sign1 && Sign2);
- }
- else
- {
- Result = Value2;
- }
- }
- }
-
- return Result;
- }
-
- public static float FPMaxNum(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_32.FPMaxNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- if (Type1 == FPType.QNaN && Type2 != FPType.QNaN)
- {
- Value1 = FPInfinity(true);
- }
- else if (Type1 != FPType.QNaN && Type2 == FPType.QNaN)
- {
- Value2 = FPInfinity(true);
- }
-
- return FPMax(Value1, Value2, State);
- }
-
- public static float FPMin(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMin: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- if (Value1 < Value2)
- {
- if (Type1 == FPType.Infinity)
- {
- Result = FPInfinity(Sign1);
- }
- else if (Type1 == FPType.Zero)
- {
- Result = FPZero(Sign1 || Sign2);
- }
- else
- {
- Result = Value1;
- }
- }
- else
- {
- if (Type2 == FPType.Infinity)
- {
- Result = FPInfinity(Sign2);
- }
- else if (Type2 == FPType.Zero)
- {
- Result = FPZero(Sign1 || Sign2);
- }
- else
- {
- Result = Value2;
- }
- }
- }
-
- return Result;
- }
-
- public static float FPMinNum(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_32.FPMinNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- if (Type1 == FPType.QNaN && Type2 != FPType.QNaN)
- {
- Value1 = FPInfinity(false);
- }
- else if (Type1 != FPType.QNaN && Type2 == FPType.QNaN)
- {
- Value2 = FPInfinity(false);
- }
-
- return FPMin(Value1, Value2, State);
- }
-
- public static float FPMul(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMul: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else if (Zero1 || Zero2)
- {
- Result = FPZero(Sign1 ^ Sign2);
- }
- else
- {
- Result = Value1 * Value2;
- }
- }
-
- return Result;
- }
-
- public static float FPMulAdd(float ValueA, float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMulAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- ValueA = ValueA.FPUnpack(out FPType TypeA, out bool SignA, out uint Addend);
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- float Result = FPProcessNaNs3(TypeA, Type1, Type2, Addend, Op1, Op2, State, out bool Done);
-
- if (TypeA == FPType.QNaN && ((Inf1 && Zero2) || (Zero1 && Inf2)))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
-
- if (!Done)
- {
- bool InfA = TypeA == FPType.Infinity; bool ZeroA = TypeA == FPType.Zero;
-
- bool SignP = Sign1 ^ Sign2;
- bool InfP = Inf1 || Inf2;
- bool ZeroP = Zero1 || Zero2;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2) || (InfA && InfP && SignA != SignP))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if ((InfA && !SignA) || (InfP && !SignP))
- {
- Result = FPInfinity(false);
- }
- else if ((InfA && SignA) || (InfP && SignP))
- {
- Result = FPInfinity(true);
- }
- else if (ZeroA && ZeroP && SignA == SignP)
- {
- Result = FPZero(SignA);
- }
- else
- {
- // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T);
- // https://github.com/dotnet/corefx/issues/31903
-
- Result = ValueA + (Value1 * Value2);
- }
- }
-
- return Result;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float FPMulSub(float ValueA, float Value1, float Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_32.FPMulSub: ");
-
- Value1 = Value1.FPNeg();
-
- return FPMulAdd(ValueA, Value1, Value2, State);
- }
-
- public static float FPMulX(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPMulX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPTwo(Sign1 ^ Sign2);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else if (Zero1 || Zero2)
- {
- Result = FPZero(Sign1 ^ Sign2);
- }
- else
- {
- Result = Value1 * Value2;
- }
- }
-
- return Result;
- }
-
- public static float FPRecipStepFused(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPRecipStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPTwo(false);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else
- {
- // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T);
- // https://github.com/dotnet/corefx/issues/31903
-
- Result = 2f + (Value1 * Value2);
- }
- }
-
- return Result;
- }
-
- public static float FPRecpX(float Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPRecpX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value.FPUnpack(out FPType Type, out bool Sign, out uint Op);
-
- float Result;
-
- if (Type == FPType.SNaN || Type == FPType.QNaN)
- {
- Result = FPProcessNaN(Type, Op, State);
- }
- else
- {
- uint NotExp = (~Op >> 23) & 0xFFu;
- uint MaxExp = 0xFEu;
-
- Result = BitConverter.Int32BitsToSingle(
- (int)((Sign ? 1u : 0u) << 31 | (NotExp == 0xFFu ? MaxExp : NotExp) << 23));
- }
-
- return Result;
- }
-
- public static float FPRSqrtStepFused(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPRSqrtStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPOnePointFive(false);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else
- {
- // TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T);
- // https://github.com/dotnet/corefx/issues/31903
-
- Result = (3f + (Value1 * Value2)) / 2f;
- }
- }
-
- return Result;
- }
-
- public static float FPSqrt(float Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSqrt: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value = Value.FPUnpack(out FPType Type, out bool Sign, out uint Op);
-
- float Result;
-
- if (Type == FPType.SNaN || Type == FPType.QNaN)
- {
- Result = FPProcessNaN(Type, Op, State);
- }
- else if (Type == FPType.Zero)
- {
- Result = FPZero(Sign);
- }
- else if (Type == FPType.Infinity && !Sign)
- {
- Result = FPInfinity(Sign);
- }
- else if (Sign)
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else
- {
- Result = MathF.Sqrt(Value);
- }
-
- return Result;
- }
-
- public static float FPSub(float Value1, float Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out uint Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out uint Op2);
-
- float Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if (Inf1 && Inf2 && Sign1 == Sign2)
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if ((Inf1 && !Sign1) || (Inf2 && Sign2))
- {
- Result = FPInfinity(false);
- }
- else if ((Inf1 && Sign1) || (Inf2 && !Sign2))
- {
- Result = FPInfinity(true);
- }
- else if (Zero1 && Zero2 && Sign1 == !Sign2)
- {
- Result = FPZero(Sign1);
- }
- else
- {
- Result = Value1 - Value2;
- }
- }
-
- return Result;
- }
-
- private static float FPDefaultNaN()
- {
- return -float.NaN;
- }
-
- private static float FPInfinity(bool Sign)
- {
- return Sign ? float.NegativeInfinity : float.PositiveInfinity;
- }
-
- private static float FPZero(bool Sign)
- {
- return Sign ? -0f : +0f;
- }
-
- private static float FPTwo(bool Sign)
- {
- return Sign ? -2f : +2f;
- }
-
- private static float FPOnePointFive(bool Sign)
- {
- return Sign ? -1.5f : +1.5f;
- }
-
- private static float FPNeg(this float Value)
- {
- return -Value;
- }
-
- private static float FPUnpack(this float Value, out FPType Type, out bool Sign, out uint ValueBits)
- {
- ValueBits = (uint)BitConverter.SingleToInt32Bits(Value);
-
- Sign = (~ValueBits & 0x80000000u) == 0u;
-
- if ((ValueBits & 0x7F800000u) == 0u)
- {
- if ((ValueBits & 0x007FFFFFu) == 0u)
- {
- Type = FPType.Zero;
- }
- else
- {
- Type = FPType.Nonzero;
- }
- }
- else if ((~ValueBits & 0x7F800000u) == 0u)
- {
- if ((ValueBits & 0x007FFFFFu) == 0u)
- {
- Type = FPType.Infinity;
- }
- else
- {
- Type = (~ValueBits & 0x00400000u) == 0u
- ? FPType.QNaN
- : FPType.SNaN;
-
- return FPZero(Sign);
- }
- }
- else
- {
- Type = FPType.Nonzero;
- }
-
- return Value;
- }
-
- private static float FPProcessNaNs(
- FPType Type1,
- FPType Type2,
- uint Op1,
- uint Op2,
- AThreadState State,
- out bool Done)
- {
- Done = true;
-
- if (Type1 == FPType.SNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.SNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
- else if (Type1 == FPType.QNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.QNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
-
- Done = false;
-
- return FPZero(false);
- }
-
- private static float FPProcessNaNs3(
- FPType Type1,
- FPType Type2,
- FPType Type3,
- uint Op1,
- uint Op2,
- uint Op3,
- AThreadState State,
- out bool Done)
- {
- Done = true;
-
- if (Type1 == FPType.SNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.SNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
- else if (Type3 == FPType.SNaN)
- {
- return FPProcessNaN(Type3, Op3, State);
- }
- else if (Type1 == FPType.QNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.QNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
- else if (Type3 == FPType.QNaN)
- {
- return FPProcessNaN(Type3, Op3, State);
- }
-
- Done = false;
-
- return FPZero(false);
- }
-
- private static float FPProcessNaN(FPType Type, uint Op, AThreadState State)
- {
- if (Type == FPType.SNaN)
- {
- Op |= 1u << 22;
-
- FPProcessException(FPExc.InvalidOp, State);
- }
-
- if (State.GetFpcrFlag(FPCR.DN))
- {
- return FPDefaultNaN();
- }
-
- return BitConverter.Int32BitsToSingle((int)Op);
- }
-
- private static void FPProcessException(FPExc Exc, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-
- static class ASoftFloat_64
- {
- public static double FPAdd(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if (Inf1 && Inf2 && Sign1 == !Sign2)
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if ((Inf1 && !Sign1) || (Inf2 && !Sign2))
- {
- Result = FPInfinity(false);
- }
- else if ((Inf1 && Sign1) || (Inf2 && Sign2))
- {
- Result = FPInfinity(true);
- }
- else if (Zero1 && Zero2 && Sign1 == Sign2)
- {
- Result = FPZero(Sign1);
- }
- else
- {
- Result = Value1 + Value2;
- }
- }
-
- return Result;
- }
-
- public static double FPDiv(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPDiv: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Inf2) || (Zero1 && Zero2))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if (Inf1 || Zero2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
-
- if (!Inf1) FPProcessException(FPExc.DivideByZero, State);
- }
- else if (Zero1 || Inf2)
- {
- Result = FPZero(Sign1 ^ Sign2);
- }
- else
- {
- Result = Value1 / Value2;
- }
- }
-
- return Result;
- }
-
- public static double FPMax(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMax: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- if (Value1 > Value2)
- {
- if (Type1 == FPType.Infinity)
- {
- Result = FPInfinity(Sign1);
- }
- else if (Type1 == FPType.Zero)
- {
- Result = FPZero(Sign1 && Sign2);
- }
- else
- {
- Result = Value1;
- }
- }
- else
- {
- if (Type2 == FPType.Infinity)
- {
- Result = FPInfinity(Sign2);
- }
- else if (Type2 == FPType.Zero)
- {
- Result = FPZero(Sign1 && Sign2);
- }
- else
- {
- Result = Value2;
- }
- }
- }
-
- return Result;
- }
-
- public static double FPMaxNum(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_64.FPMaxNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- if (Type1 == FPType.QNaN && Type2 != FPType.QNaN)
- {
- Value1 = FPInfinity(true);
- }
- else if (Type1 != FPType.QNaN && Type2 == FPType.QNaN)
- {
- Value2 = FPInfinity(true);
- }
-
- return FPMax(Value1, Value2, State);
- }
-
- public static double FPMin(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMin: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- if (Value1 < Value2)
- {
- if (Type1 == FPType.Infinity)
- {
- Result = FPInfinity(Sign1);
- }
- else if (Type1 == FPType.Zero)
- {
- Result = FPZero(Sign1 || Sign2);
- }
- else
- {
- Result = Value1;
- }
- }
- else
- {
- if (Type2 == FPType.Infinity)
- {
- Result = FPInfinity(Sign2);
- }
- else if (Type2 == FPType.Zero)
- {
- Result = FPZero(Sign1 || Sign2);
- }
- else
- {
- Result = Value2;
- }
- }
- }
-
- return Result;
- }
-
- public static double FPMinNum(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_64.FPMinNum: ");
-
- Value1.FPUnpack(out FPType Type1, out _, out _);
- Value2.FPUnpack(out FPType Type2, out _, out _);
-
- if (Type1 == FPType.QNaN && Type2 != FPType.QNaN)
- {
- Value1 = FPInfinity(false);
- }
- else if (Type1 != FPType.QNaN && Type2 == FPType.QNaN)
- {
- Value2 = FPInfinity(false);
- }
-
- return FPMin(Value1, Value2, State);
- }
-
- public static double FPMul(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMul: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else if (Zero1 || Zero2)
- {
- Result = FPZero(Sign1 ^ Sign2);
- }
- else
- {
- Result = Value1 * Value2;
- }
- }
-
- return Result;
- }
-
- public static double FPMulAdd(double ValueA, double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMulAdd: State.Fpcr = 0x{State.Fpcr:X8}");
-
- ValueA = ValueA.FPUnpack(out FPType TypeA, out bool SignA, out ulong Addend);
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- double Result = FPProcessNaNs3(TypeA, Type1, Type2, Addend, Op1, Op2, State, out bool Done);
-
- if (TypeA == FPType.QNaN && ((Inf1 && Zero2) || (Zero1 && Inf2)))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
-
- if (!Done)
- {
- bool InfA = TypeA == FPType.Infinity; bool ZeroA = TypeA == FPType.Zero;
-
- bool SignP = Sign1 ^ Sign2;
- bool InfP = Inf1 || Inf2;
- bool ZeroP = Zero1 || Zero2;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2) || (InfA && InfP && SignA != SignP))
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if ((InfA && !SignA) || (InfP && !SignP))
- {
- Result = FPInfinity(false);
- }
- else if ((InfA && SignA) || (InfP && SignP))
- {
- Result = FPInfinity(true);
- }
- else if (ZeroA && ZeroP && SignA == SignP)
- {
- Result = FPZero(SignA);
- }
- else
- {
- // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T);
- // https://github.com/dotnet/corefx/issues/31903
-
- Result = ValueA + (Value1 * Value2);
- }
- }
-
- return Result;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static double FPMulSub(double ValueA, double Value1, double Value2, AThreadState State)
- {
- Debug.WriteIf(State.Fpcr != 0, "ASoftFloat_64.FPMulSub: ");
-
- Value1 = Value1.FPNeg();
-
- return FPMulAdd(ValueA, Value1, Value2, State);
- }
-
- public static double FPMulX(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPMulX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPTwo(Sign1 ^ Sign2);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else if (Zero1 || Zero2)
- {
- Result = FPZero(Sign1 ^ Sign2);
- }
- else
- {
- Result = Value1 * Value2;
- }
- }
-
- return Result;
- }
-
- public static double FPRecipStepFused(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPRecipStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPTwo(false);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else
- {
- // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T);
- // https://github.com/dotnet/corefx/issues/31903
-
- Result = 2d + (Value1 * Value2);
- }
- }
-
- return Result;
- }
-
- public static double FPRecpX(double Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPRecpX: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value.FPUnpack(out FPType Type, out bool Sign, out ulong Op);
-
- double Result;
-
- if (Type == FPType.SNaN || Type == FPType.QNaN)
- {
- Result = FPProcessNaN(Type, Op, State);
- }
- else
- {
- ulong NotExp = (~Op >> 52) & 0x7FFul;
- ulong MaxExp = 0x7FEul;
-
- Result = BitConverter.Int64BitsToDouble(
- (long)((Sign ? 1ul : 0ul) << 63 | (NotExp == 0x7FFul ? MaxExp : NotExp) << 52));
- }
-
- return Result;
- }
-
- public static double FPRSqrtStepFused(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPRSqrtStepFused: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPNeg();
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if ((Inf1 && Zero2) || (Zero1 && Inf2))
- {
- Result = FPOnePointFive(false);
- }
- else if (Inf1 || Inf2)
- {
- Result = FPInfinity(Sign1 ^ Sign2);
- }
- else
- {
- // TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T);
- // https://github.com/dotnet/corefx/issues/31903
-
- Result = (3d + (Value1 * Value2)) / 2d;
- }
- }
-
- return Result;
- }
-
- public static double FPSqrt(double Value, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSqrt: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value = Value.FPUnpack(out FPType Type, out bool Sign, out ulong Op);
-
- double Result;
-
- if (Type == FPType.SNaN || Type == FPType.QNaN)
- {
- Result = FPProcessNaN(Type, Op, State);
- }
- else if (Type == FPType.Zero)
- {
- Result = FPZero(Sign);
- }
- else if (Type == FPType.Infinity && !Sign)
- {
- Result = FPInfinity(Sign);
- }
- else if (Sign)
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else
- {
- Result = Math.Sqrt(Value);
- }
-
- return Result;
- }
-
- public static double FPSub(double Value1, double Value2, AThreadState State)
- {
- Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
-
- Value1 = Value1.FPUnpack(out FPType Type1, out bool Sign1, out ulong Op1);
- Value2 = Value2.FPUnpack(out FPType Type2, out bool Sign2, out ulong Op2);
-
- double Result = FPProcessNaNs(Type1, Type2, Op1, Op2, State, out bool Done);
-
- if (!Done)
- {
- bool Inf1 = Type1 == FPType.Infinity; bool Zero1 = Type1 == FPType.Zero;
- bool Inf2 = Type2 == FPType.Infinity; bool Zero2 = Type2 == FPType.Zero;
-
- if (Inf1 && Inf2 && Sign1 == Sign2)
- {
- Result = FPDefaultNaN();
-
- FPProcessException(FPExc.InvalidOp, State);
- }
- else if ((Inf1 && !Sign1) || (Inf2 && Sign2))
- {
- Result = FPInfinity(false);
- }
- else if ((Inf1 && Sign1) || (Inf2 && !Sign2))
- {
- Result = FPInfinity(true);
- }
- else if (Zero1 && Zero2 && Sign1 == !Sign2)
- {
- Result = FPZero(Sign1);
- }
- else
- {
- Result = Value1 - Value2;
- }
- }
-
- return Result;
- }
-
- private static double FPDefaultNaN()
- {
- return -double.NaN;
- }
-
- private static double FPInfinity(bool Sign)
- {
- return Sign ? double.NegativeInfinity : double.PositiveInfinity;
- }
-
- private static double FPZero(bool Sign)
- {
- return Sign ? -0d : +0d;
- }
-
- private static double FPTwo(bool Sign)
- {
- return Sign ? -2d : +2d;
- }
-
- private static double FPOnePointFive(bool Sign)
- {
- return Sign ? -1.5d : +1.5d;
- }
-
- private static double FPNeg(this double Value)
- {
- return -Value;
- }
-
- private static double FPUnpack(this double Value, out FPType Type, out bool Sign, out ulong ValueBits)
- {
- ValueBits = (ulong)BitConverter.DoubleToInt64Bits(Value);
-
- Sign = (~ValueBits & 0x8000000000000000ul) == 0ul;
-
- if ((ValueBits & 0x7FF0000000000000ul) == 0ul)
- {
- if ((ValueBits & 0x000FFFFFFFFFFFFFul) == 0ul)
- {
- Type = FPType.Zero;
- }
- else
- {
- Type = FPType.Nonzero;
- }
- }
- else if ((~ValueBits & 0x7FF0000000000000ul) == 0ul)
- {
- if ((ValueBits & 0x000FFFFFFFFFFFFFul) == 0ul)
- {
- Type = FPType.Infinity;
- }
- else
- {
- Type = (~ValueBits & 0x0008000000000000ul) == 0ul
- ? FPType.QNaN
- : FPType.SNaN;
-
- return FPZero(Sign);
- }
- }
- else
- {
- Type = FPType.Nonzero;
- }
-
- return Value;
- }
-
- private static double FPProcessNaNs(
- FPType Type1,
- FPType Type2,
- ulong Op1,
- ulong Op2,
- AThreadState State,
- out bool Done)
- {
- Done = true;
-
- if (Type1 == FPType.SNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.SNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
- else if (Type1 == FPType.QNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.QNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
-
- Done = false;
-
- return FPZero(false);
- }
-
- private static double FPProcessNaNs3(
- FPType Type1,
- FPType Type2,
- FPType Type3,
- ulong Op1,
- ulong Op2,
- ulong Op3,
- AThreadState State,
- out bool Done)
- {
- Done = true;
-
- if (Type1 == FPType.SNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.SNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
- else if (Type3 == FPType.SNaN)
- {
- return FPProcessNaN(Type3, Op3, State);
- }
- else if (Type1 == FPType.QNaN)
- {
- return FPProcessNaN(Type1, Op1, State);
- }
- else if (Type2 == FPType.QNaN)
- {
- return FPProcessNaN(Type2, Op2, State);
- }
- else if (Type3 == FPType.QNaN)
- {
- return FPProcessNaN(Type3, Op3, State);
- }
-
- Done = false;
-
- return FPZero(false);
- }
-
- private static double FPProcessNaN(FPType Type, ulong Op, AThreadState State)
- {
- if (Type == FPType.SNaN)
- {
- Op |= 1ul << 51;
-
- FPProcessException(FPExc.InvalidOp, State);
- }
-
- if (State.GetFpcrFlag(FPCR.DN))
- {
- return FPDefaultNaN();
- }
-
- return BitConverter.Int64BitsToDouble((long)Op);
- }
-
- private static void FPProcessException(FPExc Exc, AThreadState State)
- {
- int Enable = (int)Exc + 8;
-
- if ((State.Fpcr & (1 << Enable)) != 0)
- {
- throw new NotImplementedException("floating-point trap handling");
- }
- else
- {
- State.Fpsr |= 1 << (int)Exc;
- }
- }
- }
-}
diff --git a/ChocolArm64/Instruction/AVectorHelper.cs b/ChocolArm64/Instruction/AVectorHelper.cs
deleted file mode 100644
index 41e865b9..00000000
--- a/ChocolArm64/Instruction/AVectorHelper.cs
+++ /dev/null
@@ -1,790 +0,0 @@
-using ChocolArm64.State;
-using ChocolArm64.Translation;
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-namespace ChocolArm64.Instruction
-{
- static class AVectorHelper
- {
- private static readonly Vector128<float> Zero32_128Mask;
-
- static AVectorHelper()
- {
- if (!Sse2.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
-
- Zero32_128Mask = Sse.StaticCast<uint, float>(Sse2.SetVector128(0, 0, 0, 0xffffffff));
- }
-
- public static void EmitCall(AILEmitterCtx Context, string Name64, string Name128)
- {
- bool IsSimd64 = Context.CurrOp.RegisterSize == ARegisterSize.SIMD64;
-
- Context.EmitCall(typeof(AVectorHelper), IsSimd64 ? Name64 : Name128);
- }
-
- public static void EmitCall(AILEmitterCtx Context, string MthdName)
- {
- Context.EmitCall(typeof(AVectorHelper), MthdName);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SatF32ToS32(float Value)
- {
- if (float.IsNaN(Value)) return 0;
-
- return Value > int.MaxValue ? int.MaxValue :
- Value < int.MinValue ? int.MinValue : (int)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long SatF32ToS64(float Value)
- {
- if (float.IsNaN(Value)) return 0;
-
- return Value > long.MaxValue ? long.MaxValue :
- Value < long.MinValue ? long.MinValue : (long)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint SatF32ToU32(float Value)
- {
- if (float.IsNaN(Value)) return 0;
-
- return Value > uint.MaxValue ? uint.MaxValue :
- Value < uint.MinValue ? uint.MinValue : (uint)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong SatF32ToU64(float Value)
- {
- if (float.IsNaN(Value)) return 0;
-
- return Value > ulong.MaxValue ? ulong.MaxValue :
- Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SatF64ToS32(double Value)
- {
- if (double.IsNaN(Value)) return 0;
-
- return Value > int.MaxValue ? int.MaxValue :
- Value < int.MinValue ? int.MinValue : (int)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long SatF64ToS64(double Value)
- {
- if (double.IsNaN(Value)) return 0;
-
- return Value > long.MaxValue ? long.MaxValue :
- Value < long.MinValue ? long.MinValue : (long)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint SatF64ToU32(double Value)
- {
- if (double.IsNaN(Value)) return 0;
-
- return Value > uint.MaxValue ? uint.MaxValue :
- Value < uint.MinValue ? uint.MinValue : (uint)Value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong SatF64ToU64(double Value)
- {
- if (double.IsNaN(Value)) return 0;
-
- return Value > ulong.MaxValue ? ulong.MaxValue :
- Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
- }
-
- public static double Round(double Value, AThreadState State)
- {
- switch (State.FPRoundingMode())
- {
- case ARoundMode.ToNearest: return Math.Round (Value);
- case ARoundMode.TowardsPlusInfinity: return Math.Ceiling (Value);
- case ARoundMode.TowardsMinusInfinity: return Math.Floor (Value);
- case ARoundMode.TowardsZero: return Math.Truncate(Value);
- }
-
- throw new InvalidOperationException();
- }
-
- public static float RoundF(float Value, AThreadState State)
- {
- switch (State.FPRoundingMode())
- {
- case ARoundMode.ToNearest: return MathF.Round (Value);
- case ARoundMode.TowardsPlusInfinity: return MathF.Ceiling (Value);
- case ARoundMode.TowardsMinusInfinity: return MathF.Floor (Value);
- case ARoundMode.TowardsZero: return MathF.Truncate(Value);
- }
-
- throw new InvalidOperationException();
- }
-
- public static Vector128<float> Tbl1_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0)
- {
- return Tbl(Vector, 8, Tb0);
- }
-
- public static Vector128<float> Tbl1_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0)
- {
- return Tbl(Vector, 16, Tb0);
- }
-
- public static Vector128<float> Tbl2_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1)
- {
- return Tbl(Vector, 8, Tb0, Tb1);
- }
-
- public static Vector128<float> Tbl2_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1)
- {
- return Tbl(Vector, 16, Tb0, Tb1);
- }
-
- public static Vector128<float> Tbl3_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2)
- {
- return Tbl(Vector, 8, Tb0, Tb1, Tb2);
- }
-
- public static Vector128<float> Tbl3_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2)
- {
- return Tbl(Vector, 16, Tb0, Tb1, Tb2);
- }
-
- public static Vector128<float> Tbl4_V64(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2,
- Vector128<float> Tb3)
- {
- return Tbl(Vector, 8, Tb0, Tb1, Tb2, Tb3);
- }
-
- public static Vector128<float> Tbl4_V128(
- Vector128<float> Vector,
- Vector128<float> Tb0,
- Vector128<float> Tb1,
- Vector128<float> Tb2,
- Vector128<float> Tb3)
- {
- return Tbl(Vector, 16, Tb0, Tb1, Tb2, Tb3);
- }
-
- private static Vector128<float> Tbl(Vector128<float> Vector, int Bytes, params Vector128<float>[] Tb)
- {
- Vector128<float> Res = new Vector128<float>();
-
- byte[] Table = new byte[Tb.Length * 16];
-
- for (byte Index = 0; Index < Tb.Length; Index++)
- for (byte Index2 = 0; Index2 < 16; Index2++)
- {
- Table[Index * 16 + Index2] = (byte)VectorExtractIntZx(Tb[Index], Index2, 0);
- }
-
- for (byte Index = 0; Index < Bytes; Index++)
- {
- byte TblIdx = (byte)VectorExtractIntZx(Vector, Index, 0);
-
- if (TblIdx < Table.Length)
- {
- Res = VectorInsertInt(Table[TblIdx], Res, Index, 0);
- }
- }
-
- return Res;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static double VectorExtractDouble(Vector128<float> Vector, byte Index)
- {
- if (Sse41.IsSupported)
- {
- return BitConverter.Int64BitsToDouble(Sse41.Extract(Sse.StaticCast<float, long>(Vector), Index));
- }
- else if (Sse2.IsSupported)
- {
- return BitConverter.Int64BitsToDouble((long)VectorExtractIntZx(Vector, Index, 3));
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static long VectorExtractIntSx(Vector128<float> Vector, byte Index, int Size)
- {
- if (Sse41.IsSupported)
- {
- if (Size == 0)
- {
- return (sbyte)Sse41.Extract(Sse.StaticCast<float, byte>(Vector), Index);
- }
- else if (Size == 1)
- {
- return (short)Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), Index);
- }
- else if (Size == 2)
- {
- return Sse41.Extract(Sse.StaticCast<float, int>(Vector), Index);
- }
- else if (Size == 3)
- {
- return Sse41.Extract(Sse.StaticCast<float, long>(Vector), Index);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
- else if (Sse2.IsSupported)
- {
- if (Size == 0)
- {
- return (sbyte)VectorExtractIntZx(Vector, Index, Size);
- }
- else if (Size == 1)
- {
- return (short)VectorExtractIntZx(Vector, Index, Size);
- }
- else if (Size == 2)
- {
- return (int)VectorExtractIntZx(Vector, Index, Size);
- }
- else if (Size == 3)
- {
- return (long)VectorExtractIntZx(Vector, Index, Size);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong VectorExtractIntZx(Vector128<float> Vector, byte Index, int Size)
- {
- if (Sse41.IsSupported)
- {
- if (Size == 0)
- {
- return Sse41.Extract(Sse.StaticCast<float, byte>(Vector), Index);
- }
- else if (Size == 1)
- {
- return Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), Index);
- }
- else if (Size == 2)
- {
- return Sse41.Extract(Sse.StaticCast<float, uint>(Vector), Index);
- }
- else if (Size == 3)
- {
- return Sse41.Extract(Sse.StaticCast<float, ulong>(Vector), Index);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
- else if (Sse2.IsSupported)
- {
- int ShortIdx = Size == 0
- ? Index >> 1
- : Index << (Size - 1);
-
- ushort Value = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)ShortIdx);
-
- if (Size == 0)
- {
- return (byte)(Value >> (Index & 1) * 8);
- }
- else if (Size == 1)
- {
- return Value;
- }
- else if (Size == 2 || Size == 3)
- {
- ushort Value1 = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)(ShortIdx + 1));
-
- if (Size == 2)
- {
- return (uint)(Value | (Value1 << 16));
- }
-
- ushort Value2 = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)(ShortIdx + 2));
- ushort Value3 = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)(ShortIdx + 3));
-
- return ((ulong)Value << 0) |
- ((ulong)Value1 << 16) |
- ((ulong)Value2 << 32) |
- ((ulong)Value3 << 48);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float VectorExtractSingle(Vector128<float> Vector, byte Index)
- {
- if (Sse41.IsSupported)
- {
- return Sse41.Extract(Vector, Index);
- }
- else if (Sse2.IsSupported)
- {
- Vector128<ushort> ShortVector = Sse.StaticCast<float, ushort>(Vector);
-
- int Low = Sse2.Extract(ShortVector, (byte)(Index * 2 + 0));
- int High = Sse2.Extract(ShortVector, (byte)(Index * 2 + 1));
-
- return BitConverter.Int32BitsToSingle(Low | (High << 16));
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInsertDouble(double Value, Vector128<float> Vector, byte Index)
- {
- return VectorInsertInt((ulong)BitConverter.DoubleToInt64Bits(Value), Vector, Index, 3);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInsertInt(ulong Value, Vector128<float> Vector, byte Index, int Size)
- {
- if (Sse41.IsSupported)
- {
- if (Size == 0)
- {
- return Sse.StaticCast<byte, float>(Sse41.Insert(Sse.StaticCast<float, byte>(Vector), (byte)Value, Index));
- }
- else if (Size == 1)
- {
- return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(Vector), (ushort)Value, Index));
- }
- else if (Size == 2)
- {
- return Sse.StaticCast<uint, float>(Sse41.Insert(Sse.StaticCast<float, uint>(Vector), (uint)Value, Index));
- }
- else if (Size == 3)
- {
- return Sse.StaticCast<ulong, float>(Sse41.Insert(Sse.StaticCast<float, ulong>(Vector), Value, Index));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
- else if (Sse2.IsSupported)
- {
- Vector128<ushort> ShortVector = Sse.StaticCast<float, ushort>(Vector);
-
- int ShortIdx = Size == 0
- ? Index >> 1
- : Index << (Size - 1);
-
- if (Size == 0)
- {
- ushort ShortVal = Sse2.Extract(Sse.StaticCast<float, ushort>(Vector), (byte)ShortIdx);
-
- int Shift = (Index & 1) * 8;
-
- ShortVal &= (ushort)(0xff00 >> Shift);
-
- ShortVal |= (ushort)((byte)Value << Shift);
-
- return Sse.StaticCast<ushort, float>(Sse2.Insert(ShortVector, ShortVal, (byte)ShortIdx));
- }
- else if (Size == 1)
- {
- return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(Vector), (ushort)Value, Index));
- }
- else if (Size == 2 || Size == 3)
- {
- ShortVector = Sse2.Insert(ShortVector, (ushort)(Value >> 0), (byte)(ShortIdx + 0));
- ShortVector = Sse2.Insert(ShortVector, (ushort)(Value >> 16), (byte)(ShortIdx + 1));
-
- if (Size == 3)
- {
- ShortVector = Sse2.Insert(ShortVector, (ushort)(Value >> 32), (byte)(ShortIdx + 2));
- ShortVector = Sse2.Insert(ShortVector, (ushort)(Value >> 48), (byte)(ShortIdx + 3));
- }
-
- return Sse.StaticCast<ushort, float>(ShortVector);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Size));
- }
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInsertSingle(float Value, Vector128<float> Vector, byte Index)
- {
- if (Sse41.IsSupported)
- {
- //Note: The if/else if is necessary to enable the JIT to
- //produce a single INSERTPS instruction instead of the
- //jump table fallback.
- if (Index == 0)
- {
- return Sse41.Insert(Vector, Value, 0x00);
- }
- else if (Index == 1)
- {
- return Sse41.Insert(Vector, Value, 0x10);
- }
- else if (Index == 2)
- {
- return Sse41.Insert(Vector, Value, 0x20);
- }
- else if (Index == 3)
- {
- return Sse41.Insert(Vector, Value, 0x30);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(Index));
- }
- }
- else if (Sse2.IsSupported)
- {
- int IntValue = BitConverter.SingleToInt32Bits(Value);
-
- ushort Low = (ushort)(IntValue >> 0);
- ushort High = (ushort)(IntValue >> 16);
-
- Vector128<ushort> ShortVector = Sse.StaticCast<float, ushort>(Vector);
-
- ShortVector = Sse2.Insert(ShortVector, Low, (byte)(Index * 2 + 0));
- ShortVector = Sse2.Insert(ShortVector, High, (byte)(Index * 2 + 1));
-
- return Sse.StaticCast<ushort, float>(ShortVector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> Sse41VectorInsertScalarSingle(float Value, Vector128<float> Vector)
- {
- //Note: 0b1110 is the mask to zero the upper bits.
- return Sse41.Insert(Vector, Value, 0b1110);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<sbyte> VectorSByteZero()
- {
- if (Sse2.IsSupported)
- {
- return Sse2.SetZeroVector128<sbyte>();
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<short> VectorInt16Zero()
- {
- if (Sse2.IsSupported)
- {
- return Sse2.SetZeroVector128<short>();
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<int> VectorInt32Zero()
- {
- if (Sse2.IsSupported)
- {
- return Sse2.SetZeroVector128<int>();
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<long> VectorInt64Zero()
- {
- if (Sse2.IsSupported)
- {
- return Sse2.SetZeroVector128<long>();
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorSingleZero()
- {
- if (Sse.IsSupported)
- {
- return Sse.SetZeroVector128();
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<double> VectorDoubleZero()
- {
- if (Sse2.IsSupported)
- {
- return Sse2.SetZeroVector128<double>();
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorZero32_128(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.And(Vector, Zero32_128Mask);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<sbyte> VectorSingleToSByte(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, sbyte>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<short> VectorSingleToInt16(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, short>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<int> VectorSingleToInt32(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, int>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<long> VectorSingleToInt64(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, long>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<byte> VectorSingleToByte(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, byte>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<ushort> VectorSingleToUInt16(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, ushort>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<uint> VectorSingleToUInt32(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, uint>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<ulong> VectorSingleToUInt64(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, ulong>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<double> VectorSingleToDouble(Vector128<float> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<float, double>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorSByteToSingle(Vector128<sbyte> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<sbyte, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInt16ToSingle(Vector128<short> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<short, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInt32ToSingle(Vector128<int> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<int, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorInt64ToSingle(Vector128<long> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<long, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorByteToSingle(Vector128<byte> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<byte, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorUInt16ToSingle(Vector128<ushort> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<ushort, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorUInt32ToSingle(Vector128<uint> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<uint, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorUInt64ToSingle(Vector128<ulong> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<ulong, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector128<float> VectorDoubleToSingle(Vector128<double> Vector)
- {
- if (Sse.IsSupported)
- {
- return Sse.StaticCast<double, float>(Vector);
- }
-
- throw new PlatformNotSupportedException();
- }
- }
-}