Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Elliott <selliott@lowrisc.org>2019-12-16 19:35:17 +0300
committerSam Elliott <selliott@lowrisc.org>2019-12-16 19:36:56 +0300
commitce3d1c6d61dcd96f44492516f8b613bbcadaeb8e (patch)
tree297e688d1dee79660d1f06d9eecb12ab5e5a3952 /libunwind
parent055aeb5275153ee61ccd59cab2987fdcaca73756 (diff)
[libunwind][RISCV] Add 64-bit RISC-V support
Summary: Add unwinding support for 64-bit RISC-V. This is from the FreeBSD implementation with the following minor changes: - Renamed and renumbered DWARF registers to match the RISC-V ABI [1] - Use the ABI mneumonics in getRegisterName() instead of the exact register names - Include checks for __riscv_xlen == 64 to facilitate adding the 32-bit ABI in the future. [1] https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md Patch by Mitchell Horne (mhorne) Reviewers: lenary, luismarques, compnerd, phosek Reviewed By: lenary, luismarques Subscribers: arichardson, sameer.abuasal, abidh, asb, aprantl, krytarowski, simoncook, kito-cheng, christof, shiva0217, rogfer01, rkruppe, PkmX, psnobl, benna, lenary, s.egerton, luismarques, emaste, cfe-commits Differential Revision: https://reviews.llvm.org/D68362
Diffstat (limited to 'libunwind')
-rw-r--r--libunwind/include/__libunwind_config.h11
-rw-r--r--libunwind/include/libunwind.h71
-rw-r--r--libunwind/src/Registers.hpp265
-rw-r--r--libunwind/src/UnwindCursor.hpp18
-rw-r--r--libunwind/src/UnwindRegistersRestore.S81
-rw-r--r--libunwind/src/UnwindRegistersSave.S80
-rw-r--r--libunwind/src/config.h3
-rw-r--r--libunwind/src/libunwind.cpp2
8 files changed, 530 insertions, 1 deletions
diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h
index 6e7e5e6f7f86..4d03bd83d8c6 100644
--- a/libunwind/include/__libunwind_config.h
+++ b/libunwind/include/__libunwind_config.h
@@ -23,6 +23,7 @@
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# if defined(__i386__)
@@ -118,6 +119,15 @@
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
#define _LIBUNWIND_CONTEXT_SIZE 16
#define _LIBUNWIND_CURSOR_SIZE 23
+# elif defined(__riscv)
+# if __riscv_xlen == 64
+# define _LIBUNWIND_TARGET_RISCV 1
+# define _LIBUNWIND_CONTEXT_SIZE 64
+# define _LIBUNWIND_CURSOR_SIZE 76
+# else
+# error "Unsupported RISC-V ABI"
+# endif
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV
# else
# error "Unsupported architecture."
# endif
@@ -132,6 +142,7 @@
# define _LIBUNWIND_TARGET_MIPS_O32 1
# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
# define _LIBUNWIND_TARGET_SPARC 1
+# define _LIBUNWIND_TARGET_RISCV 1
# define _LIBUNWIND_CONTEXT_SIZE 167
# define _LIBUNWIND_CURSOR_SIZE 179
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h
index d06724d3c31f..1a501b867dda 100644
--- a/libunwind/include/libunwind.h
+++ b/libunwind/include/libunwind.h
@@ -832,4 +832,75 @@ enum {
UNW_SPARC_I7 = 31,
};
+// RISC-V registers. These match the DWARF register numbers defined by section
+// 4 of the RISC-V ELF psABI specification, which can be found at:
+//
+// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
+enum {
+ UNW_RISCV_X0 = 0,
+ UNW_RISCV_X1 = 1,
+ UNW_RISCV_X2 = 2,
+ UNW_RISCV_X3 = 3,
+ UNW_RISCV_X4 = 4,
+ UNW_RISCV_X5 = 5,
+ UNW_RISCV_X6 = 6,
+ UNW_RISCV_X7 = 7,
+ UNW_RISCV_X8 = 8,
+ UNW_RISCV_X9 = 9,
+ UNW_RISCV_X10 = 10,
+ UNW_RISCV_X11 = 11,
+ UNW_RISCV_X12 = 12,
+ UNW_RISCV_X13 = 13,
+ UNW_RISCV_X14 = 14,
+ UNW_RISCV_X15 = 15,
+ UNW_RISCV_X16 = 16,
+ UNW_RISCV_X17 = 17,
+ UNW_RISCV_X18 = 18,
+ UNW_RISCV_X19 = 19,
+ UNW_RISCV_X20 = 20,
+ UNW_RISCV_X21 = 21,
+ UNW_RISCV_X22 = 22,
+ UNW_RISCV_X23 = 23,
+ UNW_RISCV_X24 = 24,
+ UNW_RISCV_X25 = 25,
+ UNW_RISCV_X26 = 26,
+ UNW_RISCV_X27 = 27,
+ UNW_RISCV_X28 = 28,
+ UNW_RISCV_X29 = 29,
+ UNW_RISCV_X30 = 30,
+ UNW_RISCV_X31 = 31,
+ UNW_RISCV_F0 = 32,
+ UNW_RISCV_F1 = 33,
+ UNW_RISCV_F2 = 34,
+ UNW_RISCV_F3 = 35,
+ UNW_RISCV_F4 = 36,
+ UNW_RISCV_F5 = 37,
+ UNW_RISCV_F6 = 38,
+ UNW_RISCV_F7 = 39,
+ UNW_RISCV_F8 = 40,
+ UNW_RISCV_F9 = 41,
+ UNW_RISCV_F10 = 42,
+ UNW_RISCV_F11 = 43,
+ UNW_RISCV_F12 = 44,
+ UNW_RISCV_F13 = 45,
+ UNW_RISCV_F14 = 46,
+ UNW_RISCV_F15 = 47,
+ UNW_RISCV_F16 = 48,
+ UNW_RISCV_F17 = 49,
+ UNW_RISCV_F18 = 50,
+ UNW_RISCV_F19 = 51,
+ UNW_RISCV_F20 = 52,
+ UNW_RISCV_F21 = 53,
+ UNW_RISCV_F22 = 54,
+ UNW_RISCV_F23 = 55,
+ UNW_RISCV_F24 = 56,
+ UNW_RISCV_F25 = 57,
+ UNW_RISCV_F26 = 58,
+ UNW_RISCV_F27 = 59,
+ UNW_RISCV_F28 = 60,
+ UNW_RISCV_F29 = 61,
+ UNW_RISCV_F30 = 62,
+ UNW_RISCV_F31 = 63,
+};
+
#endif
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index a36c6cf90d3f..416ed61df74a 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -34,6 +34,7 @@ enum {
REGISTERS_MIPS_O32,
REGISTERS_MIPS_NEWABI,
REGISTERS_SPARC,
+ REGISTERS_RISCV,
};
#if defined(_LIBUNWIND_TARGET_I386)
@@ -3517,6 +3518,270 @@ inline const char *Registers_sparc::getRegisterName(int regNum) {
}
#endif // _LIBUNWIND_TARGET_SPARC
+#if defined(_LIBUNWIND_TARGET_RISCV)
+/// Registers_riscv holds the register state of a thread in a 64-bit RISC-V
+/// process.
+class _LIBUNWIND_HIDDEN Registers_riscv {
+public:
+ Registers_riscv();
+ Registers_riscv(const void *registers);
+
+ bool validRegister(int num) const;
+ uint64_t getRegister(int num) const;
+ void setRegister(int num, uint64_t value);
+ bool validFloatRegister(int num) const;
+ double getFloatRegister(int num) const;
+ void setFloatRegister(int num, double value);
+ bool validVectorRegister(int num) const;
+ v128 getVectorRegister(int num) const;
+ void setVectorRegister(int num, v128 value);
+ static const char *getRegisterName(int num);
+ void jumpto();
+ static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; }
+ static int getArch() { return REGISTERS_RISCV; }
+
+ uint64_t getSP() const { return _registers[2]; }
+ void setSP(uint64_t value) { _registers[2] = value; }
+ uint64_t getIP() const { return _registers[1]; }
+ void setIP(uint64_t value) { _registers[1] = value; }
+
+private:
+
+ uint64_t _registers[32];
+ double _floats[32];
+};
+
+inline Registers_riscv::Registers_riscv(const void *registers) {
+ static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),
+ "riscv registers do not fit into unw_context_t");
+ memcpy(&_registers, registers, sizeof(_registers));
+ static_assert(sizeof(_registers) == 0x100,
+ "expected float registers to be at offset 256");
+ memcpy(_floats,
+ static_cast<const uint8_t *>(registers) + sizeof(_registers),
+ sizeof(_floats));
+}
+
+inline Registers_riscv::Registers_riscv() {
+ memset(&_registers, 0, sizeof(_registers));
+ memset(&_floats, 0, sizeof(_floats));
+}
+
+inline bool Registers_riscv::validRegister(int regNum) const {
+ if (regNum == UNW_REG_IP)
+ return true;
+ if (regNum == UNW_REG_SP)
+ return true;
+ if (regNum < 0)
+ return false;
+ if (regNum > UNW_RISCV_F31)
+ return false;
+ return true;
+}
+
+inline uint64_t Registers_riscv::getRegister(int regNum) const {
+ if (regNum == UNW_REG_IP)
+ return _registers[1];
+ if (regNum == UNW_REG_SP)
+ return _registers[2];
+ if (regNum == UNW_RISCV_X0)
+ return 0;
+ if ((regNum > 0) && (regNum < 32))
+ return _registers[regNum];
+ _LIBUNWIND_ABORT("unsupported riscv register");
+}
+
+inline void Registers_riscv::setRegister(int regNum, uint64_t value) {
+ if (regNum == UNW_REG_IP)
+ _registers[1] = value;
+ else if (regNum == UNW_REG_SP)
+ _registers[2] = value;
+ else if (regNum == UNW_RISCV_X0)
+ /* x0 is hardwired to zero */
+ return;
+ else if ((regNum > 0) && (regNum < 32))
+ _registers[regNum] = value;
+ else
+ _LIBUNWIND_ABORT("unsupported riscv register");
+}
+
+inline const char *Registers_riscv::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return "pc";
+ case UNW_REG_SP:
+ return "sp";
+ case UNW_RISCV_X0:
+ return "zero";
+ case UNW_RISCV_X1:
+ return "ra";
+ case UNW_RISCV_X2:
+ return "sp";
+ case UNW_RISCV_X3:
+ return "gp";
+ case UNW_RISCV_X4:
+ return "tp";
+ case UNW_RISCV_X5:
+ return "t0";
+ case UNW_RISCV_X6:
+ return "t1";
+ case UNW_RISCV_X7:
+ return "t2";
+ case UNW_RISCV_X8:
+ return "s0";
+ case UNW_RISCV_X9:
+ return "s1";
+ case UNW_RISCV_X10:
+ return "a0";
+ case UNW_RISCV_X11:
+ return "a1";
+ case UNW_RISCV_X12:
+ return "a2";
+ case UNW_RISCV_X13:
+ return "a3";
+ case UNW_RISCV_X14:
+ return "a4";
+ case UNW_RISCV_X15:
+ return "a5";
+ case UNW_RISCV_X16:
+ return "a6";
+ case UNW_RISCV_X17:
+ return "a7";
+ case UNW_RISCV_X18:
+ return "s2";
+ case UNW_RISCV_X19:
+ return "s3";
+ case UNW_RISCV_X20:
+ return "s4";
+ case UNW_RISCV_X21:
+ return "s5";
+ case UNW_RISCV_X22:
+ return "s6";
+ case UNW_RISCV_X23:
+ return "s7";
+ case UNW_RISCV_X24:
+ return "s8";
+ case UNW_RISCV_X25:
+ return "s9";
+ case UNW_RISCV_X26:
+ return "s10";
+ case UNW_RISCV_X27:
+ return "s11";
+ case UNW_RISCV_X28:
+ return "t3";
+ case UNW_RISCV_X29:
+ return "t4";
+ case UNW_RISCV_X30:
+ return "t5";
+ case UNW_RISCV_X31:
+ return "t6";
+ case UNW_RISCV_F0:
+ return "ft0";
+ case UNW_RISCV_F1:
+ return "ft1";
+ case UNW_RISCV_F2:
+ return "ft2";
+ case UNW_RISCV_F3:
+ return "ft3";
+ case UNW_RISCV_F4:
+ return "ft4";
+ case UNW_RISCV_F5:
+ return "ft5";
+ case UNW_RISCV_F6:
+ return "ft6";
+ case UNW_RISCV_F7:
+ return "ft7";
+ case UNW_RISCV_F8:
+ return "fs0";
+ case UNW_RISCV_F9:
+ return "fs1";
+ case UNW_RISCV_F10:
+ return "fa0";
+ case UNW_RISCV_F11:
+ return "fa1";
+ case UNW_RISCV_F12:
+ return "fa2";
+ case UNW_RISCV_F13:
+ return "fa3";
+ case UNW_RISCV_F14:
+ return "fa4";
+ case UNW_RISCV_F15:
+ return "fa5";
+ case UNW_RISCV_F16:
+ return "fa6";
+ case UNW_RISCV_F17:
+ return "fa7";
+ case UNW_RISCV_F18:
+ return "fs2";
+ case UNW_RISCV_F19:
+ return "fs3";
+ case UNW_RISCV_F20:
+ return "fs4";
+ case UNW_RISCV_F21:
+ return "fs5";
+ case UNW_RISCV_F22:
+ return "fs6";
+ case UNW_RISCV_F23:
+ return "fs7";
+ case UNW_RISCV_F24:
+ return "fs8";
+ case UNW_RISCV_F25:
+ return "fs9";
+ case UNW_RISCV_F26:
+ return "fs10";
+ case UNW_RISCV_F27:
+ return "fs11";
+ case UNW_RISCV_F28:
+ return "ft8";
+ case UNW_RISCV_F29:
+ return "ft9";
+ case UNW_RISCV_F30:
+ return "ft10";
+ case UNW_RISCV_F31:
+ return "ft11";
+ default:
+ return "unknown register";
+ }
+}
+
+inline bool Registers_riscv::validFloatRegister(int regNum) const {
+ if (regNum < UNW_RISCV_F0)
+ return false;
+ if (regNum > UNW_RISCV_F31)
+ return false;
+ return true;
+}
+
+inline double Registers_riscv::getFloatRegister(int regNum) const {
+#if defined(__riscv_flen) && __riscv_flen == 64
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_RISCV_F0];
+#else
+ _LIBUNWIND_ABORT("libunwind not built with float support");
+#endif
+}
+
+inline void Registers_riscv::setFloatRegister(int regNum, double value) {
+#if defined(__riscv_flen) && __riscv_flen == 64
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_RISCV_F0] = value;
+#else
+ _LIBUNWIND_ABORT("libunwind not built with float support");
+#endif
+}
+
+inline bool Registers_riscv::validVectorRegister(int) const {
+ return false;
+}
+
+inline v128 Registers_riscv::getVectorRegister(int) const {
+ _LIBUNWIND_ABORT("no riscv vector register support yet");
+}
+
+inline void Registers_riscv::setVectorRegister(int, v128) {
+ _LIBUNWIND_ABORT("no riscv vector register support yet");
+}
+#endif // _LIBUNWIND_TARGET_RISCV
} // namespace libunwind
#endif // __REGISTERS_HPP__
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 4c18614b33d2..31be8366d238 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -995,6 +995,12 @@ private:
int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
#endif
+#if defined (_LIBUNWIND_TARGET_RISCV)
+ int stepWithCompactEncoding(Registers_riscv &) {
+ return UNW_EINVAL;
+ }
+#endif
+
bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
R dummy;
return compactSaysUseDwarf(dummy, offset);
@@ -1061,6 +1067,12 @@ private:
bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
#endif
+#if defined (_LIBUNWIND_TARGET_RISCV)
+ bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const {
+ return true;
+ }
+#endif
+
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -1127,6 +1139,12 @@ private:
compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
#endif
+#if defined (_LIBUNWIND_TARGET_RISCV)
+ compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const {
+ return 0;
+ }
+#endif
+
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 8122bf3e1b2e..cbb2fd447005 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -1029,6 +1029,87 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
jmp %o7
nop
+#elif defined(__riscv) && __riscv_xlen == 64
+
+//
+// void libunwind::Registers_riscv::jumpto()
+//
+// On entry:
+// thread_state pointer is in a0
+//
+ .p2align 2
+DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
+#if defined(__riscv_flen) && __riscv_flen == 64
+ fld f0, (8 * 32 + 8 * 0)(a0)
+ fld f1, (8 * 32 + 8 * 1)(a0)
+ fld f2, (8 * 32 + 8 * 2)(a0)
+ fld f3, (8 * 32 + 8 * 3)(a0)
+ fld f4, (8 * 32 + 8 * 4)(a0)
+ fld f5, (8 * 32 + 8 * 5)(a0)
+ fld f6, (8 * 32 + 8 * 6)(a0)
+ fld f7, (8 * 32 + 8 * 7)(a0)
+ fld f8, (8 * 32 + 8 * 8)(a0)
+ fld f9, (8 * 32 + 8 * 9)(a0)
+ fld f10, (8 * 32 + 8 * 10)(a0)
+ fld f11, (8 * 32 + 8 * 11)(a0)
+ fld f12, (8 * 32 + 8 * 12)(a0)
+ fld f13, (8 * 32 + 8 * 13)(a0)
+ fld f14, (8 * 32 + 8 * 14)(a0)
+ fld f15, (8 * 32 + 8 * 15)(a0)
+ fld f16, (8 * 32 + 8 * 16)(a0)
+ fld f17, (8 * 32 + 8 * 17)(a0)
+ fld f18, (8 * 32 + 8 * 18)(a0)
+ fld f19, (8 * 32 + 8 * 19)(a0)
+ fld f20, (8 * 32 + 8 * 20)(a0)
+ fld f21, (8 * 32 + 8 * 21)(a0)
+ fld f22, (8 * 32 + 8 * 22)(a0)
+ fld f23, (8 * 32 + 8 * 23)(a0)
+ fld f24, (8 * 32 + 8 * 24)(a0)
+ fld f25, (8 * 32 + 8 * 25)(a0)
+ fld f26, (8 * 32 + 8 * 26)(a0)
+ fld f27, (8 * 32 + 8 * 27)(a0)
+ fld f28, (8 * 32 + 8 * 28)(a0)
+ fld f29, (8 * 32 + 8 * 29)(a0)
+ fld f30, (8 * 32 + 8 * 30)(a0)
+ fld f31, (8 * 32 + 8 * 31)(a0)
+#endif
+
+ // x0 is zero
+ ld x1, (8 * 1)(a0)
+ ld x2, (8 * 2)(a0)
+ ld x3, (8 * 3)(a0)
+ ld x4, (8 * 4)(a0)
+ ld x5, (8 * 5)(a0)
+ ld x6, (8 * 6)(a0)
+ ld x7, (8 * 7)(a0)
+ ld x8, (8 * 8)(a0)
+ ld x9, (8 * 9)(a0)
+ // skip a0 for now
+ ld x11, (8 * 11)(a0)
+ ld x12, (8 * 12)(a0)
+ ld x13, (8 * 13)(a0)
+ ld x14, (8 * 14)(a0)
+ ld x15, (8 * 15)(a0)
+ ld x16, (8 * 16)(a0)
+ ld x17, (8 * 17)(a0)
+ ld x18, (8 * 18)(a0)
+ ld x19, (8 * 19)(a0)
+ ld x20, (8 * 20)(a0)
+ ld x21, (8 * 21)(a0)
+ ld x22, (8 * 22)(a0)
+ ld x23, (8 * 23)(a0)
+ ld x24, (8 * 24)(a0)
+ ld x25, (8 * 25)(a0)
+ ld x26, (8 * 26)(a0)
+ ld x27, (8 * 27)(a0)
+ ld x28, (8 * 28)(a0)
+ ld x29, (8 * 29)(a0)
+ ld x30, (8 * 30)(a0)
+ ld x31, (8 * 31)(a0)
+ ld x10, (8 * 10)(a0) // restore a0
+
+ ret // jump to ra
+
#endif
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index 54505e53bac7..da91abc233de 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -974,6 +974,86 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
std %i6, [%o0 + 120]
jmp %o7
clr %o0 // return UNW_ESUCCESS
+
+#elif defined(__riscv) && __riscv_xlen == 64
+
+#
+# extern int __unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+# thread_state pointer is in a0
+#
+DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
+ // x0 is zero
+ sd x1, (8 * 1)(a0)
+ sd x2, (8 * 2)(a0)
+ sd x3, (8 * 3)(a0)
+ sd x4, (8 * 4)(a0)
+ sd x5, (8 * 5)(a0)
+ sd x6, (8 * 6)(a0)
+ sd x7, (8 * 7)(a0)
+ sd x8, (8 * 8)(a0)
+ sd x9, (8 * 9)(a0)
+ sd x10, (8 * 10)(a0)
+ sd x11, (8 * 11)(a0)
+ sd x12, (8 * 12)(a0)
+ sd x13, (8 * 13)(a0)
+ sd x14, (8 * 14)(a0)
+ sd x15, (8 * 15)(a0)
+ sd x16, (8 * 16)(a0)
+ sd x17, (8 * 17)(a0)
+ sd x18, (8 * 18)(a0)
+ sd x19, (8 * 19)(a0)
+ sd x20, (8 * 20)(a0)
+ sd x21, (8 * 21)(a0)
+ sd x22, (8 * 22)(a0)
+ sd x23, (8 * 23)(a0)
+ sd x24, (8 * 24)(a0)
+ sd x25, (8 * 25)(a0)
+ sd x26, (8 * 26)(a0)
+ sd x27, (8 * 27)(a0)
+ sd x28, (8 * 28)(a0)
+ sd x29, (8 * 29)(a0)
+ sd x30, (8 * 30)(a0)
+ sd x31, (8 * 31)(a0)
+
+#if defined(__riscv_flen) && __riscv_flen == 64
+ fsd f0, (8 * 32 + 8 * 0)(a0)
+ fsd f1, (8 * 32 + 8 * 1)(a0)
+ fsd f2, (8 * 32 + 8 * 2)(a0)
+ fsd f3, (8 * 32 + 8 * 3)(a0)
+ fsd f4, (8 * 32 + 8 * 4)(a0)
+ fsd f5, (8 * 32 + 8 * 5)(a0)
+ fsd f6, (8 * 32 + 8 * 6)(a0)
+ fsd f7, (8 * 32 + 8 * 7)(a0)
+ fsd f8, (8 * 32 + 8 * 8)(a0)
+ fsd f9, (8 * 32 + 8 * 9)(a0)
+ fsd f10, (8 * 32 + 8 * 10)(a0)
+ fsd f11, (8 * 32 + 8 * 11)(a0)
+ fsd f12, (8 * 32 + 8 * 12)(a0)
+ fsd f13, (8 * 32 + 8 * 13)(a0)
+ fsd f14, (8 * 32 + 8 * 14)(a0)
+ fsd f15, (8 * 32 + 8 * 15)(a0)
+ fsd f16, (8 * 32 + 8 * 16)(a0)
+ fsd f17, (8 * 32 + 8 * 17)(a0)
+ fsd f18, (8 * 32 + 8 * 18)(a0)
+ fsd f19, (8 * 32 + 8 * 19)(a0)
+ fsd f20, (8 * 32 + 8 * 20)(a0)
+ fsd f21, (8 * 32 + 8 * 21)(a0)
+ fsd f22, (8 * 32 + 8 * 22)(a0)
+ fsd f23, (8 * 32 + 8 * 23)(a0)
+ fsd f24, (8 * 32 + 8 * 24)(a0)
+ fsd f25, (8 * 32 + 8 * 25)(a0)
+ fsd f26, (8 * 32 + 8 * 26)(a0)
+ fsd f27, (8 * 32 + 8 * 27)(a0)
+ fsd f28, (8 * 32 + 8 * 28)(a0)
+ fsd f29, (8 * 32 + 8 * 29)(a0)
+ fsd f30, (8 * 32 + 8 * 30)(a0)
+ fsd f31, (8 * 32 + 8 * 31)(a0)
+#endif
+
+ li a0, 0 // return UNW_ESUCCESS
+ ret // jump to ra
#endif
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
diff --git a/libunwind/src/config.h b/libunwind/src/config.h
index 09bb261647ca..dcd3cef94552 100644
--- a/libunwind/src/config.h
+++ b/libunwind/src/config.h
@@ -103,7 +103,8 @@
defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
(!defined(__APPLE__) && defined(__arm__)) || \
(defined(__arm64__) || defined(__aarch64__)) || \
- defined(__mips__)
+ defined(__mips__) || \
+ defined(__riscv)
#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
#define _LIBUNWIND_BUILD_ZERO_COST_APIS
#endif
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index 31f30f5cd709..1ee58ad1971e 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -58,6 +58,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
# warning The MIPS architecture is not supported with this ABI and environment!
#elif defined(__sparc__)
# define REGISTER_KIND Registers_sparc
+#elif defined(__riscv) && __riscv_xlen == 64
+# define REGISTER_KIND Registers_riscv
#else
# error Architecture not supported
#endif