Merge types and decoders for intenger and fp load/store operations.

Bug: 265372622

Test: berberis_host_tests/berberis_host_tests

Change-Id: I6a8e3de92607b031f7160a0d9d61adf381f4a5ea
diff --git a/decoder/include/berberis/decoder/riscv64/decoder.h b/decoder/include/berberis/decoder/riscv64/decoder.h
index e42a1df..5736175 100644
--- a/decoder/include/berberis/decoder/riscv64/decoder.h
+++ b/decoder/include/berberis/decoder/riscv64/decoder.h
@@ -118,12 +118,6 @@
     kFenceMaxOpcode = 0b1111,
   };
 
-  enum class LoadFpOpcode {
-    kFlw = 0b010,
-    kFld = 0b011,
-    kLoadFpMaxOpcode = 0b111,
-  };
-
   enum class OpOpcode {
     kAdd = 0b0000'000'000,
     kSub = 0b0100'000'000,
@@ -197,6 +191,12 @@
     kMaxLoadOpcode = 0b1111,
   };
 
+  enum class LoadFpOpcode {
+    kFlw = 0b010,
+    kFld = 0b011,
+    kLoadFpMaxOpcode = 0b111,
+  };
+
   enum class OpImmOpcode {
     kAddi = 0b000,
     kSlti = 0b010,
@@ -276,13 +276,6 @@
     int16_t imm;
   };
 
-  struct LoadFpArgs {
-    LoadFpOpcode opcode;
-    uint8_t dst;
-    uint8_t src;
-    int16_t offset;
-  };
-
   struct OpArgs {
     OpOpcode opcode;
     uint8_t dst;
@@ -306,13 +299,17 @@
     bool aq : 1;
   };
 
-  struct LoadArgs {
-    LoadOpcode opcode;
+  template <typename OpcodeType>
+  struct LoadArgsTemplate {
+    OpcodeType opcode;
     uint8_t dst;
     uint8_t src;
     int16_t offset;
   };
 
+  using LoadArgs = LoadArgsTemplate<LoadOpcode>;
+  using LoadFpArgs = LoadArgsTemplate<LoadFpOpcode>;
+
   struct OpImmArgs {
     OpImmOpcode opcode;
     uint8_t dst;
@@ -345,19 +342,16 @@
     uint8_t imm;
   };
 
-  struct StoreArgs {
-    StoreOpcode opcode;
+  template <typename OpcodeType>
+  struct StoreArgsTemplate {
+    OpcodeType opcode;
     uint8_t src;
     int16_t offset;
     uint8_t data;
   };
 
-  struct StoreFpArgs {
-    StoreFpOpcode opcode;
-    uint8_t src;
-    int16_t offset;
-    uint8_t data;
-  };
+  using StoreArgs = StoreArgsTemplate<StoreOpcode>;
+  using StoreFpArgs = StoreArgsTemplate<StoreFpOpcode>;
 
   struct BranchArgs {
     BranchOpcode opcode;
@@ -472,10 +466,10 @@
         DecodeAmo();
         break;
       case BaseOpcode::kLoad:
-        DecodeLoad();
+        DecodeLoad<LoadOpcode, &InsnConsumer::Load>();
         break;
       case BaseOpcode::kLoadFp:
-        DecodeLoadFp();
+        DecodeLoad<LoadFpOpcode, &InsnConsumer::LoadFp>();
         break;
       case BaseOpcode::kOpImm:
         DecodeOpImm();
@@ -484,10 +478,10 @@
         DecodeOpImm32();
         break;
       case BaseOpcode::kStore:
-        DecodeStore();
+        DecodeStore<StoreOpcode, &InsnConsumer::Store>();
         break;
       case BaseOpcode::kStoreFp:
-        DecodeStoreFp();
+        DecodeStore<StoreFpOpcode, &InsnConsumer::StoreFp>();
         break;
       case BaseOpcode::kBranch:
         DecodeBranch();
@@ -643,56 +637,32 @@
     insn_consumer_->Auipc(args);
   }
 
+  template <typename OpcodeType, auto LoadFunction>
   void DecodeLoad() {
-    LoadOpcode opcode{GetBits<uint8_t, 12, 3>()};
-    const LoadArgs args = {
+    OpcodeType opcode{GetBits<uint8_t, 12, 3>()};
+    const LoadArgsTemplate<OpcodeType> args = {
         .opcode = opcode,
         .dst = GetBits<uint8_t, 7, 5>(),
         .src = GetBits<uint8_t, 15, 5>(),
         .offset = SignExtend<12>(GetBits<uint16_t, 20, 12>()),
     };
-    insn_consumer_->Load(args);
+    (insn_consumer_->*LoadFunction)(args);
   }
 
-  void DecodeLoadFp() {
-    LoadFpOpcode opcode{GetBits<uint8_t, 12, 3>()};
-    const LoadFpArgs args = {
-        .opcode = opcode,
-        .dst = GetBits<uint8_t, 7, 5>(),
-        .src = GetBits<uint8_t, 15, 5>(),
-        .offset = SignExtend<12>(GetBits<uint16_t, 20, 12>()),
-    };
-    insn_consumer_->LoadFp(args);
-  }
-
+  template <typename OpcodeType, auto StoreFunction>
   void DecodeStore() {
-    StoreOpcode opcode{GetBits<uint8_t, 12, 3>()};
+    OpcodeType opcode{GetBits<uint8_t, 12, 3>()};
 
     uint16_t low_imm = GetBits<uint16_t, 7, 5>();
     uint16_t high_imm = GetBits<uint16_t, 25, 7>();
 
-    const StoreArgs args = {
+    const StoreArgsTemplate<OpcodeType> args = {
         .opcode = opcode,
         .src = GetBits<uint8_t, 15, 5>(),
         .offset = SignExtend<12>(int16_t(low_imm | (high_imm << 5))),
         .data = GetBits<uint8_t, 20, 5>(),
     };
-    insn_consumer_->Store(args);
-  }
-
-  void DecodeStoreFp() {
-    StoreFpOpcode opcode{GetBits<uint8_t, 12, 3>()};
-
-    uint16_t low_imm = GetBits<uint16_t, 7, 5>();
-    uint16_t high_imm = GetBits<uint16_t, 25, 7>();
-
-    const StoreFpArgs args = {
-        .opcode = opcode,
-        .src = GetBits<uint8_t, 15, 5>(),
-        .offset = SignExtend<12>(int16_t(low_imm | (high_imm << 5))),
-        .data = GetBits<uint8_t, 20, 5>(),
-    };
-    insn_consumer_->StoreFp(args);
+    (insn_consumer_->*StoreFunction)(args);
   }
 
   void DecodeOpImm() {