1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 // Test call from asembly
17 
18 #include <iostream>
19 #include <cstdint>
20 #include <cmath>
21 #include <cassert>
22 
23 #include <gtest/gtest.h>
24 
25 class AsmCaller : public ::testing::Test {
26 };
27 
28 #define EMITED_ONE_PARAM_INST_LIST(DEF)                               \
29     DEF(mov, [](auto param) { return param; })                        \
30     DEF(neg, [](auto param) { return -param; })                       \
31     DEF(abs, [](auto param) { return (param > 0) ? param : -param; }) \
32     DEF(not, [](auto param) { return -param - 1L; })
33 
34 #define EMITED_TWO_PARAM_INST_LIST(DEF)                                \
35     DEF(add, [](auto param1, auto param2) { return param1 + param2; }) \
36     DEF(sub, [](auto param1, auto param2) { return param1 - param2; }) \
37     DEF(mul, [](auto param1, auto param2) { return param1 * param2; }) \
38     DEF(and, [](auto param1, auto param2) { return param1 & param2; }) \
39     DEF(or, [](auto param1, auto param2) { return param1 | param2; })  \
40     DEF(xor, [](auto param1, auto param2) {                            \
41         return param1 ^ param2;                                        \
42     })
43 
44 #define C_EXTERN_ONE_PARAM(opc, param)                       \
45     extern "C" std::uint8_t test_##opc##_8(std::uint8_t);    \
46     extern "C" std::uint16_t test_##opc##_16(std::uint16_t); \
47     extern "C" std::uint32_t test_##opc##_32(std::uint32_t); \
48     extern "C" std::uint64_t test_##opc##_64(std::uint64_t);
49 
50 EMITED_ONE_PARAM_INST_LIST(C_EXTERN_ONE_PARAM)
51 
52 #define C_EXTERN_TWO_PARAM(opc, param)                                      \
53     extern "C" std::uint8_t test_##opc##_8(std::uint8_t, std::uint8_t);     \
54     extern "C" std::uint16_t test_##opc##_16(std::uint16_t, std::uint16_t); \
55     extern "C" std::uint32_t test_##opc##_32(std::uint32_t, std::uint32_t); \
56     extern "C" std::uint64_t test_##opc##_64(std::uint64_t, std::uint64_t);
57 
58 EMITED_TWO_PARAM_INST_LIST(C_EXTERN_TWO_PARAM)
59 
TEST_F(AsmCaller, call_math)60 TEST_F(AsmCaller, call_math)
61 {
62     std::int8_t ui8 = 1;
63     std::int8_t ui8_2 = -12;
64     std::int16_t ui16 = 6518;
65     std::int16_t ui16_2 = 6;
66     std::int32_t ui32 = 3;
67     std::int32_t ui32_2 = 0xecf27abf;
68     std::int64_t ui64 = 2423590325;
69     std::int64_t ui64_2 = 8;
70 
71 #ifdef STDOUT_PRINT
72 #define CALL_ONE_PARAM_OUTPUT(opc, param)                                                   \
73     std::cerr << "------------ OUTPUT FOR " << #opc << "------------\n";                    \
74     std::cerr << "ui8 result:" << std::hex << static_cast<uint64_t>(test_##opc##_8(ui8))    \
75               << "  input:" << static_cast<uint64_t>(ui8) << "\n";                          \
76     std::cerr << "ui16 result:" << std::hex << static_cast<uint64_t>(test_##opc##_16(ui16)) \
77               << "  input:" << static_cast<uint64_t>(ui16) << "\n";                         \
78     std::cerr << "ui32 result:" << std::hex << static_cast<uint64_t>(test_##opc##_32(ui32)) \
79               << "  input:" << static_cast<uint64_t>(ui32) << "\n";                         \
80     std::cerr << "ui64 result:" << std::hex << static_cast<uint64_t>(test_##opc##_64(ui64)) \
81               << "  input:" << static_cast<uint64_t>(ui64) << "\n";
82 #else
83 #define CALL_ONE_PARAM_OUTPUT(opc, param)                                 \
84     EXPECT_EQ(test_##opc##_8(ui8), static_cast<uint8_t>(param(ui8)));     \
85     EXPECT_EQ(test_##opc##_16(ui16), static_cast<uint16_t>(param(ui16))); \
86     EXPECT_EQ(test_##opc##_32(ui32), static_cast<uint32_t>(param(ui32))); \
87     EXPECT_EQ(test_##opc##_64(ui64), static_cast<uint64_t>(param(ui64)));
88 #endif
89 
90     EMITED_ONE_PARAM_INST_LIST(CALL_ONE_PARAM_OUTPUT)
91 
92 #ifdef STDOUT_PRINT
93 #define CALL_TWO_PARAM_OUTPUT(opc, param)                                                                            \
94     std::cerr << "------------ OUTPUT FOR " << #opc << "------------\n";                                             \
95     std::cerr << "ui8 result:" << std::hex << static_cast<uint64_t>(test_##opc##_8(ui8, ui8_2))                      \
96               << "  input_1:" << static_cast<uint64_t>(ui8) << "  input_2:" << static_cast<uint64_t>(ui8_2) << "\n"; \
97     std::cerr << "ui16 result:" << std::hex << static_cast<uint64_t>(test_##opc##_16(ui16, ui16_2))                  \
98               << "  input:" << static_cast<uint64_t>(ui16) << "  input_2:" << static_cast<uint64_t>(ui16_2) << "\n"; \
99     std::cerr << "ui32 result:" << std::hex << static_cast<uint64_t>(test_##opc##_32(ui32, ui32_2))                  \
100               << "  input:" << static_cast<uint64_t>(ui32) << "  input_2:" << static_cast<uint64_t>(ui32_2) << "\n"; \
101     std::cerr << "ui64 result:" << std::hex << static_cast<uint64_t>(test_##opc##_64(ui64, ui64_2))                  \
102               << "  input:" << static_cast<uint64_t>(ui64) << "  input_2:" << static_cast<uint64_t>(ui64_2) << "\n";
103 #else
104 #define CALL_TWO_PARAM_OUTPUT(opc, param)                                                 \
105     EXPECT_EQ(test_##opc##_8(ui8, ui8_2), static_cast<uint8_t>(param(ui8, ui8_2)));       \
106     EXPECT_EQ(test_##opc##_16(ui16, ui16_2), static_cast<uint16_t>(param(ui16, ui16_2))); \
107     EXPECT_EQ(test_##opc##_32(ui32, ui32_2), static_cast<uint32_t>(param(ui32, ui32_2))); \
108     EXPECT_EQ(test_##opc##_64(ui64, ui64_2), static_cast<uint64_t>(param(ui64, ui64_2)));
109 #endif
110     EMITED_TWO_PARAM_INST_LIST(CALL_TWO_PARAM_OUTPUT)
111 }
112