mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
[libunwind][LoongArch] Add 64-bit LoongArch support
Defines enums for the LoongArch registers. Adds the register class implementation for LoongArch. Adds save and restore context functionality. This only supports 64 bits integer and float-point register implementation. Fix https://github.com/llvm/llvm-project/issues/55398 Reviewed By: SixWeining Differential Revision: https://reviews.llvm.org/D137010
This commit is contained in:
parent
25dcca60f4
commit
c507269512
@ -30,6 +30,7 @@
|
||||
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64
|
||||
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143
|
||||
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83
|
||||
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH 64
|
||||
|
||||
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
|
||||
# if defined(__linux__)
|
||||
@ -166,6 +167,16 @@
|
||||
# define _LIBUNWIND_CONTEXT_SIZE 34
|
||||
# define _LIBUNWIND_CURSOR_SIZE 46
|
||||
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X
|
||||
#elif defined(__loongarch__)
|
||||
#define _LIBUNWIND_TARGET_LOONGARCH 1
|
||||
#if __loongarch_grlen == 64
|
||||
#define _LIBUNWIND_CONTEXT_SIZE 65
|
||||
#define _LIBUNWIND_CURSOR_SIZE 77
|
||||
#else
|
||||
#error "Unsupported LoongArch ABI"
|
||||
#endif
|
||||
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER \
|
||||
_LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH
|
||||
# else
|
||||
# error "Unsupported architecture."
|
||||
# endif
|
||||
@ -185,6 +196,7 @@
|
||||
# define _LIBUNWIND_TARGET_RISCV 1
|
||||
# define _LIBUNWIND_TARGET_VE 1
|
||||
# define _LIBUNWIND_TARGET_S390X 1
|
||||
#define _LIBUNWIND_TARGET_LOONGARCH 1
|
||||
# define _LIBUNWIND_CONTEXT_SIZE 167
|
||||
# define _LIBUNWIND_CURSOR_SIZE 179
|
||||
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
|
||||
|
@ -1219,4 +1219,72 @@ enum {
|
||||
// 68-83 Vector Registers %v16-%v31
|
||||
};
|
||||
|
||||
// LoongArch registers.
|
||||
enum {
|
||||
UNW_LOONGARCH_R0 = 0,
|
||||
UNW_LOONGARCH_R1 = 1,
|
||||
UNW_LOONGARCH_R2 = 2,
|
||||
UNW_LOONGARCH_R3 = 3,
|
||||
UNW_LOONGARCH_R4 = 4,
|
||||
UNW_LOONGARCH_R5 = 5,
|
||||
UNW_LOONGARCH_R6 = 6,
|
||||
UNW_LOONGARCH_R7 = 7,
|
||||
UNW_LOONGARCH_R8 = 8,
|
||||
UNW_LOONGARCH_R9 = 9,
|
||||
UNW_LOONGARCH_R10 = 10,
|
||||
UNW_LOONGARCH_R11 = 11,
|
||||
UNW_LOONGARCH_R12 = 12,
|
||||
UNW_LOONGARCH_R13 = 13,
|
||||
UNW_LOONGARCH_R14 = 14,
|
||||
UNW_LOONGARCH_R15 = 15,
|
||||
UNW_LOONGARCH_R16 = 16,
|
||||
UNW_LOONGARCH_R17 = 17,
|
||||
UNW_LOONGARCH_R18 = 18,
|
||||
UNW_LOONGARCH_R19 = 19,
|
||||
UNW_LOONGARCH_R20 = 20,
|
||||
UNW_LOONGARCH_R21 = 21,
|
||||
UNW_LOONGARCH_R22 = 22,
|
||||
UNW_LOONGARCH_R23 = 23,
|
||||
UNW_LOONGARCH_R24 = 24,
|
||||
UNW_LOONGARCH_R25 = 25,
|
||||
UNW_LOONGARCH_R26 = 26,
|
||||
UNW_LOONGARCH_R27 = 27,
|
||||
UNW_LOONGARCH_R28 = 28,
|
||||
UNW_LOONGARCH_R29 = 29,
|
||||
UNW_LOONGARCH_R30 = 30,
|
||||
UNW_LOONGARCH_R31 = 31,
|
||||
UNW_LOONGARCH_F0 = 32,
|
||||
UNW_LOONGARCH_F1 = 33,
|
||||
UNW_LOONGARCH_F2 = 34,
|
||||
UNW_LOONGARCH_F3 = 35,
|
||||
UNW_LOONGARCH_F4 = 36,
|
||||
UNW_LOONGARCH_F5 = 37,
|
||||
UNW_LOONGARCH_F6 = 38,
|
||||
UNW_LOONGARCH_F7 = 39,
|
||||
UNW_LOONGARCH_F8 = 40,
|
||||
UNW_LOONGARCH_F9 = 41,
|
||||
UNW_LOONGARCH_F10 = 42,
|
||||
UNW_LOONGARCH_F11 = 43,
|
||||
UNW_LOONGARCH_F12 = 44,
|
||||
UNW_LOONGARCH_F13 = 45,
|
||||
UNW_LOONGARCH_F14 = 46,
|
||||
UNW_LOONGARCH_F15 = 47,
|
||||
UNW_LOONGARCH_F16 = 48,
|
||||
UNW_LOONGARCH_F17 = 49,
|
||||
UNW_LOONGARCH_F18 = 50,
|
||||
UNW_LOONGARCH_F19 = 51,
|
||||
UNW_LOONGARCH_F20 = 52,
|
||||
UNW_LOONGARCH_F21 = 53,
|
||||
UNW_LOONGARCH_F22 = 54,
|
||||
UNW_LOONGARCH_F23 = 55,
|
||||
UNW_LOONGARCH_F24 = 56,
|
||||
UNW_LOONGARCH_F25 = 57,
|
||||
UNW_LOONGARCH_F26 = 58,
|
||||
UNW_LOONGARCH_F27 = 59,
|
||||
UNW_LOONGARCH_F28 = 60,
|
||||
UNW_LOONGARCH_F29 = 61,
|
||||
UNW_LOONGARCH_F30 = 62,
|
||||
UNW_LOONGARCH_F31 = 63,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -40,6 +40,7 @@ enum {
|
||||
REGISTERS_RISCV,
|
||||
REGISTERS_VE,
|
||||
REGISTERS_S390X,
|
||||
REGISTERS_LOONGARCH,
|
||||
};
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_I386)
|
||||
@ -5031,6 +5032,271 @@ inline const char *Registers_s390x::getRegisterName(int regNum) {
|
||||
}
|
||||
#endif // _LIBUNWIND_TARGET_S390X
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
/// Registers_loongarch holds the register state of a thread in a 64-bit
|
||||
/// LoongArch process.
|
||||
class _LIBUNWIND_HIDDEN Registers_loongarch {
|
||||
public:
|
||||
Registers_loongarch();
|
||||
Registers_loongarch(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 constexpr int lastDwarfRegNum() {
|
||||
return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;
|
||||
}
|
||||
static int getArch() { return REGISTERS_LOONGARCH; }
|
||||
|
||||
uint64_t getSP() const { return _registers.__r[3]; }
|
||||
void setSP(uint64_t value) { _registers.__r[3] = value; }
|
||||
uint64_t getIP() const { return _registers.__pc; }
|
||||
void setIP(uint64_t value) { _registers.__pc = value; }
|
||||
|
||||
private:
|
||||
struct loongarch_thread_state_t {
|
||||
uint64_t __r[32];
|
||||
uint64_t __pc;
|
||||
};
|
||||
|
||||
loongarch_thread_state_t _registers;
|
||||
#if __loongarch_frlen == 64
|
||||
double _floats[32];
|
||||
#endif
|
||||
};
|
||||
|
||||
inline Registers_loongarch::Registers_loongarch(const void *registers) {
|
||||
static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),
|
||||
"loongarch registers do not fit into unw_context_t");
|
||||
memcpy(&_registers, registers, sizeof(_registers));
|
||||
static_assert(sizeof(_registers) == 0x108,
|
||||
"expected float registers to be at offset 264");
|
||||
#if __loongarch_frlen == 64
|
||||
memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),
|
||||
sizeof(_floats));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Registers_loongarch::Registers_loongarch() {
|
||||
memset(&_registers, 0, sizeof(_registers));
|
||||
#if __loongarch_frlen == 64
|
||||
memset(&_floats, 0, sizeof(_floats));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool Registers_loongarch::validRegister(int regNum) const {
|
||||
if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
|
||||
return true;
|
||||
if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline uint64_t Registers_loongarch::getRegister(int regNum) const {
|
||||
if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
|
||||
return _registers.__r[regNum - UNW_LOONGARCH_R0];
|
||||
|
||||
if (regNum == UNW_REG_IP)
|
||||
return _registers.__pc;
|
||||
if (regNum == UNW_REG_SP)
|
||||
return _registers.__r[3];
|
||||
_LIBUNWIND_ABORT("unsupported loongarch register");
|
||||
}
|
||||
|
||||
inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {
|
||||
if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
|
||||
_registers.__r[regNum - UNW_LOONGARCH_R0] = value;
|
||||
else if (regNum == UNW_REG_IP)
|
||||
_registers.__pc = value;
|
||||
else if (regNum == UNW_REG_SP)
|
||||
_registers.__r[3] = value;
|
||||
else
|
||||
_LIBUNWIND_ABORT("unsupported loongarch register");
|
||||
}
|
||||
|
||||
inline const char *Registers_loongarch::getRegisterName(int regNum) {
|
||||
switch (regNum) {
|
||||
case UNW_REG_IP:
|
||||
return "$pc";
|
||||
case UNW_REG_SP:
|
||||
return "$sp";
|
||||
case UNW_LOONGARCH_R0:
|
||||
return "$r0";
|
||||
case UNW_LOONGARCH_R1:
|
||||
return "$r1";
|
||||
case UNW_LOONGARCH_R2:
|
||||
return "$r2";
|
||||
case UNW_LOONGARCH_R3:
|
||||
return "$r3";
|
||||
case UNW_LOONGARCH_R4:
|
||||
return "$r4";
|
||||
case UNW_LOONGARCH_R5:
|
||||
return "$r5";
|
||||
case UNW_LOONGARCH_R6:
|
||||
return "$r6";
|
||||
case UNW_LOONGARCH_R7:
|
||||
return "$r7";
|
||||
case UNW_LOONGARCH_R8:
|
||||
return "$r8";
|
||||
case UNW_LOONGARCH_R9:
|
||||
return "$r9";
|
||||
case UNW_LOONGARCH_R10:
|
||||
return "$r10";
|
||||
case UNW_LOONGARCH_R11:
|
||||
return "$r11";
|
||||
case UNW_LOONGARCH_R12:
|
||||
return "$r12";
|
||||
case UNW_LOONGARCH_R13:
|
||||
return "$r13";
|
||||
case UNW_LOONGARCH_R14:
|
||||
return "$r14";
|
||||
case UNW_LOONGARCH_R15:
|
||||
return "$r15";
|
||||
case UNW_LOONGARCH_R16:
|
||||
return "$r16";
|
||||
case UNW_LOONGARCH_R17:
|
||||
return "$r17";
|
||||
case UNW_LOONGARCH_R18:
|
||||
return "$r18";
|
||||
case UNW_LOONGARCH_R19:
|
||||
return "$r19";
|
||||
case UNW_LOONGARCH_R20:
|
||||
return "$r20";
|
||||
case UNW_LOONGARCH_R21:
|
||||
return "$r21";
|
||||
case UNW_LOONGARCH_R22:
|
||||
return "$r22";
|
||||
case UNW_LOONGARCH_R23:
|
||||
return "$r23";
|
||||
case UNW_LOONGARCH_R24:
|
||||
return "$r24";
|
||||
case UNW_LOONGARCH_R25:
|
||||
return "$r25";
|
||||
case UNW_LOONGARCH_R26:
|
||||
return "$r26";
|
||||
case UNW_LOONGARCH_R27:
|
||||
return "$r27";
|
||||
case UNW_LOONGARCH_R28:
|
||||
return "$r28";
|
||||
case UNW_LOONGARCH_R29:
|
||||
return "$r29";
|
||||
case UNW_LOONGARCH_R30:
|
||||
return "$r30";
|
||||
case UNW_LOONGARCH_R31:
|
||||
return "$r31";
|
||||
case UNW_LOONGARCH_F0:
|
||||
return "$f0";
|
||||
case UNW_LOONGARCH_F1:
|
||||
return "$f1";
|
||||
case UNW_LOONGARCH_F2:
|
||||
return "$f2";
|
||||
case UNW_LOONGARCH_F3:
|
||||
return "$f3";
|
||||
case UNW_LOONGARCH_F4:
|
||||
return "$f4";
|
||||
case UNW_LOONGARCH_F5:
|
||||
return "$f5";
|
||||
case UNW_LOONGARCH_F6:
|
||||
return "$f6";
|
||||
case UNW_LOONGARCH_F7:
|
||||
return "$f7";
|
||||
case UNW_LOONGARCH_F8:
|
||||
return "$f8";
|
||||
case UNW_LOONGARCH_F9:
|
||||
return "$f9";
|
||||
case UNW_LOONGARCH_F10:
|
||||
return "$f10";
|
||||
case UNW_LOONGARCH_F11:
|
||||
return "$f11";
|
||||
case UNW_LOONGARCH_F12:
|
||||
return "$f12";
|
||||
case UNW_LOONGARCH_F13:
|
||||
return "$f13";
|
||||
case UNW_LOONGARCH_F14:
|
||||
return "$f14";
|
||||
case UNW_LOONGARCH_F15:
|
||||
return "$f15";
|
||||
case UNW_LOONGARCH_F16:
|
||||
return "$f16";
|
||||
case UNW_LOONGARCH_F17:
|
||||
return "$f17";
|
||||
case UNW_LOONGARCH_F18:
|
||||
return "$f18";
|
||||
case UNW_LOONGARCH_F19:
|
||||
return "$f19";
|
||||
case UNW_LOONGARCH_F20:
|
||||
return "$f20";
|
||||
case UNW_LOONGARCH_F21:
|
||||
return "$f21";
|
||||
case UNW_LOONGARCH_F22:
|
||||
return "$f22";
|
||||
case UNW_LOONGARCH_F23:
|
||||
return "$f23";
|
||||
case UNW_LOONGARCH_F24:
|
||||
return "$f24";
|
||||
case UNW_LOONGARCH_F25:
|
||||
return "$f25";
|
||||
case UNW_LOONGARCH_F26:
|
||||
return "$f26";
|
||||
case UNW_LOONGARCH_F27:
|
||||
return "$f27";
|
||||
case UNW_LOONGARCH_F28:
|
||||
return "$f28";
|
||||
case UNW_LOONGARCH_F29:
|
||||
return "$f29";
|
||||
case UNW_LOONGARCH_F30:
|
||||
return "$f30";
|
||||
case UNW_LOONGARCH_F31:
|
||||
return "$f31";
|
||||
default:
|
||||
return "unknown register";
|
||||
}
|
||||
}
|
||||
|
||||
inline bool Registers_loongarch::validFloatRegister(int regNum) const {
|
||||
if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline double Registers_loongarch::getFloatRegister(int regNum) const {
|
||||
#if __loongarch_frlen == 64
|
||||
assert(validFloatRegister(regNum));
|
||||
return _floats[regNum - UNW_LOONGARCH_F0];
|
||||
#else
|
||||
_LIBUNWIND_ABORT("libunwind not built with float support");
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void Registers_loongarch::setFloatRegister(int regNum, double value) {
|
||||
#if __loongarch_frlen == 64
|
||||
assert(validFloatRegister(regNum));
|
||||
_floats[regNum - UNW_LOONGARCH_F0] = value;
|
||||
#else
|
||||
_LIBUNWIND_ABORT("libunwind not built with float support");
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool Registers_loongarch::validVectorRegister(int) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline v128 Registers_loongarch::getVectorRegister(int) const {
|
||||
_LIBUNWIND_ABORT("loongarch vector support not implemented");
|
||||
}
|
||||
|
||||
inline void Registers_loongarch::setVectorRegister(int, v128) {
|
||||
_LIBUNWIND_ABORT("loongarch vector support not implemented");
|
||||
}
|
||||
#endif //_LIBUNWIND_TARGET_LOONGARCH
|
||||
|
||||
} // namespace libunwind
|
||||
|
||||
|
@ -1064,6 +1064,10 @@ private:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; }
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_SPARC)
|
||||
int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
|
||||
#endif
|
||||
@ -1140,6 +1144,12 @@ private:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_SPARC)
|
||||
bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
|
||||
#endif
|
||||
@ -1224,6 +1234,12 @@ private:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_SPARC)
|
||||
compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
|
||||
#endif
|
||||
|
@ -1289,6 +1289,88 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv)
|
||||
// Return to PSWA (was loaded into %r1 above)
|
||||
br %r1
|
||||
|
||||
#elif defined(__loongarch__) && __loongarch_grlen == 64
|
||||
|
||||
//
|
||||
// void libunwind::Registers_loongarch::jumpto()
|
||||
//
|
||||
// On entry:
|
||||
// thread_state pointer is in $a0($r4)
|
||||
//
|
||||
.p2align 2
|
||||
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
|
||||
# if __loongarch_frlen == 64
|
||||
fld.d $f0, $a0, (8 * 33 + 8 * 0)
|
||||
fld.d $f1, $a0, (8 * 33 + 8 * 1)
|
||||
fld.d $f2, $a0, (8 * 33 + 8 * 2)
|
||||
fld.d $f3, $a0, (8 * 33 + 8 * 3)
|
||||
fld.d $f4, $a0, (8 * 33 + 8 * 4)
|
||||
fld.d $f5, $a0, (8 * 33 + 8 * 5)
|
||||
fld.d $f6, $a0, (8 * 33 + 8 * 6)
|
||||
fld.d $f7, $a0, (8 * 33 + 8 * 7)
|
||||
fld.d $f8, $a0, (8 * 33 + 8 * 8)
|
||||
fld.d $f9, $a0, (8 * 33 + 8 * 9)
|
||||
fld.d $f10, $a0, (8 * 33 + 8 * 10)
|
||||
fld.d $f11, $a0, (8 * 33 + 8 * 11)
|
||||
fld.d $f12, $a0, (8 * 33 + 8 * 12)
|
||||
fld.d $f13, $a0, (8 * 33 + 8 * 13)
|
||||
fld.d $f14, $a0, (8 * 33 + 8 * 14)
|
||||
fld.d $f15, $a0, (8 * 33 + 8 * 15)
|
||||
fld.d $f16, $a0, (8 * 33 + 8 * 16)
|
||||
fld.d $f17, $a0, (8 * 33 + 8 * 17)
|
||||
fld.d $f18, $a0, (8 * 33 + 8 * 18)
|
||||
fld.d $f19, $a0, (8 * 33 + 8 * 19)
|
||||
fld.d $f20, $a0, (8 * 33 + 8 * 20)
|
||||
fld.d $f21, $a0, (8 * 33 + 8 * 21)
|
||||
fld.d $f22, $a0, (8 * 33 + 8 * 22)
|
||||
fld.d $f23, $a0, (8 * 33 + 8 * 23)
|
||||
fld.d $f24, $a0, (8 * 33 + 8 * 24)
|
||||
fld.d $f25, $a0, (8 * 33 + 8 * 25)
|
||||
fld.d $f26, $a0, (8 * 33 + 8 * 26)
|
||||
fld.d $f27, $a0, (8 * 33 + 8 * 27)
|
||||
fld.d $f28, $a0, (8 * 33 + 8 * 28)
|
||||
fld.d $f29, $a0, (8 * 33 + 8 * 29)
|
||||
fld.d $f30, $a0, (8 * 33 + 8 * 30)
|
||||
fld.d $f31, $a0, (8 * 33 + 8 * 31)
|
||||
# endif
|
||||
|
||||
// $r0 is zero
|
||||
ld.d $r1, $a0, (8 * 1)
|
||||
ld.d $r2, $a0, (8 * 2)
|
||||
ld.d $r3, $a0, (8 * 3)
|
||||
// skip $a0 for now
|
||||
ld.d $r5, $a0, (8 * 5)
|
||||
ld.d $r6, $a0, (8 * 6)
|
||||
ld.d $r7, $a0, (8 * 7)
|
||||
ld.d $r8, $a0, (8 * 8)
|
||||
ld.d $r9, $a0, (8 * 9)
|
||||
ld.d $r10, $a0, (8 * 10)
|
||||
ld.d $r11, $a0, (8 * 11)
|
||||
ld.d $r12, $a0, (8 * 12)
|
||||
ld.d $r13, $a0, (8 * 13)
|
||||
ld.d $r14, $a0, (8 * 14)
|
||||
ld.d $r15, $a0, (8 * 15)
|
||||
ld.d $r16, $a0, (8 * 16)
|
||||
ld.d $r17, $a0, (8 * 17)
|
||||
ld.d $r18, $a0, (8 * 18)
|
||||
ld.d $r19, $a0, (8 * 19)
|
||||
ld.d $r20, $a0, (8 * 20)
|
||||
ld.d $r21, $a0, (8 * 21)
|
||||
ld.d $r22, $a0, (8 * 22)
|
||||
ld.d $r23, $a0, (8 * 23)
|
||||
ld.d $r24, $a0, (8 * 24)
|
||||
ld.d $r25, $a0, (8 * 25)
|
||||
ld.d $r26, $a0, (8 * 26)
|
||||
ld.d $r27, $a0, (8 * 27)
|
||||
ld.d $r28, $a0, (8 * 28)
|
||||
ld.d $r29, $a0, (8 * 29)
|
||||
ld.d $r30, $a0, (8 * 30)
|
||||
ld.d $r31, $a0, (8 * 31)
|
||||
ld.d $r4, $a0, (8 * 4) // restore $a0 last
|
||||
ld.d $r1, $a0, (8 * 32) // load new pc into $ra
|
||||
|
||||
jr $ra
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
|
||||
|
@ -1222,6 +1222,86 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
|
||||
lghi %r2, 0
|
||||
br %r14
|
||||
|
||||
#elif defined(__loongarch__) && __loongarch_grlen == 64
|
||||
|
||||
#
|
||||
# extern int __unw_getcontext(unw_context_t* thread_state)
|
||||
#
|
||||
# On entry:
|
||||
# thread_state pointer is in $a0($r4)
|
||||
#
|
||||
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
|
||||
st.d $r1, $a0, (8 * 1)
|
||||
st.d $r2, $a0, (8 * 2)
|
||||
st.d $r3, $a0, (8 * 3)
|
||||
st.d $r4, $a0, (8 * 4)
|
||||
st.d $r5, $a0, (8 * 5)
|
||||
st.d $r6, $a0, (8 * 6)
|
||||
st.d $r7, $a0, (8 * 7)
|
||||
st.d $r8, $a0, (8 * 8)
|
||||
st.d $r9, $a0, (8 * 9)
|
||||
st.d $r10, $a0, (8 * 10)
|
||||
st.d $r11, $a0, (8 * 11)
|
||||
st.d $r12, $a0, (8 * 12)
|
||||
st.d $r13, $a0, (8 * 13)
|
||||
st.d $r14, $a0, (8 * 14)
|
||||
st.d $r15, $a0, (8 * 15)
|
||||
st.d $r16, $a0, (8 * 16)
|
||||
st.d $r17, $a0, (8 * 17)
|
||||
st.d $r18, $a0, (8 * 18)
|
||||
st.d $r19, $a0, (8 * 19)
|
||||
st.d $r20, $a0, (8 * 20)
|
||||
st.d $r21, $a0, (8 * 21)
|
||||
st.d $r22, $a0, (8 * 22)
|
||||
st.d $r23, $a0, (8 * 23)
|
||||
st.d $r24, $a0, (8 * 24)
|
||||
st.d $r25, $a0, (8 * 25)
|
||||
st.d $r26, $a0, (8 * 26)
|
||||
st.d $r27, $a0, (8 * 27)
|
||||
st.d $r28, $a0, (8 * 28)
|
||||
st.d $r29, $a0, (8 * 29)
|
||||
st.d $r30, $a0, (8 * 30)
|
||||
st.d $r31, $a0, (8 * 31)
|
||||
st.d $r1, $a0, (8 * 32) // store $ra to pc
|
||||
|
||||
# if __loongarch_frlen == 64
|
||||
fst.d $f0, $a0, (8 * 33 + 8 * 0)
|
||||
fst.d $f1, $a0, (8 * 33 + 8 * 1)
|
||||
fst.d $f2, $a0, (8 * 33 + 8 * 2)
|
||||
fst.d $f3, $a0, (8 * 33 + 8 * 3)
|
||||
fst.d $f4, $a0, (8 * 33 + 8 * 4)
|
||||
fst.d $f5, $a0, (8 * 33 + 8 * 5)
|
||||
fst.d $f6, $a0, (8 * 33 + 8 * 6)
|
||||
fst.d $f7, $a0, (8 * 33 + 8 * 7)
|
||||
fst.d $f8, $a0, (8 * 33 + 8 * 8)
|
||||
fst.d $f9, $a0, (8 * 33 + 8 * 9)
|
||||
fst.d $f10, $a0, (8 * 33 + 8 * 10)
|
||||
fst.d $f11, $a0, (8 * 33 + 8 * 11)
|
||||
fst.d $f12, $a0, (8 * 33 + 8 * 12)
|
||||
fst.d $f13, $a0, (8 * 33 + 8 * 13)
|
||||
fst.d $f14, $a0, (8 * 33 + 8 * 14)
|
||||
fst.d $f15, $a0, (8 * 33 + 8 * 15)
|
||||
fst.d $f16, $a0, (8 * 33 + 8 * 16)
|
||||
fst.d $f17, $a0, (8 * 33 + 8 * 17)
|
||||
fst.d $f18, $a0, (8 * 33 + 8 * 18)
|
||||
fst.d $f19, $a0, (8 * 33 + 8 * 19)
|
||||
fst.d $f20, $a0, (8 * 33 + 8 * 20)
|
||||
fst.d $f21, $a0, (8 * 33 + 8 * 21)
|
||||
fst.d $f22, $a0, (8 * 33 + 8 * 22)
|
||||
fst.d $f23, $a0, (8 * 33 + 8 * 23)
|
||||
fst.d $f24, $a0, (8 * 33 + 8 * 24)
|
||||
fst.d $f25, $a0, (8 * 33 + 8 * 25)
|
||||
fst.d $f26, $a0, (8 * 33 + 8 * 26)
|
||||
fst.d $f27, $a0, (8 * 33 + 8 * 27)
|
||||
fst.d $f28, $a0, (8 * 33 + 8 * 28)
|
||||
fst.d $f29, $a0, (8 * 33 + 8 * 29)
|
||||
fst.d $f30, $a0, (8 * 33 + 8 * 30)
|
||||
fst.d $f31, $a0, (8 * 33 + 8 * 31)
|
||||
# endif
|
||||
|
||||
move $a0, $zero // UNW_ESUCCESS
|
||||
jr $ra
|
||||
|
||||
#endif
|
||||
|
||||
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
|
||||
|
@ -115,7 +115,7 @@
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
|
||||
(!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \
|
||||
defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \
|
||||
defined(__sparc__) || defined(__s390x__)
|
||||
defined(__sparc__) || defined(__s390x__) || defined(__loongarch__)
|
||||
#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
|
||||
#define _LIBUNWIND_BUILD_ZERO_COST_APIS
|
||||
#endif
|
||||
|
@ -77,6 +77,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
|
||||
# define REGISTER_KIND Registers_ve
|
||||
#elif defined(__s390x__)
|
||||
# define REGISTER_KIND Registers_s390x
|
||||
#elif defined(__loongarch__) && __loongarch_grlen == 64
|
||||
#define REGISTER_KIND Registers_loongarch
|
||||
#else
|
||||
# error Architecture not supported
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user