فهرست منبع

Add support for 64 bit MIPS

This is a patch to add support for 64-bit MIPS.

Signed-off-by: Hev heiher <heiher@users.sf.net>
Signed-off-by: Nigel Croxon <noxorc@mac.com>
Nigel Croxon 8 سال پیش
والد
کامیت
3f234f5b6f

+ 7 - 0
Make.defaults

@@ -117,15 +117,22 @@ ifeq ($(ARCH),x86_64)
   endif
 endif
 
+ifeq ($(ARCH),mips64el)
+  CFLAGS += -march=mips64r2
+  ARCH3264 = -mabi=64
+endif
+
 #
 # Set HAVE_EFI_OBJCOPY if objcopy understands --target efi-[app|bsdrv|rtdrv],
 # otherwise we need to compose the PE/COFF header using the assembler
 #
 ifneq ($(ARCH),aarch64)
 ifneq ($(ARCH),arm)
+ifneq ($(ARCH),mips64el)
 export HAVE_EFI_OBJCOPY=y
 endif
 endif
+endif
 
 ifneq ($(ARCH),arm)
 export LIBGCC=$(shell $(CC) $(ARCH3264) -print-libgcc-file-name)

+ 188 - 0
gnuefi/crt0-efi-mips64el.S

@@ -0,0 +1,188 @@
+/*
+ * crt0-efi-mips64el.S - PE/COFF header for MIPS64 EFI applications
+ *
+ * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copright (C) 2017 Heiher <r@hev.cc>
+ *
+ * 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	0x166				// MIPS 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)
+
+	.set		push
+	.set		noreorder
+	.align		4
+
+	.globl	_start
+	.ent	_start
+	.type	_start, @function
+_start:
+	daddiu		$sp, -32
+	sd		$ra, ($sp)
+
+	// Get pc & gp
+	.align		3
+	bal		1f
+	sd		$gp, 8($sp)
+_pc:
+	.dword		_gp
+	.dword		_DYNAMIC
+	.dword		_relocate
+1:
+	// pc in ra
+	ld		$gp, ($ra)
+	dli		$t0, _pc
+	dsubu		$gp, $t0
+	daddu		$gp, $ra
+
+	sd		$a0, 16($sp)
+	sd		$a1, 24($sp)
+
+	// a2: ImageHandle
+	move		$a2, $a0
+	// a3: SystemTable
+	move		$a3, $a1
+	// a0: ImageBase
+	dli		$t1, ImageBase - _pc
+	daddu		$a0, $ra, $t1
+	// a1: DynamicSection
+	ld		$t1, 8($ra)
+	dsubu		$t1, $t0
+	daddu		$a1, $ra, $t1
+	// call _relocate
+	ld		$t1, 16($ra)
+	dsubu		$t1, $t0
+	daddu		$t9, $ra, $t1
+	jalr		$t9
+	nop
+	bnez		$v0, 1b
+	nop
+
+	// a0: ImageHandle
+	ld		$a0, 16($sp)
+	// call efi_main
+	dla		$t9, efi_main
+	jalr		$t9
+	// a1: SystemTable
+	ld		$a1, 24($sp)
+
+1:
+	ld		$gp, 8($sp)
+	ld		$ra, ($sp)
+	jr		$ra
+	daddiu		$sp, 32
+	.end		_start
+
+	.set		pop

+ 64 - 0
gnuefi/elf_mips64el_efi.lds

@@ -0,0 +1,64 @@
+OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+  .text 0x0 : {
+    _text = .;
+    *(.text.head)
+    *(.text)
+    *(.text.*)
+    *(.gnu.linkonce.t.*)
+    *(.srodata)
+    *(.rodata*)
+    . = ALIGN(16);
+  }
+  _etext = .;
+  _text_size = . - _text;
+  .dynamic  : { *(.dynamic) }
+  .data :
+  {
+   _data = .;
+   *(.sdata)
+   *(.data)
+   *(.data1)
+   *(.data.*)
+   *(.got.plt)
+   HIDDEN (_gp = ALIGN (16) + 0x7ff0);
+   *(.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 = .;
+  }
+
+  .rel.dyn : { *(.rel.dyn) }
+  .rel.plt : { *(.rel.plt) }
+  .rel.got : { *(.rel.got) }
+  .rel.data : { *(.rel.data) *(.rel.data*) }
+  _edata = .;
+  _data_size = . - _etext;
+
+  . = ALIGN(4096);
+  .dynsym   : { *(.dynsym) }
+  . = ALIGN(4096);
+  .dynstr   : { *(.dynstr) }
+  . = ALIGN(4096);
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  /DISCARD/ :
+  {
+    *(.rel.reloc)
+    *(.eh_frame)
+    *(.MIPS.abiflags)
+    *(.note.GNU-stack)
+  }
+  .comment 0 : { *(.comment) }
+}

+ 115 - 0
gnuefi/reloc_mips64el.c

@@ -0,0 +1,115 @@
+/* reloc_mips64el.c - position independent MIPS64 ELF shared object relocator
+   Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+   Copyright (C) 1999 Hewlett-Packard Co.
+	Contributed by David Mosberger <davidm@hpl.hp.com>.
+   Copyright (C) 2017 Lemote Co.
+	Contributed by Heiher <r@hev.cc>
+
+    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, gotsz = 0;
+	Elf64_Rel *rel = 0;
+	unsigned long *addr = 0;
+	int i;
+
+	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+		switch (dyn[i].d_tag) {
+			case DT_REL:
+				rel = (Elf64_Rel*)
+					((unsigned long)dyn[i].d_un.d_ptr
+					 + ldbase);
+				break;
+
+			case DT_RELSZ:
+				relsz = dyn[i].d_un.d_val;
+				break;
+
+			case DT_RELENT:
+				relent = dyn[i].d_un.d_val;
+				break;
+
+			case DT_PLTGOT:
+				addr = (unsigned long *)
+					((unsigned long)dyn[i].d_un.d_ptr
+					 + ldbase);
+				break;
+
+			case DT_MIPS_LOCAL_GOTNO:
+				gotsz = dyn[i].d_un.d_val;
+				break;
+
+			default:
+				break;
+		}
+	}
+
+	if ((!rel && relent == 0) && (!addr && gotsz == 0))
+		return EFI_SUCCESS;
+
+	if ((!rel && relent != 0) || (!addr && gotsz != 0))
+		return EFI_LOAD_ERROR;
+
+	while (gotsz > 0) {
+		*addr += ldbase;
+		addr += 1;
+		gotsz --;
+	}
+
+	while (relsz > 0) {
+		/* apply the relocs */
+		switch (ELF64_R_TYPE (swap_uint64 (rel->r_info))) {
+			case R_MIPS_NONE:
+				break;
+
+			case (R_MIPS_64 << 8) | R_MIPS_REL32:
+				addr = (unsigned long *)
+					(ldbase + rel->r_offset);
+				*addr += ldbase;
+				break;
+
+			default:
+				break;
+		}
+		rel = (Elf64_Rel*) ((char *) rel + relent);
+		relsz -= relent;
+	}
+	return EFI_SUCCESS;
+}

