diff --git a/gnu-efi/Make.defaults b/gnu-efi/Make.defaults index 59b6508..eca3c67 100755 --- a/gnu-efi/Make.defaults +++ b/gnu-efi/Make.defaults @@ -36,7 +36,7 @@ TOPDIR ?= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) -ARCHES = ia32 x86_64 ia64 aarch64 arm mips64el +ARCHES = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 # # Variables below overridable from command-line: diff --git a/gnu-efi/gnuefi/crt0-efi-riscv64.S b/gnu-efi/gnuefi/crt0-efi-riscv64.S new file mode 100644 index 0000000..296d03d --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-riscv64.S @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ +/* + * Copyright (C) 2014 Linaro Ltd. + * Copyright (C) 2018 Alexander Graf + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + + .text + .globl _start + .type _start,%function +_start: + addi sp, sp, -24 + sd a0, 0(sp) + sd a1, 8(sp) + sd ra, 16(sp) + lla a0, ImageBase + lla a1, _DYNAMIC + call _relocate + bne a0, zero, .L_exit + ld a1, 8(sp) + ld a0, 0(sp) + call efi_main + ld ra, 16(sp) +.L_exit: + addi sp, sp, 24 + ret + +// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: + + .data +dummy0: .4byte 0 +dummy1: .4byte 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc, "a", %progbits + .4byte dummy1 - dummy0 // Page RVA + .4byte 12 // Block Size (2*4+2*2), must be aligned by 32 Bits + .2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy + .2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy + +#if defined(__ELF__) && defined(__linux__) + .section .note.GNU-stack,"",%progbits +#endif diff --git a/gnu-efi/gnuefi/elf_riscv64_efi.lds b/gnu-efi/gnuefi/elf_riscv64_efi.lds new file mode 100644 index 0000000..d6663ee --- /dev/null +++ b/gnu-efi/gnuefi/elf_riscv64_efi.lds @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ + +OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .eh_frame : { *(.eh_frame) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .gcc_except_table : { *(.gcc_except_table*) } + . = ALIGN(4096); + .text : { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + . = ALIGN(16); + } + _etext = .; + _text_size = _etext - _text; + . = ALIGN(65536); + _DYNAMIC = .; + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .data : + { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + __init_array_start = .; + *(SORT(.init_array.*)) + *(.init_array) + __init_array_end = .; + . = ALIGN(16); + __CTOR_LIST__ = .; + *(SORT(.ctors.*)) + *(.ctors) + __CTOR_END__ = .; + . = ALIGN(16); + __DTOR_LIST__ = .; + *(SORT(.dtors.*)) + *(.dtors) + __DTOR_END__ = .; + . = ALIGN(16); + __fini_array_start = .; + *(SORT(.fini_array.*)) + *(.fini_array) + __fini_array_end = .; + + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss*) + *(COMMON) + *(.rel.local) + . = ALIGN(16); + + _bss_end = .; + } + . = ALIGN(4096); + .reloc : + { + KEEP (*(.reloc)) + } + + . = ALIGN(4096); + .rela : + { + *(.rela.text*) + *(.rela.data*) + *(.rela.got) + *(.rela.dyn) + *(.rela.stab) + *(.rela.init_array*) + *(.rela.fini_array*) + *(.rela.ctors*) + *(.rela.dtors*) + + } + . = ALIGN(4096); + .rela.plt : { *(.rela.plt) } + . = ALIGN(4096); + .rodata : { *(.rodata*) } + . = ALIGN(512); + _edata = .; + _data_size = _edata - _data; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + .ignored.reloc : + { + *(.rela.reloc) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/reloc_riscv64.c b/gnu-efi/gnuefi/reloc_riscv64.c new file mode 100644 index 0000000..207a76b --- /dev/null +++ b/gnu-efi/gnuefi/reloc_riscv64.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* reloc_riscv.c - position independent ELF shared object relocator + Copyright (C) 2018 Alexander Graf + Copyright (C) 2014 Linaro Ltd. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include + +#include "subst/elf.h" + +#define Elf_Dyn Elf64_Dyn +#define Elf_Rela Elf64_Rela +#define ELF_R_TYPE ELF64_R_TYPE + +EFI_STATUS EFIAPI _relocate(long ldbase, Elf_Dyn *dyn) +{ + long relsz = 0, relent = 0; + Elf_Rela *rel = NULL; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf_Rela *)((unsigned long)dyn[i].d_un.d_ptr + ldbase); + break; + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF_R_TYPE(rel->r_info)) { + case R_RISCV_RELATIVE: + addr = (unsigned long *)(ldbase + rel->r_offset); + *addr = ldbase + rel->r_addend; + break; + default: + break; + } + rel = (Elf_Rela *)((char *)rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/inc/efi.h b/gnu-efi/inc/efi.h index bd99451..f87477b 100644 --- a/gnu-efi/inc/efi.h +++ b/gnu-efi/inc/efi.h @@ -50,6 +50,8 @@ Revision History #include "arm/efibind.h" #elif defined (_M_MIPS64) || defined(__mips64__) #include "mips64el/efibind.h" +#elif defined (__riscv) && __riscv_xlen == 64 +#include "riscv64/efibind.h" #else #error Usupported architecture #endif diff --git a/gnu-efi/inc/efilib.h b/gnu-efi/inc/efilib.h index 6c34653..568d327 100644 --- a/gnu-efi/inc/efilib.h +++ b/gnu-efi/inc/efilib.h @@ -33,6 +33,8 @@ Revision History #include "arm/efilibplat.h" #elif defined (_M_MIPS64) || defined(__mips64__) #include "mips64el/efilibplat.h" +#elif defined (__riscv) && __riscv_xlen == 64 +#include "riscv64/efilibplat.h" #endif #include "efilink.h" #include "efirtlib.h" diff --git a/gnu-efi/inc/efirtlib.h b/gnu-efi/inc/efirtlib.h index 5071493..8643061 100644 --- a/gnu-efi/inc/efirtlib.h +++ b/gnu-efi/inc/efirtlib.h @@ -32,6 +32,8 @@ Revision History #include "arm/efilibplat.h" #elif defined (_M_MIPS64) || defined(__mips64__) #include "mips64el/efilibplat.h" +#elif defined (__riscv) && __riscv_xlen == 64 +#include "riscv64/efilibplat.h" #endif diff --git a/gnu-efi/inc/riscv64/efibind.h b/gnu-efi/inc/riscv64/efibind.h new file mode 100644 index 0000000..a2b9c18 --- /dev/null +++ b/gnu-efi/inc/riscv64/efibind.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ +/* + * Copyright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#include +#include + +// +// Basic EFI types of various widths +// + +typedef uint64_t UINT64; +typedef int64_t INT64; +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef unsigned char CHAR8; +typedef uint16_t CHAR16; +#define WCHAR CHAR16 +#undef VOID +typedef void VOID; +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR(a) (EFI_ERROR_MASK | a) +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while(1); + +// +// Pointers must be aligned to these address to function +// +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value, Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + +// +// Define macros to build data structure signatures from characters. +// +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/gnu-efi/inc/riscv64/efilibplat.h b/gnu-efi/inc/riscv64/efilibplat.h new file mode 100644 index 0000000..055cb47 --- /dev/null +++ b/gnu-efi/inc/riscv64/efilibplat.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); diff --git a/gnu-efi/inc/riscv64/efisetjmp_arch.h b/gnu-efi/inc/riscv64/efisetjmp_arch.h new file mode 100644 index 0000000..b9fab7c --- /dev/null +++ b/gnu-efi/inc/riscv64/efisetjmp_arch.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ + +#ifndef GNU_EFI_RISCV64_SETJMP_H +#define GNU_EFI_RISCV64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 s0; + UINT64 s1; + UINT64 s2; + UINT64 s3; + UINT64 s4; + UINT64 s5; + UINT64 s6; + UINT64 s7; + UINT64 s8; + UINT64 s9; + UINT64 s10; + UINT64 s11; + UINT64 sp; + UINT64 ra; + + /* FP regs */ + UINT64 fs0; + UINT64 fs1; + UINT64 fs2; + UINT64 fs3; + UINT64 fs4; + UINT64 fs5; + UINT64 fs6; + UINT64 fs7; + UINT64 fs8; + UINT64 fs9; + UINT64 fs10; + UINT64 fs11; +} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1]; + +#endif /* GNU_EFI_RISCV64_SETJMP_H */ diff --git a/gnu-efi/inc/subst/elf.h b/gnu-efi/inc/subst/elf.h new file mode 100644 index 0000000..c953563 --- /dev/null +++ b/gnu-efi/inc/subst/elf.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2024 GNU-EFI Contributors + +This library is free software; +you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; +either version 2.1 of the License, or (at your option) any later version. +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along with this library; +if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#if !defined(__GNU_EFI_NO_GLIBC) +#include + +#else + +typedef uint32_t Elf32_Addr; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef uint64_t Elf64_Addr; +typedef int64_t Elf64_Sxword; +typedef uint64_t Elf64_Xword; + + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + } Elf32_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; + } Elf64_Rela; + +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; + } Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; + } Elf64_Dyn; + +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +#define DT_NULL 0 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_PLTGOT 3 + + +#define R_AARCH64_NONE 0 +#define R_AARCH64_RELATIVE 1027 +#define R_RISCV_RELATIVE 3 +#define R_LARCH_NONE 0 +#define R_LARCH_RELATIVE 3 +#define R_X86_64_NONE 0 +#define R_X86_64_RELATIVE 8 +#define R_ARM_NONE 0 +#define R_ARM_RELATIVE 23 +#define R_386_NONE 0 +#define R_386_RELATIVE 8 +#define R_MIPS_NONE 0 +#define R_MIPS_64 18 +#define R_MIPS_REL32 3 + + +#endif diff --git a/gnu-efi/lib/init.c b/gnu-efi/lib/init.c index d979029..40591c7 100644 --- a/gnu-efi/lib/init.c +++ b/gnu-efi/lib/init.c @@ -144,7 +144,7 @@ InitializeUnicodeSupport ( // Languages = Ui->SupportedLanguages; - Length = strlen(Languages); + Length = strlen((const char *)Languages); for (Position=0; Position < Length; Position += ISO_639_2_ENTRY_SIZE) { // diff --git a/gnu-efi/lib/misc.c b/gnu-efi/lib/misc.c index c9a4b0b..853ca21 100644 --- a/gnu-efi/lib/misc.c +++ b/gnu-efi/lib/misc.c @@ -556,7 +556,7 @@ LibGetUiString ( // Search for the match // while (Array->LangCode) { - if (strcmp(Array->LangCode, LangCode) == 0) { + if (strcmp((const char *)Array->LangCode, (const char *)LangCode) == 0) { return Array->UiString; } } diff --git a/gnu-efi/lib/riscv64/initplat.c b/gnu-efi/lib/riscv64/initplat.c new file mode 100644 index 0000000..3666fcc --- /dev/null +++ b/gnu-efi/lib/riscv64/initplat.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} diff --git a/gnu-efi/lib/riscv64/math.c b/gnu-efi/lib/riscv64/math.c new file mode 100644 index 0000000..3653e42 --- /dev/null +++ b/gnu-efi/lib/riscv64/math.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * This code is based on EDK II MdePkg/Library/BaseLib/Math64.c + * Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. + */ + +#include "lib.h" + +/** + * LShiftU64() - left shift + */ +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count +) +{ + return Operand << Count; +} + +/** + * RShiftU64() - right shift + */ +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count +) +{ + return Operand >> Count; +} + +/** + * MultU64x32() - multiply + */ +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier +) +{ + return Multiplicand * Multiplier; +} + +/** + * DivU64x32() - divide + */ +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL +) +{ + ASSERT(Divisor != 0); + + if (Remainder) { + *Remainder = Dividend % Divisor; + } + + return Dividend / Divisor; +} diff --git a/gnu-efi/lib/riscv64/setjmp.S b/gnu-efi/lib/riscv64/setjmp.S new file mode 100644 index 0000000..8f8d496 --- /dev/null +++ b/gnu-efi/lib/riscv64/setjmp.S @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause +/* + * Copyright Heinrich Schuchardt + */ + + .text + .p2align 3 + +#define GREG_LIST \ + REG_ONE(s0, 0); \ + REG_ONE(s1, 8); \ + REG_ONE(s2, 16); \ + REG_ONE(s3, 24); \ + REG_ONE(s4, 32); \ + REG_ONE(s5, 40); \ + REG_ONE(s6, 48); \ + REG_ONE(s7, 56); \ + REG_ONE(s8, 64); \ + REG_ONE(s9, 72); \ + REG_ONE(s10, 80); \ + REG_ONE(s11, 88); \ + REG_ONE(sp, 96); \ + REG_ONE(ra, 104); + +#define FREG_LIST \ + FREG_ONE(fs0, 112); \ + FREG_ONE(fs1, 120); \ + FREG_ONE(fs2, 128); \ + FREG_ONE(fs3, 136); \ + FREG_ONE(fs4, 144); \ + FREG_ONE(fs5, 152); \ + FREG_ONE(fs6, 160); \ + FREG_ONE(fs7, 168); \ + FREG_ONE(fs8, 176); \ + FREG_ONE(fs9, 184); \ + FREG_ONE(fs10, 192); \ + FREG_ONE(fs11, 200); + +#define REG_ONE(R, P) sd R, P(a0) +#define FREG_ONE(R, P) fsd R, P(a0) + + .globl setjmp + .type setjmp, @function + +setjmp: + GREG_LIST +#ifndef __riscv_float_abi_soft + FREG_LIST +#endif + li a0, 0 + ret + +#undef REG_ONE +#undef FREG_ONE + +#define REG_ONE(R, P) ld R, P(a0) +#define FREG_ONE(R, P) fld R, P(a0) + + .globl longjmp + .type longjmp, @function + +longjmp: + GREG_LIST +#ifndef __riscv_float_abi_soft + FREG_LIST +#endif + seqz a0, a1 + add a0, a0, a1 + ret + +#if defined(__ELF__) && defined(__linux__) + .section .note.GNU-stack,"",%progbits +#endif