aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Khimenko <khim@google.com>2023-04-21 13:25:09 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-04-21 13:25:09 +0000
commit1fa8877495a3938773a18455afe8bbd677fcb9f9 (patch)
tree9e8bd7283676827de05401c1bd9ce417626e031d
parent61e4b31bad6107df519d81b8fe9435981215bb86 (diff)
parentd9cda790db7cc1681a722be35844b78b4f1ba5a6 (diff)
downloadbinary_translation-1fa8877495a3938773a18455afe8bbd677fcb9f9.tar.gz
Merge "Merge load/store helper functions." am: d0acef2e61 am: 2a828e653e am: d9cda790db
Original change: https://android-review.googlesource.com/c/platform/frameworks/libs/binary_translation/+/2554050 Change-Id: I11a335d49d0ffaa754a6da43af91401cf61d1304 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--base/include/berberis/base/dependent_false.h32
-rw-r--r--decoder/include/berberis/decoder/riscv64/decoder.h45
-rw-r--r--guest_state/include/berberis/guest_state/guest_state_riscv64.h28
-rw-r--r--interpreter/riscv64/interpreter_test.cc60
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 57e79287..9f785732 100644
--- a/decoder/include/berberis/decoder/riscv64/decoder.h
+++ b/decoder/include/berberis/decoder/riscv64/decoder.h
@@ -458,19 +458,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();
@@ -478,15 +478,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,
@@ -494,7 +501,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),
@@ -504,22 +511,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 f72437f7..adc13a66 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) {
@@ -279,14 +255,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);
}
}
@@ -325,13 +303,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) {