+ 164 - 0
inc/mips64el/efibind.h

@@ -0,0 +1,164 @@
+/*
+ * Copright (C) 2014 - 2015 Linaro Ltd.
+ * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+ * Copright (C) 2017 Lemote Co.
+ * Author: Heiher <r@hev.cc>
+ *
+ * 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 )
+
+// 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
+
+#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
+
+static inline UINT64 swap_uint64 (UINT64 v)
+{
+	asm volatile (
+		"dsbh	%[v], %[v] \n\t"
+		"dshd	%[v], %[v] \n\t"
+		:[v]"+r"(v)
+	);
+
+	return v;
+}

+ 25 - 0
inc/mips64el/efilibplat.h

@@ -0,0 +1,25 @@
+/*++
+
+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
+    );
+

+ 34 - 0
inc/mips64el/efisetjmp_arch.h

@@ -0,0 +1,34 @@
+#ifndef GNU_EFI_MIPS64EL_SETJMP_H
+#define GNU_EFI_MIPS64EL_SETJMP_H
+
+#define JMPBUF_ALIGN 8
+
+typedef struct {
+	/* GP regs */
+	UINT64	RA;
+	UINT64	SP;
+	UINT64	FP;
+	UINT64	GP;
+	UINT64	S0;
+	UINT64	S1;
+	UINT64	S2;
+	UINT64	S3;
+	UINT64	S4;
+	UINT64	S5;
+	UINT64	S6;
+	UINT64	S7;
+
+#ifdef	__mips_hard_float
+	/* FP regs */
+	UINT64	F24;
+	UINT64	F25;
+	UINT64	F26;
+	UINT64	F27;
+	UINT64	F28;
+	UINT64	F29;
+	UINT64	F30;
+	UINT64	F31;
+#endif
+} ALIGN(JMPBUF_ALIGN) jmp_buf;
+
+#endif /* GNU_EFI_MIPS64EL_SETJMP_H */

