From 3f446b3fa42593783a9ea0c188090f87144464b6 Mon Sep 17 00:00:00 2001 From: Maxim Menshikov Date: Tue, 11 Aug 2026 15:32:35 +0100 Subject: [PATCH 1/3] [RISC-V] Allow building the runtime asm without an FPU The riscv64 assembly uses f-extension loads, stores and CSR accesses unconditionally, so it does not assemble for a -march without an FPU (e.g. rv64ima). Guard those sequences on __riscv_flen. The stack slots stay reserved, so frame layouts and offsets are unchanged. fld/fsd need the D extension and are guarded on __riscv_flen >= 64: on an F-only target __riscv_flen is 32 and the double-width forms are still unavailable. This is build enablement only - on such a target nothing is transferred through the FP registers anymore, so it is usable only where the ABI never routes arguments or returns there. Signed-off-by: Maxim Menshikov --- .../debug/di/riscv64/floatconversion.S | 2 + .../Runtime/riscv64/ExceptionHandling.S | 16 ++ .../nativeaot/Runtime/riscv64/GcProbe.S | 4 + .../Runtime/riscv64/UniversalTransition.S | 6 + src/coreclr/pal/inc/unixasmmacrosriscv64.inc | 10 + src/coreclr/pal/src/arch/riscv64/context2.S | 8 + src/coreclr/vm/riscv64/asmhelpers.S | 175 ++++++++++++++++++ .../vm/riscv64/calldescrworkerriscv64.S | 6 + 8 files changed, 227 insertions(+) diff --git a/src/coreclr/debug/di/riscv64/floatconversion.S b/src/coreclr/debug/di/riscv64/floatconversion.S index 138db0bc9dd243..1b8e02957d387e 100644 --- a/src/coreclr/debug/di/riscv64/floatconversion.S +++ b/src/coreclr/debug/di/riscv64/floatconversion.S @@ -7,6 +7,8 @@ // input: (in A0) the address of the ULONGLONG to be converted to a double // output: the double corresponding to the ULONGLONG input value LEAF_ENTRY FPFillR8, .TEXT +#if __riscv_flen >= 64 fld fa0, 0(a0) +#endif ret LEAF_END FPFillR8, .TEXT diff --git a/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S b/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S index 8cbe1b6a276982..5a402bd3ce205b 100644 --- a/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S +++ b/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S @@ -31,6 +31,7 @@ .endif // Safely using available registers for floating-point saves +#if __riscv_flen >= 64 fsd fs0, 0x10(sp) fsd fs1, 0x18(sp) fsd fs2, 0x20(sp) @@ -43,6 +44,7 @@ fsd fs9, 0x58(sp) fsd fs10, 0x60(sp) fsd fs11, 0x68(sp) +#endif PROLOG_SAVE_REG_PAIR_INDEXED fp, ra, 0x78 @@ -140,6 +142,7 @@ // Load FP preserved registers // addi t3, \regdisplayReg, OFFSETOF__REGDISPLAY__F // Base address of floating-point registers +#if __riscv_flen >= 64 fld fs0, 0x40(t3) // Load fs0 fld fs1, 0x48(t3) // Load fs1 fld fs2, 0x90(t3) // Load fs2 @@ -152,6 +155,7 @@ fld fs9, 0xc8(t3) // Load fs9 fld fs10, 0xd0(t3) // Load fs10 fld fs11, 0xd8(t3) // Load fs11 +#endif .endm @@ -188,6 +192,7 @@ // Save floating-point registers addi t3, \regdisplayReg, OFFSETOF__REGDISPLAY__F +#if __riscv_flen >= 64 fsd fs0, 0x40(t3) fsd fs1, 0x48(t3) fsd fs2, 0x90(t3) @@ -200,6 +205,7 @@ fsd fs9, 0xc8(t3) fsd fs10, 0xd0(t3) fsd fs11, 0xd8(t3) +#endif .endm @@ -474,6 +480,7 @@ LOCAL_LABEL(NotHijacked): ALLOC_CALL_FUNCLET_FRAME 0x90 // Save floating-point registers +#if __riscv_flen >= 64 fsd fs0, 0x00(sp) fsd fs1, 0x08(sp) fsd fs2, 0x10(sp) @@ -486,6 +493,7 @@ LOCAL_LABEL(NotHijacked): fsd fs9, 0x48(sp) fsd fs10, 0x50(sp) fsd fs11, 0x58(sp) +#endif // Save integer registers sd a0, 0x60(sp) // Save a0 to a3 @@ -593,6 +601,7 @@ LOCAL_LABEL(DonePopping): ALLOC_CALL_FUNCLET_FRAME 0x80 // Save floating-point registers +#if __riscv_flen >= 64 fsd fs0, 0x00(sp) fsd fs1, 0x08(sp) fsd fs2, 0x10(sp) @@ -605,6 +614,7 @@ LOCAL_LABEL(DonePopping): fsd fs9, 0x48(sp) fsd fs10, 0x50(sp) fsd fs11, 0x58(sp) +#endif // Save integer registers sd a0, 0x60(sp) // Save a0 to 0x60 @@ -649,6 +659,7 @@ LOCAL_LABEL(DonePopping): amoor.w a1, a3, (t3) // Restore floating-point registers +#if __riscv_flen >= 64 fld fs0, 0x00(sp) fld fs1, 0x08(sp) fld fs2, 0x10(sp) @@ -661,6 +672,7 @@ LOCAL_LABEL(DonePopping): fld fs9, 0x48(sp) fld fs10, 0x50(sp) fld fs11, 0x58(sp) +#endif // Free call funclet frame FREE_CALL_FUNCLET_FRAME 0x80 @@ -685,6 +697,7 @@ LOCAL_LABEL(DonePopping): NESTED_ENTRY RhpCallFilterFunclet, _TEXT, NoHandler ALLOC_CALL_FUNCLET_FRAME 0x60 +#if __riscv_flen >= 64 fsd fs0, 0x00(sp) fsd fs1, 0x08(sp) fsd fs2, 0x10(sp) @@ -697,6 +710,7 @@ LOCAL_LABEL(DonePopping): fsd fs9, 0x48(sp) fsd fs10, 0x50(sp) fsd fs11, 0x58(sp) +#endif ld t3, OFFSETOF__REGDISPLAY__pFP(a2) ld fp, 0(t3) @@ -709,6 +723,7 @@ LOCAL_LABEL(DonePopping): ALTERNATE_ENTRY RhpCallFilterFunclet2 +#if __riscv_flen >= 64 fld fs0, 0x00(sp) fld fs1, 0x08(sp) fld fs2, 0x10(sp) @@ -721,6 +736,7 @@ LOCAL_LABEL(DonePopping): fld fs9, 0x48(sp) fld fs10, 0x50(sp) fld fs11, 0x58(sp) +#endif FREE_CALL_FUNCLET_FRAME 0x60 EPILOG_RETURN diff --git a/src/coreclr/nativeaot/Runtime/riscv64/GcProbe.S b/src/coreclr/nativeaot/Runtime/riscv64/GcProbe.S index 8522bc01037412..050770e34b0fc7 100644 --- a/src/coreclr/nativeaot/Runtime/riscv64/GcProbe.S +++ b/src/coreclr/nativeaot/Runtime/riscv64/GcProbe.S @@ -39,8 +39,10 @@ sd a2, 0x90(sp) # Save the FP return registers +#if __riscv_flen >= 64 fsd fa0, 0x98(sp) fsd fa1, 0xa0(sp) +#endif # Slot at sp+0xa8 is alignment padding # Perform the rest of the PInvokeTransitionFrame initialization. @@ -64,8 +66,10 @@ ld a2, 0x90(sp) // Restore the FP return registers +#if __riscv_flen >= 64 fld fa0, 0x98(sp) fld fa1, 0xa0(sp) +#endif // Restore callee saved registers EPILOG_RESTORE_REG_PAIR s1, s2, 0x20 diff --git a/src/coreclr/nativeaot/Runtime/riscv64/UniversalTransition.S b/src/coreclr/nativeaot/Runtime/riscv64/UniversalTransition.S index b38480f8113d2b..7e5fce8ced32ba 100644 --- a/src/coreclr/nativeaot/Runtime/riscv64/UniversalTransition.S +++ b/src/coreclr/nativeaot/Runtime/riscv64/UniversalTransition.S @@ -89,6 +89,7 @@ PROLOG_SAVE_REG_PAIR_INDEXED fp, ra, STACK_SIZE # Floating point registers +#if __riscv_flen >= 64 fsd fa0, FLOAT_ARG_OFFSET(sp) fsd fa1, FLOAT_ARG_OFFSET + 0x08(sp) fsd fa2, FLOAT_ARG_OFFSET + 0x10(sp) @@ -97,6 +98,7 @@ fsd fa5, FLOAT_ARG_OFFSET + 0x28(sp) fsd fa6, FLOAT_ARG_OFFSET + 0x30(sp) fsd fa7, FLOAT_ARG_OFFSET + 0x38(sp) +#endif # Space for return block data (0x10 bytes) @@ -113,6 +115,7 @@ #ifdef TRASH_SAVED_ARGUMENT_REGISTERS PREPARE_EXTERNAL_VAR RhpFpTrashValues, a1 +#if __riscv_flen >= 64 fld fa0, 0x00(a1) fld fa1, 0x08(a1) fld fa2, 0x10(a1) @@ -121,6 +124,7 @@ fld fa5, 0x28(a1) fld fa6, 0x30(a1) fld fa7, 0x38(a1) +#endif PREPARE_EXTERNAL_VAR RhpIntegerTrashValues, a1 @@ -143,6 +147,7 @@ ALTERNATE_ENTRY ReturnFrom\FunctionName mv t2, a0 # Restore floating point registers +#if __riscv_flen >= 64 fld fa0, FLOAT_ARG_OFFSET(sp) fld fa1, FLOAT_ARG_OFFSET + 0x08(sp) fld fa2, FLOAT_ARG_OFFSET + 0x10(sp) @@ -151,6 +156,7 @@ ALTERNATE_ENTRY ReturnFrom\FunctionName fld fa5, FLOAT_ARG_OFFSET + 0x28(sp) fld fa6, FLOAT_ARG_OFFSET + 0x30(sp) fld fa7, FLOAT_ARG_OFFSET + 0x38(sp) +#endif # Restore the argument registers ld a0, ARGUMENT_REGISTERS_OFFSET(sp) diff --git a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc index 406074d6f49436..5342ef99465bf9 100644 --- a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc @@ -161,6 +161,9 @@ C_FUNC(\Name): // Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS .macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs + // No-op without an FPU; the caller reserves the slots either way, so frame + // offsets are unaffected. Same for the other FP sequences in this file. +#if __riscv_flen >= 64 fsd fa0, (\ofs)(\reg) fsd fa1, (\ofs + 8)(\reg) fsd fa2, (\ofs + 16)(\reg) @@ -169,6 +172,7 @@ C_FUNC(\Name): fsd fa5, (\ofs + 40)(\reg) fsd fa6, (\ofs + 48)(\reg) fsd fa7, (\ofs + 56)(\reg) +#endif .endm // Reserve 64 bytes of memory before calling SAVE_FLOAT_CALLEESAVED_REGISTERS @@ -199,6 +203,7 @@ C_FUNC(\Name): .endm .macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs +#if __riscv_flen >= 64 fld fa0, (\ofs)(\reg) fld fa1, (\ofs + 8)(\reg) fld fa2, (\ofs + 16)(\reg) @@ -207,6 +212,7 @@ C_FUNC(\Name): fld fa5, (\ofs + 40)(\reg) fld fa6, (\ofs + 48)(\reg) fld fa7, (\ofs + 56)(\reg) +#endif .endm .macro RESTORE_FLOAT_CALLEESAVED_REGISTERS reg, ofs @@ -310,6 +316,7 @@ C_FUNC(\Name): // Save callee-saved floating point registers if requested (fs0-fs11) .if (__PWTB_PushCalleeSavedFloatRegs == 1) +#if __riscv_flen >= 64 fsd fs0, (__PWTB_FloatCalleeSavedRegisters)(sp) fsd fs1, (__PWTB_FloatCalleeSavedRegisters + 8)(sp) fsd fs2, (__PWTB_FloatCalleeSavedRegisters + 16)(sp) @@ -322,6 +329,7 @@ C_FUNC(\Name): fsd fs9, (__PWTB_FloatCalleeSavedRegisters + 72)(sp) fsd fs10, (__PWTB_FloatCalleeSavedRegisters + 80)(sp) fsd fs11, (__PWTB_FloatCalleeSavedRegisters + 88)(sp) +#endif .endif .endm @@ -405,6 +413,7 @@ C_FUNC(\Name): // Save FP callee-saved registers (fs0-fs11 = f8,f9,f18-f27) at offset 0 // RISC-V FP callee-saved: fs0=f8, fs1=f9, fs2-fs11=f18-f27 +#if __riscv_flen >= 64 fsd fs0, 0(sp) // f8 fsd fs1, 8(sp) // f9 fsd fs2, 16(sp) // f18 @@ -417,6 +426,7 @@ C_FUNC(\Name): fsd fs9, 72(sp) // f25 fsd fs10, 80(sp) // f26 fsd fs11, 88(sp) // f27 +#endif // Set target to TransitionBlock pointer addi \target, sp, 160 diff --git a/src/coreclr/pal/src/arch/riscv64/context2.S b/src/coreclr/pal/src/arch/riscv64/context2.S index 5bb06b0ecea702..7914eae9921244 100644 --- a/src/coreclr/pal/src/arch/riscv64/context2.S +++ b/src/coreclr/pal/src/arch/riscv64/context2.S @@ -26,6 +26,7 @@ LEAF_ENTRY RtlRestoreContext, _TEXT //64-bits FPR. addi t0, t4, CONTEXT_FPU_OFFSET +#if __riscv_flen >= 64 fld f0, (CONTEXT_F0)(t0) fld f1, (CONTEXT_F1)(t0) fld f2, (CONTEXT_F2)(t0) @@ -58,9 +59,12 @@ LEAF_ENTRY RtlRestoreContext, _TEXT fld f29, (CONTEXT_F29)(t0) fld f30, (CONTEXT_F30)(t0) fld f31, (CONTEXT_F31)(t0) +#endif lw t1, (CONTEXT_FLOAT_CONTROL_OFFSET)(t0) +#if __riscv_flen != 0 fscsr x0, t1 +#endif LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): @@ -205,6 +209,7 @@ LOCAL_LABEL(Done_CONTEXT_INTEGER): addi a0, a0, CONTEXT_FPU_OFFSET +#if __riscv_flen >= 64 fsd f0, (CONTEXT_F0)(a0) fsd f1, (CONTEXT_F1)(a0) fsd f2, (CONTEXT_F2)(a0) @@ -237,8 +242,11 @@ LOCAL_LABEL(Done_CONTEXT_INTEGER): fsd f29, (CONTEXT_F29)(a0) fsd f30, (CONTEXT_F30)(a0) fsd f31, (CONTEXT_F31)(a0) +#endif +#if __riscv_flen != 0 frcsr t0 +#endif sd t0, (CONTEXT_FLOAT_CONTROL_OFFSET)(a0) LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index 32614d1d2b74dc..54e3e1b139445d 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -489,8 +489,10 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler sd a2, 136(sp) // save any FP/HFA return value(s) +#if __riscv_flen >= 64 fsd f0, 144(sp) fsd f1, 152(sp) +#endif addi a0, sp, 0 call C_FUNC(OnHijackWorker) @@ -504,8 +506,10 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler ld a2, 136(sp) // restore any FP/HFA return value(s) +#if __riscv_flen >= 64 fld f0, 144(sp) fld f1, 152(sp) +#endif EPILOG_RESTORE_REG_PAIR s1, s2, 16 EPILOG_RESTORE_REG_PAIR s3, s4, 32 @@ -1244,7 +1248,9 @@ NESTED_ENTRY CallJittedMethodRetDouble, _TEXT, NoHandler ld a4, 24(fp) sd a2, 0(a4) ld a2, 16(fp) +#if __riscv_flen >= 64 fsd fa0, 0(a2) +#endif EPILOG_STACK_RESTORE EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 32 EPILOG_RETURN @@ -1268,7 +1274,9 @@ NESTED_ENTRY CallJittedMethodRetFloat, _TEXT, NoHandler ld a4, 24(fp) sd a2, 0(a4) ld a2, 16(fp) +#if __riscv_flen != 0 fsw fa0, 0(a2) +#endif EPILOG_STACK_RESTORE EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 32 EPILOG_RETURN @@ -1317,8 +1325,10 @@ NESTED_ENTRY CallJittedMethodRet2Double, _TEXT, NoHandler ld a4, 24(fp) sd a2, 0(a4) ld a2, 16(fp) +#if __riscv_flen >= 64 fsd fa0, 0(a2) fsd fa1, 8(a2) +#endif EPILOG_STACK_RESTORE EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 32 EPILOG_RETURN @@ -1342,8 +1352,10 @@ NESTED_ENTRY CallJittedMethodRet2Float, _TEXT, NoHandler ld a4, 24(fp) sd a2, 0(a4) ld a2, 16(fp) +#if __riscv_flen != 0 fsw fa0, 0(a2) fsw fa1, 4(a2) +#endif EPILOG_STACK_RESTORE EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 32 EPILOG_RETURN @@ -1367,7 +1379,9 @@ NESTED_ENTRY CallJittedMethodRetFloatInt, _TEXT, NoHandler ld a4, 24(fp) sd a2, 0(a4) ld a2, 16(fp) +#if __riscv_flen >= 64 fsd fa0, 0(a2) +#endif sd a0, 8(a2) EPILOG_STACK_RESTORE EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 32 @@ -1393,7 +1407,9 @@ NESTED_ENTRY CallJittedMethodRetIntFloat, _TEXT, NoHandler sd a2, 0(a4) ld a2, 16(fp) sd a0, 0(a2) +#if __riscv_flen >= 64 fsd fa0, 8(a2) +#endif EPILOG_STACK_RESTORE EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 32 EPILOG_RETURN @@ -1472,7 +1488,9 @@ NESTED_ENTRY InterpreterStubRetDouble, _TEXT, NoHandler mv a1, s1 // the IR bytecode pointer mv a2, zero call C_FUNC(ExecuteInterpretedMethod) +#if __riscv_flen >= 64 fld fa0, 0(a0) +#endif EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 16 EPILOG_RETURN NESTED_END InterpreterStubRetDouble, _TEXT @@ -1508,8 +1526,10 @@ NESTED_ENTRY InterpreterStubRet2Double, _TEXT, NoHandler mv a1, s1 // the IR bytecode pointer mv a2, zero call C_FUNC(ExecuteInterpretedMethod) +#if __riscv_flen >= 64 fld fa0, 0(a0) fld fa1, 8(a0) +#endif EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 16 EPILOG_RETURN NESTED_END InterpreterStubRet2Double, _TEXT @@ -1521,7 +1541,9 @@ NESTED_ENTRY InterpreterStubRetFloat, _TEXT, NoHandler mv a1, s1 // the IR bytecode pointer mv a2, zero call C_FUNC(ExecuteInterpretedMethod) +#if __riscv_flen != 0 flw fa0, 0(a0) +#endif EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 16 EPILOG_RETURN NESTED_END InterpreterStubRetFloat, _TEXT @@ -1533,8 +1555,10 @@ NESTED_ENTRY InterpreterStubRet2Float, _TEXT, NoHandler mv a1, s1 // the IR bytecode pointer mv a2, zero call C_FUNC(ExecuteInterpretedMethod) +#if __riscv_flen != 0 flw fa0, 0(a0) flw fa1, 4(a0) +#endif EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 16 EPILOG_RETURN NESTED_END InterpreterStubRet2Float, _TEXT @@ -1546,7 +1570,9 @@ NESTED_ENTRY InterpreterStubRetFloatInt, _TEXT, NoHandler mv a1, s1 // the IR bytecode pointer mv a2, zero call C_FUNC(ExecuteInterpretedMethod) +#if __riscv_flen >= 64 fld fa0, 0(a0) +#endif ld a0, 8(a0) EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 16 EPILOG_RETURN @@ -1560,7 +1586,9 @@ NESTED_ENTRY InterpreterStubRetIntFloat, _TEXT, NoHandler mv a2, zero call C_FUNC(ExecuteInterpretedMethod) ld a1, 0(a0) +#if __riscv_flen >= 64 fld fa0, 8(a0) +#endif mv a0, a1 EPILOG_RESTORE_REG_PAIR_INDEXED fp, ra, 16 EPILOG_RETURN @@ -2017,9 +2045,14 @@ ALTERNATE_ENTRY Store_A7 LEAF_END Store_A1_A2_A3_A4_A5_A6_A7 // Float point load/store routines +// +// The symbols are always defined because the call stub generator references +// them; without an FPU nothing is routed through fa0-fa7, so they are unused. LEAF_ENTRY Load_FA0 +#if __riscv_flen >= 64 fld fa0, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2027,8 +2060,10 @@ LEAF_ENTRY Load_FA0 LEAF_END Load_FA0 LEAF_ENTRY Load_FA0_FA1 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2036,11 +2071,15 @@ LEAF_ENTRY Load_FA0_FA1 LEAF_END Load_FA0_FA1 LEAF_ENTRY Load_FA0_FA1_FA2 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA2 +#if __riscv_flen >= 64 fld fa2, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2048,12 +2087,16 @@ ALTERNATE_ENTRY Load_FA2 LEAF_END Load_FA0_FA1_FA2 LEAF_ENTRY Load_FA0_FA1_FA2_FA3 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA2_FA3 +#if __riscv_flen >= 64 fld fa2, 0(t3) fld fa3, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2061,15 +2104,21 @@ ALTERNATE_ENTRY Load_FA2_FA3 LEAF_END Load_FA0_FA1_FA2_FA3 LEAF_ENTRY Load_FA0_FA1_FA2_FA3_FA4 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA2_FA3_FA4 +#if __riscv_flen >= 64 fld fa2, 0(t3) fld fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA4 +#if __riscv_flen >= 64 fld fa4, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2077,16 +2126,22 @@ ALTERNATE_ENTRY Load_FA4 LEAF_END Load_FA0_FA1_FA2_FA3_FA4 LEAF_ENTRY Load_FA0_FA1_FA2_FA3_FA4_FA5 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA2_FA3_FA4_FA5 +#if __riscv_flen >= 64 fld fa2, 0(t3) fld fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA4_FA5 +#if __riscv_flen >= 64 fld fa4, 0(t3) fld fa5, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2094,19 +2149,27 @@ ALTERNATE_ENTRY Load_FA4_FA5 LEAF_END Load_FA0_FA1_FA2_FA3_FA4_FA5 LEAF_ENTRY Load_FA0_FA1_FA2_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA2_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fld fa2, 0(t3) fld fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA4_FA5_FA6 +#if __riscv_flen >= 64 fld fa4, 0(t3) fld fa5, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA6 +#if __riscv_flen >= 64 fld fa6, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2114,20 +2177,28 @@ ALTERNATE_ENTRY Load_FA6 LEAF_END Load_FA0_FA1_FA2_FA3_FA4_FA5_FA6 LEAF_ENTRY Load_FA0_FA1_FA2_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fld fa0, 0(t3) fld fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA2_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fld fa2, 0(t3) fld fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fld fa4, 0(t3) fld fa5, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Load_FA6_FA7 +#if __riscv_flen >= 64 fld fa6, 0(t3) fld fa7, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2136,7 +2207,9 @@ LEAF_END Load_FA0_FA1_FA2_FA3_FA4_FA5_FA6_FA7 // Additional Load_FA* routines starting from FA1, FA3, FA5, FA7 LEAF_ENTRY Load_FA1 +#if __riscv_flen >= 64 fld fa1, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2144,8 +2217,10 @@ LEAF_ENTRY Load_FA1 LEAF_END Load_FA1 LEAF_ENTRY Load_FA1_FA2 +#if __riscv_flen >= 64 fld fa1, 0(t3) fld fa2, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2153,9 +2228,11 @@ LEAF_ENTRY Load_FA1_FA2 LEAF_END Load_FA1_FA2 LEAF_ENTRY Load_FA1_FA2_FA3 +#if __riscv_flen >= 64 fld fa1, 0(t3) fld fa2, 8(t3) fld fa3, 16(t3) +#endif addi t3, t3, 24 ld t4, 0(t2) addi t2, t2, 8 @@ -2163,10 +2240,12 @@ LEAF_ENTRY Load_FA1_FA2_FA3 LEAF_END Load_FA1_FA2_FA3 LEAF_ENTRY Load_FA1_FA2_FA3_FA4 +#if __riscv_flen >= 64 fld fa1, 0(t3) fld fa2, 8(t3) fld fa3, 16(t3) fld fa4, 24(t3) +#endif addi t3, t3, 32 ld t4, 0(t2) addi t2, t2, 8 @@ -2174,11 +2253,13 @@ LEAF_ENTRY Load_FA1_FA2_FA3_FA4 LEAF_END Load_FA1_FA2_FA3_FA4 LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5 +#if __riscv_flen >= 64 fld fa1, 0(t3) fld fa2, 8(t3) fld fa3, 16(t3) fld fa4, 24(t3) fld fa5, 32(t3) +#endif addi t3, t3, 40 ld t4, 0(t2) addi t2, t2, 8 @@ -2186,12 +2267,14 @@ LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5 LEAF_END Load_FA1_FA2_FA3_FA4_FA5 LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fld fa1, 0(t3) fld fa2, 8(t3) fld fa3, 16(t3) fld fa4, 24(t3) fld fa5, 32(t3) fld fa6, 40(t3) +#endif addi t3, t3, 48 ld t4, 0(t2) addi t2, t2, 8 @@ -2199,6 +2282,7 @@ LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5_FA6 LEAF_END Load_FA1_FA2_FA3_FA4_FA5_FA6 LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fld fa1, 0(t3) fld fa2, 8(t3) fld fa3, 16(t3) @@ -2206,6 +2290,7 @@ LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5_FA6_FA7 fld fa5, 32(t3) fld fa6, 40(t3) fld fa7, 48(t3) +#endif addi t3, t3, 56 ld t4, 0(t2) addi t2, t2, 8 @@ -2213,7 +2298,9 @@ LEAF_ENTRY Load_FA1_FA2_FA3_FA4_FA5_FA6_FA7 LEAF_END Load_FA1_FA2_FA3_FA4_FA5_FA6_FA7 LEAF_ENTRY Load_FA3 +#if __riscv_flen >= 64 fld fa3, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2221,8 +2308,10 @@ LEAF_ENTRY Load_FA3 LEAF_END Load_FA3 LEAF_ENTRY Load_FA3_FA4 +#if __riscv_flen >= 64 fld fa3, 0(t3) fld fa4, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2230,9 +2319,11 @@ LEAF_ENTRY Load_FA3_FA4 LEAF_END Load_FA3_FA4 LEAF_ENTRY Load_FA3_FA4_FA5 +#if __riscv_flen >= 64 fld fa3, 0(t3) fld fa4, 8(t3) fld fa5, 16(t3) +#endif addi t3, t3, 24 ld t4, 0(t2) addi t2, t2, 8 @@ -2240,10 +2331,12 @@ LEAF_ENTRY Load_FA3_FA4_FA5 LEAF_END Load_FA3_FA4_FA5 LEAF_ENTRY Load_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fld fa3, 0(t3) fld fa4, 8(t3) fld fa5, 16(t3) fld fa6, 24(t3) +#endif addi t3, t3, 32 ld t4, 0(t2) addi t2, t2, 8 @@ -2251,11 +2344,13 @@ LEAF_ENTRY Load_FA3_FA4_FA5_FA6 LEAF_END Load_FA3_FA4_FA5_FA6 LEAF_ENTRY Load_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fld fa3, 0(t3) fld fa4, 8(t3) fld fa5, 16(t3) fld fa6, 24(t3) fld fa7, 32(t3) +#endif addi t3, t3, 40 ld t4, 0(t2) addi t2, t2, 8 @@ -2263,7 +2358,9 @@ LEAF_ENTRY Load_FA3_FA4_FA5_FA6_FA7 LEAF_END Load_FA3_FA4_FA5_FA6_FA7 LEAF_ENTRY Load_FA5 +#if __riscv_flen >= 64 fld fa5, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2271,8 +2368,10 @@ LEAF_ENTRY Load_FA5 LEAF_END Load_FA5 LEAF_ENTRY Load_FA5_FA6 +#if __riscv_flen >= 64 fld fa5, 0(t3) fld fa6, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2280,9 +2379,11 @@ LEAF_ENTRY Load_FA5_FA6 LEAF_END Load_FA5_FA6 LEAF_ENTRY Load_FA5_FA6_FA7 +#if __riscv_flen >= 64 fld fa5, 0(t3) fld fa6, 8(t3) fld fa7, 16(t3) +#endif addi t3, t3, 24 ld t4, 0(t2) addi t2, t2, 8 @@ -2290,7 +2391,9 @@ LEAF_ENTRY Load_FA5_FA6_FA7 LEAF_END Load_FA5_FA6_FA7 LEAF_ENTRY Load_FA7 +#if __riscv_flen >= 64 fld fa7, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2298,7 +2401,9 @@ LEAF_ENTRY Load_FA7 LEAF_END Load_FA7 LEAF_ENTRY Store_FA0 +#if __riscv_flen >= 64 fsd fa0, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2306,8 +2411,10 @@ LEAF_ENTRY Store_FA0 LEAF_END Store_FA0 LEAF_ENTRY Store_FA0_FA1 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2315,11 +2422,15 @@ LEAF_ENTRY Store_FA0_FA1 LEAF_END Store_FA0_FA1 LEAF_ENTRY Store_FA0_FA1_FA2 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA2 +#if __riscv_flen >= 64 fsd fa2, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2327,12 +2438,16 @@ ALTERNATE_ENTRY Store_FA2 LEAF_END Store_FA0_FA1_FA2 LEAF_ENTRY Store_FA0_FA1_FA2_FA3 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA2_FA3 +#if __riscv_flen >= 64 fsd fa2, 0(t3) fsd fa3, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2340,15 +2455,21 @@ ALTERNATE_ENTRY Store_FA2_FA3 LEAF_END Store_FA0_FA1_FA2_FA3 LEAF_ENTRY Store_FA0_FA1_FA2_FA3_FA4 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA2_FA3_FA4 +#if __riscv_flen >= 64 fsd fa2, 0(t3) fsd fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA4 +#if __riscv_flen >= 64 fsd fa4, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2356,16 +2477,22 @@ ALTERNATE_ENTRY Store_FA4 LEAF_END Store_FA0_FA1_FA2_FA3_FA4 LEAF_ENTRY Store_FA0_FA1_FA2_FA3_FA4_FA5 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA2_FA3_FA4_FA5 +#if __riscv_flen >= 64 fsd fa2, 0(t3) fsd fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA4_FA5 +#if __riscv_flen >= 64 fsd fa4, 0(t3) fsd fa5, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2373,19 +2500,27 @@ ALTERNATE_ENTRY Store_FA4_FA5 LEAF_END Store_FA0_FA1_FA2_FA3_FA4_FA5 LEAF_ENTRY Store_FA0_FA1_FA2_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA2_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fsd fa2, 0(t3) fsd fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA4_FA5_FA6 +#if __riscv_flen >= 64 fsd fa4, 0(t3) fsd fa5, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA6 +#if __riscv_flen >= 64 fsd fa6, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2393,20 +2528,28 @@ ALTERNATE_ENTRY Store_FA6 LEAF_END Store_FA0_FA1_FA2_FA3_FA4_FA5_FA6 LEAF_ENTRY Store_FA0_FA1_FA2_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fsd fa0, 0(t3) fsd fa1, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA2_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fsd fa2, 0(t3) fsd fa3, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fsd fa4, 0(t3) fsd fa5, 8(t3) +#endif addi t3, t3, 16 ALTERNATE_ENTRY Store_FA6_FA7 +#if __riscv_flen >= 64 fsd fa6, 0(t3) fsd fa7, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2415,7 +2558,9 @@ LEAF_END Store_FA0_FA1_FA2_FA3_FA4_FA5_FA6_FA7 // Additional Store_FA* routines starting from FA1, FA3, FA5, FA7 LEAF_ENTRY Store_FA1 +#if __riscv_flen >= 64 fsd fa1, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2423,8 +2568,10 @@ LEAF_ENTRY Store_FA1 LEAF_END Store_FA1 LEAF_ENTRY Store_FA1_FA2 +#if __riscv_flen >= 64 fsd fa1, 0(t3) fsd fa2, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2432,9 +2579,11 @@ LEAF_ENTRY Store_FA1_FA2 LEAF_END Store_FA1_FA2 LEAF_ENTRY Store_FA1_FA2_FA3 +#if __riscv_flen >= 64 fsd fa1, 0(t3) fsd fa2, 8(t3) fsd fa3, 16(t3) +#endif addi t3, t3, 24 ld t4, 0(t2) addi t2, t2, 8 @@ -2442,10 +2591,12 @@ LEAF_ENTRY Store_FA1_FA2_FA3 LEAF_END Store_FA1_FA2_FA3 LEAF_ENTRY Store_FA1_FA2_FA3_FA4 +#if __riscv_flen >= 64 fsd fa1, 0(t3) fsd fa2, 8(t3) fsd fa3, 16(t3) fsd fa4, 24(t3) +#endif addi t3, t3, 32 ld t4, 0(t2) addi t2, t2, 8 @@ -2453,11 +2604,13 @@ LEAF_ENTRY Store_FA1_FA2_FA3_FA4 LEAF_END Store_FA1_FA2_FA3_FA4 LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5 +#if __riscv_flen >= 64 fsd fa1, 0(t3) fsd fa2, 8(t3) fsd fa3, 16(t3) fsd fa4, 24(t3) fsd fa5, 32(t3) +#endif addi t3, t3, 40 ld t4, 0(t2) addi t2, t2, 8 @@ -2465,12 +2618,14 @@ LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5 LEAF_END Store_FA1_FA2_FA3_FA4_FA5 LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fsd fa1, 0(t3) fsd fa2, 8(t3) fsd fa3, 16(t3) fsd fa4, 24(t3) fsd fa5, 32(t3) fsd fa6, 40(t3) +#endif addi t3, t3, 48 ld t4, 0(t2) addi t2, t2, 8 @@ -2478,6 +2633,7 @@ LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5_FA6 LEAF_END Store_FA1_FA2_FA3_FA4_FA5_FA6 LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fsd fa1, 0(t3) fsd fa2, 8(t3) fsd fa3, 16(t3) @@ -2485,6 +2641,7 @@ LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5_FA6_FA7 fsd fa5, 32(t3) fsd fa6, 40(t3) fsd fa7, 48(t3) +#endif addi t3, t3, 56 ld t4, 0(t2) addi t2, t2, 8 @@ -2492,7 +2649,9 @@ LEAF_ENTRY Store_FA1_FA2_FA3_FA4_FA5_FA6_FA7 LEAF_END Store_FA1_FA2_FA3_FA4_FA5_FA6_FA7 LEAF_ENTRY Store_FA3 +#if __riscv_flen >= 64 fsd fa3, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2500,8 +2659,10 @@ LEAF_ENTRY Store_FA3 LEAF_END Store_FA3 LEAF_ENTRY Store_FA3_FA4 +#if __riscv_flen >= 64 fsd fa3, 0(t3) fsd fa4, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2509,9 +2670,11 @@ LEAF_ENTRY Store_FA3_FA4 LEAF_END Store_FA3_FA4 LEAF_ENTRY Store_FA3_FA4_FA5 +#if __riscv_flen >= 64 fsd fa3, 0(t3) fsd fa4, 8(t3) fsd fa5, 16(t3) +#endif addi t3, t3, 24 ld t4, 0(t2) addi t2, t2, 8 @@ -2519,10 +2682,12 @@ LEAF_ENTRY Store_FA3_FA4_FA5 LEAF_END Store_FA3_FA4_FA5 LEAF_ENTRY Store_FA3_FA4_FA5_FA6 +#if __riscv_flen >= 64 fsd fa3, 0(t3) fsd fa4, 8(t3) fsd fa5, 16(t3) fsd fa6, 24(t3) +#endif addi t3, t3, 32 ld t4, 0(t2) addi t2, t2, 8 @@ -2530,11 +2695,13 @@ LEAF_ENTRY Store_FA3_FA4_FA5_FA6 LEAF_END Store_FA3_FA4_FA5_FA6 LEAF_ENTRY Store_FA3_FA4_FA5_FA6_FA7 +#if __riscv_flen >= 64 fsd fa3, 0(t3) fsd fa4, 8(t3) fsd fa5, 16(t3) fsd fa6, 24(t3) fsd fa7, 32(t3) +#endif addi t3, t3, 40 ld t4, 0(t2) addi t2, t2, 8 @@ -2542,7 +2709,9 @@ LEAF_ENTRY Store_FA3_FA4_FA5_FA6_FA7 LEAF_END Store_FA3_FA4_FA5_FA6_FA7 LEAF_ENTRY Store_FA5 +#if __riscv_flen >= 64 fsd fa5, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 @@ -2550,8 +2719,10 @@ LEAF_ENTRY Store_FA5 LEAF_END Store_FA5 LEAF_ENTRY Store_FA5_FA6 +#if __riscv_flen >= 64 fsd fa5, 0(t3) fsd fa6, 8(t3) +#endif addi t3, t3, 16 ld t4, 0(t2) addi t2, t2, 8 @@ -2559,9 +2730,11 @@ LEAF_ENTRY Store_FA5_FA6 LEAF_END Store_FA5_FA6 LEAF_ENTRY Store_FA5_FA6_FA7 +#if __riscv_flen >= 64 fsd fa5, 0(t3) fsd fa6, 8(t3) fsd fa7, 16(t3) +#endif addi t3, t3, 24 ld t4, 0(t2) addi t2, t2, 8 @@ -2569,7 +2742,9 @@ LEAF_ENTRY Store_FA5_FA6_FA7 LEAF_END Store_FA5_FA6_FA7 LEAF_ENTRY Store_FA7 +#if __riscv_flen >= 64 fsd fa7, 0(t3) +#endif addi t3, t3, 8 ld t4, 0(t2) addi t2, t2, 8 diff --git a/src/coreclr/vm/riscv64/calldescrworkerriscv64.S b/src/coreclr/vm/riscv64/calldescrworkerriscv64.S index 54725758b41b27..73e901a15e11ca 100644 --- a/src/coreclr/vm/riscv64/calldescrworkerriscv64.S +++ b/src/coreclr/vm/riscv64/calldescrworkerriscv64.S @@ -44,6 +44,7 @@ LOCAL_LABEL(donestack): ld t4, CallDescrData__pFloatArgumentRegisters(s1) beq t4, zero, LOCAL_LABEL(NoFloatingPoint) +#if __riscv_flen >= 64 fld fa0, 0(t4) fld fa1, 8(t4) fld fa2, 16(t4) @@ -52,6 +53,7 @@ LOCAL_LABEL(donestack): fld fa5, 40(t4) fld fa6, 48(t4) fld fa7, 56(t4) +#endif LOCAL_LABEL(NoFloatingPoint): // Copy [pArgumentRegisters, ..., pArgumentRegisters + 56] @@ -80,7 +82,9 @@ LOCAL_LABEL(CallDescrWorkerInternalReturnAddress): // Just save the returned registers (fa0, fa1/a0) and let CopyReturnedFpStructFromRegisters worry about placing // the fields as they were originally laid out in memory. +#if __riscv_flen >= 64 fsd fa0, CallDescrData__returnValue(s1) // fa0 is always occupied; we have at least one floating field +#endif andi a3, a3, FpStruct__BothFloat bne a3, zero, LOCAL_LABEL(SecondFieldFloatReturn) @@ -91,7 +95,9 @@ LOCAL_LABEL(CallDescrWorkerInternalReturnAddress): j LOCAL_LABEL(ReturnDone) LOCAL_LABEL(SecondFieldFloatReturn): +#if __riscv_flen >= 64 fsd fa1, (CallDescrData__returnValue + 8)(s1) +#endif j LOCAL_LABEL(ReturnDone) LOCAL_LABEL(IntReturn): From 0b13d7d04a5f698a8ad0f1e2b8e22dddaad275c0 Mon Sep 17 00:00:00 2001 From: Maxim Menshikov Date: Tue, 11 Aug 2026 15:32:43 +0100 Subject: [PATCH 2/3] [RISC-V] Fix FixupPrecodeCode without the C extension FixupPrecodeCode hardcodes a 2-byte c.jr and the data offsets derived from it, so it neither assembles nor lays out correctly for a -march without the compressed extension. Pick the layout on __riscv_compressed: with the 4-byte jr the second auipc moves from 0xe to 0x10 and the thunk grows to 32 bytes, exactly FixupPrecode::CodeSize. The jump also decides where the thunk's second half begins, which the VM installs as the initial Target, so FixupPrecode::FixupCodeOffset follows the same switch - 0xa with c.jr, 0xc with jr. Without it the first fixup of every method jumps into the middle of an instruction. The constant is compile-time, so the runtime and any DAC built for it have to use the same -march. Signed-off-by: Maxim Menshikov --- src/coreclr/vm/precode.h | 6 ++++++ src/coreclr/vm/riscv64/thunktemplates.S | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/coreclr/vm/precode.h b/src/coreclr/vm/precode.h index 2b6aef0db9251a..ff5b21fa0a12be 100644 --- a/src/coreclr/vm/precode.h +++ b/src/coreclr/vm/precode.h @@ -394,7 +394,13 @@ struct FixupPrecode static const int FixupCodeOffset = 12; #elif defined(TARGET_RISCV64) static const SIZE_T CodeSize = 32; + // The thunk's second half starts after the tail jump, which is 2 bytes + // shorter with the C extension. Keep in sync with thunktemplates.S. +#ifdef __riscv_compressed static const int FixupCodeOffset = 10; +#else + static const int FixupCodeOffset = 12; +#endif #endif // TARGET_AMD64 BYTE m_code[CodeSize]; diff --git a/src/coreclr/vm/riscv64/thunktemplates.S b/src/coreclr/vm/riscv64/thunktemplates.S index ce4e1d4b912025..34fae32559e42d 100644 --- a/src/coreclr/vm/riscv64/thunktemplates.S +++ b/src/coreclr/vm/riscv64/thunktemplates.S @@ -14,6 +14,9 @@ LEAF_END_MARKED StubPrecodeCode LEAF_ENTRY FixupPrecodeCode auipc t2, 0x4 ld t2, (FixupPrecodeData__Target)(t2) + // Without the C extension the tail jump is 4 bytes instead of 2, shifting + // the rest of the thunk by 2. Keep in sync with FixupPrecode::FixupCodeOffset. +#ifdef __riscv_compressed c.jr t2 fence r,rw @@ -21,6 +24,15 @@ LEAF_ENTRY FixupPrecodeCode ld t1, (FixupPrecodeData__PrecodeFixupThunk - 0xe)(t2) ld t2, (FixupPrecodeData__MethodDesc - 0xe)(t2) jr t1 +#else + jr t2 + + fence r,rw + auipc t2, 0x4 + ld t1, (FixupPrecodeData__PrecodeFixupThunk - 0x10)(t2) + ld t2, (FixupPrecodeData__MethodDesc - 0x10)(t2) + jr t1 +#endif LEAF_END_MARKED FixupPrecodeCode #ifdef FEATURE_TIERED_COMPILATION From b5931735571ece77746c99f231ae3e32c7341439 Mon Sep 17 00:00:00 2001 From: Maxim Menshikov Date: Tue, 11 Aug 2026 15:46:24 +0100 Subject: [PATCH 3/3] [RISC-V] Allow building the runtime asm without the A extension The NativeAOT exception handling helpers and the write barriers use amoand.w, amoor.w, lr.d/sc.d and amoswap.d unconditionally, so they do not assemble for a -march without the A extension (e.g. rv64ima). Emit plain load/modify/store sequences there instead. The fallbacks are not atomic: RhpCheckedLockCmpXchg and RhpCheckedXchg lose the interlocked guarantee the GC relies on for objectref updates, and so do the Thread state flag updates. This is build enablement for targets that cannot observe the difference, not a substitute for the A extension. The fallbacks also leave the new value in rd where amo* leaves the old one; no caller uses rd. Signed-off-by: Maxim Menshikov --- .../Runtime/riscv64/ExceptionHandling.S | 28 +++++++++++++++++++ src/coreclr/runtime/riscv64/WriteBarriers.S | 13 +++++++++ 2 files changed, 41 insertions(+) diff --git a/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S b/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S index 5a402bd3ce205b..21b1ac1b2e22a7 100644 --- a/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S +++ b/src/coreclr/nativeaot/Runtime/riscv64/ExceptionHandling.S @@ -519,7 +519,14 @@ LOCAL_LABEL(NotHijacked): addi t3, a5, OFFSETOF__Thread__m_ThreadStateFlags addiw a6, zero, -17 // Mask value (0xFFFFFFEF) +#ifdef __riscv_atomic amoand.w a4, a6, (t3) +#else + // No A extension: non-atomic read-modify-write. + lw a4, (t3) + and a4, a4, a6 + sw a4, (t3) +#endif // Set preserved regs to the values expected by the funclet RESTORE_PRESERVED_REGISTERS a2 @@ -633,7 +640,14 @@ LOCAL_LABEL(DonePopping): // Set the DoNotTriggerGc flag addi t3, a2, OFFSETOF__Thread__m_ThreadStateFlags addiw a3, zero, -17 // Mask value (0xFFFFFFEF) +#ifdef __riscv_atomic amoand.w a4, a3, (t3) +#else + // No A extension: non-atomic read-modify-write. + lw a4, (t3) + and a4, a4, a3 + sw a4, (t3) +#endif // Restore preserved registers RESTORE_PRESERVED_REGISTERS a1 @@ -656,7 +670,14 @@ LOCAL_LABEL(DonePopping): addi t3, a2, OFFSETOF__Thread__m_ThreadStateFlags addiw a3, zero, 16 // Mask value (0x10) +#ifdef __riscv_atomic amoor.w a1, a3, (t3) +#else + // No A extension: non-atomic read-modify-write. + lw a1, (t3) + or a1, a1, a3 + sw a1, (t3) +#endif // Restore floating-point registers #if __riscv_flen >= 64 @@ -790,7 +811,14 @@ LOCAL_LABEL(DonePopping): addi t3, a5, OFFSETOF__Thread__m_ThreadStateFlags addiw a6, zero, -17 // Mask value (0xFFFFFFEF) +#ifdef __riscv_atomic amoand.w a4, t3, a6 +#else + // No A extension: non-atomic read-modify-write. + lw a4, (t3) + and a4, a4, a6 + sw a4, (t3) +#endif // set preserved regs to the values expected by the funclet RESTORE_PRESERVED_REGISTERS a2 diff --git a/src/coreclr/runtime/riscv64/WriteBarriers.S b/src/coreclr/runtime/riscv64/WriteBarriers.S index c4a336be1caeb4..4dc36d2822d772 100644 --- a/src/coreclr/runtime/riscv64/WriteBarriers.S +++ b/src/coreclr/runtime/riscv64/WriteBarriers.S @@ -277,6 +277,7 @@ LEAF_END RhpAssignRef, _TEXT LEAF_ENTRY RhpCheckedLockCmpXchg LOCAL_LABEL(CmpXchgRetry): +#ifdef __riscv_atomic // Load the current value at the destination address. lr.d.aqrl t0, (a0) // t0 = *dest (load with acquire-release ordering) // Compare the loaded value with the comparand. @@ -285,6 +286,12 @@ LOCAL_LABEL(CmpXchgRetry): // Attempt to store the exchange value at the destination address. sc.d.rl t1, a1, (a0) // t1 = (store conditional result: 0 if successful, with release ordering) bnez t1, LOCAL_LABEL(CmpXchgRetry) // if store conditional failed, retry +#else + // No A extension: non-atomic compare-and-swap. + ld t0, (a0) + bne t0, a2, LOCAL_LABEL(CmpXchgNoUpdate) + sd a1, (a0) +#endif // See comment at the top of PalInterlockedOperationBarrier method for explanation why this memory // barrier is necessary. @@ -321,7 +328,13 @@ LEAF_END RhpCheckedLockCmpXchg // t1, t6: trashed // LEAF_ENTRY RhpCheckedXchg +#ifdef __riscv_atomic amoswap.d.aqrl t1, a1, (a0) +#else + // No A extension: non-atomic exchange, old value in t1. + ld t1, (a0) + sd a1, (a0) +#endif // See comment at the top of PalInterlockedOperationBarrier method for explanation why this memory // barrier is necessary.