aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Khimenko <khim@google.com>2023-04-15 21:12:00 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-04-15 21:12:00 +0000
commit57a120cf6589e0d45738da935700001af463bcd1 (patch)
treecf9c4f673f3fd415c226006bd6d57f7e7c67f2c2
parentc124e0110ffb3f284229f3f5ceee2d030bcd079d (diff)
parent5d31766c2a4676404c7d77d42a9587b00b7072d5 (diff)
downloadbinary_translation-57a120cf6589e0d45738da935700001af463bcd1.tar.gz
Merge "interp: Add c.fld compressed instruction."
-rw-r--r--decoder/include/berberis/decoder/riscv64/decoder.h18
-rw-r--r--interpreter/riscv64/interpreter_test.cc40
2 files changed, 58 insertions, 0 deletions
diff --git a/decoder/include/berberis/decoder/riscv64/decoder.h b/decoder/include/berberis/decoder/riscv64/decoder.h
index de0b9d44..677e715e 100644
--- a/decoder/include/berberis/decoder/riscv64/decoder.h
+++ b/decoder/include/berberis/decoder/riscv64/decoder.h
@@ -394,12 +394,30 @@ class Decoder {
case CompressedOpcode::kAddi:
DecodeCAddi();
break;
+ case CompressedOpcode::kFld:
+ DecodeCFld();
+ break;
default:
insn_consumer_->Unimplemented();
}
return 2;
}
+ void DecodeCFld() {
+ 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 rd = GetBits<uint8_t, 2, 3>();
+ uint8_t rs = GetBits<uint8_t, 7, 3>();
+ const LoadFpArgs args = {
+ .opcode = LoadFpOpcode::kFld,
+ .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/interpreter/riscv64/interpreter_test.cc b/interpreter/riscv64/interpreter_test.cc
index b82a2dfa..299b6e46 100644
--- a/interpreter/riscv64/interpreter_test.cc
+++ b/interpreter/riscv64/interpreter_test.cc
@@ -34,6 +34,14 @@ namespace {
class Riscv64InterpreterTest : public ::testing::Test {
public:
+ 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<8>(state_.cpu), kDataToLoad);
+ }
+
void InterpretCAddi4spn(uint16_t insn_bytes, uint64_t expected_offset) {
auto code_start = ToGuestAddr(&insn_bytes);
state_.cpu.insn_addr = code_start;
@@ -190,6 +198,38 @@ class Riscv64InterpreterTest : public ::testing::Test {
ThreadState state_;
};
+TEST_F(Riscv64InterpreterTest, CFld) {
+ union {
+ uint16_t offset;
+ struct {
+ uint8_t : 3;
+ uint8_t i3_i5 : 3;
+ uint8_t i6_i7 : 2;
+ } i_bits;
+ };
+ for (offset = int16_t{0}; offset < int16_t{256}; offset += 8) {
+ union {
+ int16_t parcel;
+ struct {
+ uint8_t low_opcode : 2;
+ uint8_t rd : 3;
+ uint8_t i6_i7 : 2;
+ uint8_t rs : 3;
+ uint8_t i3_i5 : 3;
+ uint8_t high_opcode : 3;
+ } __attribute__((__packed__));
+ } o_bits = {
+ .low_opcode = 0b00,
+ .rd = 0,
+ .i6_i7 = i_bits.i6_i7,
+ .rs = 0,
+ .i3_i5 = i_bits.i3_i5,
+ .high_opcode = 0b001,
+ };
+ InterpretCFld(o_bits.parcel, offset);
+ }
+}
+
TEST_F(Riscv64InterpreterTest, CAddi) {
union {
int8_t offset;