mirror of
https://github.com/ipxe/ipxe
synced 2026-06-29 00:07:28 +03:00
[s390x] Add support for the IBM s390x CPU architecture
Add support for building iPXE as a 64-bit s390x binary for the Linux userspace platform. For example: make CROSS=s390x-linux-gnu- bin-s390x-linux/tests.linux Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
# Specify compressor
|
||||||
|
#
|
||||||
|
ZBIN = $(ZBIN64)
|
||||||
|
|
||||||
|
# Assembler section type character
|
||||||
|
#
|
||||||
|
ASM_TCHAR := @
|
||||||
|
ASM_TCHAR_OPS := @
|
||||||
|
|
||||||
|
# S/390-specific flags
|
||||||
|
#
|
||||||
|
CFLAGS += -mno-backchain -mpacked-stack -msoft-float
|
||||||
|
|
||||||
|
# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
|
||||||
|
#
|
||||||
|
CFLAGS += -fshort-wchar
|
||||||
|
|
||||||
|
# Include S/390-specific headers
|
||||||
|
#
|
||||||
|
INCDIRS := arch/$(ARCH)/include $(INCDIRS)
|
||||||
|
|
||||||
|
# S/390-specific directories containing source files
|
||||||
|
#
|
||||||
|
SRCDIRS += arch/s390x/core
|
||||||
|
|
||||||
|
# Include platform-specific Makefile
|
||||||
|
#
|
||||||
|
MAKEDEPS += arch/s390x/Makefile.$(PLATFORM)
|
||||||
|
include arch/s390x/Makefile.$(PLATFORM)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||||
|
|
||||||
|
# Include generic Linux Makefile
|
||||||
|
#
|
||||||
|
MAKEDEPS += Makefile.linux
|
||||||
|
include Makefile.linux
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Optimised string operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy (possibly overlapping) memory region
|
||||||
|
*
|
||||||
|
* @v dest Destination region
|
||||||
|
* @v src Source region
|
||||||
|
* @v len Length
|
||||||
|
*/
|
||||||
|
void s390x_memmove ( void *dest, const void *src, size_t len ) {
|
||||||
|
const uint8_t *src_bytes = ( src + len );
|
||||||
|
uint8_t *dest_bytes = ( dest + len );
|
||||||
|
|
||||||
|
/* Use memcpy() if copy direction is forwards */
|
||||||
|
if ( dest <= src ) {
|
||||||
|
memcpy ( dest, src, len );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assume memmove() is not performance-critical, and perform a
|
||||||
|
* bytewise copy backwards for simplicity.
|
||||||
|
*/
|
||||||
|
while ( len-- )
|
||||||
|
*(--dest_bytes) = *(--src_bytes);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or any later version.
|
||||||
|
*
|
||||||
|
* This program 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
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* You can also choose to distribute this program under the terms of
|
||||||
|
* the Unmodified Binary Distribution Licence (as given in the file
|
||||||
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Long jumps
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".note.GNU-stack", "", @progbits
|
||||||
|
.text
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save stack context for non-local goto
|
||||||
|
*/
|
||||||
|
.section ".text.setjmp", "ax", @progbits
|
||||||
|
.globl setjmp
|
||||||
|
setjmp:
|
||||||
|
/* Save registers */
|
||||||
|
stmg %r6, %r15, 0(%r2)
|
||||||
|
/* Return zero when returning as setjmp() */
|
||||||
|
lghi %r2, 0
|
||||||
|
br %r14
|
||||||
|
.size setjmp, . - setjmp
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-local jump to a saved stack context
|
||||||
|
*/
|
||||||
|
.section ".text.longjmp", "ax", @progbits
|
||||||
|
.globl longjmp
|
||||||
|
longjmp:
|
||||||
|
/* Restore registers */
|
||||||
|
lmg %r6, %r15, 0(%r2)
|
||||||
|
/* Force result to non-zero */
|
||||||
|
ltgr %r2, %r3
|
||||||
|
lochiz %r2, 1
|
||||||
|
/* Return to setjmp() caller */
|
||||||
|
br %r14
|
||||||
|
.size longjmp, . - longjmp
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
#ifndef _BITS_BIGINT_H
|
||||||
|
#define _BITS_BIGINT_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Big integer support
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/** Element of a big integer */
|
||||||
|
typedef unsigned long bigint_element_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add big integers
|
||||||
|
*
|
||||||
|
* @v addend0 Element 0 of big integer to add
|
||||||
|
* @v value0 Element 0 of big integer to be added to
|
||||||
|
* @v size Number of elements
|
||||||
|
* @ret carry Carry out
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
bigint_add_raw ( const unsigned long *addend0, unsigned long *value0,
|
||||||
|
unsigned int size ) {
|
||||||
|
bigint_t ( size ) __attribute__ (( may_alias )) *addend =
|
||||||
|
( ( void * ) addend0 );
|
||||||
|
bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||||
|
( ( void * ) value0 );
|
||||||
|
unsigned long discard_offset;
|
||||||
|
unsigned long discard_temp;
|
||||||
|
unsigned int index_carry;
|
||||||
|
|
||||||
|
__asm__ ( /* Zero offset and clear carry-in */
|
||||||
|
"xgr %0, %0\n\t"
|
||||||
|
/* Add element by element */
|
||||||
|
"\n1:\n\t"
|
||||||
|
"lg %1, %O3(%0, %R3)\n\t"
|
||||||
|
"alcg %1, %O4(%0, %R4)\n\t"
|
||||||
|
"stg %1, %O3(%0, %R3)\n\t"
|
||||||
|
"la %0, 8(%0)\n\t"
|
||||||
|
"brct %2, 1b\n\t"
|
||||||
|
/* Obtain carry-out */
|
||||||
|
"alcr %2, %2\n\t"
|
||||||
|
: "=&a" ( discard_offset ),
|
||||||
|
"=&r" ( discard_temp ),
|
||||||
|
"=&r" ( index_carry ),
|
||||||
|
"+S" ( *value )
|
||||||
|
: "S" ( *addend ),
|
||||||
|
"2" ( size ) );
|
||||||
|
|
||||||
|
return index_carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract big integers
|
||||||
|
*
|
||||||
|
* @v subtrahend0 Element 0 of big integer to subtract
|
||||||
|
* @v value0 Element 0 of big integer to be subtracted from
|
||||||
|
* @v size Number of elements
|
||||||
|
* @ret borrow Borrow out
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
bigint_subtract_raw ( const unsigned long *subtrahend0, unsigned long *value0,
|
||||||
|
unsigned int size ) {
|
||||||
|
bigint_t ( size ) __attribute__ (( may_alias )) *subtrahend =
|
||||||
|
( ( void * ) subtrahend0 );
|
||||||
|
bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||||
|
( ( void * ) value0 );
|
||||||
|
unsigned long discard_offset;
|
||||||
|
unsigned long discard_temp;
|
||||||
|
unsigned int index_borrow;
|
||||||
|
|
||||||
|
__asm__ ( /* Zero offset and clear (inverted) borrow-in */
|
||||||
|
"slgr %0, %0\n\t"
|
||||||
|
/* Subtract element by element */
|
||||||
|
"\n1:\n\t"
|
||||||
|
"lg %1, %O3(%0, %R3)\n\t"
|
||||||
|
"slbg %1, %O4(%0, %R4)\n\t"
|
||||||
|
"stg %1, %O3(%0, %R3)\n\t"
|
||||||
|
"la %0, 8(%0)\n\t"
|
||||||
|
"brct %2, 1b\n\t"
|
||||||
|
/* Obtain (negative) borrow-out */
|
||||||
|
"slbr %2, %2\n\t"
|
||||||
|
: "=&a" ( discard_offset ),
|
||||||
|
"=&r" ( discard_temp ),
|
||||||
|
"=&r" ( index_borrow ),
|
||||||
|
"+S" ( *value )
|
||||||
|
: "S" ( *subtrahend ),
|
||||||
|
"2" ( size ) );
|
||||||
|
|
||||||
|
return ( -index_borrow );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift big integer left
|
||||||
|
*
|
||||||
|
* @v value0 Element 0 of big integer
|
||||||
|
* @v size Number of elements
|
||||||
|
* @ret out Bit shifted out
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
bigint_shl_raw ( unsigned long *value0, unsigned int size ) {
|
||||||
|
bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||||
|
( ( void * ) value0 );
|
||||||
|
unsigned long discard_offset;
|
||||||
|
unsigned long discard_temp;
|
||||||
|
unsigned int discard_index;
|
||||||
|
unsigned int carry;
|
||||||
|
|
||||||
|
__asm__ ( /* Shift element by element */
|
||||||
|
"\n1:\n\t"
|
||||||
|
"lg %1, %O4(%0, %R4)\n\t"
|
||||||
|
"risbg %3, %1, 0, 62, 1\n\t"
|
||||||
|
"stg %3, %O4(%0, %R4)\n\t"
|
||||||
|
"srlg %3, %1, 63\n\t"
|
||||||
|
"la %0, 8(%0)\n\t"
|
||||||
|
"brct %2, 1b\n\t"
|
||||||
|
: "=&a" ( discard_offset ),
|
||||||
|
"=&r" ( discard_temp ),
|
||||||
|
"=&r" ( discard_index ),
|
||||||
|
"=&r" ( carry ),
|
||||||
|
"+S" ( *value )
|
||||||
|
: "0" ( 0UL ),
|
||||||
|
"2" ( size ),
|
||||||
|
"3" ( 0U ) );
|
||||||
|
|
||||||
|
return carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift big integer right
|
||||||
|
*
|
||||||
|
* @v value0 Element 0 of big integer
|
||||||
|
* @v size Number of elements
|
||||||
|
* @ret out Bit shifted out
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
bigint_shr_raw ( unsigned long *value0, unsigned int size ) {
|
||||||
|
bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||||
|
( ( void * ) value0 );
|
||||||
|
unsigned long discard_offset;
|
||||||
|
unsigned long discard_temp;
|
||||||
|
unsigned int carry;
|
||||||
|
|
||||||
|
__asm__ ( /* Shift element by element */
|
||||||
|
"\n1:\n\t"
|
||||||
|
"sllg %1, %2, 63\n\t"
|
||||||
|
"lg %2, (%O3 - 8)(%0, %R3)\n\t"
|
||||||
|
"risbg %1, %2, 1, 63, 63\n\t"
|
||||||
|
"stg %1, (%O3 - 8)(%0, %R3)\n\t"
|
||||||
|
"aghi %0, -8\n\t"
|
||||||
|
"jnz 1b\n\t"
|
||||||
|
: "=&a" ( discard_offset ),
|
||||||
|
"=&r" ( discard_temp ),
|
||||||
|
"=&r" ( carry ),
|
||||||
|
"+S" ( *value )
|
||||||
|
: "0" ( sizeof ( *value ) ),
|
||||||
|
"2" ( 0 ) );
|
||||||
|
|
||||||
|
return ( carry & 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grow big integer
|
||||||
|
*
|
||||||
|
* @v source0 Element 0 of source big integer
|
||||||
|
* @v source_size Number of elements in source big integer
|
||||||
|
* @v dest0 Element 0 of destination big integer
|
||||||
|
* @v dest_size Number of elements in destination big integer
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
bigint_grow_raw ( const unsigned long *source0, unsigned int source_size,
|
||||||
|
unsigned long *dest0, unsigned int dest_size ) {
|
||||||
|
const bigint_t ( source_size ) __attribute__ (( may_alias )) *source =
|
||||||
|
( ( const void * ) source0 );
|
||||||
|
bigint_t ( dest_size ) __attribute__ (( may_alias )) *dest =
|
||||||
|
( ( void * ) dest0 );
|
||||||
|
struct s390x_pointer_pair spair = { source, sizeof ( *source ) };
|
||||||
|
struct s390x_pointer_pair dpair = { dest, sizeof ( *dest ) };
|
||||||
|
|
||||||
|
__asm__ ( /* Copy source to destination, zero-padding as needed */
|
||||||
|
"\n1:\n\t"
|
||||||
|
"mvcle %0, %1, 0\n\t"
|
||||||
|
"jo 1b\n\t"
|
||||||
|
: "+r" ( dpair ), "+r" ( spair ), "=m" ( *dest )
|
||||||
|
: "m" ( *source ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shrink big integer
|
||||||
|
*
|
||||||
|
* @v source0 Element 0 of source big integer
|
||||||
|
* @v source_size Number of elements in source big integer
|
||||||
|
* @v dest0 Element 0 of destination big integer
|
||||||
|
* @v dest_size Number of elements in destination big integer
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
bigint_shrink_raw ( const unsigned long *source0, unsigned int source_size,
|
||||||
|
unsigned long *dest0, unsigned int dest_size ) {
|
||||||
|
const bigint_t ( source_size ) __attribute__ (( may_alias )) *source =
|
||||||
|
( ( const void * ) source0 );
|
||||||
|
bigint_t ( dest_size ) __attribute__ (( may_alias )) *dest =
|
||||||
|
( ( void * ) dest0 );
|
||||||
|
struct s390x_pointer_pair spair = { source, sizeof ( *source ) };
|
||||||
|
struct s390x_pointer_pair dpair = { dest, sizeof ( *dest ) };
|
||||||
|
|
||||||
|
__asm__ ( /* Copy source to destination, truncating if needed */
|
||||||
|
"\n1:\n\t"
|
||||||
|
"mvcle %0, %1, 0\n\t"
|
||||||
|
"jo 1b\n\t"
|
||||||
|
: "+r" ( dpair ), "+r" ( spair ), "=m" ( *dest )
|
||||||
|
: "m" ( *source ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply big integer elements
|
||||||
|
*
|
||||||
|
* @v multiplicand Multiplicand element
|
||||||
|
* @v multiplier Multiplier element
|
||||||
|
* @v result Result element
|
||||||
|
* @v carry Carry element
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
bigint_multiply_one ( const unsigned long multiplicand,
|
||||||
|
const unsigned long multiplier,
|
||||||
|
unsigned long *result, unsigned long *carry ) {
|
||||||
|
struct s390x_scalar_pair pair;
|
||||||
|
|
||||||
|
__asm__ ( /* Perform multiplication */
|
||||||
|
"lgr %N0, %3\n\t"
|
||||||
|
"mlgr %0, %4\n\t"
|
||||||
|
/* Add carry-in */
|
||||||
|
"algr %N0, %2\n\t"
|
||||||
|
"slbgr %2, %2\n\t"
|
||||||
|
"aghi %2, 1\n\t"
|
||||||
|
/* Accumulate result */
|
||||||
|
"alg %N0, %1\n\t"
|
||||||
|
"stg %N0, %1\n\t"
|
||||||
|
/* Accumulate carry-out */
|
||||||
|
"alcgr %2, %0\n\t"
|
||||||
|
: "=&r" ( pair ),
|
||||||
|
"+T" ( *result ),
|
||||||
|
"+r" ( *carry )
|
||||||
|
: "r" ( multiplicand ),
|
||||||
|
"r" ( multiplier ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BITS_BIGINT_H */
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#ifndef _BITS_BITOPS_H
|
||||||
|
#define _BITS_BITOPS_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* S/390 bit operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <byteswap.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test and set bit atomically
|
||||||
|
*
|
||||||
|
* @v bit Bit to set
|
||||||
|
* @v bits Bit field
|
||||||
|
* @ret old Old value of bit (zero or non-zero)
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
test_and_set_bit ( unsigned int bit, volatile void *bits ) {
|
||||||
|
unsigned int index = ( bit / 32 );
|
||||||
|
unsigned int offset = ( bit % 32 );
|
||||||
|
volatile uint32_t *word = ( ( ( volatile uint32_t * ) bits ) + index );
|
||||||
|
uint32_t mask = cpu_to_le32 ( 1U << offset );
|
||||||
|
uint32_t old;
|
||||||
|
|
||||||
|
__asm__ __volatile__ ( "lao %0, %2, %1"
|
||||||
|
: "=r" ( old ), "+S" ( *word )
|
||||||
|
: "r" ( mask ) );
|
||||||
|
|
||||||
|
return ( !! ( old & mask ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test and clear bit atomically
|
||||||
|
*
|
||||||
|
* @v bit Bit to set
|
||||||
|
* @v bits Bit field
|
||||||
|
* @ret old Old value of bit (zero or non-zero)
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
test_and_clear_bit ( unsigned int bit, volatile void *bits ) {
|
||||||
|
unsigned int index = ( bit / 32 );
|
||||||
|
unsigned int offset = ( bit % 32 );
|
||||||
|
volatile uint32_t *word = ( ( ( volatile uint32_t * ) bits ) + index );
|
||||||
|
uint32_t mask = cpu_to_le32 ( 1U << offset );
|
||||||
|
uint32_t old;
|
||||||
|
|
||||||
|
__asm__ __volatile__ ( "lan %0, %2, %1"
|
||||||
|
: "=r" ( old ), "+S" ( *word )
|
||||||
|
: "r" ( ~mask ) );
|
||||||
|
|
||||||
|
return ( !! ( old & mask ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bit atomically
|
||||||
|
*
|
||||||
|
* @v bit Bit to set
|
||||||
|
* @v bits Bit field
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
set_bit ( unsigned int bit, volatile void *bits ) {
|
||||||
|
|
||||||
|
test_and_set_bit ( bit, bits );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear bit atomically
|
||||||
|
*
|
||||||
|
* @v bit Bit to set
|
||||||
|
* @v bits Bit field
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
clear_bit ( unsigned int bit, volatile void *bits ) {
|
||||||
|
|
||||||
|
test_and_clear_bit ( bit, bits );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BITS_BITOPS_H */
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef _BITS_BYTESWAP_H
|
||||||
|
#define _BITS_BYTESWAP_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Byte-order swapping functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
static inline __attribute__ (( always_inline, const )) uint16_t
|
||||||
|
__bswap_variable_16 ( uint16_t x ) {
|
||||||
|
unsigned int swapped;
|
||||||
|
|
||||||
|
__asm__ ( "lrvr %0, %1" : "=r" ( swapped ) : "r" ( x ) );
|
||||||
|
return ( swapped >> 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
__bswap_16s ( uint16_t *x ) {
|
||||||
|
unsigned int swapped;
|
||||||
|
|
||||||
|
__asm__ ( "lrvh %0, %1" : "=r" ( swapped ) : "T" ( *x ) );
|
||||||
|
*x = swapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__ (( always_inline, const )) uint32_t
|
||||||
|
__bswap_variable_32 ( uint32_t x ) {
|
||||||
|
unsigned int swapped;
|
||||||
|
|
||||||
|
__asm__ ( "lrvr %0, %1" : "=r" ( swapped ) : "r" ( x ) );
|
||||||
|
return swapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
__bswap_32s ( uint32_t *x ) {
|
||||||
|
unsigned int swapped;
|
||||||
|
|
||||||
|
__asm__ ( "lrv %0, %1" : "=r" ( swapped ) : "T" ( *x ) );
|
||||||
|
*x = swapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__ (( always_inline, const )) uint64_t
|
||||||
|
__bswap_variable_64 ( uint64_t x ) {
|
||||||
|
unsigned long swapped;
|
||||||
|
|
||||||
|
__asm__ ( "lrvgr %0, %1" : "=r" ( swapped ) : "r" ( x ) );
|
||||||
|
return swapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
__bswap_64s ( uint64_t *x ) {
|
||||||
|
unsigned long swapped;
|
||||||
|
|
||||||
|
__asm__ ( "lrvg %0, %1" : "=r" ( swapped ) : "T" ( *x ) );
|
||||||
|
*x = swapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BITS_BYTESWAP_H */
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef _BITS_COMPILER_H
|
||||||
|
#define _BITS_COMPILER_H
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** Dummy relocation type */
|
||||||
|
#define RELOC_TYPE_NONE R_390_NONE
|
||||||
|
|
||||||
|
#ifndef ASSEMBLY
|
||||||
|
|
||||||
|
/** Unprefixed constant operand modifier */
|
||||||
|
#define ASM_NO_PREFIX "c"
|
||||||
|
|
||||||
|
/** Declare a function with standard calling conventions */
|
||||||
|
#define __asmcall
|
||||||
|
|
||||||
|
/** Declare a function with libgcc implicit linkage */
|
||||||
|
#define __libgcc
|
||||||
|
|
||||||
|
/** An even/odd register pair for scalar values */
|
||||||
|
struct s390x_scalar_pair {
|
||||||
|
/** Scalar value in even 64-bit register */
|
||||||
|
unsigned long even;
|
||||||
|
/** Scalar value in odd 64-bit register */
|
||||||
|
unsigned long odd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An even/odd register pair for pointer and length values */
|
||||||
|
struct s390x_pointer_pair {
|
||||||
|
/** Pointer value in even 64-bit register */
|
||||||
|
const void *even;
|
||||||
|
/** Length value in odd 64-bit register */
|
||||||
|
unsigned long odd;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ASSEMBLY */
|
||||||
|
|
||||||
|
#endif /* _BITS_COMPILER_H */
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _BITS_ENDIAN_H
|
||||||
|
#define _BITS_ENDIAN_H
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#define __BYTE_ORDER __BIG_ENDIAN
|
||||||
|
|
||||||
|
#endif /* _BITS_ENDIAN_H */
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _BITS_ERRFILE_H
|
||||||
|
#define _BITS_ERRFILE_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* S/390 error file identifiers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup errfile Error file identifiers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* _BITS_ERRFILE_H */
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _BITS_IO_H
|
||||||
|
#define _BITS_IO_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* S/390-specific I/O API implementations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** Page shift */
|
||||||
|
#define PAGE_SHIFT 12
|
||||||
|
|
||||||
|
#endif /* _BITS_IO_H */
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _BITS_PROFILE_H
|
||||||
|
#define _BITS_PROFILE_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Profiling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get profiling timestamp
|
||||||
|
*
|
||||||
|
* @ret timestamp Timestamp
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) unsigned long
|
||||||
|
profile_timestamp ( void ) {
|
||||||
|
uint64_t cycles;
|
||||||
|
|
||||||
|
/* Read timestamp counter */
|
||||||
|
__asm__ ( "stckf %0" : "=Q" ( cycles ) );
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BITS_PROFILE_H */
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _BITS_SETJMP_H
|
||||||
|
#define _BITS_SETJMP_H
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** A jump buffer */
|
||||||
|
typedef struct {
|
||||||
|
/** Callee-saved registers (r6-r15) */
|
||||||
|
unsigned long regs[12];
|
||||||
|
} jmp_buf[1];
|
||||||
|
|
||||||
|
#endif /* _BITS_SETJMP_H */
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _BITS_STDINT_H
|
||||||
|
#define _BITS_STDINT_H
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
typedef signed long ssize_t;
|
||||||
|
typedef signed long off_t;
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef signed short int16_t;
|
||||||
|
typedef signed int int32_t;
|
||||||
|
typedef signed long long int64_t;
|
||||||
|
|
||||||
|
typedef unsigned long physaddr_t;
|
||||||
|
typedef unsigned long intptr_t;
|
||||||
|
|
||||||
|
#endif /* _BITS_STDINT_H */
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#ifndef _BITS_STRING_H
|
||||||
|
#define _BITS_STRING_H
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* String functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern void s390x_memmove ( void *dest, const void *src, size_t len );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill memory region
|
||||||
|
*
|
||||||
|
* @v dest Destination region
|
||||||
|
* @v character Fill character
|
||||||
|
* @v len Length
|
||||||
|
* @ret dest Destination region
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void *
|
||||||
|
memset ( void *dest, int character, size_t len ) {
|
||||||
|
const struct s390x_pointer_pair spair = { NULL, 0 };
|
||||||
|
struct s390x_pointer_pair dpair = { dest, len };
|
||||||
|
char ( * dmem ) [ len ] = dest;
|
||||||
|
|
||||||
|
if ( __builtin_constant_p ( character ) ) {
|
||||||
|
/* Constant fill character: use an immediate */
|
||||||
|
__asm__ ( "\n1:\n\t"
|
||||||
|
"mvcle %0, %2, %3\n\t"
|
||||||
|
"jo 1b\n\t"
|
||||||
|
: "+r" ( dpair ), "=m" ( *dmem )
|
||||||
|
: "r" ( spair ), "i" ( character ) );
|
||||||
|
} else {
|
||||||
|
/* Variable fill character: use a register */
|
||||||
|
__asm__ ( "\n1:\n\t"
|
||||||
|
"mvcle %0, %2, 0(%3)\n\t"
|
||||||
|
"jo 1b\n\t"
|
||||||
|
: "+r" ( dpair ), "=m" ( *dmem )
|
||||||
|
: "r" ( spair ), "a" ( character ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy memory region
|
||||||
|
*
|
||||||
|
* @v dest Destination region
|
||||||
|
* @v src Source region
|
||||||
|
* @v len Length
|
||||||
|
* @ret dest Destination region
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void *
|
||||||
|
memcpy ( void *dest, const void *src, size_t len ) {
|
||||||
|
struct s390x_pointer_pair spair = { src, len };
|
||||||
|
struct s390x_pointer_pair dpair = { dest, len };
|
||||||
|
const char ( * smem ) [ len ] = src;
|
||||||
|
char ( * dmem ) [ len ] = dest;
|
||||||
|
|
||||||
|
if ( __builtin_constant_p ( len ) && ( len == 0 ) ) {
|
||||||
|
/* Constant zero length: do nothing */
|
||||||
|
} else if ( __builtin_constant_p ( len ) && ( len <= 256 ) ) {
|
||||||
|
/* Constant small non-zero length: use "mvc" */
|
||||||
|
__asm__ ( "mvc %O0(%2,%R0), %1"
|
||||||
|
: "=Q" ( *dmem )
|
||||||
|
: "Q" ( *smem ), "i" ( len ) );
|
||||||
|
} else {
|
||||||
|
/* Variable or large length: use "mvcle" */
|
||||||
|
__asm__ ( "\n1:\n\t"
|
||||||
|
"mvcle %0, %1, 0\n\t"
|
||||||
|
"jo 1b\n\t"
|
||||||
|
: "+r" ( dpair ), "+r" ( spair ), "=m" ( *dmem )
|
||||||
|
: "m" ( *smem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy (possibly overlapping) memory region
|
||||||
|
*
|
||||||
|
* @v dest Destination region
|
||||||
|
* @v src Source region
|
||||||
|
* @v len Length
|
||||||
|
* @ret dest Destination region
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void *
|
||||||
|
memmove ( void *dest, const void *src, size_t len ) {
|
||||||
|
ssize_t offset = ( dest - src );
|
||||||
|
|
||||||
|
/* If direction of copy is known to be forwards at build time,
|
||||||
|
* then use standard memcpy().
|
||||||
|
*/
|
||||||
|
if ( __builtin_constant_p ( offset ) && ( offset <= 0 ) ) {
|
||||||
|
memcpy ( dest, src, len );
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, use ambidirectional copy */
|
||||||
|
s390x_memmove ( dest, src, len );
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BITS_STRING_H */
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
#ifndef _BITS_STRINGS_H
|
||||||
|
#define _BITS_STRINGS_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* String functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find first (i.e. least significant) set bit
|
||||||
|
*
|
||||||
|
* @v value Value
|
||||||
|
* @ret lsb Least significant bit set in value (LSB=1), or zero
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int __ffsll ( long long value ){
|
||||||
|
struct s390x_scalar_pair pair;
|
||||||
|
|
||||||
|
/* Extract least significant set bit */
|
||||||
|
value &= -value;
|
||||||
|
|
||||||
|
/* Count number of leading zeros before LSB */
|
||||||
|
__asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) );
|
||||||
|
|
||||||
|
return ( 64 - pair.even );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find first (i.e. least significant) set bit
|
||||||
|
*
|
||||||
|
* @v value Value
|
||||||
|
* @ret lsb Least significant bit set in value (LSB=1), or zero
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int __ffsl ( long value ) {
|
||||||
|
|
||||||
|
return __ffsll ( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find last (i.e. most significant) set bit
|
||||||
|
*
|
||||||
|
* @v value Value
|
||||||
|
* @ret msb Most significant bit set in value (LSB=1), or zero
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int __flsll ( long long value ){
|
||||||
|
struct s390x_scalar_pair pair;
|
||||||
|
|
||||||
|
/* Count leading zeros */
|
||||||
|
__asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) );
|
||||||
|
return ( 64 - pair.even );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find last (i.e. most significant) set bit
|
||||||
|
*
|
||||||
|
* @v value Value
|
||||||
|
* @ret msb Most significant bit set in value (LSB=1), or zero
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
|
||||||
|
|
||||||
|
return __flsll ( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BITS_STRINGS_H */
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _IPXE_EFI_DHCPARCH_H
|
||||||
|
#define _IPXE_EFI_DHCPARCH_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* DHCP client architecture definitions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
|
#include <ipxe/dhcp.h>
|
||||||
|
|
||||||
|
/** DHCP client architecture */
|
||||||
|
#define DHCP_ARCH_CLIENT_ARCHITECTURE 0xffff /* Not assigned */
|
||||||
|
|
||||||
|
/** DHCP client network device interface */
|
||||||
|
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||||
|
|
||||||
|
#endif /* _IPXE_EFI_DHCPARCH_H */
|
||||||
Reference in New Issue
Block a user