diff options
author | Victor Khimenko <khim@google.com> | 2023-04-21 00:09:04 +0000 |
---|---|---|
committer | Victor Khimenko <khim@google.com> | 2023-04-21 09:04:00 +0000 |
commit | 96dedfd85fa7f3648ed487f910ea48db1f68a5ec (patch) | |
tree | 443037f383e34fa4ec28e4c6a7e32e6e6657cb8d | |
parent | 7358ad077e6046160d27b1dc9096e9d8689ad3b7 (diff) | |
download | binary_translation-96dedfd85fa7f3648ed487f910ea48db1f68a5ec.tar.gz |
Merge load/store helper functions.
Bug: 265372622
Test: berberis_host_tests/berberis_host_tests
Change-Id: I1cbab04c23b06c4f4b64c195aeed81ed4b620f94
-rw-r--r-- | base/include/berberis/base/dependent_false.h | 32 | ||||
-rw-r--r-- | decoder/include/berberis/decoder/riscv64/decoder.h | 45 | ||||
-rw-r--r-- | guest_state/include/berberis/guest_state/guest_state_riscv64.h | 28 | ||||
-rw-r--r-- | interpreter/riscv64/interpreter_test.cc | 60 |
4 files changed, 101 insertions, 64 deletions
diff --git a/base/include/berberis/base/dependent_false.h b/base/include/berberis/base/dependent_false.h new file mode 100644 index 00000000..f01a48e0 --- /dev/null +++ b/base/include/berberis/base/dependent_false.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef BERBERIS_BASE_DEPENDENT_FALSE_H_ +#define BERBERIS_BASE_DEPENDENT_FALSE_H_ + +#include <type_traits> + +namespace berberis { + +template <typename T> +inline constexpr bool kDependentTypeFalse = false; + +template <auto T> +inline constexpr bool kDependentValueFalse = false; + +} // namespace berberis + +#endif // BERBERIS_BASE_DEPENDENT_FALSE_H_ diff --git a/decoder/include/berberis/decoder/riscv64/decoder.h b/decoder/include/berberis/decoder/riscv64/decoder.h index ec51fe37..585b16e8 100644 --- a/decoder/include/berberis/decoder/riscv64/decoder.h +++ b/decoder/include/berberis/decoder/riscv64/decoder.h @@ -430,19 +430,19 @@ class Decoder { DecodeCAddi(); break; case CompressedOpcode::kFld: - DecodeCLoadStore<LoadFpArgs, LoadFpOpcode::kFld, false>(); + DecodeCompressedLoadStore<LoadFpOpcode::kFld>(); break; case CompressedOpcode::kLw: - DecodeCLw(); + DecodeCompressedLoadStore<LoadOpcode::kLw>(); break; case CompressedOpcode::kLd: - DecodeCLoadStore<LoadArgs, LoadOpcode::kLd, false>(); + DecodeCompressedLoadStore<LoadOpcode::kLd>(); break; case CompressedOpcode::kFsd: - DecodeCLoadStore<StoreFpArgs, StoreFpOpcode::kFsd, true>(); + DecodeCompressedLoadStore<StoreFpOpcode::kFsd>(); break; case CompressedOpcode::kSd: - DecodeCLoadStore<StoreArgs, StoreOpcode::kSd, true>(); + DecodeCompressedLoadStore<StoreOpcode::kSd>(); break; default: insn_consumer_->Unimplemented(); @@ -450,15 +450,22 @@ class Decoder { return 2; } - template <typename Args, auto opcode, bool kStore> - void DecodeCLoadStore() { + template <auto opcode> + void DecodeCompressedLoadStore() { uint8_t low_imm = GetBits<uint8_t, 5, 2>(); uint8_t high_imm = GetBits<uint8_t, 10, 3>(); - uint8_t imm = (low_imm << 6 | high_imm << 3); + uint8_t imm; + if constexpr ((uint8_t(opcode) & 1) == 0) { + constexpr uint8_t kLwLow[4] = {0x0, 0x40, 0x04, 0x44}; + imm = (kLwLow[low_imm] | high_imm << 3); + } else { + imm = (low_imm << 6 | high_imm << 3); + } uint8_t rd = GetBits<uint8_t, 2, 3>(); uint8_t rs = GetBits<uint8_t, 7, 3>(); - if constexpr (kStore) { - const Args args = { + if constexpr (std::is_same_v<decltype(opcode), StoreOpcode> || + std::is_same_v<decltype(opcode), StoreFpOpcode>) { + const StoreArgsTemplate<decltype(opcode)> args = { .opcode = opcode, .src = uint8_t(8 + rs), .offset = imm, @@ -466,7 +473,7 @@ class Decoder { }; insn_consumer_->Store(args); } else { - const Args args = { + const LoadArgsTemplate<decltype(opcode)> args = { .opcode = opcode, .dst = uint8_t(8 + rd), .src = uint8_t(8 + rs), @@ -476,22 +483,6 @@ class Decoder { } } - void DecodeCLw() { - constexpr uint8_t kLwLow[4] = {0x0, 0x40, 0x04, 0x44}; - uint8_t low_imm = GetBits<uint8_t, 5, 2>(); - uint8_t high_imm = GetBits<uint8_t, 10, 3>(); - uint8_t imm = (kLwLow[low_imm] | high_imm << 3); - uint8_t rd = GetBits<uint8_t, 2, 3>(); - uint8_t rs = GetBits<uint8_t, 7, 3>(); - const LoadArgs args = { - .opcode = LoadOpcode::kLw, - .dst = uint8_t(8 + rd), - .src = uint8_t(8 + rs), - .offset = imm, - }; - insn_consumer_->Load(args); - } - void DecodeCAddi() { uint8_t low_imm = GetBits<uint8_t, 2, 5>(); uint8_t high_imm = GetBits<uint8_t, 12, 1>(); diff --git a/guest_state/include/berberis/guest_state/guest_state_riscv64.h b/guest_state/include/berberis/guest_state/guest_state_riscv64.h index 8546311f..82aad665 100644 --- a/guest_state/include/berberis/guest_state/guest_state_riscv64.h +++ b/guest_state/include/berberis/guest_state/guest_state_riscv64.h @@ -19,6 +19,7 @@ #include <cstdint> +#include "berberis/base/dependent_false.h" #include "berberis/base/macros.h" #include "berberis/guest_state/guest_addr.h" @@ -74,6 +75,33 @@ inline void SetFReg(CPUState& state, uint64_t val) { state.f[kIndex] = val; } +enum class RegisterType { + kReg, + kFpReg, +}; + +template <RegisterType register_type, uint8_t kIndex> +inline auto GetReg(const CPUState& state) { + if constexpr (register_type == RegisterType::kReg) { + return GetXReg<kIndex>(state); + } else if constexpr (register_type == RegisterType::kFpReg) { + return GetFReg<kIndex>(state); + } else { + static_assert(kDependentValueFalse<register_type>, "Unsupported register type"); + } +} + +template <RegisterType register_type, uint8_t kIndex, typename Register> +inline auto SetReg(CPUState& state, Register val) { + if constexpr (register_type == RegisterType::kReg) { + return SetXReg<kIndex>(state, val); + } else if constexpr (register_type == RegisterType::kFpReg) { + return SetFReg<kIndex>(state, val); + } else { + static_assert(kDependentValueFalse<register_type>, "Unsupported register type"); + } +} + struct ThreadState { CPUState cpu; }; diff --git a/interpreter/riscv64/interpreter_test.cc b/interpreter/riscv64/interpreter_test.cc index 742cf028..3582e588 100644 --- a/interpreter/riscv64/interpreter_test.cc +++ b/interpreter/riscv64/interpreter_test.cc @@ -35,48 +35,24 @@ namespace { class Riscv64InterpreterTest : public ::testing::Test { public: - void InterpretCSd(uint16_t insn_bytes, uint64_t offset) { + template <RegisterType register_type, uint64_t expected_result> + void InterpretCompressedStore(uint16_t insn_bytes, uint64_t offset) { auto code_start = ToGuestAddr(&insn_bytes); state_.cpu.insn_addr = code_start; store_area_ = 0; SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&store_area_) - offset)); - SetXReg<9>(state_.cpu, kDataToLoad); + SetReg<register_type, 9>(state_.cpu, kDataToLoad); InterpretInsn(&state_); - EXPECT_EQ(store_area_, kDataToLoad); - } - - void InterpretCFsd(uint16_t insn_bytes, uint64_t offset) { - auto code_start = ToGuestAddr(&insn_bytes); - state_.cpu.insn_addr = code_start; - store_area_ = 0; - SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&store_area_) - offset)); - SetFReg<9>(state_.cpu, kDataToLoad); - InterpretInsn(&state_); - EXPECT_EQ(store_area_, kDataToLoad); - } - - void InterpretCFld(uint16_t insn_bytes, uint64_t offset) { - auto code_start = ToGuestAddr(&insn_bytes); - state_.cpu.insn_addr = code_start; - SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&kDataToLoad) - offset)); - InterpretInsn(&state_); - EXPECT_EQ(GetFReg<9>(state_.cpu), kDataToLoad); - } - - void InterpretCLd(uint16_t insn_bytes, uint64_t offset) { - auto code_start = ToGuestAddr(&insn_bytes); - state_.cpu.insn_addr = code_start; - SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&kDataToLoad) - offset)); - InterpretInsn(&state_); - EXPECT_EQ(GetXReg<9>(state_.cpu), kDataToLoad); + EXPECT_EQ(store_area_, expected_result); } - void InterpretCLw(uint16_t insn_bytes, uint64_t offset) { + template <RegisterType register_type, uint64_t expected_result> + void InterpretCompressedLoad(uint16_t insn_bytes, uint64_t offset) { auto code_start = ToGuestAddr(&insn_bytes); state_.cpu.insn_addr = code_start; SetXReg<8>(state_.cpu, ToGuestAddr(bit_cast<uint8_t*>(&kDataToLoad) - offset)); InterpretInsn(&state_); - EXPECT_EQ(GetXReg<8>(state_.cpu), uint64_t(int32_t(kDataToLoad))); + EXPECT_EQ((GetReg<register_type, 9>(state_.cpu)), expected_result); } void InterpretCAddi4spn(uint16_t insn_bytes, uint64_t expected_offset) { @@ -268,14 +244,16 @@ TEST_F(Riscv64InterpreterTest, CLw) { } __attribute__((__packed__)); } o_bits = { .low_opcode = 0b00, - .rd = 0, + .rd = 1, .i6 = i_bits.i6, .i2 = i_bits.i2, .rs = 0, .i3_i5 = i_bits.i3_i5, .high_opcode = 0b010, }; - InterpretCLw(o_bits.parcel, offset); + InterpretCompressedLoad<RegisterType::kReg, + static_cast<uint64_t>(static_cast<int32_t>(kDataToLoad))>(o_bits.parcel, + offset); } } @@ -314,13 +292,21 @@ void TestCompressedLoadOrStore(Riscv64InterpreterTest* that) { TEST_F(Riscv64InterpreterTest, CompressedLoadAndStores) { // c.Fld - TestCompressedLoadOrStore<0b001'000'000'00'000'00, &Riscv64InterpreterTest::InterpretCFld>(this); + TestCompressedLoadOrStore< + 0b001'000'000'00'000'00, + &Riscv64InterpreterTest::InterpretCompressedLoad<RegisterType::kFpReg, kDataToLoad>>(this); // c.Ld - TestCompressedLoadOrStore<0b011'000'000'00'000'00, &Riscv64InterpreterTest::InterpretCLd>(this); + TestCompressedLoadOrStore< + 0b011'000'000'00'000'00, + &Riscv64InterpreterTest::InterpretCompressedLoad<RegisterType::kReg, kDataToLoad>>(this); // c.Fsd - TestCompressedLoadOrStore<0b101'000'000'00'000'00, &Riscv64InterpreterTest::InterpretCFsd>(this); + TestCompressedLoadOrStore< + 0b101'000'000'00'000'00, + &Riscv64InterpreterTest::InterpretCompressedStore<RegisterType::kFpReg, kDataToLoad>>(this); // c.Sd - TestCompressedLoadOrStore<0b111'000'000'00'000'00, &Riscv64InterpreterTest::InterpretCSd>(this); + TestCompressedLoadOrStore< + 0b111'000'000'00'000'00, + &Riscv64InterpreterTest::InterpretCompressedStore<RegisterType::kReg, kDataToLoad>>(this); } TEST_F(Riscv64InterpreterTest, CAddi) { |