1 /*
2 * Copyright (C) 2023 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 <array>
20 #include <cstring>
21
22 #include "berberis/base/bit_util.h"
23 #include "berberis/guest_abi/guest_params.h"
24 #include "berberis/guest_state/guest_addr.h"
25 #include "berberis/guest_state/guest_state.h"
26
27 namespace berberis {
28
29 namespace {
30
TEST(GuestParams_riscv64_lp64d,PtrIntArgs)31 TEST(GuestParams_riscv64_lp64d, PtrIntArgs) {
32 ThreadState state{};
33
34 static int x;
35
36 SetXReg<A0>(state.cpu, ToGuestAddr(&x));
37 SetXReg<A1>(state.cpu, 1234);
38 SetXReg<A2>(state.cpu, 0xffff'ffff'ffff'fff9U);
39
40 auto [param1, param2, param3] =
41 GuestParamsValues<void(int*, unsigned int, int), GuestAbi::kLp64d>(&state);
42 auto [param1f, param2f, param3f] =
43 GuestParamsValues<void (*)(int*, unsigned int, int), GuestAbi::kLp64d>(&state);
44 auto [param1v, param2v, param3v] =
45 GuestParamsValues<void(int*, unsigned int, int, ...), GuestAbi::kLp64d>(&state);
46 auto [param1fv, param2fv, param3fv] =
47 GuestParamsValues<void (*)(int*, unsigned int, int, ...), GuestAbi::kLp64d>(&state);
48
49 EXPECT_EQ(param1, &x);
50 EXPECT_EQ(param2, 1234U);
51 EXPECT_EQ(param3, -7);
52
53 EXPECT_EQ(param1f, &x);
54 EXPECT_EQ(param2f, 1234U);
55 EXPECT_EQ(param3f, -7);
56
57 EXPECT_EQ(param1v, &x);
58 EXPECT_EQ(param2v, 1234U);
59 EXPECT_EQ(param3v, -7);
60
61 EXPECT_EQ(param1fv, &x);
62 EXPECT_EQ(param2fv, 1234U);
63 EXPECT_EQ(param3fv, -7);
64 }
65
TEST(GuestParams_riscv64_lp64d,IntRes)66 TEST(GuestParams_riscv64_lp64d, IntRes) {
67 ThreadState state{};
68
69 auto&& [ret] = GuestReturnReference<int(), GuestAbi::kLp64d>(&state);
70 auto&& [retf] = GuestReturnReference<int (*)(), GuestAbi::kLp64d>(&state);
71 auto&& [retv] = GuestReturnReference<int(...), GuestAbi::kLp64d>(&state);
72 auto&& [retfv] = GuestReturnReference<int (*)(...), GuestAbi::kLp64d>(&state);
73
74 ret = 123;
75 EXPECT_EQ(GetXReg<A0>(state.cpu), 123U);
76
77 ret = -123;
78 EXPECT_EQ(GetXReg<A0>(state.cpu), 0xffff'ffff'ffff'ff85U);
79
80 retf = 234;
81 EXPECT_EQ(GetXReg<A0>(state.cpu), 234U);
82
83 retv = 345;
84 EXPECT_EQ(GetXReg<A0>(state.cpu), 345U);
85
86 retv = -345;
87 EXPECT_EQ(GetXReg<A0>(state.cpu), 0xffff'ffff'ffff'fea7U);
88
89 retfv = 456;
90 EXPECT_EQ(GetXReg<A0>(state.cpu), 456U);
91 }
92
TEST(GuestParams_riscv64_lp64d,SignedCharRes)93 TEST(GuestParams_riscv64_lp64d, SignedCharRes) {
94 ThreadState state{};
95
96 SetXReg<A0>(state.cpu, 0);
97
98 auto&& [ret] = GuestReturnReference<signed char(), GuestAbi::kLp64d>(&state);
99 auto&& [retf] = GuestReturnReference<signed char (*)(), GuestAbi::kLp64d>(&state);
100 auto&& [retv] = GuestReturnReference<signed char(...), GuestAbi::kLp64d>(&state);
101 auto&& [retfv] = GuestReturnReference<signed char (*)(...), GuestAbi::kLp64d>(&state);
102
103 ret = -1;
104 EXPECT_EQ(GetXReg<A0>(state.cpu), 0xffff'ffff'ffff'ffffU);
105
106 retf = -2;
107 EXPECT_EQ(GetXReg<A0>(state.cpu), 0xffff'ffff'ffff'fffeU);
108
109 retv = -3;
110 EXPECT_EQ(GetXReg<A0>(state.cpu), 0xffff'ffff'ffff'fffdU);
111
112 retfv = -4;
113 EXPECT_EQ(GetXReg<A0>(state.cpu), 0xffff'ffff'ffff'fffcU);
114 }
115
TEST(GuestParams_riscv64_lp64d,PtrRes)116 TEST(GuestParams_riscv64_lp64d, PtrRes) {
117 ThreadState state{};
118
119 SetXReg<A0>(state.cpu, static_cast<uint64_t>(42));
120
121 auto&& [ret] = GuestReturnReference<void*(), GuestAbi::kLp64d>(&state);
122
123 ret = nullptr;
124 EXPECT_EQ(GetXReg<A0>(state.cpu), 0U);
125 }
126
TEST(GuestParams_riscv64_lp64d,SignedCharArg)127 TEST(GuestParams_riscv64_lp64d, SignedCharArg) {
128 ThreadState state{};
129
130 SetXReg<A0>(state.cpu, 0xf0f0f0f0f0f0f0f0ULL);
131
132 auto [arg] = GuestParamsValues<void(signed char), GuestAbi::kLp64d>(&state);
133 auto [argf] = GuestParamsValues<void (*)(signed char), GuestAbi::kLp64d>(&state);
134 auto [argv] = GuestParamsValues<void(signed char, ...), GuestAbi::kLp64d>(&state);
135 auto [argfv] = GuestParamsValues<void (*)(signed char, ...), GuestAbi::kLp64d>(&state);
136
137 EXPECT_EQ(arg, -16);
138
139 EXPECT_EQ(argf, -16);
140
141 EXPECT_EQ(argv, -16);
142
143 EXPECT_EQ(argfv, -16);
144 }
145
TEST(GuestParams_riscv64_lp64d,IntFloatIntDoubleArgs)146 TEST(GuestParams_riscv64_lp64d, IntFloatIntDoubleArgs) {
147 ThreadState state{};
148
149 SetXReg<A0>(state.cpu, 1234);
150 SetXReg<A1>(state.cpu, static_cast<uint64_t>(-7));
151 SetFReg<FA0>(state.cpu, bit_cast<uint32_t>(2.71f));
152 SetFReg<FA1>(state.cpu, bit_cast<uint64_t>(3.14));
153
154 auto [param1, param2, param3, param4] =
155 GuestParamsValues<void(unsigned int, float, int, double), GuestAbi::kLp64d>(&state);
156 auto [param1f, param2f, param3f, param4f] =
157 GuestParamsValues<void (*)(unsigned int, float, int, double), GuestAbi::kLp64d>(&state);
158 auto [param1v, param2v, param3v, param4v] =
159 GuestParamsValues<void(unsigned int, float, int, double, ...), GuestAbi::kLp64d>(&state);
160 auto [param1fv, param2fv, param3fv, param4fv] =
161 GuestParamsValues<void (*)(unsigned int, float, int, double, ...), GuestAbi::kLp64d>(&state);
162
163 EXPECT_EQ(param1, 1234U);
164 EXPECT_FLOAT_EQ(param2, 2.71f);
165 EXPECT_EQ(param3, -7);
166 EXPECT_DOUBLE_EQ(param4, 3.14);
167
168 EXPECT_EQ(param1f, 1234U);
169 EXPECT_FLOAT_EQ(param2f, 2.71f);
170 EXPECT_EQ(param3f, -7);
171 EXPECT_DOUBLE_EQ(param4f, 3.14);
172
173 EXPECT_EQ(param1v, 1234U);
174 EXPECT_FLOAT_EQ(param2v, 2.71f);
175 EXPECT_EQ(param3v, -7);
176 EXPECT_DOUBLE_EQ(param4v, 3.14);
177
178 EXPECT_EQ(param1fv, 1234U);
179 EXPECT_FLOAT_EQ(param2fv, 2.71f);
180 EXPECT_EQ(param3fv, -7);
181 EXPECT_DOUBLE_EQ(param4fv, 3.14);
182 }
183
TEST(GuestParams_riscv64_lp64d,DoubleRes)184 TEST(GuestParams_riscv64_lp64d, DoubleRes) {
185 ThreadState state{};
186
187 auto&& [ret] = GuestReturnReference<double(), GuestAbi::kLp64d>(&state);
188 auto&& [retf] = GuestReturnReference<double (*)(), GuestAbi::kLp64d>(&state);
189 auto&& [retv] = GuestReturnReference<double(...), GuestAbi::kLp64d>(&state);
190 auto&& [retfv] = GuestReturnReference<double (*)(...), GuestAbi::kLp64d>(&state);
191
192 ret = 3.14;
193 EXPECT_DOUBLE_EQ(bit_cast<double>(GetFReg<FA0>(state.cpu)), 3.14);
194
195 retf = 3.15;
196 EXPECT_DOUBLE_EQ(bit_cast<double>(GetFReg<FA0>(state.cpu)), 3.15);
197
198 retv = 3.15;
199 EXPECT_DOUBLE_EQ(bit_cast<double>(GetFReg<FA0>(state.cpu)), 3.15);
200
201 retfv = 3.16;
202 EXPECT_DOUBLE_EQ(bit_cast<double>(GetFReg<FA0>(state.cpu)), 3.16);
203 }
204
TEST(GuestParams_riscv64_lp64d,StackArgs)205 TEST(GuestParams_riscv64_lp64d, StackArgs) {
206 std::array<uint64_t, 8> stack;
207 ThreadState state{};
208 SetXReg<SP>(state.cpu, ToGuestAddr(stack.data()));
209
210 SetXReg<A0>(state.cpu, 0);
211 SetXReg<A1>(state.cpu, 1);
212 SetXReg<A2>(state.cpu, 2);
213 SetXReg<A3>(state.cpu, 3);
214 SetXReg<A4>(state.cpu, 4);
215 SetXReg<A5>(state.cpu, 5);
216 SetXReg<A6>(state.cpu, 6);
217 SetXReg<A7>(state.cpu, 7);
218 stack[0] = 8;
219 stack[1] = 9;
220
221 SetFReg<FA0>(state.cpu, bit_cast<uint64_t>(0.0));
222 SetFReg<FA1>(state.cpu, bit_cast<uint64_t>(1.1));
223 SetFReg<FA2>(state.cpu, bit_cast<uint64_t>(2.2));
224 SetFReg<FA3>(state.cpu, bit_cast<uint64_t>(3.3));
225 SetFReg<FA4>(state.cpu, bit_cast<uint64_t>(4.4));
226 SetFReg<FA5>(state.cpu, bit_cast<uint64_t>(5.5));
227 SetFReg<FA6>(state.cpu, bit_cast<uint64_t>(6.6));
228 SetFReg<FA7>(state.cpu, bit_cast<uint64_t>(7.7));
229 stack[2] = bit_cast<uint64_t>(8.8);
230 stack[3] = bit_cast<uint64_t>(9.9);
231
232 auto [param1,
233 param2,
234 param3,
235 param4,
236 param5,
237 param6,
238 param7,
239 param8,
240 param9,
241 param10,
242 param11,
243 param12,
244 param13,
245 param14,
246 param15,
247 param16,
248 param17,
249 param18,
250 param19,
251 param20] = GuestParamsValues<void(int,
252 int,
253 int,
254 int,
255 int,
256 int,
257 int,
258 int,
259 int,
260 int,
261 double,
262 double,
263 double,
264 double,
265 double,
266 double,
267 double,
268 double,
269 double,
270 double),
271 GuestAbi::kLp64d>(&state);
272 auto [param1f,
273 param2f,
274 param3f,
275 param4f,
276 param5f,
277 param6f,
278 param7f,
279 param8f,
280 param9f,
281 param10f,
282 param11f,
283 param12f,
284 param13f,
285 param14f,
286 param15f,
287 param16f,
288 param17f,
289 param18f,
290 param19f,
291 param20f] = GuestParamsValues<void (*)(int,
292 int,
293 int,
294 int,
295 int,
296 int,
297 int,
298 int,
299 int,
300 int,
301 double,
302 double,
303 double,
304 double,
305 double,
306 double,
307 double,
308 double,
309 double,
310 double),
311 GuestAbi::kLp64d>(&state);
312 auto [param1v,
313 param2v,
314 param3v,
315 param4v,
316 param5v,
317 param6v,
318 param7v,
319 param8v,
320 param9v,
321 param10v,
322 param11v,
323 param12v,
324 param13v,
325 param14v,
326 param15v,
327 param16v,
328 param17v,
329 param18v,
330 param19v,
331 param20v] = GuestParamsValues<void(int,
332 int,
333 int,
334 int,
335 int,
336 int,
337 int,
338 int,
339 int,
340 int,
341 double,
342 double,
343 double,
344 double,
345 double,
346 double,
347 double,
348 double,
349 double,
350 double,
351 ...),
352 GuestAbi::kLp64d>(&state);
353 auto [param1fv,
354 param2fv,
355 param3fv,
356 param4fv,
357 param5fv,
358 param6fv,
359 param7fv,
360 param8fv,
361 param9fv,
362 param10fv,
363 param11fv,
364 param12fv,
365 param13fv,
366 param14fv,
367 param15fv,
368 param16fv,
369 param17fv,
370 param18fv,
371 param19fv,
372 param20fv] = GuestParamsValues<void (*)(int,
373 int,
374 int,
375 int,
376 int,
377 int,
378 int,
379 int,
380 int,
381 int,
382 double,
383 double,
384 double,
385 double,
386 double,
387 double,
388 double,
389 double,
390 double,
391 double,
392 ...),
393 GuestAbi::kLp64d>(&state);
394
395 EXPECT_EQ(param1, 0);
396 EXPECT_EQ(param2, 1);
397 EXPECT_EQ(param3, 2);
398 EXPECT_EQ(param4, 3);
399 EXPECT_EQ(param5, 4);
400 EXPECT_EQ(param6, 5);
401 EXPECT_EQ(param7, 6);
402 EXPECT_EQ(param8, 7);
403 EXPECT_EQ(param9, 8);
404 EXPECT_EQ(param10, 9);
405
406 EXPECT_DOUBLE_EQ(param11, 0.0);
407 EXPECT_DOUBLE_EQ(param12, 1.1);
408 EXPECT_DOUBLE_EQ(param13, 2.2);
409 EXPECT_DOUBLE_EQ(param14, 3.3);
410 EXPECT_DOUBLE_EQ(param15, 4.4);
411 EXPECT_DOUBLE_EQ(param16, 5.5);
412 EXPECT_DOUBLE_EQ(param17, 6.6);
413 EXPECT_DOUBLE_EQ(param18, 7.7);
414 EXPECT_DOUBLE_EQ(param19, 8.8);
415 EXPECT_DOUBLE_EQ(param20, 9.9);
416
417 EXPECT_EQ(param1f, 0);
418 EXPECT_EQ(param2f, 1);
419 EXPECT_EQ(param3f, 2);
420 EXPECT_EQ(param4f, 3);
421 EXPECT_EQ(param5f, 4);
422 EXPECT_EQ(param6f, 5);
423 EXPECT_EQ(param7f, 6);
424 EXPECT_EQ(param8f, 7);
425 EXPECT_EQ(param9f, 8);
426 EXPECT_EQ(param10f, 9);
427
428 EXPECT_DOUBLE_EQ(param11f, 0.0);
429 EXPECT_DOUBLE_EQ(param12f, 1.1);
430 EXPECT_DOUBLE_EQ(param13f, 2.2);
431 EXPECT_DOUBLE_EQ(param14f, 3.3);
432 EXPECT_DOUBLE_EQ(param15f, 4.4);
433 EXPECT_DOUBLE_EQ(param16f, 5.5);
434 EXPECT_DOUBLE_EQ(param17f, 6.6);
435 EXPECT_DOUBLE_EQ(param18f, 7.7);
436 EXPECT_DOUBLE_EQ(param19f, 8.8);
437 EXPECT_DOUBLE_EQ(param20f, 9.9);
438
439 EXPECT_EQ(param1v, 0);
440 EXPECT_EQ(param2v, 1);
441 EXPECT_EQ(param3v, 2);
442 EXPECT_EQ(param4v, 3);
443 EXPECT_EQ(param5v, 4);
444 EXPECT_EQ(param6v, 5);
445 EXPECT_EQ(param7v, 6);
446 EXPECT_EQ(param8v, 7);
447 EXPECT_EQ(param9v, 8);
448 EXPECT_EQ(param10v, 9);
449
450 EXPECT_DOUBLE_EQ(param11v, 0.0);
451 EXPECT_DOUBLE_EQ(param12v, 1.1);
452 EXPECT_DOUBLE_EQ(param13v, 2.2);
453 EXPECT_DOUBLE_EQ(param14v, 3.3);
454 EXPECT_DOUBLE_EQ(param15v, 4.4);
455 EXPECT_DOUBLE_EQ(param16v, 5.5);
456 EXPECT_DOUBLE_EQ(param17v, 6.6);
457 EXPECT_DOUBLE_EQ(param18v, 7.7);
458 EXPECT_DOUBLE_EQ(param19v, 8.8);
459 EXPECT_DOUBLE_EQ(param20v, 9.9);
460
461 EXPECT_EQ(param1fv, 0);
462 EXPECT_EQ(param2fv, 1);
463 EXPECT_EQ(param3fv, 2);
464 EXPECT_EQ(param4fv, 3);
465 EXPECT_EQ(param5fv, 4);
466 EXPECT_EQ(param6fv, 5);
467 EXPECT_EQ(param7fv, 6);
468 EXPECT_EQ(param8fv, 7);
469 EXPECT_EQ(param9fv, 8);
470 EXPECT_EQ(param10fv, 9);
471
472 EXPECT_DOUBLE_EQ(param11fv, 0.0);
473 EXPECT_DOUBLE_EQ(param12fv, 1.1);
474 EXPECT_DOUBLE_EQ(param13fv, 2.2);
475 EXPECT_DOUBLE_EQ(param14fv, 3.3);
476 EXPECT_DOUBLE_EQ(param15fv, 4.4);
477 EXPECT_DOUBLE_EQ(param16fv, 5.5);
478 EXPECT_DOUBLE_EQ(param17fv, 6.6);
479 EXPECT_DOUBLE_EQ(param18fv, 7.7);
480 EXPECT_DOUBLE_EQ(param19fv, 8.8);
481 EXPECT_DOUBLE_EQ(param20fv, 9.9);
482 }
483
TEST(GuestParams_riscv64_lp64d,LongArgLargeStructRes)484 TEST(GuestParams_riscv64_lp64d, LongArgLargeStructRes) {
485 ThreadState state{};
486
487 struct Result {
488 std::array<uint64_t, 10> values;
489 } result{};
490
491 SetXReg<A0>(state.cpu, ToGuestAddr(&result));
492 SetXReg<A1>(state.cpu, 0xdead0000beef);
493
494 auto [arg] = GuestParamsValues<Result(uint64_t), GuestAbi::kLp64d>(&state);
495
496 EXPECT_EQ(arg, 0xdead0000beefU);
497
498 auto&& [ret] = GuestReturnReference<Result(uint64_t), GuestAbi::kLp64d>(&state);
499
500 ret = Result{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
501
502 EXPECT_EQ(result.values[0], 1U);
503 EXPECT_EQ(result.values[1], 2U);
504 EXPECT_EQ(result.values[2], 3U);
505 EXPECT_EQ(result.values[3], 4U);
506 EXPECT_EQ(result.values[4], 5U);
507 EXPECT_EQ(result.values[5], 6U);
508 EXPECT_EQ(result.values[6], 7U);
509 EXPECT_EQ(result.values[7], 8U);
510 EXPECT_EQ(result.values[8], 9U);
511 EXPECT_EQ(result.values[9], 10U);
512 }
513
TEST(GuestVAListParams_riscv64_lp64d,PtrIntArgs)514 TEST(GuestVAListParams_riscv64_lp64d, PtrIntArgs) {
515 ThreadState state{};
516
517 static int x;
518
519 SetXReg<A0>(state.cpu, ToGuestAddr(&x));
520 SetXReg<A1>(state.cpu, 1234);
521 SetXReg<A2>(state.cpu, static_cast<uint64_t>(-7));
522
523 GuestVAListParams params = GuestParamsValues<void(...), GuestAbi::kLp64d>(&state);
524
525 EXPECT_EQ(params.GetPointerParam<int>(), &x);
526 EXPECT_EQ(params.GetParam<unsigned int>(), 1234U);
527 EXPECT_EQ(params.GetParam<int>(), -7);
528 }
529
TEST(GuestVAListParams_riscv64_lp64d,IntFloatIntDoubleArgs)530 TEST(GuestVAListParams_riscv64_lp64d, IntFloatIntDoubleArgs) {
531 ThreadState state{};
532
533 SetXReg<A0>(state.cpu, 1234);
534 SetXReg<A1>(state.cpu, bit_cast<uint32_t>(2.71f));
535 SetXReg<A2>(state.cpu, static_cast<uint64_t>(-7));
536 SetXReg<A3>(state.cpu, bit_cast<uint64_t>(3.14));
537
538 GuestVAListParams params = GuestParamsValues<void(...), GuestAbi::kLp64d>(&state);
539
540 EXPECT_EQ(params.GetParam<unsigned int>(), 1234U);
541 EXPECT_FLOAT_EQ(params.GetParam<float>(), 2.71f);
542 EXPECT_EQ(params.GetParam<int>(), -7);
543 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 3.14);
544 }
545
TEST(GuestVAListParams_riscv64_lp64d,StackArgs)546 TEST(GuestVAListParams_riscv64_lp64d, StackArgs) {
547 std::array<uint64_t, 4> stack;
548 ThreadState state{};
549 SetXReg<SP>(state.cpu, ToGuestAddr(stack.data()));
550
551 SetXReg<A0>(state.cpu, 0);
552 SetXReg<A1>(state.cpu, bit_cast<uint64_t>(1.1));
553 SetXReg<A2>(state.cpu, 2);
554 SetXReg<A3>(state.cpu, bit_cast<uint64_t>(3.3));
555 SetXReg<A4>(state.cpu, 4);
556 SetXReg<A5>(state.cpu, bit_cast<uint64_t>(5.5));
557 SetXReg<A6>(state.cpu, 6);
558 SetXReg<A7>(state.cpu, bit_cast<uint64_t>(7.7));
559 stack[0] = 8;
560 stack[1] = bit_cast<uint64_t>(9.9);
561 stack[2] = 10;
562 stack[3] = bit_cast<uint64_t>(11.11);
563
564 GuestVAListParams params = GuestParamsValues<void(...), GuestAbi::kLp64d>(&state);
565
566 EXPECT_EQ(params.GetParam<int>(), 0);
567 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 1.1);
568 EXPECT_EQ(params.GetParam<int>(), 2);
569 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 3.3);
570 EXPECT_EQ(params.GetParam<int>(), 4);
571 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 5.5);
572 EXPECT_EQ(params.GetParam<int>(), 6);
573 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 7.7);
574 EXPECT_EQ(params.GetParam<int>(), 8);
575 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 9.9);
576 EXPECT_EQ(params.GetParam<int>(), 10);
577 EXPECT_DOUBLE_EQ(params.GetParam<double>(), 11.11);
578 }
579
580 } // namespace
581
582 } // namespace berberis
583