diff options
| author | Alex Barney <thealexbarney@gmail.com> | 2018-10-30 19:43:02 -0600 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-10-30 22:43:02 -0300 |
| commit | 9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d (patch) | |
| tree | 0c97425aeb311c142bc92a6fcc503cb2c07d4376 /ChocolArm64/Instruction | |
| parent | 5a87e58183578f5b84ca8d01cbb76aed11820f78 (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')
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(); - } - } -} |