+ 1 - 1
lib/Makefile

@@ -64,7 +64,7 @@ endif
 
 OBJS  = $(FILES:%=%.o)
 
-SUBDIRS = ia32 x86_64 ia64 aarch64 arm runtime
+SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el runtime
 
 LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR)
 

+ 1 - 0
lib/mips64el/efi_stub.S

@@ -0,0 +1 @@
+/* This stub is a stub to make the build happy */

+ 51 - 0
lib/mips64el/initplat.c

@@ -0,0 +1,51 @@
+/*
+ * 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
+    )
+{
+}
+
+/*
+ * Calls to these functions may be emitted implicitly by GCC even when
+ * -ffreestanding is in effect.
+ */
+void *memset(void *s, int c, __SIZE_TYPE__ n)
+{
+    unsigned char *p = s;
+
+    while (n--)
+        *p++ = c;
+
+    return s;
+}
+
+void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n)
+{
+    const unsigned char *q = src;
+    unsigned char *p = dest;
+
+    while (n--)
+        *p++ = *q++;
+
+    return dest;
+}

+ 63 - 0
lib/mips64el/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;
+}

+ 92 - 0
lib/mips64el/setjmp.S

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ * Copright (c) 2017 Lemote Co.
+ * Author: Heiher <r@hev.cc>
+ *
+ * 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
+
+	.globl	setjmp
+	.type	setjmp, @function
+setjmp:
+	sd	$ra, 0x00($a0)
+	sd	$sp, 0x08($a0)
+	sd	$fp, 0x10($a0)
+	sd	$gp, 0x18($a0)
+
+	sd	$s0, 0x20($a0)
+	sd	$s1, 0x28($a0)
+	sd	$s2, 0x30($a0)
+	sd	$s3, 0x38($a0)
+	sd	$s4, 0x40($a0)
+	sd	$s5, 0x48($a0)
+	sd	$s6, 0x50($a0)
+	sd	$s7, 0x58($a0)
+
+#ifdef	__mips_hard_float
+	mfc0	$v0, $12
+	ext	$v0, $v0, 29, 1
+	beqz	$v0, 1f
+
+	s.d	$f24, 0x60($a0)
+	s.d	$f25, 0x68($a0)
+	s.d	$f26, 0x70($a0)
+	s.d	$f27, 0x78($a0)
+	s.d	$f28, 0x80($a0)
+	s.d	$f29, 0x88($a0)
+	s.d	$f30, 0x90($a0)
+	s.d	$f31, 0x98($a0)
+
+1:
+#endif
+	move	$v0, $zero
+	jr	$ra
+
+	.globl	longjmp
+	.type	longjmp, @function
+longjmp:
+	ld	$ra, 0x00($a0)
+	ld	$sp, 0x08($a0)
+	ld	$fp, 0x10($a0)
+	ld	$gp, 0x18($a0)
+
+	ld	$s0, 0x20($a0)
+	ld	$s1, 0x28($a0)
+	ld	$s2, 0x30($a0)
+	ld	$s3, 0x38($a0)
+	ld	$s4, 0x40($a0)
+	ld	$s5, 0x48($a0)
+	ld	$s6, 0x50($a0)
+	ld	$s7, 0x58($a0)
+
+#ifdef	__mips_hard_float
+	mfc0	$v0, $12
+	ext	$v0, $v0, 29, 1
+	beqz	$v0, 1f
+
+	l.d	$f24, 0x60($a0)
+	l.d	$f25, 0x68($a0)
+	l.d	$f26, 0x70($a0)
+	l.d	$f27, 0x78($a0)
+	l.d	$f28, 0x80($a0)
+	l.d	$f29, 0x88($a0)
+	l.d	$f30, 0x90($a0)
+	l.d	$f31, 0x98($a0)
+
+1:
+#endif
+	li	$v0, 1
+	movn	$v0, $a1, $a1
+	jr	$ra