riscv64: add UNIMP instruction to the assembler.

This is useful for debugging purposes or as a guard for unimplemented
code.

Test: m test-art-host-gtest
Bug: 283082089
Change-Id: I6d95402cce8c1904f9801957bccb9e4ca74caee8
diff --git a/compiler/utils/riscv64/assembler_riscv64.cc b/compiler/utils/riscv64/assembler_riscv64.cc
index 98d2489..8cf33fc 100644
--- a/compiler/utils/riscv64/assembler_riscv64.cc
+++ b/compiler/utils/riscv64/assembler_riscv64.cc
@@ -1183,6 +1183,11 @@
   LoadLiteral(literal, rd, Branch::kLiteralDouble);
 }
 
+void Riscv64Assembler::Unimp() {
+  // TODO(riscv64): use 16-bit zero C.UNIMP once we support compression
+  Emit(0xC0001073);
+}
+
 /////////////////////////////// RV64 MACRO Instructions END ///////////////////////////////
 
 const Riscv64Assembler::Branch::BranchInfo Riscv64Assembler::Branch::branch_info_[] = {
diff --git a/compiler/utils/riscv64/assembler_riscv64.h b/compiler/utils/riscv64/assembler_riscv64.h
index 09bbef0..d94433f 100644
--- a/compiler/utils/riscv64/assembler_riscv64.h
+++ b/compiler/utils/riscv64/assembler_riscv64.h
@@ -559,6 +559,9 @@
   void FLoadw(FRegister rd, Literal* literal);
   void FLoadd(FRegister rd, Literal* literal);
 
+  // Illegal instruction that triggers SIGILL.
+  void Unimp();
+
   /////////////////////////////// RV64 MACRO Instructions END ///////////////////////////////
 
   void Bind(Label* label) override { Bind(down_cast<Riscv64Label*>(label)); }
diff --git a/compiler/utils/riscv64/assembler_riscv64_test.cc b/compiler/utils/riscv64/assembler_riscv64_test.cc
index b48b168..31f72ae 100644
--- a/compiler/utils/riscv64/assembler_riscv64_test.cc
+++ b/compiler/utils/riscv64/assembler_riscv64_test.cc
@@ -2328,6 +2328,11 @@
   TestFPLoadStoreArbitraryOffset("FStored", "fsd", &Riscv64Assembler::FStored);
 }
 
+TEST_F(AssemblerRISCV64Test, Unimp) {
+  __ Unimp();
+  DriverStr("unimp\n", "Unimp");
+}
+
 TEST_F(AssemblerRISCV64Test, LoadLabelAddress) {
   std::string expected;
   constexpr size_t kNumLoadsForward = 4 * KB;