[heavy_optimizer/riscv64] Implement fp state accessors

Also adds "Unimplemented()" functions for most of the
SemanticPlayer interfaces and adds success status.

Bug: 291126189
Test: mm and berberis_host_tests
Change-Id: Icbf5022e8faba81d995ced9fad92f5c8fb0bdb70
Merged-In: Icbf5022e8faba81d995ced9fad92f5c8fb0bdb70
diff --git a/heavy_optimizer/riscv64/frontend.cc b/heavy_optimizer/riscv64/frontend.cc
index f265aed..3a78cac 100644
--- a/heavy_optimizer/riscv64/frontend.cc
+++ b/heavy_optimizer/riscv64/frontend.cc
@@ -26,6 +26,7 @@
 namespace berberis {
 
 using BranchOpcode = HeavyOptimizerFrontend::Decoder::BranchOpcode;
+using FpRegister = HeavyOptimizerFrontend::FpRegister;
 using Register = HeavyOptimizerFrontend::Register;
 
 void HeavyOptimizerFrontend::CompareAndBranch(BranchOpcode opcode,
@@ -119,7 +120,6 @@
 void HeavyOptimizerFrontend::ExitRegionIndirect(Register target) {
   Gen<PseudoIndirectJump>(target);
 }
-
 void HeavyOptimizerFrontend::Unimplemented() {
   ExitGeneratedCode(GetInsnAddr());
   // We don't require region to end here as control flow may jump around
@@ -253,11 +253,26 @@
   }
 }
 
+Register HeavyOptimizerFrontend::GetReg(uint8_t reg) {
+  CHECK_LT(reg, kNumGuestRegs);
+  Register dst = AllocTempReg();
+  builder_.GenGet(dst, reg);
+  return dst;
+}
+
 void HeavyOptimizerFrontend::SetReg(uint8_t reg, Register value) {
   CHECK_LT(reg, kNumGuestRegs);
   builder_.GenPut(reg, value);
 }
 
+FpRegister HeavyOptimizerFrontend::GetFpReg(uint8_t reg) {
+  FpRegister result = AllocTempSimdReg();
+  builder_.GenGetSimd(result.machine_reg(), reg);
+  return result;
+}
+
+void HeavyOptimizerFrontend::Nop() {}
+
 //
 //  Methods that are not part of SemanticsListener implementation.
 //
diff --git a/heavy_optimizer/riscv64/frontend.h b/heavy_optimizer/riscv64/frontend.h
index 7b92114..b15a61c 100644
--- a/heavy_optimizer/riscv64/frontend.h
+++ b/heavy_optimizer/riscv64/frontend.h
@@ -24,7 +24,10 @@
 #include "berberis/decoder/riscv64/decoder.h"
 #include "berberis/decoder/riscv64/semantics_player.h"
 #include "berberis/guest_state/guest_addr.h"
+#include "berberis/guest_state/guest_state_arch.h"
 #include "berberis/intrinsics/intrinsics.h"
+#include "berberis/intrinsics/macro_assembler.h"
+#include "berberis/runtime_primitives/platform.h"
 
 #include "call_intrinsic.h"
 #include "inline_intrinsic.h"
@@ -43,6 +46,7 @@
 
   explicit HeavyOptimizerFrontend(x86_64::MachineIR* machine_ir, GuestAddr pc)
       : pc_(pc),
+        success_(true),
         builder_(machine_ir),
         flag_register_(machine_ir->AllocVReg()),
         is_uncond_branch_(false),
@@ -61,8 +65,196 @@
     return result;
   }
 
+  [[nodiscard]] Register GetReg(uint8_t reg);
   void SetReg(uint8_t reg, Register value);
+
   void Unimplemented();
