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 <cstdint>
20
21 #include "berberis/assembler/machine_code.h"
22 #include "berberis/guest_state/guest_addr.h"
23
24 #include "lite_translator.h"
25 #include "register_maintainer.h"
26
27 namespace berberis {
28
29 namespace {
30
TEST(Riscv64LiteTranslatorTest,GetMappedRegs)31 TEST(Riscv64LiteTranslatorTest, GetMappedRegs) {
32 MachineCode machine_code;
33 LiteTranslator translator(&machine_code, 0);
34 auto [mapped_reg, is_new] = translator.GetMappedRegisterOrMap(1);
35 EXPECT_TRUE(is_new);
36 auto [mapped_reg2, is_new2] = translator.GetMappedRegisterOrMap(1);
37 EXPECT_FALSE(is_new2);
38 EXPECT_EQ(mapped_reg, mapped_reg2);
39 auto [mapped_reg3, is_new3] = translator.GetMappedRegisterOrMap(2);
40 EXPECT_TRUE(is_new3);
41 EXPECT_NE(mapped_reg, mapped_reg3);
42 }
43
TEST(Riscv64LiteTranslatorTest,GetRegs)44 TEST(Riscv64LiteTranslatorTest, GetRegs) {
45 // if size of machine_code does not change load is skipped.
46 MachineCode machine_code;
47 LiteTranslator translator(&machine_code, 0);
48 translator.GetReg(1);
49 EXPECT_TRUE(translator.gp_maintainer()->IsMapped(1));
50 int size1 = machine_code.install_size();
51 translator.GetReg(1);
52 int size2 = machine_code.install_size();
53 EXPECT_EQ(size1, size2);
54 translator.GetReg(2);
55 EXPECT_TRUE(translator.gp_maintainer()->IsMapped(2));
56 int size3 = machine_code.install_size();
57 EXPECT_LT(size2, size3);
58 translator.GetReg(3);
59 EXPECT_TRUE(translator.gp_maintainer()->IsMapped(3));
60 int size4 = machine_code.install_size();
61 EXPECT_LT(size3, size4);
62 }
63
TEST(Riscv64LiteTranslatorTest,GetFpReg)64 TEST(Riscv64LiteTranslatorTest, GetFpReg) {
65 // if size of machine_code does not change load is skipped.
66 MachineCode machine_code;
67 LiteTranslator translator(&machine_code, 0);
68 translator.GetFpReg(1);
69 EXPECT_TRUE(translator.simd_maintainer()->IsMapped(1));
70 int size1 = machine_code.install_size();
71 translator.GetFpReg(1);
72 int size2 = machine_code.install_size();
73 EXPECT_EQ(size1, size2);
74 translator.GetFpReg(2);
75 EXPECT_TRUE(translator.simd_maintainer()->IsMapped(2));
76 int size3 = machine_code.install_size();
77 EXPECT_LT(size2, size3);
78 translator.GetFpReg(3);
79 EXPECT_TRUE(translator.simd_maintainer()->IsMapped(3));
80 int size4 = machine_code.install_size();
81 EXPECT_LT(size3, size4);
82 }
83
TEST(Riscv64LiteTranslatorTest,NanBoxAndSetFpReg)84 TEST(Riscv64LiteTranslatorTest, NanBoxAndSetFpReg) {
85 MachineCode machine_code;
86 LiteTranslator translator(&machine_code, 0);
87 LiteTranslator::FpRegister reg;
88 int32_t offset = offsetof(ThreadState, cpu.f) + 1 * sizeof(LiteTranslator::Float64);
89 size_t store_insn_base = machine_code.install_size();
90 translator.StoreFpReg(reg, offset);
91 size_t store_insn_size = machine_code.install_size() - store_insn_base;
92
93 size_t mov_insn_base = machine_code.install_size();
94 translator.MoveFpReg(reg, reg);
95 size_t mov_insn_size = machine_code.install_size() - mov_insn_base;
96
97 size_t nan_box_insn_base = machine_code.install_size();
98 translator.NanBoxFpReg<LiteTranslator::Float32>(reg);
99 size_t nan_box_insn_size = machine_code.install_size() - nan_box_insn_base;
100
101 ASSERT_NE(store_insn_size, mov_insn_size);
102
103 size_t nan_box_and_set_base = machine_code.install_size();
104 translator.NanBoxAndSetFpReg<LiteTranslator::Float32>(1, reg);
105 EXPECT_EQ(nan_box_insn_size + mov_insn_size, machine_code.install_size() - nan_box_and_set_base);
106
107 nan_box_and_set_base = machine_code.install_size();
108 translator.NanBoxAndSetFpReg<LiteTranslator::Float32>(1, reg);
109 EXPECT_EQ(nan_box_insn_size + mov_insn_size, machine_code.install_size() - nan_box_and_set_base);
110 }
111
TEST(Riscv64LiteTranslatorTest,SetReg)112 TEST(Riscv64LiteTranslatorTest, SetReg) {
113 MachineCode machine_code;
114 LiteTranslator translator(&machine_code, 0);
115 LiteTranslator::Register reg;
116 int32_t offset = offsetof(ThreadState, cpu.x[0]) + 1 * 8;
117 size_t store_insn_base = machine_code.install_size();
118 translator.as()->Movq({.base = translator.as()->rbp, .disp = offset}, reg);
119 size_t store_insn_size = machine_code.install_size() - store_insn_base;
120
121 size_t mov_insn_base = machine_code.install_size();
122 translator.as()->Movq(reg, reg);
123 size_t mov_insn_size = machine_code.install_size() - mov_insn_base;
124
125 ASSERT_NE(store_insn_size, mov_insn_size);
126
127 size_t set_base = machine_code.install_size();
128 translator.SetReg(1, reg);
129 EXPECT_EQ(mov_insn_size, machine_code.install_size() - set_base);
130
131 set_base = machine_code.install_size();
132 translator.SetReg(1, reg);
133 EXPECT_EQ(mov_insn_size, machine_code.install_size() - set_base);
134 }
135
136 } // namespace
137
138 } // namespace berberis
139