/* * Copyright (C) 2023 The Android Open Source Project * * 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. */ #include "gtest/gtest.h" #include #include #include "berberis/base/bit_util.h" #include "berberis/guest_abi/guest_params.h" #include "berberis/guest_state/guest_addr.h" #include "berberis/guest_state/guest_state.h" namespace berberis { namespace { TEST(GuestParams_riscv64_lp64d, PtrIntArgs) { ThreadState state{}; static int x; SetXReg(state.cpu, ToGuestAddr(&x)); SetXReg(state.cpu, 1234); SetXReg(state.cpu, 0xffff'ffff'ffff'fff9U); auto [param1, param2, param3] = GuestParamsValues(&state); auto [param1f, param2f, param3f] = GuestParamsValues(&state); auto [param1v, param2v, param3v] = GuestParamsValues(&state); auto [param1fv, param2fv, param3fv] = GuestParamsValues(&state); EXPECT_EQ(param1, &x); EXPECT_EQ(param2, 1234U); EXPECT_EQ(param3, -7); EXPECT_EQ(param1f, &x); EXPECT_EQ(param2f, 1234U); EXPECT_EQ(param3f, -7); EXPECT_EQ(param1v, &x); EXPECT_EQ(param2v, 1234U); EXPECT_EQ(param3v, -7); EXPECT_EQ(param1fv, &x); EXPECT_EQ(param2fv, 1234U); EXPECT_EQ(param3fv, -7); } TEST(GuestParams_riscv64_lp64d, IntRes) { ThreadState state{}; auto&& [ret] = GuestReturnReference(&state); auto&& [retf] = GuestReturnReference(&state); auto&& [retv] = GuestReturnReference(&state); auto&& [retfv] = GuestReturnReference(&state); ret = 123; EXPECT_EQ(GetXReg(state.cpu), 123U); ret = -123; EXPECT_EQ(GetXReg(state.cpu), 0xffff'ffff'ffff'ff85U); retf = 234; EXPECT_EQ(GetXReg(state.cpu), 234U); retv = 345; EXPECT_EQ(GetXReg(state.cpu), 345U); retv = -345; EXPECT_EQ(GetXReg(state.cpu), 0xffff'ffff'ffff'fea7U); retfv = 456; EXPECT_EQ(GetXReg(state.cpu), 456U); } TEST(GuestParams_riscv64_lp64d, SignedCharRes) { ThreadState state{}; SetXReg(state.cpu, 0); auto&& [ret] = GuestReturnReference(&state); auto&& [retf] = GuestReturnReference(&state); auto&& [retv] = GuestReturnReference(&state); auto&& [retfv] = GuestReturnReference(&state); ret = -1; EXPECT_EQ(GetXReg(state.cpu), 0xffff'ffff'ffff'ffffU); retf = -2; EXPECT_EQ(GetXReg(state.cpu), 0xffff'ffff'ffff'fffeU); retv = -3; EXPECT_EQ(GetXReg(state.cpu), 0xffff'ffff'ffff'fffdU); retfv = -4; EXPECT_EQ(GetXReg(state.cpu), 0xffff'ffff'ffff'fffcU); } TEST(GuestParams_riscv64_lp64d, PtrRes) { ThreadState state{}; SetXReg(state.cpu, static_cast(42)); auto&& [ret] = GuestReturnReference(&state); ret = nullptr; EXPECT_EQ(GetXReg(state.cpu), 0U); } TEST(GuestParams_riscv64_lp64d, SignedCharArg) { ThreadState state{}; SetXReg(state.cpu, 0xf0f0f0f0f0f0f0f0ULL); auto [arg] = GuestParamsValues(&state); auto [argf] = GuestParamsValues(&state); auto [argv] = GuestParamsValues(&state); auto [argfv] = GuestParamsValues(&state); EXPECT_EQ(arg, -16); EXPECT_EQ(argf, -16); EXPECT_EQ(argv, -16); EXPECT_EQ(argfv, -16); } TEST(GuestParams_riscv64_lp64d, IntFloatIntDoubleArgs) { ThreadState state{}; SetXReg(state.cpu, 1234); SetXReg(state.cpu, static_cast(-7)); SetFReg(state.cpu, bit_cast(2.71f)); SetFReg(state.cpu, bit_cast(3.14)); auto [param1, param2, param3, param4] = GuestParamsValues(&state); auto [param1f, param2f, param3f, param4f] = GuestParamsValues(&state); auto [param1v, param2v, param3v, param4v] = GuestParamsValues(&state); auto [param1fv, param2fv, param3fv, param4fv] = GuestParamsValues(&state); EXPECT_EQ(param1, 1234U); EXPECT_FLOAT_EQ(param2, 2.71f); EXPECT_EQ(param3, -7); EXPECT_DOUBLE_EQ(param4, 3.14); EXPECT_EQ(param1f, 1234U); EXPECT_FLOAT_EQ(param2f, 2.71f); EXPECT_EQ(param3f, -7); EXPECT_DOUBLE_EQ(param4f, 3.14); EXPECT_EQ(param1v, 1234U); EXPECT_FLOAT_EQ(param2v, 2.71f); EXPECT_EQ(param3v, -7); EXPECT_DOUBLE_EQ(param4v, 3.14); EXPECT_EQ(param1fv, 1234U); EXPECT_FLOAT_EQ(param2fv, 2.71f); EXPECT_EQ(param3fv, -7); EXPECT_DOUBLE_EQ(param4fv, 3.14); } TEST(GuestParams_riscv64_lp64d, DoubleRes) { ThreadState state{}; auto&& [ret] = GuestReturnReference(&state); auto&& [retf] = GuestReturnReference(&state); auto&& [retv] = GuestReturnReference(&state); auto&& [retfv] = GuestReturnReference(&state); ret = 3.14; EXPECT_DOUBLE_EQ(bit_cast(GetFReg(state.cpu)), 3.14); retf = 3.15; EXPECT_DOUBLE_EQ(bit_cast(GetFReg(state.cpu)), 3.15); retv = 3.15; EXPECT_DOUBLE_EQ(bit_cast(GetFReg(state.cpu)), 3.15); retfv = 3.16; EXPECT_DOUBLE_EQ(bit_cast(GetFReg(state.cpu)), 3.16); } TEST(GuestParams_riscv64_lp64d, StackArgs) { std::array stack; ThreadState state{}; SetXReg(state.cpu, ToGuestAddr(stack.data())); SetXReg(state.cpu, 0); SetXReg(state.cpu, 1); SetXReg(state.cpu, 2); SetXReg(state.cpu, 3); SetXReg(state.cpu, 4); SetXReg(state.cpu, 5); SetXReg(state.cpu, 6); SetXReg(state.cpu, 7); stack[0] = 8; stack[1] = 9; SetFReg(state.cpu, bit_cast(0.0)); SetFReg(state.cpu, bit_cast(1.1)); SetFReg(state.cpu, bit_cast(2.2)); SetFReg(state.cpu, bit_cast(3.3)); SetFReg(state.cpu, bit_cast(4.4)); SetFReg(state.cpu, bit_cast(5.5)); SetFReg(state.cpu, bit_cast(6.6)); SetFReg(state.cpu, bit_cast(7.7)); stack[2] = bit_cast(8.8); stack[3] = bit_cast(9.9); auto [param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20] = GuestParamsValues(&state); auto [param1f, param2f, param3f, param4f, param5f, param6f, param7f, param8f, param9f, param10f, param11f, param12f, param13f, param14f, param15f, param16f, param17f, param18f, param19f, param20f] = GuestParamsValues(&state); auto [param1v, param2v, param3v, param4v, param5v, param6v, param7v, param8v, param9v, param10v, param11v, param12v, param13v, param14v, param15v, param16v, param17v, param18v, param19v, param20v] = GuestParamsValues(&state); auto [param1fv, param2fv, param3fv, param4fv, param5fv, param6fv, param7fv, param8fv, param9fv, param10fv, param11fv, param12fv, param13fv, param14fv, param15fv, param16fv, param17fv, param18fv, param19fv, param20fv] = GuestParamsValues(&state); EXPECT_EQ(param1, 0); EXPECT_EQ(param2, 1); EXPECT_EQ(param3, 2); EXPECT_EQ(param4, 3); EXPECT_EQ(param5, 4); EXPECT_EQ(param6, 5); EXPECT_EQ(param7, 6); EXPECT_EQ(param8, 7); EXPECT_EQ(param9, 8); EXPECT_EQ(param10, 9); EXPECT_DOUBLE_EQ(param11, 0.0); EXPECT_DOUBLE_EQ(param12, 1.1); EXPECT_DOUBLE_EQ(param13, 2.2); EXPECT_DOUBLE_EQ(param14, 3.3); EXPECT_DOUBLE_EQ(param15, 4.4); EXPECT_DOUBLE_EQ(param16, 5.5); EXPECT_DOUBLE_EQ(param17, 6.6); EXPECT_DOUBLE_EQ(param18, 7.7); EXPECT_DOUBLE_EQ(param19, 8.8); EXPECT_DOUBLE_EQ(param20, 9.9); EXPECT_EQ(param1f, 0); EXPECT_EQ(param2f, 1); EXPECT_EQ(param3f, 2); EXPECT_EQ(param4f, 3); EXPECT_EQ(param5f, 4); EXPECT_EQ(param6f, 5); EXPECT_EQ(param7f, 6); EXPECT_EQ(param8f, 7); EXPECT_EQ(param9f, 8); EXPECT_EQ(param10f, 9); EXPECT_DOUBLE_EQ(param11f, 0.0); EXPECT_DOUBLE_EQ(param12f, 1.1); EXPECT_DOUBLE_EQ(param13f, 2.2); EXPECT_DOUBLE_EQ(param14f, 3.3); EXPECT_DOUBLE_EQ(param15f, 4.4); EXPECT_DOUBLE_EQ(param16f, 5.5); EXPECT_DOUBLE_EQ(param17f, 6.6); EXPECT_DOUBLE_EQ(param18f, 7.7); EXPECT_DOUBLE_EQ(param19f, 8.8); EXPECT_DOUBLE_EQ(param20f, 9.9); EXPECT_EQ(param1v, 0); EXPECT_EQ(param2v, 1); EXPECT_EQ(param3v, 2); EXPECT_EQ(param4v, 3); EXPECT_EQ(param5v, 4); EXPECT_EQ(param6v, 5); EXPECT_EQ(param7v, 6); EXPECT_EQ(param8v, 7); EXPECT_EQ(param9v, 8); EXPECT_EQ(param10v, 9); EXPECT_DOUBLE_EQ(param11v, 0.0); EXPECT_DOUBLE_EQ(param12v, 1.1); EXPECT_DOUBLE_EQ(param13v, 2.2); EXPECT_DOUBLE_EQ(param14v, 3.3); EXPECT_DOUBLE_EQ(param15v, 4.4); EXPECT_DOUBLE_EQ(param16v, 5.5); EXPECT_DOUBLE_EQ(param17v, 6.6); EXPECT_DOUBLE_EQ(param18v, 7.7); EXPECT_DOUBLE_EQ(param19v, 8.8); EXPECT_DOUBLE_EQ(param20v, 9.9); EXPECT_EQ(param1fv, 0); EXPECT_EQ(param2fv, 1); EXPECT_EQ(param3fv, 2); EXPECT_EQ(param4fv, 3); EXPECT_EQ(param5fv, 4); EXPECT_EQ(param6fv, 5); EXPECT_EQ(param7fv, 6); EXPECT_EQ(param8fv, 7); EXPECT_EQ(param9fv, 8); EXPECT_EQ(param10fv, 9); EXPECT_DOUBLE_EQ(param11fv, 0.0); EXPECT_DOUBLE_EQ(param12fv, 1.1); EXPECT_DOUBLE_EQ(param13fv, 2.2); EXPECT_DOUBLE_EQ(param14fv, 3.3); EXPECT_DOUBLE_EQ(param15fv, 4.4); EXPECT_DOUBLE_EQ(param16fv, 5.5); EXPECT_DOUBLE_EQ(param17fv, 6.6); EXPECT_DOUBLE_EQ(param18fv, 7.7); EXPECT_DOUBLE_EQ(param19fv, 8.8); EXPECT_DOUBLE_EQ(param20fv, 9.9); } TEST(GuestParams_riscv64_lp64d, LongArgLargeStructRes) { ThreadState state{}; struct Result { std::array values; } result{}; SetXReg(state.cpu, ToGuestAddr(&result)); SetXReg(state.cpu, 0xdead0000beef); auto [arg] = GuestParamsValues(&state); EXPECT_EQ(arg, 0xdead0000beefU); auto&& [ret] = GuestReturnReference(&state); ret = Result{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; EXPECT_EQ(result.values[0], 1U); EXPECT_EQ(result.values[1], 2U); EXPECT_EQ(result.values[2], 3U); EXPECT_EQ(result.values[3], 4U); EXPECT_EQ(result.values[4], 5U); EXPECT_EQ(result.values[5], 6U); EXPECT_EQ(result.values[6], 7U); EXPECT_EQ(result.values[7], 8U); EXPECT_EQ(result.values[8], 9U); EXPECT_EQ(result.values[9], 10U); } TEST(GuestVAListParams_riscv64_lp64d, PtrIntArgs) { ThreadState state{}; static int x; SetXReg(state.cpu, ToGuestAddr(&x)); SetXReg(state.cpu, 1234); SetXReg(state.cpu, static_cast(-7)); GuestVAListParams params = GuestParamsValues(&state); EXPECT_EQ(params.GetPointerParam(), &x); EXPECT_EQ(params.GetParam(), 1234U); EXPECT_EQ(params.GetParam(), -7); } TEST(GuestVAListParams_riscv64_lp64d, IntFloatIntDoubleArgs) { ThreadState state{}; SetXReg(state.cpu, 1234); SetXReg(state.cpu, bit_cast(2.71f)); SetXReg(state.cpu, static_cast(-7)); SetXReg(state.cpu, bit_cast(3.14)); GuestVAListParams params = GuestParamsValues(&state); EXPECT_EQ(params.GetParam(), 1234U); EXPECT_FLOAT_EQ(params.GetParam(), 2.71f); EXPECT_EQ(params.GetParam(), -7); EXPECT_DOUBLE_EQ(params.GetParam(), 3.14); } TEST(GuestVAListParams_riscv64_lp64d, StackArgs) { std::array stack; ThreadState state{}; SetXReg(state.cpu, ToGuestAddr(stack.data())); SetXReg(state.cpu, 0); SetXReg(state.cpu, bit_cast(1.1)); SetXReg(state.cpu, 2); SetXReg(state.cpu, bit_cast(3.3)); SetXReg(state.cpu, 4); SetXReg(state.cpu, bit_cast(5.5)); SetXReg(state.cpu, 6); SetXReg(state.cpu, bit_cast(7.7)); stack[0] = 8; stack[1] = bit_cast(9.9); stack[2] = 10; stack[3] = bit_cast(11.11); GuestVAListParams params = GuestParamsValues(&state); EXPECT_EQ(params.GetParam(), 0); EXPECT_DOUBLE_EQ(params.GetParam(), 1.1); EXPECT_EQ(params.GetParam(), 2); EXPECT_DOUBLE_EQ(params.GetParam(), 3.3); EXPECT_EQ(params.GetParam(), 4); EXPECT_DOUBLE_EQ(params.GetParam(), 5.5); EXPECT_EQ(params.GetParam(), 6); EXPECT_DOUBLE_EQ(params.GetParam(), 7.7); EXPECT_EQ(params.GetParam(), 8); EXPECT_DOUBLE_EQ(params.GetParam(), 9.9); EXPECT_EQ(params.GetParam(), 10); EXPECT_DOUBLE_EQ(params.GetParam(), 11.11); } } // namespace } // namespace berberis