diff options
author | zhoumingtao <zhoumingtao@loongson.cn> | 2021-12-30 15:39:47 +0800 |
---|---|---|
committer | zhoumingtao <zhoumingtao@loongson.cn> | 2021-12-30 15:39:47 +0800 |
commit | e7db4418b1fe6ea0220974b77c3b10918ab9b7a0 (patch) | |
tree | 43c862861b7c9ad135fc5596c5373f4b993485ab | |
parent | af773c779de0a9c271022f97723514bb9e2ba777 (diff) | |
download | gnu-efi-e7db4418b1fe6ea0220974b77c3b10918ab9b7a0.tar.gz |
Add support for LoongArch64 architecture
-rwxr-xr-x | Make.defaults | 2 | ||||
-rw-r--r-- | apps/lfbgrid.c | 6 | ||||
-rw-r--r-- | gnuefi/crt0-efi-loongarch64.S | 148 | ||||
-rw-r--r-- | gnuefi/elf_loongarch64_efi.lds | 63 | ||||
-rw-r--r-- | gnuefi/reloc_loongarch64.c | 104 | ||||
-rw-r--r-- | inc/efi.h | 2 | ||||
-rw-r--r-- | inc/efilib.h | 2 | ||||
-rw-r--r-- | inc/loongarch64/efibind.h | 157 | ||||
-rw-r--r-- | inc/loongarch64/efilibplat.h | 24 | ||||
-rw-r--r-- | inc/loongarch64/efisetjmp_arch.h | 23 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/loongarch64/efi_stub.S | 1 | ||||
-rw-r--r-- | lib/loongarch64/initplat.c | 26 | ||||
-rw-r--r-- | lib/loongarch64/math.c | 63 | ||||
-rw-r--r-- | lib/loongarch64/setjmp.S | 68 |
15 files changed, 688 insertions, 3 deletions
diff --git a/Make.defaults b/Make.defaults index 47ed361..339e82c 100755 --- a/Make.defaults +++ b/Make.defaults @@ -143,11 +143,13 @@ ifneq ($(ARCH),aarch64) ifneq ($(ARCH),arm) ifneq ($(ARCH),mips64el) ifneq ($(ARCH),riscv64) +ifneq ($(ARCH),loongarch64) export HAVE_EFI_OBJCOPY=y endif endif endif endif +endif ifneq ($(ARCH),arm) export LIBGCC=$(shell $(CC) $(ARCH3264) -print-libgcc-file-name) diff --git a/apps/lfbgrid.c b/apps/lfbgrid.c index 05977d2..3153ae1 100644 --- a/apps/lfbgrid.c +++ b/apps/lfbgrid.c @@ -52,7 +52,8 @@ draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) UINT32 *PixelBuffer; UINT32 CopySize, BufferSize; #if defined(__x86_64__) || defined(__aarch64__) || \ - (defined (__riscv) && __riscv_xlen == 64) + (defined (__riscv) && __riscv_xlen == 64) || \ + defined(__loongarch64) UINT64 FrameBufferAddr; #elif defined(__i386__) || defined(__arm__) UINT32 FrameBufferAddr; @@ -116,7 +117,8 @@ draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) return; } #if defined(__x86_64__) || defined(__aarch64__) || \ - (defined (__riscv) && __riscv_xlen == 64) + (defined (__riscv) && __riscv_xlen == 64) || \ + defined(__loongarch64) FrameBufferAddr = (UINT64)gop->Mode->FrameBufferBase; #elif defined(__i386__) || defined(__arm__) FrameBufferAddr = (UINT32)(UINT64)gop->Mode->FrameBufferBase; diff --git a/gnuefi/crt0-efi-loongarch64.S b/gnuefi/crt0-efi-loongarch64.S new file mode 100644 index 0000000..5790561 --- /dev/null +++ b/gnuefi/crt0-efi-loongarch64.S @@ -0,0 +1,148 @@ +/* + * crt0-efi-loongarch64.S - PE/COFF header for LOONGARCH64 EFI applications + * + * Copyright (C) 2021 Loongson Technology Corporation Limited. <zhoumingtao@loongson.cn> + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> + * + * 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. + */ + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .ascii "MZ" + .skip 58 // 'MZ' + pad + offset == 64 + .long pe_header - ImageBase // Offset to the PE header. +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0x6264 // loongarch64 little endian + .short 2 // nr_sections + .long 0 // TimeDateStamp + .long 0 // PointerToSymbolTable + .long 1 // NumberOfSymbols + .short section_table - optional_header // SizeOfOptionalHeader + .short 0x206 // Characteristics. + // IMAGE_FILE_DEBUG_STRIPPED | + // IMAGE_FILE_EXECUTABLE_IMAGE | + // IMAGE_FILE_LINE_NUMS_STRIPPED +optional_header: + .short 0x20b // PE32+ format + .byte 0x02 // MajorLinkerVersion + .byte 0x14 // MinorLinkerVersion + .long _edata - _start // SizeOfCode + .long 0 // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long _start - ImageBase // AddressOfEntryPoint + .long _start - ImageBase // BaseOfCode + +extra_header_fields: + .quad 0 // ImageBase + .long 0x20 // SectionAlignment + .long 0x8 // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short 0 // MajorImageVersion + .short 0 // MinorImageVersion + .short 0 // MajorSubsystemVersion + .short 0 // MinorSubsystemVersion + .long 0 // Win32VersionValue + + .long _edata - ImageBase // SizeOfImage + + // Everything before the kernel image is considered part of the header + .long _start - ImageBase // SizeOfHeaders + .long 0 // CheckSum + .short EFI_SUBSYSTEM // Subsystem + .short 0 // DllCharacteristics + .quad 0 // SizeOfStackReserve + .quad 0 // SizeOfStackCommit + .quad 0 // SizeOfHeapReserve + .quad 0 // SizeOfHeapCommit + .long 0 // LoaderFlags + .long 0x6 // NumberOfRvaAndSizes + + .quad 0 // ExportTable + .quad 0 // ImportTable + .quad 0 // ResourceTable + .quad 0 // ExceptionTable + .quad 0 // CertificationTable + .quad 0 // BaseRelocationTable + + // Section table +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 // end of 0 padding of section name + .long 0 + .long 0 + .long 0 // SizeOfRawData + .long 0 // PointerToRawData + .long 0 // PointerToRelocations + .long 0 // PointerToLineNumbers + .short 0 // NumberOfRelocations + .short 0 // NumberOfLineNumbers + .long 0x42100040 // Characteristics (section flags) + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 // end of 0 padding of section name + .long _edata - _start // VirtualSize + .long _start - ImageBase // VirtualAddress + .long _edata - _start // SizeOfRawData + .long _start - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0xe0500020 // Characteristics (section flags) + + .align 4 + + .globl _start + .type _start, @function +_start: + addi.d $sp, $sp, -24 + st.d $ra, $sp, 0 + st.d $a0, $sp, 8 + st.d $a1, $sp, 16 + + move $a2, $a0 // a2: ImageHandle + move $a3, $a1 // a3: SystemTable + la.local $a0, ImageBase // a0: ImageBase + la.local $a1, _DYNAMIC // a1: DynamicSection + bl _relocate + bnez $a0, 0f + + ld.d $a0, $sp, 8 + ld.d $a1, $sp, 16 + bl efi_main + +0: ld.d $ra, $sp, 0 + addi.d $sp, $sp, 24 + jirl $ra, $ra, 0 + .end _start diff --git a/gnuefi/elf_loongarch64_efi.lds b/gnuefi/elf_loongarch64_efi.lds new file mode 100644 index 0000000..e7b4d6b --- /dev/null +++ b/gnuefi/elf_loongarch64_efi.lds @@ -0,0 +1,63 @@ +OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch") +OUTPUT_ARCH(loongarch) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : ALIGN(4096) + { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* 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) + . = ALIGN(16); + _bss_end = .; + } + + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + .rela.got : { *(.rela.got) } + .rela.data : { *(.rela.data) *(.rela.data*) } + . = ALIGN(512); + _edata = .; + _data_size = . - _data; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnuefi/reloc_loongarch64.c b/gnuefi/reloc_loongarch64.c new file mode 100644 index 0000000..7860f9d --- /dev/null +++ b/gnuefi/reloc_loongarch64.c @@ -0,0 +1,104 @@ +/* reloc_loongarch64.c - position independent loongarch64 ELF shared object relocator + Copyright (C) 2021 Loongson Technology Corporation Limited. <zhoumingtao@loongson.cn> + Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger <davidm@hpl.hp.com>. + + 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 <efi.h> +#include <efilib.h> + +#include <elf.h> + +EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0; + Elf64_Rela *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_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; + + case DT_PLTGOT: + addr = (unsigned long *) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + 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 (ELF64_R_TYPE (rel->r_info)) { + case R_LARCH_NONE: + break; + + case R_LARCH_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf64_Rela*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} @@ -52,6 +52,8 @@ Revision History #include "mips64el/efibind.h" #elif defined (__riscv) && __riscv_xlen == 64 #include "riscv64/efibind.h" +#elif defined (__loongarch64) +#include "loongarch64/efibind.h" #else #error Usupported architecture #endif diff --git a/inc/efilib.h b/inc/efilib.h index 9f748ad..64f549f 100644 --- a/inc/efilib.h +++ b/inc/efilib.h @@ -35,6 +35,8 @@ Revision History #include "mips64el/efilibplat.h" #elif defined (__riscv) && __riscv_xlen == 64 #include "riscv64/efilibplat.h" +#elif defined (__loongarch64) +#include "loongarch64/efilibplat.h" #endif #include "efilink.h" #include "efirtlib.h" diff --git a/inc/loongarch64/efibind.h b/inc/loongarch64/efibind.h new file mode 100644 index 0000000..5dc0459 --- /dev/null +++ b/inc/loongarch64/efibind.h @@ -0,0 +1,157 @@ +/* + * Copright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org> + * Copright (C) 2017 Lemote Co. + * Author: Heiher <r@hev.cc> + * Copright (C) 2021 Loongson Technology Corporation Limited. + * Author: zhoumingtao <zhoumingtao@loongson.cn> + * + * 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. + */ + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long uint64_t; +typedef long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; + +#else +#include <stdint.h> +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +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 __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 + +// +// 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. +// + +#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"))); + +#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/inc/loongarch64/efilibplat.h b/inc/loongarch64/efilibplat.h new file mode 100644 index 0000000..eda7c83 --- /dev/null +++ b/inc/loongarch64/efilibplat.h @@ -0,0 +1,24 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); diff --git a/inc/loongarch64/efisetjmp_arch.h b/inc/loongarch64/efisetjmp_arch.h new file mode 100644 index 0000000..18aefaf --- /dev/null +++ b/inc/loongarch64/efisetjmp_arch.h @@ -0,0 +1,23 @@ +#ifndef GNU_EFI_LOONGARCH64_SETJMP_H +#define GNU_EFI_LOONGARCH64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 RA; + UINT64 SP; + UINT64 FP; + + UINT64 S0; + UINT64 S1; + UINT64 S2; + UINT64 S3; + UINT64 S4; + UINT64 S5; + UINT64 S6; + UINT64 S7; + UINT64 S8; +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_LOONGARCH64_SETJMP_H */ diff --git a/lib/Makefile b/lib/Makefile index cf4239d..6fd29ec 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -64,7 +64,7 @@ endif OBJS = $(FILES:%=%.o) -SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 runtime +SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 loongarch64 runtime LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR) diff --git a/lib/loongarch64/efi_stub.S b/lib/loongarch64/efi_stub.S new file mode 100644 index 0000000..464eae5 --- /dev/null +++ b/lib/loongarch64/efi_stub.S @@ -0,0 +1 @@ +/* This stub is a stub to make the build happy */ diff --git a/lib/loongarch64/initplat.c b/lib/loongarch64/initplat.c new file mode 100644 index 0000000..6c5e1fa --- /dev/null +++ b/lib/loongarch64/initplat.c @@ -0,0 +1,26 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org> + * + * 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 "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} diff --git a/lib/loongarch64/math.c b/lib/loongarch64/math.c new file mode 100644 index 0000000..8c16444 --- /dev/null +++ b/lib/loongarch64/math.c @@ -0,0 +1,63 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org> + * + * 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 "lib.h" + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ + return Operand >> Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiple 64bit by 32bit and get a 64bit result +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +// divide 64bit by 32bit and get a 64bit result +// N.B. only works for 31bit divisors!! +{ + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +} diff --git a/lib/loongarch64/setjmp.S b/lib/loongarch64/setjmp.S new file mode 100644 index 0000000..94955ee --- /dev/null +++ b/lib/loongarch64/setjmp.S @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * Copyright (c) 2021 Loongson Technology Corporation Limited.All rights + * reserved. + * Author: zhoumingtao <zhoumingtao@loongson.cn> + * + * This program and the accompanying materials are licensed and made + * available + * under the terms and conditions of the BSD License which accompanies + * this + * distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" + * BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR + * IMPLIED. + */ + + .text + .p2align 3 + +/* + int setjmp(jmp_buf env); +*/ + .globl setjmp + .type setjmp, @function +setjmp: + st.d $ra, $a0, 0x0 + st.d $sp, $a0, 0x8 + st.d $fp, $a0, 0x10 + st.d $s0, $a0, 0x18 + st.d $s1, $a0, 0x20 + st.d $s2, $a0, 0x28 + st.d $s3, $a0, 0x30 + st.d $s4, $a0, 0x38 + st.d $s5, $a0, 0x40 + st.d $s6, $a0, 0x48 + st.d $s7, $a0, 0x50 + st.d $s8, $a0, 0x58 + + move $a0, $zero + jirl $zero,$ra,0 + +/* + void longjmp(jmp_buf env, int val); +*/ + .globl longjmp + .type longjmp, @function +longjmp: + ld.d $ra, $a0, 0x0 + ld.d $sp, $a0, 0x8 + ld.d $fp, $a0, 0x10 + ld.d $s0, $a0, 0x18 + ld.d $s1, $a0, 0x20 + ld.d $s2, $a0, 0x28 + ld.d $s3, $a0, 0x30 + ld.d $s4, $a0, 0x38 + ld.d $s5, $a0, 0x40 + ld.d $s6, $a0, 0x48 + ld.d $s7, $a0, 0x50 + ld.d $s8, $a0, 0x58 + + addi.d $a0, $zero, 1 # a0 = 1 + beqz $a1, .L0 # if (a1 == 0); goto L0 + move $a0, $a1 # a0 = a1 +.L0: + jirl $zero,$ra,0 |