+  //
+  // Instruction implementations.
+  //
+  void Nop();
+  Register Op(Decoder::OpOpcode /* opcode */, Register /* arg1 */, Register /* arg2 */) {
+    Unimplemented();
+    return {};
+  }
+  Register Op32(Decoder::Op32Opcode /* opcode */, Register /* arg1 */, Register /* arg2 */) {
+    Unimplemented();
+    return {};
+  }
+  Register OpImm(Decoder::OpImmOpcode /* opcode */, Register /* arg */, int16_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register OpImm32(Decoder::OpImm32Opcode /* opcode */, Register /* arg */, int16_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register Slli(Register /* arg */, int8_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register Srli(Register /* arg */, int8_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register Srai(Register /* arg */, int8_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register ShiftImm32(Decoder::ShiftImm32Opcode /* opcode */,
+                      Register /* arg */,
+                      uint16_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register Rori(Register /* arg */, int8_t /* shamt */) {
+    Unimplemented();
+    return {};
+  }
+  Register Roriw(Register /* arg */, int8_t /* shamt */) {
+    Unimplemented();
+    return {};
+  }
+  Register Lui(int32_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+  Register Auipc(int32_t /* imm */) {
+    Unimplemented();
+    return {};
+  }
+
+  Register Ecall(Register /* syscall_nr */,
+                 Register /* arg0 */,
+                 Register /* arg1 */,
+                 Register /* arg2 */,
+                 Register /* arg3 */,
+                 Register /* arg4 */,
+                 Register /* arg5 */) {
+    Unimplemented();
+    return {};
+  }
+
+  void Store(Decoder::StoreOperandType /* operand_type */,
+             Register /* arg */,
+             int16_t /* offset */,
+             Register /* data */) {
+    Unimplemented();
+  }
+  Register Load(Decoder::LoadOperandType /* operand_type */,
+                Register /* arg */,
+                int16_t /* offset */) {
+    Unimplemented();
+    return {};
+  }
+
+  //
+  // Atomic extensions.
+  //
+
+  template <typename IntType, bool aq, bool rl>
+  Register Lr(Register /* addr */) {
+    Unimplemented();
+    return {};
+  }
+
+  template <typename IntType, bool aq, bool rl>
+  Register Sc(Register /* addr */, Register /* data */) {
+    Unimplemented();
+    return {};
+  }
+
+  void Fence(Decoder::FenceOpcode /*opcode*/,
+             Register /*src*/,
+             bool sw,
+             bool sr,
+             bool /*so*/,
+             bool /*si*/,
+             bool pw,
+             bool pr,
+             bool /*po*/,
+             bool /*pi*/) {
+    UNUSED(sw, sr, pw, pr);
+    Unimplemented();
+  }
+
+  void FenceI(Register /*arg*/, int16_t /*imm*/) { Unimplemented(); }
+
+  //
+  // F and D extensions.
+  //
+  [[nodiscard]] FpRegister GetFpReg(uint8_t reg);
+
+  template <typename FloatType>
+  [[nodiscard]] FpRegister GetFRegAndUnboxNan(uint8_t reg) {
+    CHECK_LE(reg, kNumGuestFpRegs);
+    FpRegister result = AllocTempSimdReg();
+    builder_.GenGetSimd(result.machine_reg(), reg);
+    FpRegister unboxed_result = AllocTempSimdReg();
+    if (host_platform::kHasAVX) {
+      builder_.Gen<x86_64::MacroUnboxNanFloat32AVX>(unboxed_result.machine_reg(),
+                                                    result.machine_reg());
+    } else {
+      builder_.Gen<x86_64::MacroUnboxNanFloat32>(unboxed_result.machine_reg(),
+                                                 result.machine_reg());
+    }
+    return unboxed_result;
+  }
+
+  template <typename FloatType>
+  void NanBoxAndSetFpReg(uint8_t reg, FpRegister value) {
+    CHECK_LE(reg, kNumGuestFpRegs);
+    if (host_platform::kHasAVX) {
+      builder_.Gen<x86_64::MacroNanBoxFloat32AVX>(value.machine_reg(), value.machine_reg());
+    } else {
+      builder_.Gen<x86_64::MacroNanBoxFloat32>(value.machine_reg());
+    }
+
+    builder_.GenSetSimd(reg, value.machine_reg());
+  }
+
+  template <typename DataType>
+  FpRegister LoadFp(Register /* arg */, int16_t /* offset */) {
+    Unimplemented();
+    return {};
+  }
+
+  template <typename DataType>
+  void StoreFp(Register /* arg */, int16_t /* offset */, FpRegister /* data */) {
+    Unimplemented();
+  }
+
+  FpRegister Fmv(FpRegister /* arg */) {
+    Unimplemented();
+    return {};
+  }
+
+  //
+  // V extension.
+  //
+
+  template <typename VOpArgs, typename... ExtraAegs>
+  void OpVector(const VOpArgs& /*args*/, ExtraAegs... /*extra_args*/) {
+    // TODO(b/300690740): develop and implement strategy which would allow us to support vector
+    // intrinsics not just in the interpreter.
+    Unimplemented();
+  }
+
+  //
+  // Csr
+  //
+
+  Register UpdateCsr(Decoder::CsrOpcode /* opcode */, Register /* arg */, Register /* csr */) {
+    Unimplemented();
+    return {};
+  }
+
+  Register UpdateCsr(Decoder::CsrImmOpcode /* opcode */, uint8_t /* imm */, Register /* csr */) {
+    Unimplemented();
+    return {};
+  }
+
+  [[nodiscard]] bool success() const { return success_; }
 
   //
   // Intrinsic proxy methods.
@@ -86,6 +278,22 @@
     return branch_targets_;
   }
 
+  template <CsrName kName>
+  [[nodiscard]] Register GetCsr() {
+    Unimplemented();
+    return {};
+  }
+
+  template <CsrName kName>
+  void SetCsr(uint8_t /* imm */) {
+    Unimplemented();
+  }
+
+  template <CsrName kName>
+  void SetCsr(Register /* arg */) {
+    Unimplemented();
+  }
+
  private:
   // Specialization for AssemblerResType=void
   template <auto kFunction,
@@ -183,6 +391,7 @@
   }
 
   GuestAddr pc_;
+  bool success_;
   x86_64::MachineIRBuilder builder_;
   MachineReg flag_register_;
   bool is_uncond_branch_;