diff --git a/lib/Arch/X86/Semantics/SSE.cpp b/lib/Arch/X86/Semantics/SSE.cpp index 8eecd762..b973f09d 100644 --- a/lib/Arch/X86/Semantics/SSE.cpp +++ b/lib/Arch/X86/Semantics/SSE.cpp @@ -2160,7 +2160,6 @@ MAKE_PMOVSXx(V, DQ, 32, 64, int64_t, 4); } // namespace - DEF_ISEL(PMOVSXBW_XMMdq_MEMq) = PMOVSXBW; DEF_ISEL(PMOVSXBW_XMMdq_XMMq) = PMOVSXBW; IF_AVX(DEF_ISEL(VPMOVSXBW_XMMdq_XMMq) = PMOVSXBW;) @@ -2168,7 +2167,6 @@ IF_AVX(DEF_ISEL(VPMOVSXBW_XMMdq_MEMq) = PMOVSXBW;) IF_AVX(DEF_ISEL(VPMOVSXBW_YMMqq_XMMdq) = VPMOVSXBW;) IF_AVX(DEF_ISEL(VPMOVSXBW_YMMqq_MEMdq) = VPMOVSXBW;) - DEF_ISEL(PMOVSXBD_XMMdq_MEMd) = PMOVSXBD; DEF_ISEL(PMOVSXBD_XMMdq_XMMd) = PMOVSXBD; IF_AVX(DEF_ISEL(VPMOVSXBD_XMMdq_XMMd) = PMOVSXBD;) @@ -2190,7 +2188,6 @@ IF_AVX(DEF_ISEL(VPMOVSXWD_XMMdq_MEMq) = PMOVSXWD;) IF_AVX(DEF_ISEL(VPMOVSXWD_YMMqq_XMMdq) = VPMOVSXWD;) IF_AVX(DEF_ISEL(VPMOVSXWD_YMMqq_MEMdq) = VPMOVSXWD;) - DEF_ISEL(PMOVSXWQ_XMMdq_MEMd) = PMOVSXWQ; DEF_ISEL(PMOVSXWQ_XMMdq_XMMd) = PMOVSXWQ; IF_AVX(DEF_ISEL(VPMOVSXWQ_XMMdq_XMMd) = PMOVSXWQ;) @@ -2241,7 +2238,6 @@ MAKE_PMOVZXx(V, DQ, 32, 64, int64_t, 4); } // namespace - DEF_ISEL(PMOVZXBW_XMMdq_MEMq) = PMOVZXBW; DEF_ISEL(PMOVZXBW_XMMdq_XMMq) = PMOVZXBW; IF_AVX(DEF_ISEL(VPMOVZXBW_XMMdq_XMMq) = PMOVZXBW;) @@ -2249,7 +2245,6 @@ IF_AVX(DEF_ISEL(VPMOVZXBW_XMMdq_MEMq) = PMOVZXBW;) IF_AVX(DEF_ISEL(VPMOVZXBW_YMMqq_XMMdq) = VPMOVZXBW;) IF_AVX(DEF_ISEL(VPMOVZXBW_YMMqq_MEMdq) = VPMOVZXBW;) - DEF_ISEL(PMOVZXBD_XMMdq_MEMd) = PMOVZXBD; DEF_ISEL(PMOVZXBD_XMMdq_XMMd) = PMOVZXBD; IF_AVX(DEF_ISEL(VPMOVZXBD_XMMdq_XMMd) = PMOVZXBD;) @@ -2271,7 +2266,6 @@ IF_AVX(DEF_ISEL(VPMOVZXWD_XMMdq_MEMq) = PMOVZXWD;) IF_AVX(DEF_ISEL(VPMOVZXWD_YMMqq_XMMdq) = VPMOVZXWD;) IF_AVX(DEF_ISEL(VPMOVZXWD_YMMqq_MEMdq) = VPMOVZXWD;) - DEF_ISEL(PMOVZXWQ_XMMdq_MEMd) = PMOVZXWQ; DEF_ISEL(PMOVZXWQ_XMMdq_XMMd) = PMOVZXWQ; IF_AVX(DEF_ISEL(VPMOVZXWQ_XMMdq_XMMd) = PMOVZXWQ;) @@ -2284,4 +2278,45 @@ DEF_ISEL(PMOVZXDQ_XMMdq_XMMq) = PMOVZXDQ; IF_AVX(DEF_ISEL(VPMOVZXDQ_XMMdq_XMMq) = PMOVZXDQ;) IF_AVX(DEF_ISEL(VPMOVZXDQ_XMMdq_MEMq) = PMOVZXDQ;) IF_AVX(DEF_ISEL(VPMOVZXDQ_YMMqq_XMMdq) = VPMOVZXDQ;) -IF_AVX(DEF_ISEL(VPMOVZXDQ_YMMqq_MEMdq) = VPMOVZXDQ;) \ No newline at end of file +IF_AVX(DEF_ISEL(VPMOVZXDQ_YMMqq_MEMdq) = VPMOVZXDQ;) + +namespace { + +#define MAKE_ADDSUBx(suffix, element_width) \ + template \ + DEF_SEM(ADDSUB##suffix, D dst, S1 src1, S2 src2) { \ + auto src1_vec = FReadV##element_width(src1); \ + auto src2_vec = FReadV##element_width(src2); \ + auto dst_vec = FClearV##element_width(FReadV##element_width(dst)); \ +\ + auto num_elements = NumVectorElems(src1_vec); \ +\ + _Pragma("unroll") for (auto idx = 0u; idx < num_elements; ++idx) { \ + auto src1_val = FExtractV##element_width(src1_vec, idx); \ + auto src2_val = FExtractV##element_width(src2_vec, idx); \ + auto op_val = \ + Select(idx % 2, FAdd(src1_val, src2_val), FSub(src1_val, src2_val)); \ + dst_vec = FInsertV##element_width(dst_vec, idx, op_val); \ + } \ + FWriteV##element_width(dst, dst_vec); \ + return memory; \ + } + +MAKE_ADDSUBx(PS, 32) MAKE_ADDSUBx(PD, 64) + +#undef MAKE_ADDSUBx +} // namespace + +DEF_ISEL(ADDSUBPS_XMMps_MEMps) = ADDSUBPS; +DEF_ISEL(ADDSUBPS_XMMps_XMMps) = ADDSUBPS; +IF_AVX(DEF_ISEL(VADDSUBPS_XMMdq_XMMdq_MEMdq) = ADDSUBPS;) +IF_AVX(DEF_ISEL(VADDSUBPS_XMMdq_XMMdq_XMMdq) = ADDSUBPS;) +IF_AVX(DEF_ISEL(VADDSUBPS_YMMqq_YMMqq_MEMqq) = ADDSUBPS;) +IF_AVX(DEF_ISEL(VADDSUBPS_YMMqq_YMMqq_YMMqq) = ADDSUBPS;) + +DEF_ISEL(ADDSUBPD_XMMpd_MEMpd) = ADDSUBPD; +DEF_ISEL(ADDSUBPD_XMMpd_XMMpd) = ADDSUBPD; +IF_AVX(DEF_ISEL(VADDSUBPD_XMMdq_XMMdq_MEMdq) = ADDSUBPD;) +IF_AVX(DEF_ISEL(VADDSUBPD_XMMdq_XMMdq_XMMdq) = ADDSUBPD;) +IF_AVX(DEF_ISEL(VADDSUBPD_YMMqq_YMMqq_MEMqq) = ADDSUBPD;) +IF_AVX(DEF_ISEL(VADDSUBPD_YMMqq_YMMqq_YMMqq) = ADDSUBPD;) diff --git a/tests/X86/SSE/ADDSUB.S b/tests/X86/SSE/ADDSUB.S new file mode 100644 index 00000000..3e54d20f --- /dev/null +++ b/tests/X86/SSE/ADDSUB.S @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017 Trail of Bits, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TEST_INPUT_ADDSUB \ + 0.0, 0.0, \ + 0.0, 100000.5, \ + 100000.5, 100000.5 + +TEST_BEGIN_64(ADDSUBPSv128v128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + movupd xmm2, [rsp] + addsubps xmm2, xmm1 +TEST_END_64 + +TEST_BEGIN_64(ADDSUBPSv128m128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + addsubps xmm2, [rsp] +TEST_END_64 + +#if HAS_FEATURE_AVX + +TEST_BEGIN_64(VADDSUBPSv128v128v128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + movupd xmm2, [rsp] + vaddsubps xmm0, xmm2, xmm1 +TEST_END_64 + +TEST_BEGIN_64(VADDSUBPSv128v128m128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + vaddsubps xmm0, xmm2, [rsp] +TEST_END_64 + +TEST_BEGIN_64(VADDSUBPSv256v256v256, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push 0 + push 0 + push ARG1_64 + vmovupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + push ARG2_64 + push ARG2_64 + vmovupd xmm2, [rsp] + vaddsubps xmm0, xmm2, xmm1 +TEST_END_64 + +TEST_BEGIN_64(VADDSUBPSv256v256m256, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push 0 + push 0 + push ARG1_64 + vmovupd xmm1, [rsp] + push ARG2_64 + push 0 + push 0 + push ARG2_64 + vaddsubps xmm0, xmm2, [rsp] +TEST_END_64 + +#endif // HAS_FEATURE_AVX + +TEST_BEGIN_64(ADDSUBPDv128v128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + movupd xmm2, [rsp] + addsubps xmm2, xmm1 +TEST_END_64 + +TEST_BEGIN_64(ADDSUBPDv128m128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + addsubps xmm2, [rsp] +TEST_END_64 + +#if HAS_FEATURE_AVX + +TEST_BEGIN_64(VADDSUBPDv128v128v128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + movupd xmm2, [rsp] + vaddsubpd xmm0, xmm2, xmm1 +TEST_END_64 + +TEST_BEGIN_64(VADDSUBPDv128v128m128, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push ARG1_64 + movupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + vaddsubpd xmm0, xmm2, [rsp] +TEST_END_64 + +TEST_BEGIN_64(VADDSUBPDv256v256v256, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push 0 + push 0 + push ARG1_64 + vmovupd xmm1, [rsp] + push ARG2_64 + push ARG2_64 + push ARG2_64 + push ARG2_64 + vmovupd xmm2, [rsp] + vaddsubpd xmm0, xmm2, xmm1 +TEST_END_64 + +TEST_BEGIN_64(VADDSUBPDv256v256m256, 2) +TEST_INPUTS(TEST_INPUT_ADDSUB) + push ARG1_64 + push 0 + push 0 + push ARG1_64 + vmovupd xmm1, [rsp] + push ARG2_64 + push 0 + push 0 + push ARG2_64 + vaddsubpd xmm0, xmm2, [rsp] +TEST_END_64 + +#endif // HAS_FEATURE_AVX \ No newline at end of file diff --git a/tests/X86/Tests.S b/tests/X86/Tests.S index aa7679dd..3b2d91c7 100644 --- a/tests/X86/Tests.S +++ b/tests/X86/Tests.S @@ -504,6 +504,7 @@ SYMBOL(__x86_test_table_begin): #include "tests/X86/SHIFT/SHR.S" #include "tests/X86/SHIFT/SHRD.S" +#include "tests/X86/SSE/ADDSUB.S" #include "tests/X86/SSE/CMPSS.S" #include "tests/X86/SSE/COMISD.S" #include "tests/X86/SSE/COMISS.S"