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,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 */
|
||||
Reference in New Issue
Block a user