1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gtest/gtest.h"
18 
19 #include "berberis/base/bit_util.h"
20 #include "berberis/guest_abi/guest_params.h"
21 #include "berberis/guest_state/guest_state.h"
22 
23 namespace berberis {
24 
25 namespace {
26 
SetVfpFloat(ThreadState * state,int index,float v)27 void SetVfpFloat(ThreadState* state, int index, float v) {
28   reinterpret_cast<float*>(state->cpu.d)[index] = v;
29 }
30 
SetVfpDouble(ThreadState * state,int index,double v)31 void SetVfpDouble(ThreadState* state, int index, double v) {
32   reinterpret_cast<double*>(state->cpu.d)[index] = v;
33 }
34 
TEST(Params,IntRes)35 TEST(Params, IntRes) {
36   ThreadState state{};
37 
38   auto&& [ret] = GuestReturnReference<int()>(&state);
39   auto&& [retf] = GuestReturnReference<int (*)()>(&state);
40   auto&& [retv] = GuestReturnReference<int(...)>(&state);
41   auto&& [retfv] = GuestReturnReference<int (*)(...)>(&state);
42 
43   ret = 123;
44   EXPECT_EQ(123u, state.cpu.r[0]);
45 
46   retf = 234;
47   EXPECT_EQ(234u, state.cpu.r[0]);
48 
49   retv = 345;
50   EXPECT_EQ(345u, state.cpu.r[0]);
51 
52   retfv = 456;
53   EXPECT_EQ(456u, state.cpu.r[0]);
54 }
55 
TEST(Params,SignedCharRes)56 TEST(Params, SignedCharRes) {
57   ThreadState state{};
58 
59   state.cpu.r[0] = 0;
60 
61   auto&& [ret] = GuestReturnReference<signed char()>(&state);
62   auto&& [retf] = GuestReturnReference<signed char (*)()>(&state);
63   auto&& [retv] = GuestReturnReference<signed char(...)>(&state);
64   auto&& [retfv] = GuestReturnReference<signed char (*)(...)>(&state);
65 
66   ret = -1;
67   EXPECT_EQ(0xFFFFFFFFu, state.cpu.r[0]);
68 
69   retf = -2;
70   EXPECT_EQ(0xFFFFFFFEu, state.cpu.r[0]);
71 
72   retv = -3;
73   EXPECT_EQ(0xFFFFFFFDu, state.cpu.r[0]);
74 
75   retfv = -4;
76   EXPECT_EQ(0xFFFFFFFCu, state.cpu.r[0]);
77 }
78 
TEST(Params,PtrFloatFloatArgs)79 TEST(Params, PtrFloatFloatArgs) {
80   ThreadState state{};
81 
82   static int x;
83 
84   state.cpu.r[0] = bit_cast<uint32_t>(&x);
85   state.cpu.r[1] = bit_cast<uint32_t>(1.0f);
86   state.cpu.r[2] = bit_cast<uint32_t>(-.75f);
87 
88   auto [arg1, arg2, arg3] = GuestParamsValues<void(int*, float, float)>(&state);
89   auto [arg1f, arg2f, arg3f] = GuestParamsValues<void (*)(int*, float, float)>(&state);
90   auto [arg1v, arg2v, arg3v] = GuestParamsValues<void(int*, float, float, ...)>(&state);
91   auto [arg1fv, arg2fv, arg3fv] = GuestParamsValues<void (*)(int*, float, float, ...)>(&state);
92 
93   EXPECT_EQ(&x, arg1);
94   EXPECT_FLOAT_EQ(1.0f, arg2);
95   EXPECT_FLOAT_EQ(-.75f, arg3);
96 
97   EXPECT_EQ(&x, arg1f);
98   EXPECT_FLOAT_EQ(1.0f, arg2f);
99   EXPECT_FLOAT_EQ(-.75f, arg3f);
100 
101   EXPECT_EQ(&x, arg1v);
102   EXPECT_FLOAT_EQ(1.0f, arg2v);
103   EXPECT_FLOAT_EQ(-.75f, arg3v);
104 
105   EXPECT_EQ(&x, arg1fv);
106   EXPECT_FLOAT_EQ(1.0f, arg2fv);
107   EXPECT_FLOAT_EQ(-.75f, arg3fv);
108 }
109 
TEST(Params,PtrFloatFloatArgsVfp)110 TEST(Params, PtrFloatFloatArgsVfp) {
111   ThreadState state{};
112 
113   static int x;
114 
115   state.cpu.r[0] = bit_cast<uint32_t>(&x);
116   state.cpu.r[1] = bit_cast<uint32_t>(42.0f);
117   state.cpu.r[2] = 0xa3d70a3d;     // -0.57 - bottom half
118   state.cpu.r[3] = 0xbfe23d70;     // -0.57 - top half
119   SetVfpFloat(&state, 0, 1.0f);    // s0
120   SetVfpDouble(&state, 1, -.75f);  // d1
121 
122   auto [arg1, arg2, arg3] =
123       GuestParamsValues<void(int*, float, double), GuestAbi::kAapcsVfp>(&state);
124   auto [arg1f, arg2f, arg3f] =
125       GuestParamsValues<void (*)(int*, float, double), GuestAbi::kAapcsVfp>(&state);
126   auto [arg1v, arg2v, arg3v] =
127       GuestParamsValues<void(int*, float, double, ...), GuestAbi::kAapcsVfp>(&state);
128   auto [arg1fv, arg2fv, arg3fv] =
129       GuestParamsValues<void (*)(int*, float, double, ...), GuestAbi::kAapcsVfp>(&state);
130 
131   EXPECT_EQ(&x, arg1);
132   EXPECT_FLOAT_EQ(1.0f, arg2);
133   EXPECT_DOUBLE_EQ(-.75, arg3);
134 
135   EXPECT_EQ(&x, arg1f);
136   EXPECT_FLOAT_EQ(1.0f, arg2f);
137   EXPECT_DOUBLE_EQ(-.75, arg3f);
138 
139   // “Note: There are no VFP CPRCs in a variadic procedure” ⇦ from AAPCS
140   EXPECT_EQ(&x, arg1v);
141   EXPECT_FLOAT_EQ(42.0f, arg2v);
142   EXPECT_DOUBLE_EQ(-.57, arg3v);
143 
144   EXPECT_EQ(&x, arg1fv);
145   EXPECT_FLOAT_EQ(42.0f, arg2fv);
146   EXPECT_DOUBLE_EQ(-.57, arg3fv);
147 }
148 
TEST(Params,PtrIntPtrLongLongArgs)149 TEST(Params, PtrIntPtrLongLongArgs) {
150   ThreadState state{};
151 
152   alignas(8) uint64_t stack[4];
153   state.cpu.r[13] = bit_cast<uint32_t>(&stack[0]);
154 
155   static int x;
156   constexpr uint64_t kTestValue64 = 0xffff0000ffff0000ULL;
157 
158   state.cpu.r[0] = bit_cast<uint32_t>(&x);
159   state.cpu.r[1] = bit_cast<uint32_t>(123);
160   state.cpu.r[2] = bit_cast<uint32_t>(&x);
161   stack[0] = kTestValue64;
162 
163   auto [arg1, arg2, arg3, arg4] = GuestParamsValues<void(int*, int, int*, uint64_t)>(&state);
164   auto [arg1f, arg2f, arg3f, arg4f] =
165       GuestParamsValues<void (*)(int*, int, int*, uint64_t)>(&state);
166   auto [arg1v, arg2v, arg3v, arg4v] =
167       GuestParamsValues<void(int*, int, int*, uint64_t, ...)>(&state);
168   auto [arg1fv, arg2fv, arg3fv, arg4fv] =
169       GuestParamsValues<void (*)(int*, int, int*, uint64_t, ...)>(&state);
170 
171   EXPECT_EQ(&x, arg1);
172   EXPECT_EQ(123, arg2);
173   EXPECT_EQ(&x, arg3);
174   EXPECT_EQ(kTestValue64, arg4);
175 
176   EXPECT_EQ(&x, arg1f);
177   EXPECT_EQ(123, arg2f);
178   EXPECT_EQ(&x, arg3f);
179   EXPECT_EQ(kTestValue64, arg4f);
180 
181   EXPECT_EQ(&x, arg1v);
182   EXPECT_EQ(123, arg2v);
183   EXPECT_EQ(&x, arg3v);
184   EXPECT_EQ(kTestValue64, arg4v);
185 
186   EXPECT_EQ(&x, arg1fv);
187   EXPECT_EQ(123, arg2fv);
188   EXPECT_EQ(&x, arg3fv);
189   EXPECT_EQ(kTestValue64, arg4fv);
190 }
191 
TEST(Params,LongLongArgHugeStructResult)192 TEST(Params, LongLongArgHugeStructResult) {
193   ThreadState state{};
194 
195   struct Result {
196     uint64_t values[10];
197   } result{};
198 
199   state.cpu.r[0] = bit_cast<uint32_t>(&result);
200   state.cpu.r[2] = 0xbeef;
201   state.cpu.r[3] = 0xdead;
202 
203   auto [arg] = GuestParamsValues<Result(uint64_t)>(&state);
204 
205   EXPECT_EQ(0xdead0000beefULL, arg);
206 
207   auto&& [ret] = GuestReturnReference<Result(uint64_t)>(&state);
208 
209   ret = Result{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
210 
211   EXPECT_EQ(1U, result.values[0]);
212   EXPECT_EQ(2U, result.values[1]);
213   EXPECT_EQ(3U, result.values[2]);
214   EXPECT_EQ(4U, result.values[3]);
215   EXPECT_EQ(5U, result.values[4]);
216   EXPECT_EQ(6U, result.values[5]);
217   EXPECT_EQ(7U, result.values[6]);
218   EXPECT_EQ(8U, result.values[7]);
219   EXPECT_EQ(9U, result.values[8]);
220   EXPECT_EQ(10U, result.values[9]);
221 }
222 
TEST(GuestVAListParams,PtrFloatFloatArgs)223 TEST(GuestVAListParams, PtrFloatFloatArgs) {
224   ThreadState state{};
225 
226   static int x;
227 
228   state.cpu.r[0] = bit_cast<uint32_t>(&x);
229   state.cpu.r[1] = bit_cast<uint32_t>(1.0f);
230   state.cpu.r[2] = bit_cast<uint32_t>(-.75f);
231 
232   GuestVAListParams params = GuestParamsValues<void(...)>(&state);
233 
234   EXPECT_EQ(&x, params.GetPointerParam<int>());
235   EXPECT_FLOAT_EQ(1.0f, params.GetParam<float>());
236   EXPECT_FLOAT_EQ(-.75f, params.GetParam<float>());
237 }
238 
TEST(GuestVAListParams,PtrIntPtrLongLongArgs)239 TEST(GuestVAListParams, PtrIntPtrLongLongArgs) {
240   ThreadState state{};
241 
242   alignas(8) uint64_t stack[4];
243   state.cpu.r[13] = bit_cast<uint32_t>(&stack[0]);
244 
245   static int x;
246   constexpr uint64_t kTestValue64 = 0xffff0000ffff0000ULL;
247 
248   state.cpu.r[0] = bit_cast<uint32_t>(&x);
249   state.cpu.r[1] = bit_cast<uint32_t>(123);
250   state.cpu.r[2] = bit_cast<uint32_t>(&x);
251   stack[0] = kTestValue64;
252 
253   GuestVAListParams params = GuestParamsValues<void(...)>(&state);
254 
255   EXPECT_EQ(&x, params.GetPointerParam<int>());
256   EXPECT_EQ(123, params.GetParam<int>());
257   EXPECT_EQ(&x, params.GetPointerParam<int>());
258   EXPECT_EQ(kTestValue64, params.GetParam<uint64_t>());
259 }
260 
261 }  // namespace
262 
263 }  // namespace berberis
264