diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index 84b6f81606f3fa..8d515a174385cf 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -426,6 +426,8 @@ enum #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_S390X) #define DAC_CS_NATIVE_DATA_SIZE 96 +#elif defined(TARGET_LINUX) && defined(TARGET_LOONGARCH64) +#define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_ARM) diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 237b75275cec96..11aae3f98e1dee 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -94,6 +94,8 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define _M_ARM 7 #elif defined(__aarch64__) && !defined(_M_ARM64) #define _M_ARM64 1 +#elif defined(__loongarch64) && !defined(_M_LOONGARCH64) +#define _M_LOONGARCH64 1 #elif defined(__s390x__) && !defined(_M_S390X) #define _M_S390X 1 #endif @@ -106,6 +108,8 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define HOST_ARM #elif defined(_M_ARM64) && !defined(HOST_ARM64) #define HOST_ARM64 +#elif defined(_M_LOONGARCH64) && !defined(HOST_LOONGARCH64) +#define HOST_LOONGARCH64 #elif defined(_M_S390X) && !defined(HOST_S390X) #define HOST_S390X #endif @@ -2202,6 +2206,150 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; +#elif defined(HOST_LOONGARCH64) + +//Please refence "src/pal/src/arch/loongarch64/asmconstants.h" +#define CONTEXT_LOONGARCH64 0x00800000 + +#define CONTEXT_CONTROL (CONTEXT_LOONGARCH64 | 0x1) +#define CONTEXT_INTEGER (CONTEXT_LOONGARCH64 | 0x2) +#define CONTEXT_FLOATING_POINT (CONTEXT_LOONGARCH64 | 0x4) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_LOONGARCH64 | 0x8) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000 +#define CONTEXT_SERVICE_ACTIVE 0x10000000 +#define CONTEXT_EXCEPTION_REQUEST 0x40000000 +#define CONTEXT_EXCEPTION_REPORTING 0x80000000 + +// +// This flag is set by the unwinder if it has unwound to a call +// site, and cleared whenever it unwinds through a trap frame. +// It is used by language-specific exception handlers to help +// differentiate exception scopes during dispatching. +// + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +// begin_ntoshvp + +// +// Specify the number of breakpoints and watchpoints that the OS +// will track. Architecturally, LOONGARCH64 supports up to 16. In practice, +// however, almost no one implements more than 4 of each. +// + +#define LOONGARCH64_MAX_BREAKPOINTS 8 +#define LOONGARCH64_MAX_WATCHPOINTS 2 + +// +// Context Frame +// +// This frame has a several purposes: 1) it is used as an argument to +// NtContinue, 2) it is used to constuct a call frame for APC delivery, +// and 3) it is used in the user level thread creation routines. +// +// +// The flags field within this record controls the contents of a CONTEXT +// record. +// +// If the context record is used as an input parameter, then for each +// portion of the context record controlled by a flag whose value is +// set, it is assumed that that portion of the context record contains +// valid context. If the context record is being used to modify a threads +// context, then only that portion of the threads context is modified. +// +// If the context record is used as an output parameter to capture the +// context of a thread, then only those portions of the thread's context +// corresponding to set flags will be returned. +// + +typedef struct DECLSPEC_ALIGN(16) _CONTEXT { + + // + // Control flags. + // + + /* +0x000 */ DWORD ContextFlags; + + // + // Integer registers, abi=N64. + // + DWORD64 R0; + DWORD64 Ra; + DWORD64 Tp; + DWORD64 Sp; + DWORD64 A0;//DWORD64 V0; + DWORD64 A1;//DWORD64 V1; + DWORD64 A2; + DWORD64 A3; + DWORD64 A4; + DWORD64 A5; + DWORD64 A6; + DWORD64 A7; + DWORD64 T0; + DWORD64 T1; + DWORD64 T2; + DWORD64 T3; + DWORD64 T4; + DWORD64 T5; + DWORD64 T6; + DWORD64 T7; + DWORD64 T8; + DWORD64 X0; + DWORD64 Fp; + DWORD64 S0; + DWORD64 S1; + DWORD64 S2; + DWORD64 S3; + DWORD64 S4; + DWORD64 S5; + DWORD64 S6; + DWORD64 S7; + DWORD64 S8; + DWORD64 Pc; + + // + // Floating Point Registers + // + //TODO: support the SIMD. + DWORD64 F[32]; + DWORD Fcsr; +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +// +// Nonvolatile context pointer record. +// + +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + + PDWORD64 S0; + PDWORD64 S1; + PDWORD64 S2; + PDWORD64 S3; + PDWORD64 S4; + PDWORD64 S5; + PDWORD64 S6; + PDWORD64 S7; + PDWORD64 S8; + PDWORD64 Fp; + PDWORD64 Tp; + PDWORD64 Ra; + + PDWORD64 F24; + PDWORD64 F25; + PDWORD64 F26; + PDWORD64 F27; + PDWORD64 F28; + PDWORD64 F29; + PDWORD64 F30; + PDWORD64 F31; +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + + #elif defined(HOST_S390X) // There is no context for s390x defined in winnt.h, @@ -2453,6 +2601,8 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ #define PAL_CS_NATIVE_DATA_SIZE 56 #elif defined(__sun) && defined(__x86_64__) #define PAL_CS_NATIVE_DATA_SIZE 48 +#elif defined(__linux__) && defined(__loongarch64) +#define PAL_CS_NATIVE_DATA_SIZE 96 #else #warning #error PAL_CS_NATIVE_DATA_SIZE is not defined for this architecture @@ -3255,6 +3405,9 @@ FORCEINLINE void PAL_ArmInterlockedOperationBarrier() // prevent that reordering. Code generated for arm32 includes a 'dmb' after 'cbnz', so no issue there at the moment. __sync_synchronize(); #endif // HOST_ARM64 +#ifdef HOST_LOONGARCH64 + __sync_synchronize(); +#endif } /*++ @@ -3653,6 +3806,8 @@ YieldProcessor() "nop"); #elif defined(HOST_ARM) || defined(HOST_ARM64) __asm__ __volatile__( "yield"); +#elif defined(HOST_LOONGARCH64) + __asm__ volatile( "dbar 0; \n"); #else return; #endif diff --git a/src/coreclr/pal/inc/rt/intsafe.h b/src/coreclr/pal/inc/rt/intsafe.h index 2b607e3a312e12..0119eab466eefc 100644 --- a/src/coreclr/pal/inc/rt/intsafe.h +++ b/src/coreclr/pal/inc/rt/intsafe.h @@ -31,7 +31,7 @@ #define LODWORD(_qw) ((ULONG)(_qw)) #if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \ - || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(_M_S390X) + || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(_M_S390X) || defined(_M_LOONGARCH64) #ifndef UInt32x32To64 #define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b))) diff --git a/src/coreclr/pal/inc/rt/palrt.h b/src/coreclr/pal/inc/rt/palrt.h index 0855f5991cd8c8..dee82f344464b9 100644 --- a/src/coreclr/pal/inc/rt/palrt.h +++ b/src/coreclr/pal/inc/rt/palrt.h @@ -950,6 +950,7 @@ typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 #define PROCESSOR_ARCHITECTURE_NEUTRAL 11 #define PROCESSOR_ARCHITECTURE_ARM64 12 +#define PROCESSOR_ARCHITECTURE_LOONGARCH64 13 #define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF @@ -1215,6 +1216,24 @@ typedef struct _DISPATCHER_CONTEXT { BOOLEAN ControlPcIsUnwound; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; +#elif defined(HOST_LOONGARCH64) + +typedef struct _DISPATCHER_CONTEXT { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetPc; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PVOID HistoryTable; + ULONG64 ScopeIndex; + BOOLEAN ControlPcIsUnwound; + PBYTE NonVolatileRegisters; + ULONG64 Reserved; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + #elif defined(HOST_S390X) typedef struct _DISPATCHER_CONTEXT { diff --git a/src/coreclr/pal/inc/unixasmmacros.inc b/src/coreclr/pal/inc/unixasmmacros.inc index 1fe285eef162d2..de775eba5075be 100644 --- a/src/coreclr/pal/inc/unixasmmacros.inc +++ b/src/coreclr/pal/inc/unixasmmacros.inc @@ -43,4 +43,6 @@ #include "unixasmmacrosarm64.inc" #elif defined(HOST_S390X) #include "unixasmmacross390x.inc" +#elif defined(HOST_LOONGARCH64) +#include "unixasmmacrosloongarch64.inc" #endif diff --git a/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc b/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc new file mode 100644 index 00000000000000..5a150db94bf788 --- /dev/null +++ b/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc @@ -0,0 +1,483 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .cfi_personality 0x1c, C_FUNC(\Handler) // 0x1c == DW_EH_PE_pcrel | DW_EH_PE_sdata8 + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +.endm + +.macro PATCH_LABEL Name + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_ENTRY Name, Section + .global C_FUNC(\Name) + .type \Name, %function +C_FUNC(\Name): + .cfi_startproc +.endm + +.macro LEAF_END Name, Section + .size \Name, .-\Name + .cfi_endproc +.endm + +.macro LEAF_END_MARKED Name, Section +C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section +.endm + +.macro PREPARE_EXTERNAL_VAR Name, HelperReg + la.local \HelperReg, \Name +.endm + +.macro PROLOG_STACK_ALLOC Size + addi.d $sp, $sp, -\Size + //.cfi_adjust_cfa_offset \Size + .cfi_def_cfa 3,\Size +.endm + +.macro EPILOG_STACK_FREE Size + addi.d $sp, $sp, \Size + //.cfi_adjust_cfa_offset -\Size + .cfi_def_cfa 3,-\Size +.endm + +.macro EPILOG_STACK_RESTORE + ori $sp, $fp, 0 + .cfi_restore 3 +.endm + +////NOTE: reg must be the number and GPR type !!! +.macro PROLOG_SAVE_REG reg, ofs + st.d $r\reg, $sp, \ofs + .cfi_rel_offset \reg, \ofs +.endm + +////NOTE: reg1 and reg2 must be the number and GPR type !!! +.macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs, __def_cfa_save=0 +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssq/gslq must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssq \reg2, \reg1, \ofs(sp) +//#else + st.d $r\reg1, $sp, \ofs + st.d $r\reg2, $sp, \ofs+8 +//#endif + + .cfi_rel_offset \reg1, \ofs + .cfi_rel_offset \reg2, \ofs + 8 + .if (\__def_cfa_save == 1) + ori $fp, $sp, 0 + .cfi_def_cfa_register 22 + .endif +.endm + +////NOTE: reg1 and reg2 must be the number and GPR type !!! +.macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ssize, __def_cfa_save=1 + addi.d $sp, $sp, -\ssize + //.cfi_adjust_cfa_offset \ssize + .cfi_def_cfa 3,\ssize + + st.d $r\reg1, $sp, 0 + st.d $r\reg2, $sp, 8 + + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 + .if (\__def_cfa_save == 1) + ori $fp, $sp, 0 + .cfi_def_cfa_register 22 + .endif +.endm + +.macro EPILOG_RESTORE_REG reg, ofs + ld.d $r\reg, $sp, \ofs + .cfi_restore \reg + .cfi_def_cfa_register 3 +.endm + +.macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs +//#ifdef FEATURE_LOONGSONISA +// gslq \reg2, \reg1, \ofs(sp) +//#else + ld.d $r\reg2, $sp, \ofs+8 + ld.d $r\reg1, $sp, \ofs +//#endif + .cfi_restore \reg2 + .cfi_restore \reg1 +.endm + +.macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ssize +//#ifdef FEATURE_LOONGSONISA +// gslq \reg2, \reg1, 0(sp) +//#else + ld.d $r\reg2, $sp, 8 + ld.d $r\reg1, $sp, 0 +//#endif + .cfi_restore \reg2 + .cfi_restore \reg1 + + addi.d $sp, $sp, \ssize + //.cfi_adjust_cfa_offset -\ssize + .cfi_def_cfa 3,-\ssize +.endm + +.macro EPILOG_RETURN + jirl $r0, $ra, 0 +.endm + +.macro EMIT_BREAKPOINT + break +.endm + +.macro EPILOG_BRANCH Target + b \Target + //break +.endm + +.macro EPILOG_BRANCH_REG reg + jirl $r0, \reg, 0 +.endm + +//----------------------------------------------------------------------------- +// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and +// base address to be passed in $reg +// + +// Reserve 64 bytes of memory before calling SAVE_CALLEESAVED_REGISTERS +.macro SAVE_CALLEESAVED_REGISTERS reg, ofs + + PROLOG_SAVE_REG_PAIR 23, 24, \ofs + 16 + PROLOG_SAVE_REG_PAIR 25, 26, \ofs + 32 + PROLOG_SAVE_REG_PAIR 27, 28, \ofs + 48 + PROLOG_SAVE_REG_PAIR 29, 30, \ofs + 64 + PROLOG_SAVE_REG_PAIR 31, 2, \ofs + 80 + +.endm + +// Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS +.macro SAVE_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssq/gslq must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssq a1, a0, \ofs(\reg) +// gssq a3, a2, \ofs+16(\reg) +// gssq a5, a4, \ofs+32(\reg) +// gssq a7, a6, \ofs+48(\reg) +//#else + st.d $a0, \reg, \ofs + st.d $a1, \reg, \ofs+8 + st.d $a2, \reg, \ofs+16 + st.d $a3, \reg, \ofs+24 + st.d $a4, \reg, \ofs+32 + st.d $a5, \reg, \ofs+40 + st.d $a6, \reg, \ofs+48 + st.d $a7, \reg, \ofs+56 +//#endif + +.endm + +// Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS +.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssqc1/gslqc1 must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssqc1 $f13, $f12, \ofs(\reg) +// gssqc1 $f15, $f14, \ofs+16(\reg) +// gssqc1 $f17, $f16, \ofs+32(\reg) +// gssqc1 $f19, $f18, \ofs+48(\reg) +//#else + fst.d $f0, \reg, \ofs + fst.d $f1, \reg, \ofs+8 + fst.d $f2, \reg, \ofs+16 + fst.d $f3, \reg, \ofs+24 + fst.d $f4, \reg, \ofs+32 + fst.d $f5, \reg, \ofs+40 + fst.d $f6, \reg, \ofs+48 + fst.d $f7, \reg, \ofs+56 +//#endif + +.endm + +// Reserve 64 bytes of memory before calling SAVE_FLOAT_CALLEESAVED_REGISTERS +.macro SAVE_FLOAT_CALLEESAVED_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssqc1/gslqc1 must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssqc1 $f25, $f24, \ofs(\reg) +// gssqc1 $f27, $f26, \ofs+16(\reg) +// gssqc1 $f29, $f28, \ofs+32(\reg) +// gssqc1 $f31, $f30, \ofs+48(\reg) +//#else + fst.d $f24, \reg, \ofs + fst.d $f25, \reg, \ofs+8 + fst.d $f26, \reg, \ofs+16 + fst.d $f27, \reg, \ofs+24 + fst.d $f28, \reg, \ofs+32 + fst.d $f29, \reg, \ofs+40 + fst.d $f30, \reg, \ofs+48 + fst.d $f31, \reg, \ofs+56 +//#endif + +.endm + +.macro RESTORE_CALLEESAVED_REGISTERS reg, ofs + + EPILOG_RESTORE_REG_PAIR 31, 2 \ofs + 80 + + EPILOG_RESTORE_REG_PAIR 29, 30, \ofs + 64 + EPILOG_RESTORE_REG_PAIR 27, 28, \ofs + 48 + EPILOG_RESTORE_REG_PAIR 25, 26, \ofs + 32 + EPILOG_RESTORE_REG_PAIR 23, 24, \ofs + 16 +.endm + +.macro RESTORE_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssq/gslq must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gslq a7, a6, \ofs+48(\reg) +// gslq a5, a4, \ofs+32(\reg) +// gslq a3, a2, \ofs+16(\reg) +// gslq a1, a0, \ofs(\reg) +//#else + ld.d $a7, \reg, \ofs+56 + ld.d $a6, \reg, \ofs+48 + ld.d $a5, \reg, \ofs+40 + ld.d $a4, \reg, \ofs+32 + ld.d $a3, \reg, \ofs+24 + ld.d $a2, \reg, \ofs+16 + ld.d $a1, \reg, \ofs+8 + ld.d $a0, \reg, \ofs +//#endif + +.endm + +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// gslqc1 $f19, $f18, \ofs+48(\reg) +// gslqc1 $f17, $f16, \ofs+32(\reg) +// gslqc1 $f15, $f14, \ofs+16(\reg) +// gslqc1 $f13, $f12, \ofs(\reg) +//#else + fld.d $f7, \reg, \ofs+56 + fld.d $f6, \reg, \ofs+48 + fld.d $f5, \reg, \ofs+40 + fld.d $f4, \reg, \ofs+32 + fld.d $f3, \reg, \ofs+24 + fld.d $f2, \reg, \ofs+16 + fld.d $f1, \reg, \ofs+8 + fld.d $f0, \reg, \ofs +//#endif + +.endm + +.macro RESTORE_FLOAT_CALLEESAVED_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssqc1/gslqc1 must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gslqc1 $f25, $f24, \ofs(\reg) +// gslqc1 $f27, $f26, \ofs+16(\reg) +// gslqc1 $f29, $f28, \ofs+32(\reg) +// gslqc1 $f31, $f30, \ofs+48(\reg) +//#else + fld.d $f24, $r\reg, \ofs + fld.d $f25, $r\reg, \ofs+8 + fld.d $f26, $r\reg, \ofs+16 + fld.d $f27, $r\reg, \ofs+24 + fld.d $f28, $r\reg, \ofs+32 + fld.d $f29, $r\reg, \ofs+40 + fld.d $f30, $r\reg, \ofs+48 + fld.d $f31, $r\reg, \ofs+56 +//#endif + +.endm + +//----------------------------------------------------------------------------- +// Define the prolog for a TransitionBlock-based method. This macro should be called first in the method and +// comprises the entire prolog.The locals must be 8 byte aligned +// +// Save_argument_registers: +// GPR_a7 +// GPR_a6 +// GPR_a5 +// GPR_a4 +// GPR_a3 +// GPR_a2 +// GPR_a1 +// GPR_a0 +// +// General Registers: +// GPR_tp +// GPR_s8 +// GPR_s7 +// GPR_s6 +// GPR_s5 +// GPR_s4 +// GPR_s3 +// GPR_s2 +// GPR_s1 +// GPR_s0 +// GPR_ra +// GPR_fp +// +// Float Point: +// FPR_f31 / fs7 +// FPR_f30 / fs6 +// FPR_f29 / fs5 +// FPR_f28 / fs4 +// FPR_f27 / fs3 +// FPR_f26 / fs2 +// FPR_f25 / fs1 +// FPR_f24 / fs0 +// Extra: +// +.macro PROLOG_WITH_TRANSITION_BLOCK extraParameters = 0, extraLocals = 0, SaveFPRegs = 1 + + __PWTB_SaveFPArgs = \SaveFPRegs + + __PWTB_FloatArgumentRegisters = \extraLocals + + .if ((__PWTB_FloatArgumentRegisters % 16) != 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 + .endif + + __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + + .if (__PWTB_SaveFPArgs == 1) + __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters + .endif + + + __PWTB_CalleeSavedRegisters = __PWTB_TransitionBlock + __PWTB_ArgumentRegisters = __PWTB_TransitionBlock + 96 + + // Including fp, ra, s0-s8, tp, and (a0-a7)arguments. (1+1+9+1)*8 + 8*8. + __PWTB_StackAlloc = __PWTB_TransitionBlock + 96 + 64 + PROLOG_STACK_ALLOC __PWTB_StackAlloc + // $fp,$ra + PROLOG_SAVE_REG_PAIR 22, 1, __PWTB_CalleeSavedRegisters, 1 + + // First, Spill argument registers. + SAVE_ARGUMENT_REGISTERS $sp, __PWTB_ArgumentRegisters + + // Then, Spill callee saved registers. $sp=$r3. + SAVE_CALLEESAVED_REGISTERS 3, __PWTB_CalleeSavedRegisters + + // saving is f12-19. + .if (__PWTB_SaveFPArgs == 1) + SAVE_FLOAT_ARGUMENT_REGISTERS $sp, __PWTB_FloatArgumentRegisters + .endif + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN + + RESTORE_CALLEESAVED_REGISTERS 3, __PWTB_CalleeSavedRegisters + + EPILOG_RESTORE_REG_PAIR 22, 1, __PWTB_CalleeSavedRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc + + jirl $r0, $ra, 0 + +.endm + + +//----------------------------------------------------------------------------- +// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. +// Since this is a tail call argument registers are restored. +// +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + .if (__PWTB_SaveFPArgs == 1) + RESTORE_FLOAT_ARGUMENT_REGISTERS $sp, __PWTB_FloatArgumentRegisters + .endif + + RESTORE_CALLEESAVED_REGISTERS 3, __PWTB_CalleeSavedRegisters + + RESTORE_ARGUMENT_REGISTERS $sp, __PWTB_ArgumentRegisters + + EPILOG_RESTORE_REG_PAIR 22, 1, __PWTB_CalleeSavedRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc + +.endm + +// ------------------------------------------------------------------ +// Macro to generate Redirection Stubs +// +// $reason : reason for redirection +// Eg. GCThreadControl +// NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame. +// This function is used by both the personality routine and the debugger to retrieve the original CONTEXT. +.macro GenerateRedirectedHandledJITCaseStub reason + +#if NOTYET + GBLS __RedirectionStubFuncName + GBLS __RedirectionStubEndFuncName + GBLS __RedirectionFuncName +__RedirectionStubFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_Stub" +__RedirectionStubEndFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_StubEnd" +__RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thread@@CAXXZ|" + + IMPORT $__RedirectionFuncName + + NESTED_ENTRY $__RedirectionStubFuncName + addi.d $sp, $sp, -32 // stack slot for CONTEXT * and padding + PROLOG_SAVE_REG_PAIR 22, 1, 16, 1 + + //REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame + //If CONTEXT is not saved at 0 offset from SP it must be changed as well. + ASSERT REDIRECTSTUB_SP_OFFSET_CONTEXT == 0 + + // Stack alignment. This check is necessary as this function can be + // entered before complete execution of the prolog of another function. + andi $t4, $fp, 15 + sub.d $sp, $sp, $t4 + + + // + // Save a copy of the redirect CONTEXT*. + // This is needed for the debugger to unwind the stack. + // + bl GetCurrentSavedRedirectContext + + st.d $v0, $sp, 0 + + // + // Fetch the interrupted pc and save it as our return address. + // + ld.d $a1, $a0, CONTEXT_PC + st.d $a1, $fp, 8 + + // + // Call target, which will do whatever we needed to do in the context + // of the target thread, and will RtlRestoreContext when it is done. + // + bl $__RedirectionFuncName + + EMIT_BREAKPOINT // Unreachable + +// Put a label here to tell the debugger where the end of this function is. +$__RedirectionStubEndFuncName + EXPORT $__RedirectionStubEndFuncName + + NESTED_END +#else + EMIT_BREAKPOINT +#endif +.endm diff --git a/src/coreclr/pal/prebuilt/inc/cordebug.h b/src/coreclr/pal/prebuilt/inc/cordebug.h index df876984714400..226ae1c0ca7691 100644 --- a/src/coreclr/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/pal/prebuilt/inc/cordebug.h @@ -1475,7 +1475,8 @@ enum CorDebugPlatform CORDB_PLATFORM_POSIX_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM64 + 1 ) , CORDB_PLATFORM_POSIX_X86 = ( CORDB_PLATFORM_POSIX_AMD64 + 1 ) , CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , - CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) + CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) , + CORDB_PLATFORM_POSIX_LOONGARCH64 = ( CORDB_PLATFORM_POSIX_ARM64 + 1 ) } CorDebugPlatform; @@ -9191,7 +9192,72 @@ enum CorDebugRegister REGISTER_ARM64_V28 = ( REGISTER_ARM64_V27 + 1 ) , REGISTER_ARM64_V29 = ( REGISTER_ARM64_V28 + 1 ) , REGISTER_ARM64_V30 = ( REGISTER_ARM64_V29 + 1 ) , - REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) + REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) , + REGISTER_LOONGARCH64_R0 = 0, + REGISTER_LOONGARCH64_RA = ( REGISTER_LOONGARCH64_R0 + 1 ) , + REGISTER_LOONGARCH64_TP = ( REGISTER_LOONGARCH64_RA + 1 ) , + REGISTER_LOONGARCH64_SP = ( REGISTER_LOONGARCH64_TP + 1 ) , + REGISTER_LOONGARCH64_A0 = ( REGISTER_LOONGARCH64_SP + 1 ) , + REGISTER_LOONGARCH64_A1 = ( REGISTER_LOONGARCH64_A0 + 1 ) , + REGISTER_LOONGARCH64_A2 = ( REGISTER_LOONGARCH64_A1 + 1 ) , + REGISTER_LOONGARCH64_A3 = ( REGISTER_LOONGARCH64_A2 + 1 ) , + REGISTER_LOONGARCH64_A4 = ( REGISTER_LOONGARCH64_A3 + 1 ) , + REGISTER_LOONGARCH64_A5 = ( REGISTER_LOONGARCH64_A4 + 1 ) , + REGISTER_LOONGARCH64_A6 = ( REGISTER_LOONGARCH64_A5 + 1 ) , + REGISTER_LOONGARCH64_A7 = ( REGISTER_LOONGARCH64_A6 + 1 ) , + REGISTER_LOONGARCH64_T0 = ( REGISTER_LOONGARCH64_A7 + 1 ) , + REGISTER_LOONGARCH64_T1 = ( REGISTER_LOONGARCH64_T0 + 1 ) , + REGISTER_LOONGARCH64_T2 = ( REGISTER_LOONGARCH64_T1 + 1 ) , + REGISTER_LOONGARCH64_T3 = ( REGISTER_LOONGARCH64_T2 + 1 ) , + REGISTER_LOONGARCH64_T4 = ( REGISTER_LOONGARCH64_T3 + 1 ) , + REGISTER_LOONGARCH64_T5 = ( REGISTER_LOONGARCH64_T4 + 1 ) , + REGISTER_LOONGARCH64_T6 = ( REGISTER_LOONGARCH64_T5 + 1 ) , + REGISTER_LOONGARCH64_T7 = ( REGISTER_LOONGARCH64_T6 + 1 ) , + REGISTER_LOONGARCH64_T8 = ( REGISTER_LOONGARCH64_T7 + 1 ) , + REGISTER_LOONGARCH64_X0 = ( REGISTER_LOONGARCH64_T8 + 1 ) , + REGISTER_LOONGARCH64_FP = ( REGISTER_LOONGARCH64_X0 + 1 ) , + REGISTER_LOONGARCH64_S0 = ( REGISTER_LOONGARCH64_FP + 1 ) , + REGISTER_LOONGARCH64_S1 = ( REGISTER_LOONGARCH64_S0 + 1 ) , + REGISTER_LOONGARCH64_S2 = ( REGISTER_LOONGARCH64_S1 + 1 ) , + REGISTER_LOONGARCH64_S3 = ( REGISTER_LOONGARCH64_S2 + 1 ) , + REGISTER_LOONGARCH64_S4 = ( REGISTER_LOONGARCH64_S3 + 1 ) , + REGISTER_LOONGARCH64_S5 = ( REGISTER_LOONGARCH64_S4 + 1 ) , + REGISTER_LOONGARCH64_S6 = ( REGISTER_LOONGARCH64_S5 + 1 ) , + REGISTER_LOONGARCH64_S7 = ( REGISTER_LOONGARCH64_S6 + 1 ) , + REGISTER_LOONGARCH64_S8 = ( REGISTER_LOONGARCH64_S7 + 1 ) , + REGISTER_LOONGARCH64_PC = ( REGISTER_LOONGARCH64_S8 + 1 ) , + REGISTER_LOONGARCH64_F0 = ( REGISTER_LOONGARCH64_PC + 1 ) , + REGISTER_LOONGARCH64_F1 = ( REGISTER_LOONGARCH64_F0 + 1 ) , + REGISTER_LOONGARCH64_F2 = ( REGISTER_LOONGARCH64_F1 + 1 ) , + REGISTER_LOONGARCH64_F3 = ( REGISTER_LOONGARCH64_F2 + 1 ) , + REGISTER_LOONGARCH64_F4 = ( REGISTER_LOONGARCH64_F3 + 1 ) , + REGISTER_LOONGARCH64_F5 = ( REGISTER_LOONGARCH64_F4 + 1 ) , + REGISTER_LOONGARCH64_F6 = ( REGISTER_LOONGARCH64_F5 + 1 ) , + REGISTER_LOONGARCH64_F7 = ( REGISTER_LOONGARCH64_F6 + 1 ) , + REGISTER_LOONGARCH64_F8 = ( REGISTER_LOONGARCH64_F7 + 1 ) , + REGISTER_LOONGARCH64_F9 = ( REGISTER_LOONGARCH64_F8 + 1 ) , + REGISTER_LOONGARCH64_F10 = ( REGISTER_LOONGARCH64_F9 + 1 ) , + REGISTER_LOONGARCH64_F11 = ( REGISTER_LOONGARCH64_F10 + 1 ) , + REGISTER_LOONGARCH64_F12 = ( REGISTER_LOONGARCH64_F11 + 1 ) , + REGISTER_LOONGARCH64_F13 = ( REGISTER_LOONGARCH64_F12 + 1 ) , + REGISTER_LOONGARCH64_F14 = ( REGISTER_LOONGARCH64_F13 + 1 ) , + REGISTER_LOONGARCH64_F15 = ( REGISTER_LOONGARCH64_F14 + 1 ) , + REGISTER_LOONGARCH64_F16 = ( REGISTER_LOONGARCH64_F15 + 1 ) , + REGISTER_LOONGARCH64_F17 = ( REGISTER_LOONGARCH64_F16 + 1 ) , + REGISTER_LOONGARCH64_F18 = ( REGISTER_LOONGARCH64_F17 + 1 ) , + REGISTER_LOONGARCH64_F19 = ( REGISTER_LOONGARCH64_F18 + 1 ) , + REGISTER_LOONGARCH64_F20 = ( REGISTER_LOONGARCH64_F19 + 1 ) , + REGISTER_LOONGARCH64_F21 = ( REGISTER_LOONGARCH64_F20 + 1 ) , + REGISTER_LOONGARCH64_F22 = ( REGISTER_LOONGARCH64_F21 + 1 ) , + REGISTER_LOONGARCH64_F23 = ( REGISTER_LOONGARCH64_F22 + 1 ) , + REGISTER_LOONGARCH64_F24 = ( REGISTER_LOONGARCH64_F23 + 1 ) , + REGISTER_LOONGARCH64_F25 = ( REGISTER_LOONGARCH64_F24 + 1 ) , + REGISTER_LOONGARCH64_F26 = ( REGISTER_LOONGARCH64_F25 + 1 ) , + REGISTER_LOONGARCH64_F27 = ( REGISTER_LOONGARCH64_F26 + 1 ) , + REGISTER_LOONGARCH64_F28 = ( REGISTER_LOONGARCH64_F27 + 1 ) , + REGISTER_LOONGARCH64_F29 = ( REGISTER_LOONGARCH64_F28 + 1 ) , + REGISTER_LOONGARCH64_F30 = ( REGISTER_LOONGARCH64_F29 + 1 ) , + REGISTER_LOONGARCH64_F31 = ( REGISTER_LOONGARCH64_F30 + 1 ) } CorDebugRegister; diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 4f071b21046b07..6dcd847eaf3da2 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -47,6 +47,8 @@ elseif(CLR_CMAKE_HOST_ARCH_ARM) set(PAL_ARCH_SOURCES_DIR arm) elseif(CLR_CMAKE_HOST_ARCH_ARM64) set(PAL_ARCH_SOURCES_DIR arm64) +elseif(CLR_CMAKE_HOST_ARCH_LOONGARCH64) + set(PAL_ARCH_SOURCES_DIR loongarch64) elseif(CLR_CMAKE_HOST_ARCH_I386) set(PAL_ARCH_SOURCES_DIR i386) elseif(CLR_CMAKE_HOST_ARCH_S390X) diff --git a/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S b/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S new file mode 100644 index 00000000000000..9cc8663fedf4fc --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// Offset of the return address from the ActivationHandler in the ActivationHandlerWrapper +.globl C_FUNC(ActivationHandlerReturnOffset) +C_FUNC(ActivationHandlerReturnOffset): + .int LOCAL_LABEL(ActivationHandlerReturn)-C_FUNC(ActivationHandlerWrapper) + +NESTED_ENTRY ActivationHandlerWrapper, _TEXT, NoHandler + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -(16 + CONTEXT_Size) + // Should never actually run + EMIT_BREAKPOINT + bl EXTERNAL_C_FUNC(ActivationHandler) +LOCAL_LABEL(ActivationHandlerReturn): + // Should never return + EMIT_BREAKPOINT + // $fp,$ra + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, (16 + CONTEXT_Size) + jirl $r0, $ra, 0 +NESTED_END ActivationHandlerWrapper, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/asmconstants.h b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h new file mode 100644 index 00000000000000..ca728c2745e141 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __PAL_LOONGARCH64_ASMCONSTANTS_H__ +#define __PAL_LOONGARCH64_ASMCONSTANTS_H__ + +//Please refence "src/pal/inc/pal.h" +#define CONTEXT_LOONGARCH64 0x00800000 + +#define CONTEXT_CONTROL_BIT (0) +#define CONTEXT_INTEGER_BIT (1) +#define CONTEXT_FLOATING_POINT_BIT (2) +#define CONTEXT_DEBUG_REGISTERS_BIT (3) + +#define CONTEXT_CONTROL (CONTEXT_LOONGARCH64 | (1 << CONTEXT_CONTROL_BIT)) +#define CONTEXT_INTEGER (CONTEXT_LOONGARCH64 | (1 << CONTEXT_INTEGER_BIT)) +#define CONTEXT_FLOATING_POINT (CONTEXT_LOONGARCH64 | (1 << CONTEXT_FLOATING_POINT_BIT)) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_LOONGARCH64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define SIZEOF_LOONGARCH_GPR 8 +#define SIZEOF_LOONGARCH_FPR 8 + +#define CONTEXT_ContextFlags 0 +//Note: Here CONTEXT_ContextFlags+8 for memory algin. +#define CONTEXT_R0 CONTEXT_ContextFlags+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Ra CONTEXT_R0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Tp CONTEXT_Ra+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Sp CONTEXT_Tp+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A0 CONTEXT_Sp+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A1 CONTEXT_A0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A2 CONTEXT_A1+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A3 CONTEXT_A2+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A4 CONTEXT_A3+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A5 CONTEXT_A4+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A6 CONTEXT_A5+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A7 CONTEXT_A6+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T0 CONTEXT_A7+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T1 CONTEXT_T0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T2 CONTEXT_T1+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T3 CONTEXT_T2+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T4 CONTEXT_T3+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T5 CONTEXT_T4+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T6 CONTEXT_T5+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T7 CONTEXT_T6+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T8 CONTEXT_T7+SIZEOF_LOONGARCH_GPR +#define CONTEXT_X0 CONTEXT_T8+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Fp CONTEXT_X0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S0 CONTEXT_Fp+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S1 CONTEXT_S0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S2 CONTEXT_S1+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S3 CONTEXT_S2+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S4 CONTEXT_S3+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S5 CONTEXT_S4+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S6 CONTEXT_S5+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S7 CONTEXT_S6+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S8 CONTEXT_S7+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Pc CONTEXT_S8+SIZEOF_LOONGARCH_GPR +#define CONTEXT_FPU_OFFSET CONTEXT_Pc+SIZEOF_LOONGARCH_GPR + +#define CONTEXT_F0 0 +#define CONTEXT_F1 CONTEXT_F0+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F2 CONTEXT_F1+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F3 CONTEXT_F2+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F4 CONTEXT_F3+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F5 CONTEXT_F4+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F6 CONTEXT_F5+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F7 CONTEXT_F6+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F8 CONTEXT_F7+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F9 CONTEXT_F8+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F10 CONTEXT_F9+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F11 CONTEXT_F10+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F12 CONTEXT_F11+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F13 CONTEXT_F12+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F14 CONTEXT_F13+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F15 CONTEXT_F14+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F16 CONTEXT_F15+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F17 CONTEXT_F16+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F18 CONTEXT_F17+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F19 CONTEXT_F18+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F20 CONTEXT_F19+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F21 CONTEXT_F20+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F22 CONTEXT_F21+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F23 CONTEXT_F22+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F24 CONTEXT_F23+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F25 CONTEXT_F24+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F26 CONTEXT_F25+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F27 CONTEXT_F26+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F28 CONTEXT_F27+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F29 CONTEXT_F28+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F30 CONTEXT_F29+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F31 CONTEXT_F30+SIZEOF_LOONGARCH_FPR +#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_F31+SIZEOF_LOONGARCH_FPR +#define CONTEXT_Size ((CONTEXT_FPU_OFFSET + 8 + 8 + 0xf) & ~0xf) + +#endif diff --git a/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S new file mode 100644 index 00000000000000..8084d1e3d6995c --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "unixasmmacros.inc" +#include "asmconstants.h" +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .dword LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler +__StackAllocationSize = (128 + 8 + 8 + \Alignment) // red zone + fp + ra + alignment + PROLOG_STACK_ALLOC __StackAllocationSize + .cfi_adjust_cfa_offset __StackAllocationSize + + // $fp,$ra + PROLOG_SAVE_REG_PAIR 22, 1, 0 + + bl signal_handler_worker + +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + EPILOG_RESTORE_REG_PAIR 22, 1, 0 + EPILOG_STACK_FREE __StackAllocationSize + jirl $r0, $ra, 0 + +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 8 diff --git a/src/coreclr/pal/src/arch/loongarch64/context.S b/src/coreclr/pal/src/arch/loongarch64/context.S new file mode 100644 index 00000000000000..64e8464308ca65 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/context.S @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "unixasmmacros.inc" + +#if defined(_DEBUG) +NESTED_ENTRY DBG_CheckStackAlignment, _TEXT, NoHandler + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -16 + // Reading from an unaligned stack pointer will trigger a stack alignment fault + ld.d $a0, $sp + // $fp,$ra + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, 16 + jirl $r0, $ra, 0 +NESTED_END _DBG_CheckStackAlignment, _TEXT +#endif diff --git a/src/coreclr/pal/src/arch/loongarch64/context2.S b/src/coreclr/pal/src/arch/loongarch64/context2.S new file mode 100644 index 00000000000000..ff0b6e040b42d9 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/context2.S @@ -0,0 +1,253 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// Implementation of _CONTEXT_CaptureContext for the LOONGARCH platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// Incoming: +// a0: Context* +// a1: Exception* +// +LEAF_ENTRY RtlRestoreContext, _TEXT +#ifdef HAS_ASAN + ld.w $r21, $a0, CONTEXT_ContextFlags + ext $r21, $r21, CONTEXT_FLOATING_POINT_BIT, 1 + beq $r21, $r0, LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) + + addi.d $sp, $sp, -16 + st.d a0, $sp, 0 + st.d a1, $sp, 8 + + bl __asan_handle_no_return + + ld.d $a0, $sp, 0 + ld.d $a1, $sp, 8 + addi.d $sp, $sp, 16 + +LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): +#endif + + ori $t4, $a0, 0 + ld.w $r21, $t4, CONTEXT_ContextFlags + bstrpick.w $t1, $r21, CONTEXT_FLOATING_POINT_BIT, CONTEXT_FLOATING_POINT_BIT + beq $t1, $r0, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) + + //64-bits FPR. + addi.d $t0, $t4, CONTEXT_FPU_OFFSET + + fld.d $f0, $t0, CONTEXT_F0 + fld.d $f1, $t0, CONTEXT_F1 + fld.d $f2, $t0, CONTEXT_F2 + fld.d $f3, $t0, CONTEXT_F3 + fld.d $f4, $t0, CONTEXT_F4 + fld.d $f5, $t0, CONTEXT_F5 + fld.d $f6, $t0, CONTEXT_F6 + fld.d $f7, $t0, CONTEXT_F7 + fld.d $f8, $t0, CONTEXT_F8 + fld.d $f9, $t0, CONTEXT_F9 + fld.d $f10, $t0, CONTEXT_F10 + fld.d $f11, $t0, CONTEXT_F11 + fld.d $f12, $t0, CONTEXT_F12 + fld.d $f13, $t0, CONTEXT_F13 + fld.d $f14, $t0, CONTEXT_F14 + fld.d $f15, $t0, CONTEXT_F15 + fld.d $f16, $t0, CONTEXT_F16 + fld.d $f17, $t0, CONTEXT_F17 + fld.d $f18, $t0, CONTEXT_F18 + fld.d $f19, $t0, CONTEXT_F19 + fld.d $f20, $t0, CONTEXT_F20 + fld.d $f21, $t0, CONTEXT_F21 + fld.d $f22, $t0, CONTEXT_F22 + fld.d $f23, $t0, CONTEXT_F23 + fld.d $f24, $t0, CONTEXT_F24 + fld.d $f25, $t0, CONTEXT_F25 + fld.d $f26, $t0, CONTEXT_F26 + fld.d $f27, $t0, CONTEXT_F27 + fld.d $f28, $t0, CONTEXT_F28 + fld.d $f29, $t0, CONTEXT_F29 + fld.d $f30, $t0, CONTEXT_F30 + fld.d $f31, $t0, CONTEXT_F31 + + ld.w $t1, $t0, CONTEXT_FLOAT_CONTROL_OFFSET + movgr2fcsr $fcsr0, $t1 + +LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): + + bstrpick.w $t1, $r21, CONTEXT_INTEGER_BIT, CONTEXT_INTEGER_BIT + beq $t1, $r0, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + + ld.d $tp, $a0, CONTEXT_Tp + ld.d $a1, $a0, CONTEXT_A1 + ld.d $a2, $a0, CONTEXT_A2 + ld.d $a3, $a0, CONTEXT_A3 + ld.d $a4, $a0, CONTEXT_A4 + ld.d $a5, $a0, CONTEXT_A5 + ld.d $a6, $a0, CONTEXT_A6 + ld.d $a7, $a0, CONTEXT_A7 + ld.d $t0, $a0, CONTEXT_T0 + ld.d $t1, $a0, CONTEXT_T1 + ld.d $t2, $a0, CONTEXT_T2 + ld.d $t3, $a0, CONTEXT_T3 + ld.d $t5, $a0, CONTEXT_T5 + ld.d $t6, $a0, CONTEXT_T6 + ld.d $t7, $a0, CONTEXT_T7 + ld.d $t8, $a0, CONTEXT_T8 + //ld.d $r21,$a0, CONTEXT_X0 + ld.d $s0, $a0, CONTEXT_S0 + ld.d $s1, $a0, CONTEXT_S1 + ld.d $s2, $a0, CONTEXT_S2 + ld.d $s3, $a0, CONTEXT_S3 + ld.d $s4, $a0, CONTEXT_S4 + ld.d $s5, $a0, CONTEXT_S5 + ld.d $s6, $a0, CONTEXT_S6 + ld.d $s7, $a0, CONTEXT_S7 +#ifndef CONTEXT_S8 +#error "----------------nodefine8" +#endif + ld.d $s8, $a0, CONTEXT_S8 + ld.d $a0, $a0, CONTEXT_A0 + +LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): + + ld.w $r21, $t4, CONTEXT_ContextFlags + bstrpick.w $r21, $r21, CONTEXT_CONTROL_BIT, CONTEXT_CONTROL_BIT + beq $r21, $r0, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + + ld.d $ra, $t4, CONTEXT_Ra + ld.d $fp, $t4, CONTEXT_Fp + ld.d $sp, $t4, CONTEXT_Sp + ld.d $r21, $t4, CONTEXT_Pc + ld.d $t4, $t4, CONTEXT_T4 + jirl $r0, $r21, 0 + + +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + jirl $r0, $ra, 0 +LEAF_END RtlRestoreContext, _TEXT + +// Incoming: +// a0: Context* + +LEAF_ENTRY RtlCaptureContext, _TEXT + PROLOG_STACK_ALLOC 16 + st.d $r21, $sp, 0 + li.w $r21, CONTEXT_FULL + st.w $r21, $a0, CONTEXT_ContextFlags + ld.d $r21, $sp, 0 + EPILOG_STACK_FREE 16 + b C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +// Incoming: +// a0: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + PROLOG_STACK_ALLOC 24 + st.d $t0, $sp, 0 + st.d $t1, $sp, 8 + st.d $t3, $sp, 16 + + ld.w $t1, $a0, CONTEXT_ContextFlags + li.w $t0, CONTEXT_CONTROL + and $t3, $t1, $t0 + bne $t3, $t0, LOCAL_LABEL(Done_CONTEXT_CONTROL) + + addi.d $t0, $sp, 24 + st.d $fp, $a0, CONTEXT_Fp + st.d $t0, $a0, CONTEXT_Sp + st.d $ra, $a0, CONTEXT_Ra + st.d $ra, $a0, CONTEXT_Pc + +LOCAL_LABEL(Done_CONTEXT_CONTROL): + + li.w $t0, CONTEXT_INTEGER + and $t3, $t1, $t0 + bne $t3, $t0, LOCAL_LABEL(Done_CONTEXT_INTEGER) + + ld.d $t0, $sp, 0 + ld.d $t1, $sp, 8 + ld.d $t3, $sp, 16 + + st.d $tp, $a0, CONTEXT_Tp + st.d $a0, $a0, CONTEXT_A0 + st.d $a1, $a0, CONTEXT_A1 + st.d $a2, $a0, CONTEXT_A2 + st.d $a3, $a0, CONTEXT_A3 + st.d $a4, $a0, CONTEXT_A4 + st.d $a5, $a0, CONTEXT_A5 + st.d $a6, $a0, CONTEXT_A6 + st.d $a7, $a0, CONTEXT_A7 + st.d $t0, $a0, CONTEXT_T0 + st.d $t1, $a0, CONTEXT_T1 + st.d $t2, $a0, CONTEXT_T2 + st.d $t3, $a0, CONTEXT_T3 + st.d $t4, $a0, CONTEXT_T4 + st.d $t5, $a0, CONTEXT_T5 + st.d $t6, $a0, CONTEXT_T6 + st.d $t7, $a0, CONTEXT_T7 + st.d $t8, $a0, CONTEXT_T8 + st.d $r21,$a0, CONTEXT_X0 + st.d $s0, $a0, CONTEXT_S0 + st.d $s1, $a0, CONTEXT_S1 + st.d $s2, $a0, CONTEXT_S2 + st.d $s3, $a0, CONTEXT_S3 + st.d $s4, $a0, CONTEXT_S4 + st.d $s5, $a0, CONTEXT_S5 + st.d $s6, $a0, CONTEXT_S6 + st.d $s7, $a0, CONTEXT_S7 + st.d $s8, $a0, CONTEXT_S8 + +LOCAL_LABEL(Done_CONTEXT_INTEGER): + ld.w $t1, $a0, CONTEXT_ContextFlags + + li.w $t0, CONTEXT_FLOATING_POINT + and $t3, $t1, $t0 + bne $t3, $t0, LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + + addi.d $a0, $a0, CONTEXT_FPU_OFFSET + + fst.d $f0 , $a0, CONTEXT_F0 + fst.d $f1 , $a0, CONTEXT_F1 + fst.d $f2 , $a0, CONTEXT_F2 + fst.d $f3 , $a0, CONTEXT_F3 + fst.d $f4 , $a0, CONTEXT_F4 + fst.d $f5 , $a0, CONTEXT_F5 + fst.d $f6 , $a0, CONTEXT_F6 + fst.d $f7 , $a0, CONTEXT_F7 + fst.d $f8 , $a0, CONTEXT_F8 + fst.d $f9 , $a0, CONTEXT_F9 + fst.d $f10, $a0, CONTEXT_F10 + fst.d $f11, $a0, CONTEXT_F11 + fst.d $f12, $a0, CONTEXT_F12 + fst.d $f13, $a0, CONTEXT_F13 + fst.d $f14, $a0, CONTEXT_F14 + fst.d $f15, $a0, CONTEXT_F15 + fst.d $f16, $a0, CONTEXT_F16 + fst.d $f17, $a0, CONTEXT_F17 + fst.d $f18, $a0, CONTEXT_F18 + fst.d $f19, $a0, CONTEXT_F19 + fst.d $f20, $a0, CONTEXT_F20 + fst.d $f21, $a0, CONTEXT_F21 + fst.d $f22, $a0, CONTEXT_F22 + fst.d $f23, $a0, CONTEXT_F23 + fst.d $f24, $a0, CONTEXT_F24 + fst.d $f25, $a0, CONTEXT_F25 + fst.d $f26, $a0, CONTEXT_F26 + fst.d $f27, $a0, CONTEXT_F27 + fst.d $f28, $a0, CONTEXT_F28 + fst.d $f29, $a0, CONTEXT_F29 + fst.d $f30, $a0, CONTEXT_F30 + fst.d $f31, $a0, CONTEXT_F31 + movfcsr2gr $t0, $fcsr0 + st.d $t0, $a0, CONTEXT_FLOAT_CONTROL_OFFSET + +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + EPILOG_STACK_FREE 24 + jirl $r0, $ra, 0 +LEAF_END CONTEXT_CaptureContext, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/debugbreak.S b/src/coreclr/pal/src/arch/loongarch64/debugbreak.S new file mode 100644 index 00000000000000..93fdfd8c4c5be8 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/debugbreak.S @@ -0,0 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "unixasmmacros.inc" +LEAF_ENTRY DBG_DebugBreak, _TEXT + EMIT_BREAKPOINT +LEAF_END_MARKED DBG_DebugBreak, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S b/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S new file mode 100644 index 00000000000000..bad79eeb254625 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// ==++== +// + +// ==--== +// +// Implementation of the PAL_DispatchExceptionWrapper that is +// interposed between a function that caused a hardware fault +// and PAL_DispatchException that throws an SEH exception for +// the fault, to make the stack unwindable. +// + +#include "unixasmmacros.inc" + +// Offset of the return address from the PAL_DispatchException in the PAL_DispatchExceptionWrapper +.globl C_FUNC(PAL_DispatchExceptionReturnOffset) +C_FUNC(PAL_DispatchExceptionReturnOffset): + .int LOCAL_LABEL(PAL_DispatchExceptionReturn) - C_FUNC(PAL_DispatchExceptionWrapper) + +// +// PAL_DispatchExceptionWrapper will never be called; it only serves +// to be referenced from a stack frame on the faulting thread. Its +// unwinding behavior is equivalent to any standard function. +// It is analogous to the following source file. +// +// extern "C" void PAL_DispatchException(CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord, MachExceptionInfo *pMachExceptionInfo); +// +// extern "C" void PAL_DispatchExceptionWrapper() +// { +// CONTEXT Context; +// EXCEPTION_RECORD ExceptionRecord; +// MachExceptionInfo MachExceptionInfo; +// PAL_DispatchException(&Context, &ExceptionRecord, &MachExceptionInfo); +// } +// + +NESTED_ENTRY PAL_DispatchExceptionWrapper, _TEXT, NoHandler + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -16 + // Should never actually run + EMIT_BREAKPOINT + bl EXTERNAL_C_FUNC(PAL_DispatchException) +LOCAL_LABEL(PAL_DispatchExceptionReturn): + // Should never return + EMIT_BREAKPOINT + // $fp,$ra + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, 16 + jirl $r0, $ra, 0 +NESTED_END PAL_DispatchExceptionWrapper, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S new file mode 100644 index 00000000000000..157e4149df5eb4 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers, SP, and RA from the passed in context. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT +#ifdef HAS_ASAN +#pragma error("LLVM v3.9 ASAN unimplemented on LOONGARCH yet") +#endif + addi.d $sp, $sp, -16 + .cfi_adjust_cfa_offset 16 + + // Save the FP & RA to the stack so that the unwind can work at the instruction after + // loading the FP from the context, but before loading the SP from the context. + st.d $fp, $sp, 0 + st.d $ra, $sp, 8 + .cfi_rel_offset 22, 0 + .cfi_rel_offset 1, 8 + + ld.d $tp, $a0, CONTEXT_Tp + ld.d $s0, $a0, CONTEXT_S0 + ld.d $s1, $a0, CONTEXT_S1 + ld.d $s2, $a0, CONTEXT_S2 + ld.d $s3, $a0, CONTEXT_S3 + ld.d $s4, $a0, CONTEXT_S4 + ld.d $s5, $a0, CONTEXT_S5 + ld.d $s6, $a0, CONTEXT_S6 + ld.d $s7, $a0, CONTEXT_S7 + ld.d $s8, $a0, CONTEXT_S8 + ld.d $ra, $a0, CONTEXT_Ra + + ld.d $fp, $a0, CONTEXT_Fp + ld.d $sp, $a0, CONTEXT_Sp + + // The PAL_SEHException pointer + ori $a0, $a1, 0 + b ThrowExceptionHelper +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/processor.cpp b/src/coreclr/pal/src/arch/loongarch64/processor.cpp new file mode 100644 index 00000000000000..c0cc5beb851ec0 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/processor.cpp @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/*++ + + + +Module Name: + + processor.cpp + +Abstract: + + Implementation of processor related functions for the LOONGARCH64 + platform. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" diff --git a/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp b/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp new file mode 100644 index 00000000000000..1ad1d7b0d041c5 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/signal.hpp" +#include "pal/utils.h" +#include + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) +{ + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + _ASSERTE(IS_ALIGNED(faultSp, 8)); + + if (customSp == 0) + { + // preserve 128 bytes long red zone and align stack pointer + customSp = ALIGN_DOWN(faultSp - 128, 16); + } + + size_t fakeFrameReturnAddress; + + if (IS_ALIGNED(faultSp, 16)) + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + } + else + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; + } + + // preserve 128 bytes long red zone and align stack pointer + size_t* sp = (size_t*)customSp; + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + // pushed RA + *--sp = (size_t)MCREG_Pc(ucontext->uc_mcontext); + // pushed frame pointer + *--sp = (size_t)MCREG_Fp(ucontext->uc_mcontext); + + // Switch the current context to the signal_handler_worker and the original stack + CONTEXT context2; + RtlCaptureContext(&context2); + + context2.Sp = (size_t)sp; + context2.Fp = (size_t)sp; + context2.Ra = fakeFrameReturnAddress; + context2.Pc = (size_t)signal_handler_worker; + context2.A0 = code; + context2.A1 = (size_t)siginfo; + context2.A2 = (size_t)context; + context2.A3 = (size_t)returnPoint; + + RtlRestoreContext(&context2, NULL); +} diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index b27fc9680bbedf..e8f3ac005e4dd4 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -124,7 +124,7 @@ typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size #define PRId PRId32 #define PRIA "08" #define PRIxA PRIA PRIx -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) #define PRIx PRIx64 #define PRIu PRIu64 #define PRId PRId64 @@ -1683,6 +1683,19 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_AARCH64_X27, &contextPointers->X27); GetContextPointer(cursor, unwContext, UNW_AARCH64_X28, &contextPointers->X28); GetContextPointer(cursor, unwContext, UNW_AARCH64_X29, &contextPointers->Fp); +#elif defined(TARGET_LOONGARCH64) + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R1, &contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R2, &contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R22, &contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R23, &contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R24, &contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R25, &contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R26, &contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R27, &contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R28, &contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R29, &contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R30, &contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R31, &contextPointers->S8); #elif defined(TARGET_S390X) GetContextPointer(cursor, unwContext, UNW_S390X_R6, &contextPointers->R6); GetContextPointer(cursor, unwContext, UNW_S390X_R7, &contextPointers->R7); @@ -1752,6 +1765,22 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) winContext->Pc = winContext->Pc & MACOS_ARM64_POINTER_AUTH_MASK; #endif // __APPLE__ TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp); +#elif defined(TARGET_LOONGARCH64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_LOONGARCH64_R1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_LOONGARCH64_R2, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_LOONGARCH64_R22, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_LOONGARCH64_R23, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_LOONGARCH64_R24, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_LOONGARCH64_R25, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_LOONGARCH64_R26, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_LOONGARCH64_R27, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_LOONGARCH64_R28, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_LOONGARCH64_R29, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_LOONGARCH64_R30, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_LOONGARCH64_R31, (unw_word_t *) &winContext->S8); + TRACE("sp %p pc %p fp %p tp %p ra %p\n", winContext->Sp, winContext->Pc, winContext->Fp, winContext->Tp, winContext->Ra); #elif defined(TARGET_S390X) unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->PSWAddr); unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->R15); @@ -1853,6 +1882,20 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write case UNW_AARCH64_X30: *valp = (unw_word_t)winContext->Lr; break; case UNW_AARCH64_SP: *valp = (unw_word_t)winContext->Sp; break; case UNW_AARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; +#elif defined(TARGET_LOONGARCH64) + case UNW_LOONGARCH64_R1: *valp = (unw_word_t)winContext->Ra; break; + case UNW_LOONGARCH64_R2: *valp = (unw_word_t)winContext->Tp; break; + case UNW_LOONGARCH64_R22: *valp = (unw_word_t)winContext->Fp; break; + case UNW_LOONGARCH64_R23: *valp = (unw_word_t)winContext->S0; break; + case UNW_LOONGARCH64_R24: *valp = (unw_word_t)winContext->S1; break; + case UNW_LOONGARCH64_R25: *valp = (unw_word_t)winContext->S2; break; + case UNW_LOONGARCH64_R26: *valp = (unw_word_t)winContext->S3; break; + case UNW_LOONGARCH64_R27: *valp = (unw_word_t)winContext->S4; break; + case UNW_LOONGARCH64_R28: *valp = (unw_word_t)winContext->S5; break; + case UNW_LOONGARCH64_R29: *valp = (unw_word_t)winContext->S6; break; + case UNW_LOONGARCH64_R30: *valp = (unw_word_t)winContext->S7; break; + case UNW_LOONGARCH64_R31: *valp = (unw_word_t)winContext->S8; break; + case UNW_LOONGARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; #elif defined(TARGET_S390X) case UNW_S390X_R6: *valp = (unw_word_t)winContext->R6; break; case UNW_S390X_R7: *valp = (unw_word_t)winContext->R7; break; diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index 4b149f941b5dc9..17c4d618f302df 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -176,6 +176,22 @@ enum ASSIGN_REG(R13) \ ASSIGN_REG(R14) \ ASSIGN_REG(R15) +#elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) +#define ASSIGN_UNWIND_REGS \ + ASSIGN_REG(Pc) \ + ASSIGN_REG(Tp) \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Fp) \ + ASSIGN_REG(Ra) \ + ASSIGN_REG(S0) \ + ASSIGN_REG(S1) \ + ASSIGN_REG(S2) \ + ASSIGN_REG(S3) \ + ASSIGN_REG(S4) \ + ASSIGN_REG(S5) \ + ASSIGN_REG(S6) \ + ASSIGN_REG(S7) \ + ASSIGN_REG(S8) #else #error unsupported architecture #endif @@ -404,6 +420,21 @@ void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_S390X_R12, (unw_word_t *) &winContext->R12); unw_get_reg(cursor, UNW_S390X_R13, (unw_word_t *) &winContext->R13); unw_get_reg(cursor, UNW_S390X_R14, (unw_word_t *) &winContext->R14); +#elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_LOONGARCH64_R1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_LOONGARCH64_R2, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_LOONGARCH64_R22, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_LOONGARCH64_R23, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_LOONGARCH64_R24, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_LOONGARCH64_R25, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_LOONGARCH64_R26, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_LOONGARCH64_R27, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_LOONGARCH64_R28, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_LOONGARCH64_R29, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_LOONGARCH64_R30, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_LOONGARCH64_R31, (unw_word_t *) &winContext->S8); #else #error unsupported architecture #endif @@ -489,6 +520,19 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL GetContextPointer(cursor, unwContext, UNW_S390X_R13, &contextPointers->R13); GetContextPointer(cursor, unwContext, UNW_S390X_R14, &contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_S390X_R15, &contextPointers->R15); +#elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R1, &contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R2, &contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R22, &contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R23, &contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R24, &contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R25, &contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R26, &contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R27, &contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R28, &contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R29, &contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R30, &contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R31, &contextPointers->S8); #else #error unsupported architecture #endif diff --git a/src/coreclr/pal/src/include/pal/context.h b/src/coreclr/pal/src/include/pal/context.h index 281c418aef4d2a..fd37f92693c413 100644 --- a/src/coreclr/pal/src/include/pal/context.h +++ b/src/coreclr/pal/src/include/pal/context.h @@ -78,6 +78,43 @@ using asm_sigcontext::_xstate; #elif HAVE___GREGSET_T #ifdef HOST_64BIT + +#if defined(HOST_LOONGARCH64) +#define MCREG_R0(mc) ((mc).__gregs[0]) +#define MCREG_Ra(mc) ((mc).__gregs[1]) +#define MCREG_Tp(mc) ((mc).__gregs[2]) +#define MCREG_Sp(mc) ((mc).__gregs[3]) +#define MCREG_A0(mc) ((mc).__gregs[4]) +#define MCREG_A1(mc) ((mc).__gregs[5]) +#define MCREG_A2(mc) ((mc).__gregs[6]) +#define MCREG_A3(mc) ((mc).__gregs[7]) +#define MCREG_A4(mc) ((mc).__gregs[8]) +#define MCREG_A5(mc) ((mc).__gregs[9]) +#define MCREG_A6(mc) ((mc).__gregs[10]) +#define MCREG_A7(mc) ((mc).__gregs[11]) +#define MCREG_T0(mc) ((mc).__gregs[12]) +#define MCREG_T1(mc) ((mc).__gregs[13]) +#define MCREG_T2(mc) ((mc).__gregs[14]) +#define MCREG_T3(mc) ((mc).__gregs[15]) +#define MCREG_T4(mc) ((mc).__gregs[16]) +#define MCREG_T5(mc) ((mc).__gregs[17]) +#define MCREG_T6(mc) ((mc).__gregs[18]) +#define MCREG_T7(mc) ((mc).__gregs[19]) +#define MCREG_T8(mc) ((mc).__gregs[20]) +#define MCREG_X0(mc) ((mc).__gregs[21]) +#define MCREG_Fp(mc) ((mc).__gregs[22]) +#define MCREG_S0(mc) ((mc).__gregs[23]) +#define MCREG_S1(mc) ((mc).__gregs[24]) +#define MCREG_S2(mc) ((mc).__gregs[25]) +#define MCREG_S3(mc) ((mc).__gregs[26]) +#define MCREG_S4(mc) ((mc).__gregs[27]) +#define MCREG_S5(mc) ((mc).__gregs[28]) +#define MCREG_S6(mc) ((mc).__gregs[29]) +#define MCREG_S7(mc) ((mc).__gregs[30]) +#define MCREG_S8(mc) ((mc).__gregs[31]) +#define MCREG_Pc(mc) ((mc).__pc) + +#else // HOST_LOONGARCH64 #define MCREG_Rbx(mc) ((mc).__gregs[_REG_RBX]) #define MCREG_Rcx(mc) ((mc).__gregs[_REG_RCX]) #define MCREG_Rdx(mc) ((mc).__gregs[_REG_RDX]) @@ -112,6 +149,7 @@ using asm_sigcontext::_xstate; #define FPREG_DataSelector(uc) *((WORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_dp) + 2) #define FPREG_MxCsr(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr) #define FPREG_MxCsr_Mask(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr_mask) +#endif #else // HOST_64BIT @@ -133,6 +171,43 @@ using asm_sigcontext::_xstate; #elif HAVE_GREGSET_T #ifdef HOST_64BIT + +#if defined(HOST_LOONGARCH64) +#define MCREG_R0(mc) ((mc).gregs[0]) +#define MCREG_Ra(mc) ((mc).gregs[1]) +#define MCREG_Tp(mc) ((mc).gregs[2]) +#define MCREG_Sp(mc) ((mc).gregs[3]) +#define MCREG_A0(mc) ((mc).gregs[4]) +#define MCREG_A1(mc) ((mc).gregs[5]) +#define MCREG_A2(mc) ((mc).gregs[6]) +#define MCREG_A3(mc) ((mc).gregs[7]) +#define MCREG_A4(mc) ((mc).gregs[8]) +#define MCREG_A5(mc) ((mc).gregs[9]) +#define MCREG_A6(mc) ((mc).gregs[10]) +#define MCREG_A7(mc) ((mc).gregs[11]) +#define MCREG_T0(mc) ((mc).gregs[12]) +#define MCREG_T1(mc) ((mc).gregs[13]) +#define MCREG_T2(mc) ((mc).gregs[14]) +#define MCREG_T3(mc) ((mc).gregs[15]) +#define MCREG_T4(mc) ((mc).gregs[16]) +#define MCREG_T5(mc) ((mc).gregs[17]) +#define MCREG_T6(mc) ((mc).gregs[18]) +#define MCREG_T7(mc) ((mc).gregs[19]) +#define MCREG_T8(mc) ((mc).gregs[20]) +#define MCREG_X0(mc) ((mc).gregs[21]) +#define MCREG_Fp(mc) ((mc).gregs[22]) +#define MCREG_S0(mc) ((mc).gregs[23]) +#define MCREG_S1(mc) ((mc).gregs[24]) +#define MCREG_S2(mc) ((mc).gregs[25]) +#define MCREG_S3(mc) ((mc).gregs[26]) +#define MCREG_S4(mc) ((mc).gregs[27]) +#define MCREG_S5(mc) ((mc).gregs[28]) +#define MCREG_S6(mc) ((mc).gregs[29]) +#define MCREG_S7(mc) ((mc).gregs[30]) +#define MCREG_S8(mc) ((mc).gregs[31]) +#define MCREG_Pc(mc) ((mc).pc) +#endif // HOST_LOONGARCH64 + #define MCREG_Rbx(mc) ((mc).gregs[REG_RBX]) #define MCREG_Rcx(mc) ((mc).gregs[REG_RCX]) #define MCREG_Rdx(mc) ((mc).gregs[REG_RDX]) @@ -418,6 +493,40 @@ const _STRUCT_ARM_NEON_STATE64* GetConstNativeSigSimdContext(const native_contex #endif // TARGET_OSX +#elif defined(HOST_LOONGARCH64) +#define MCREG_R0(mc) ((mc).regs[0]) +#define MCREG_Ra(mc) ((mc).regs[1]) +#define MCREG_Tp(mc) ((mc).regs[2]) +#define MCREG_Sp(mc) ((mc).regs[3]) +#define MCREG_A0(mc) ((mc).regs[4]) +#define MCREG_A1(mc) ((mc).regs[5]) +#define MCREG_A2(mc) ((mc).regs[6]) +#define MCREG_A3(mc) ((mc).regs[7]) +#define MCREG_A4(mc) ((mc).regs[8]) +#define MCREG_A5(mc) ((mc).regs[9]) +#define MCREG_A6(mc) ((mc).regs[10]) +#define MCREG_A7(mc) ((mc).regs[11]) +#define MCREG_T0(mc) ((mc).regs[12]) +#define MCREG_T1(mc) ((mc).regs[13]) +#define MCREG_T2(mc) ((mc).regs[14]) +#define MCREG_T3(mc) ((mc).regs[15]) +#define MCREG_T4(mc) ((mc).regs[16]) +#define MCREG_T5(mc) ((mc).regs[17]) +#define MCREG_T6(mc) ((mc).regs[18]) +#define MCREG_T7(mc) ((mc).regs[19]) +#define MCREG_T8(mc) ((mc).regs[20]) +#define MCREG_X0(mc) ((mc).regs[21]) +#define MCREG_Fp(mc) ((mc).regs[22]) +#define MCREG_S0(mc) ((mc).regs[23]) +#define MCREG_S1(mc) ((mc).regs[24]) +#define MCREG_S2(mc) ((mc).regs[25]) +#define MCREG_S3(mc) ((mc).regs[26]) +#define MCREG_S4(mc) ((mc).regs[27]) +#define MCREG_S5(mc) ((mc).regs[28]) +#define MCREG_S6(mc) ((mc).regs[29]) +#define MCREG_S7(mc) ((mc).regs[30]) +#define MCREG_S8(mc) ((mc).regs[31]) +#define MCREG_Pc(mc) ((mc).pc) #else // HOST_ARM64 #ifdef TARGET_OSX @@ -610,6 +719,43 @@ const VfpSigFrame* GetConstNativeSigSimdContext(const native_context_t *mc) #if HAVE_PT_REGS #ifdef HOST_64BIT + +#if defined(HOST_LOONGARCH64) +#define PTREG_R0(ptreg) ((ptreg).regs[0]) +#define PTREG_Ra(ptreg) ((ptreg).regs[1]) +#define PTREG_Tp(ptreg) ((ptreg).regs[2]) +#define PTREG_Sp(ptreg) ((ptreg).regs[3]) +#define PTREG_A0(ptreg) ((ptreg).regs[4]) +#define PTREG_A1(ptreg) ((ptreg).regs[5]) +#define PTREG_A2(ptreg) ((ptreg).regs[6]) +#define PTREG_A3(ptreg) ((ptreg).regs[7]) +#define PTREG_A4(ptreg) ((ptreg).regs[8]) +#define PTREG_A5(ptreg) ((ptreg).regs[9]) +#define PTREG_A6(ptreg) ((ptreg).regs[10]) +#define PTREG_A7(ptreg) ((ptreg).regs[11]) +#define PTREG_T0(ptreg) ((ptreg).regs[12]) +#define PTREG_T1(ptreg) ((ptreg).regs[13]) +#define PTREG_T2(ptreg) ((ptreg).regs[14]) +#define PTREG_T3(ptreg) ((ptreg).regs[15]) +#define PTREG_T4(ptreg) ((ptreg).regs[16]) +#define PTREG_T5(ptreg) ((ptreg).regs[17]) +#define PTREG_T6(ptreg) ((ptreg).regs[18]) +#define PTREG_T7(ptreg) ((ptreg).regs[19]) +#define PTREG_T8(ptreg) ((ptreg).regs[20]) +#define PTREG_X0(ptreg) ((ptreg).regs[21]) +#define PTREG_Fp(ptreg) ((ptreg).regs[22]) +#define PTREG_S0(ptreg) ((ptreg).regs[23]) +#define PTREG_S1(ptreg) ((ptreg).regs[24]) +#define PTREG_S2(ptreg) ((ptreg).regs[25]) +#define PTREG_S3(ptreg) ((ptreg).regs[26]) +#define PTREG_S4(ptreg) ((ptreg).regs[27]) +#define PTREG_S5(ptreg) ((ptreg).regs[28]) +#define PTREG_S6(ptreg) ((ptreg).regs[29]) +#define PTREG_S7(ptreg) ((ptreg).regs[30]) +#define PTREG_S8(ptreg) ((ptreg).regs[31]) +#define PTREG_Pc(ptreg) ((ptreg).csr_epc) +#endif // HOST_LOONGARCH64 + #define PTREG_Rbx(ptreg) ((ptreg).rbx) #define PTREG_Rcx(ptreg) ((ptreg).rcx) #define PTREG_Rdx(ptreg) ((ptreg).rdx) @@ -731,6 +877,8 @@ inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext) return pContext->Eip; #elif defined(HOST_ARM64) || defined(HOST_ARM) return pContext->Pc; +#elif defined(HOST_LOONGARCH64) + return pContext->Pc; #elif defined(HOST_S390X) return pContext->PSWAddr; #else @@ -746,6 +894,8 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) pContext->Eip = pc; #elif defined(HOST_ARM64) || defined(HOST_ARM) pContext->Pc = pc; +#elif defined(HOST_LOONGARCH64) + pContext->Pc = pc; #elif defined(HOST_S390X) pContext->PSWAddr = pc; #else @@ -763,6 +913,8 @@ inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) return pContext->R7; #elif defined(HOST_ARM64) return pContext->Fp; +#elif defined(HOST_LOONGARCH64) + return pContext->Fp; #elif defined(HOST_S390X) return pContext->R11; #else diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index d80bd58038cbad..f0c980a61efab7 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -46,6 +46,8 @@ namespace ELF_MACHINE = EM_X86_64, #elif defined(HOST_ARM64) ELF_MACHINE = EM_AARCH64, +#elif defined(HOST_LOONGARCH64) + ELF_MACHINE = EM_LOONGARCH, #elif defined(HOST_S390X) ELF_MACHINE = EM_S390, #else diff --git a/src/coreclr/pal/src/misc/sysinfo.cpp b/src/coreclr/pal/src/misc/sysinfo.cpp index 8f935b3e3ea1a8..f08db81244a505 100644 --- a/src/coreclr/pal/src/misc/sysinfo.cpp +++ b/src/coreclr/pal/src/misc/sysinfo.cpp @@ -581,7 +581,7 @@ PAL_GetLogicalProcessorCacheSizeFromOS() } #endif -#if defined(HOST_ARM64) && !defined(TARGET_OSX) +#if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_OSX) if (cacheSize == 0) { // It is currently expected to be missing cache size info diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index 8d630fa170fb43..80a5e3a90ffeef 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -45,6 +45,8 @@ extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode; #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #elif defined(HOST_ARM64) #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT +#elif defined(HOST_LOONGARCH64) +#define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #elif defined(HOST_S390X) #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #else @@ -171,6 +173,45 @@ typedef int __ptrace_request; ASSIGN_REG(X27) \ ASSIGN_REG(X28) +#elif defined(HOST_LOONGARCH64) +#define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Fp) \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Ra) \ + ASSIGN_REG(Pc) + + +#define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(R0) \ + ASSIGN_REG(Tp) \ + ASSIGN_REG(A0) \ + ASSIGN_REG(A1) \ + ASSIGN_REG(A2) \ + ASSIGN_REG(A3) \ + ASSIGN_REG(A4) \ + ASSIGN_REG(A5) \ + ASSIGN_REG(A6) \ + ASSIGN_REG(A7) \ + ASSIGN_REG(T0) \ + ASSIGN_REG(T1) \ + ASSIGN_REG(T2) \ + ASSIGN_REG(T3) \ + ASSIGN_REG(T4) \ + ASSIGN_REG(T5) \ + ASSIGN_REG(T6) \ + ASSIGN_REG(T7) \ + ASSIGN_REG(T8) \ + ASSIGN_REG(S0) \ + ASSIGN_REG(S1) \ + ASSIGN_REG(S2) \ + ASSIGN_REG(S3) \ + ASSIGN_REG(S4) \ + ASSIGN_REG(S5) \ + ASSIGN_REG(S6) \ + ASSIGN_REG(S7) \ + ASSIGN_REG(S8) \ + ASSIGN_REG(X0) + #elif defined(HOST_S390X) #define ASSIGN_CONTROL_REGS \ ASSIGN_REG(PSWMask) \ @@ -462,7 +503,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) #undef ASSIGN_REG #if !HAVE_FPREGS_WITH_CW -#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) +#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) #if HAVE_GREGSET_T if (native->uc_mcontext.fpregs == nullptr) #elif HAVE___GREGSET_T @@ -474,7 +515,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) // whether CONTEXT_FLOATING_POINT is set in the CONTEXT's flags. return; } -#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X +#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X && !HOST_LOONGARCH64 #endif // !HAVE_FPREGS_WITH_CW if ((lpContext->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) @@ -539,6 +580,11 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) fpregset_t *fp = &native->uc_mcontext.fpregs; static_assert_no_msg(sizeof(fp->fprs) == sizeof(lpContext->Fpr)); memcpy(fp->fprs, lpContext->Fpr, sizeof(lpContext->Fpr)); +#elif defined(HOST_LOONGARCH64) + for (int i = 0; i < 32; i++) + { + native->uc_mcontext.__fpregs[i].__val64[0] = lpContext->F[i]; + } #endif } @@ -592,7 +638,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex #undef ASSIGN_REG #if !HAVE_FPREGS_WITH_CW -#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) +#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) #if HAVE_GREGSET_T if (native->uc_mcontext.fpregs == nullptr) #elif HAVE___GREGSET_T @@ -684,6 +730,12 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex const fpregset_t *fp = &native->uc_mcontext.fpregs; static_assert_no_msg(sizeof(fp->fprs) == sizeof(lpContext->Fpr)); memcpy(lpContext->Fpr, fp->fprs, sizeof(lpContext->Fpr)); +#elif defined(HOST_LOONGARCH64) + lpContext->Fcsr = native->uc_mcontext.__fcsr; + for (int i = 0; i < 32; i++) + { + lpContext->F[i] = native->uc_mcontext.__fpregs[i].__val64[0]; + } #endif } @@ -733,6 +785,8 @@ LPVOID GetNativeContextPC(const native_context_t *context) return (LPVOID) MCREG_Pc(context->uc_mcontext); #elif defined(HOST_ARM64) return (LPVOID) MCREG_Pc(context->uc_mcontext); +#elif defined(HOST_LOONGARCH64) + return (LPVOID) MCREG_Pc(context->uc_mcontext); #elif defined(HOST_S390X) return (LPVOID) MCREG_PSWAddr(context->uc_mcontext); #else @@ -763,6 +817,8 @@ LPVOID GetNativeContextSP(const native_context_t *context) return (LPVOID) MCREG_Sp(context->uc_mcontext); #elif defined(HOST_ARM64) return (LPVOID) MCREG_Sp(context->uc_mcontext); +#elif defined(HOST_LOONGARCH64) + return (LPVOID) MCREG_Sp(context->uc_mcontext); #elif defined(HOST_S390X) return (LPVOID) MCREG_R15(context->uc_mcontext); #else diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index cd62cb917635d5..aa2ae884bced26 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -73,6 +73,8 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d # define __NR_membarrier 389 # elif defined(__aarch64__) # define __NR_membarrier 283 +# elif defined(__loongarch64) +# define __NR_membarrier 283 # else # error Unknown architecture # endif