2005-02-20 03:18:32 +03:00
|
|
|
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
|
|
|
/*
|
2006-02-13 00:03:01 +03:00
|
|
|
* Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
|
2005-11-05 22:57:48 +03:00
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
2006-02-13 00:03:01 +03:00
|
|
|
* Copyright (c) 2004-2006 The University of Tennessee and The University
|
2005-11-05 22:57:48 +03:00
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
2006-02-13 00:03:01 +03:00
|
|
|
* Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
|
2005-02-20 03:18:32 +03:00
|
|
|
* University of Stuttgart. All rights reserved.
|
2006-02-13 00:03:01 +03:00
|
|
|
* Copyright (c) 2004-2006 The Regents of the University of California.
|
2005-03-24 15:43:37 +03:00
|
|
|
* All rights reserved.
|
2008-04-18 04:26:17 +04:00
|
|
|
* Copyright (c) 2008 Cisco Systems, Inc. All rights reserved.
|
2005-02-20 03:18:32 +03:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
2008-04-18 00:43:56 +04:00
|
|
|
#ifndef OPAL_ARCH_H_HAS_BEEN_INCLUDED
|
|
|
|
#define OPAL_ARCH_H_HAS_BEEN_INCLUDED
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2008-04-18 04:26:17 +04:00
|
|
|
#include "opal_config.h"
|
|
|
|
|
2005-02-20 02:53:26 +03:00
|
|
|
#include <float.h>
|
|
|
|
#include <assert.h>
|
2008-04-18 00:43:56 +04:00
|
|
|
|
2005-02-20 02:53:26 +03:00
|
|
|
|
|
|
|
/***************************************************
|
|
|
|
** This file tries to classify the most relevant
|
2006-10-04 00:21:24 +04:00
|
|
|
** platforms regarding their data representation.
|
2005-02-20 02:53:26 +03:00
|
|
|
** Three aspects are important:
|
|
|
|
** - byte ordering (little or big endian)
|
2006-10-04 00:21:24 +04:00
|
|
|
** - integer representation
|
2005-02-20 02:53:26 +03:00
|
|
|
** - floating point representation.
|
|
|
|
|
|
|
|
** In addition, don't forget about the C/Fortran problems.
|
|
|
|
**
|
|
|
|
*****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************
|
|
|
|
** Part 1: Integer representation.
|
|
|
|
**
|
|
|
|
** The following data types are considered relevant:
|
|
|
|
**
|
|
|
|
** short
|
|
|
|
** int
|
|
|
|
** long
|
|
|
|
** long long
|
|
|
|
** integer (fortran)
|
|
|
|
**
|
|
|
|
** The fortran integer is dismissed here, since there is no
|
|
|
|
** platform known to me, were fortran and C-integer do not match
|
|
|
|
**
|
|
|
|
** The following abbriviations are introduced:
|
|
|
|
**
|
|
|
|
** a) il32 (int long are 32 bits) (e.g. IA32 LINUX, SGI n32, SUN)
|
|
|
|
**
|
|
|
|
** short: 16 (else it would appear in the name)
|
|
|
|
** int: 32
|
|
|
|
** long: 32
|
|
|
|
** long long: 64
|
|
|
|
**
|
|
|
|
** b) il64 ( int long are 64 bits) (e.g. Cray T3E )
|
|
|
|
** short: 32
|
|
|
|
** int: 64
|
|
|
|
** long: 64
|
|
|
|
** long long: 64
|
|
|
|
**
|
|
|
|
** c) l64 (long are 64 bits) (e.g. SGI 64 IRIX, NEC SX5)
|
|
|
|
**
|
|
|
|
** short: 16
|
|
|
|
** int: 32
|
|
|
|
** long: 64
|
|
|
|
** long long: 64
|
|
|
|
**
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
** Part 2: Floating point representation
|
|
|
|
**
|
|
|
|
** The following datatypes are considered relevant
|
|
|
|
**
|
|
|
|
** float
|
|
|
|
** double
|
|
|
|
** long double
|
|
|
|
** real
|
|
|
|
** double precision
|
|
|
|
**
|
|
|
|
** Unfortunatly, here we have to take care, whether float and real,
|
|
|
|
** respectively double and double precision do match...
|
|
|
|
**
|
|
|
|
** a) fr32 (float and real are 32 bits) (e.g. SGI n32 and 64, SUN, NEC SX5,...)
|
|
|
|
** float: 32
|
|
|
|
** double: 64
|
|
|
|
** long double: 128
|
|
|
|
** real: 32
|
|
|
|
** double prec.:64
|
|
|
|
**
|
|
|
|
** a1) fr32ld96 (float and real 32, long double 96) (e.g. IA32 LINUX gcc/icc)
|
|
|
|
** see a), except long double is 96
|
|
|
|
**
|
|
|
|
** a2) fr32ld64 (e.g. IBM )
|
|
|
|
** see a), except long double is 64
|
|
|
|
**
|
|
|
|
** b) cray ( e.g. Cray T3E)
|
|
|
|
** float: 32
|
|
|
|
** double: 64
|
|
|
|
** long double: 64
|
|
|
|
** real: 64
|
|
|
|
** double prec.:64
|
|
|
|
**
|
|
|
|
**
|
|
|
|
** Problem: long double is really treated differently on every machine. Therefore,
|
|
|
|
** we are storing besides the length of the long double also the length of the mantisee,
|
|
|
|
** and the number of *relevant* bits in the exponent. Here are the values:
|
|
|
|
**
|
|
|
|
** Architecture sizeof(long double) mantisee relevant bits for exp.
|
|
|
|
**
|
|
|
|
** SGIn32/64: 128 107 10
|
|
|
|
** SUN(sparc): 128 113 14
|
|
|
|
** IA64: 128 64 14
|
|
|
|
** IA32: 96 64 14
|
|
|
|
** Alpha: 128 113 14
|
|
|
|
** 64 53 10 (gcc)
|
|
|
|
** IBM: 64 53 10
|
|
|
|
** (128 106 10) (special flags required).
|
|
|
|
** SX5: 128 105 22
|
|
|
|
**
|
|
|
|
** We will not implement all of these routiens, but we consider them
|
|
|
|
** now when defining the header-settings
|
|
|
|
**
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
**
|
|
|
|
** Classification of machines:
|
|
|
|
**
|
|
|
|
** IA32 LINUX: il32, fr32ld96, little endian
|
|
|
|
** SUN: il32, fr32, big endian
|
|
|
|
** SGI n32: il32, fr32, big endian
|
|
|
|
** SGI 64: l64, fr32, big endian
|
|
|
|
** NEC SX5: l64, fr32 big endian
|
|
|
|
** Cray T3E: il64, cray, big endian
|
|
|
|
** Cray X1: i32(+), fr32, big endian
|
|
|
|
** IBM: il32, fr32ld64, big endian
|
|
|
|
** ALPHA: l64, fr32, little endian
|
|
|
|
** ITANIUM: l64, fr32, little endian
|
|
|
|
**
|
|
|
|
**
|
|
|
|
** + sizeof ( long long ) not known
|
|
|
|
** ? alpha supports both, big and little endian
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* Current conclusions:
|
|
|
|
** we need at the moment three settings:
|
|
|
|
** - big/little endian ?
|
|
|
|
** - is long 32 or 64 bits ?
|
|
|
|
** - is long double 64, 96 or 128 bits ?
|
|
|
|
** - no. of rel. bits in the exponent of a long double ( 10 or 14 )
|
|
|
|
** - no. of bits of the mantiss of a long double ( 53, 64, 105, 106, 107, 113 )
|
|
|
|
**
|
|
|
|
** To store this in a 32 bit integer, we use the following definition:
|
|
|
|
**
|
|
|
|
** 1 2 3 4
|
|
|
|
** 12345678 12345678 12345678 12345678
|
|
|
|
**
|
|
|
|
** 1. Byte:
|
|
|
|
** bits 1 & 2: 00 (header) (to recognize the correct end)
|
|
|
|
** bits 3 & 4: encoding: 00 = little, 01 = big
|
|
|
|
** bits 5 & 6: reserved for later use. currently set to 00
|
|
|
|
** bits 7 & 8: reserved for later use. currently set to 00
|
|
|
|
** 2. Byte:
|
|
|
|
** bits 1 & 2: length of long: 00 = 32, 01 = 64
|
|
|
|
** bits 3 & 4: lenght of long long (not used currently, set to 00).
|
2006-03-25 05:53:41 +03:00
|
|
|
** bits 5 & 6: length of C/C++ bool (00 = 8, 01 = 16, 10 = 32)
|
|
|
|
** bits 7 & 8: length of Fortran Logical (00 = 8, 01 = 16, 10 = 32)
|
2005-02-20 02:53:26 +03:00
|
|
|
** 3. Byte:
|
|
|
|
** bits 1 & 2: length of long double: 00=64, 01=96,10 = 128
|
|
|
|
** bits 3 & 4: no. of rel. bits in the exponent: 00 = 10, 01 = 14)
|
|
|
|
** bits 5 - 7: no. of bits of mantisse ( 000 = 53, 001 = 64, 010 = 105,
|
|
|
|
** 011 = 106, 100 = 107,101 = 113 )
|
|
|
|
** bit 8: intel or sparc representation of mantisse (0 = sparc,
|
|
|
|
** 1 = intel )
|
|
|
|
** 4. Byte:
|
|
|
|
** bits 1 & 2: 11 (header) (to recognize the correct end)
|
|
|
|
** bits 3 & 4: reserved for later use. currently set to 11
|
|
|
|
** bits 5 & 6: reserved for later use. currently set to 11
|
|
|
|
** bits 7 & 8: reserved for later use. currently set to 11
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* These masks implement the specification above above */
|
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_HEADERMASK 0x03000000 /* set the fields for the header */
|
|
|
|
#define OPAL_ARCH_HEADERMASK2 0x00000003 /* other end, needed for checks */
|
|
|
|
#define OPAL_ARCH_UNUSEDMASK 0xfc000000 /* mark the unused fields */
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2006-03-25 05:53:41 +03:00
|
|
|
/* BYTE 1 */
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_ISBIGENDIAN 0x00000008
|
2006-03-25 05:53:41 +03:00
|
|
|
|
|
|
|
/* BYTE 2 */
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_LONGISxx 0x0000c000 /* mask for sizeof long */
|
|
|
|
#define OPAL_ARCH_LONGIS64 0x00001000
|
|
|
|
#define OPAL_ARCH_LONGLONGISxx 0x00003000 /* mask for sizeof long long */
|
2006-03-25 05:53:41 +03:00
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_BOOLISxx 0x00000c00 /* mask for sizeof bool */
|
|
|
|
#define OPAL_ARCH_BOOLIS8 0x00000000 /* bool is 8 bits */
|
|
|
|
#define OPAL_ARCH_BOOLIS16 0x00000400 /* bool is 16 bits */
|
|
|
|
#define OPAL_ARCH_BOOLIS32 0x00000800 /* bool is 32 bits */
|
2006-03-25 05:53:41 +03:00
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_LOGICALISxx 0x00000300 /* mask for sizeof Fortran logical */
|
|
|
|
#define OPAL_ARCH_LOGICALIS8 0x00000000 /* logical is 8 bits */
|
|
|
|
#define OPAL_ARCH_LOGICALIS16 0x00000100 /* logical is 16 bits */
|
|
|
|
#define OPAL_ARCH_LOGICALIS32 0x00000200 /* logical is 32 bits */
|
2006-03-25 05:53:41 +03:00
|
|
|
|
|
|
|
/* BYTE 3 */
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_LONGDOUBLEIS96 0x00020000
|
|
|
|
#define OPAL_ARCH_LONGDOUBLEIS128 0x00010000
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_LDEXPSIZEIS15 0x00080000
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_LDMANTDIGIS64 0x00400000
|
|
|
|
#define OPAL_ARCH_LDMANTDIGIS105 0x00200000
|
|
|
|
#define OPAL_ARCH_LDMANTDIGIS106 0x00600000
|
|
|
|
#define OPAL_ARCH_LDMANTDIGIS107 0x00100000
|
|
|
|
#define OPAL_ARCH_LDMANTDIGIS113 0x00500000
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#define OPAL_ARCH_LDISINTEL 0x00800000
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2008-08-28 17:06:14 +04:00
|
|
|
BEGIN_C_DECLS
|
|
|
|
|
2008-04-18 04:26:17 +04:00
|
|
|
OPAL_DECLSPEC int32_t opal_arch_compute_local_id( uint32_t *var);
|
|
|
|
|
|
|
|
OPAL_DECLSPEC int32_t opal_arch_checkmask ( uint32_t *var, uint32_t mask );
|
2005-02-20 02:53:26 +03:00
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
static inline int32_t opal_arch_isbigendian ( void )
|
2005-02-20 02:53:26 +03:00
|
|
|
{
|
|
|
|
const uint32_t value = 0x12345678;
|
|
|
|
const char *ptr = (char*)&value;
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
/* if( sizeof(int) == 8 ) x = 4; */
|
|
|
|
if( ptr[x] == 0x12) return 1; /* big endian, true */
|
|
|
|
if( ptr[x] == 0x78 ) return 0; /* little endian, false */
|
|
|
|
assert( 0 ); /* unknown architecture not little nor big endian */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we must find which representation of long double is used
|
|
|
|
* intel or sparc. Both of them represent the long doubles using a close to
|
|
|
|
* IEEE representation (seeeeeee..emmm...m) where the mantissa look like
|
|
|
|
* 1.????. For the intel representaion the 1 is explicit, and for the sparc
|
|
|
|
* the first one is implicit. If we take the number 2.0 the exponent is 1
|
|
|
|
* and the mantissa is 1.0 (the sign of course should be 0). So if we check
|
|
|
|
* for the first one in the binary representation of the number, we will
|
|
|
|
* find the bit from the exponent, so the next one should be the begining
|
|
|
|
* of the mantissa. If it's 1 then we have an intel representaion, if not
|
|
|
|
* we have a sparc one. QED
|
|
|
|
*/
|
2008-04-18 00:43:56 +04:00
|
|
|
static inline int32_t opal_arch_ldisintel( void )
|
2005-02-20 02:53:26 +03:00
|
|
|
{
|
|
|
|
long double ld = 2.0;
|
|
|
|
int i, j;
|
2005-11-07 07:59:46 +03:00
|
|
|
uint32_t* pui = (uint32_t*)(void*)&ld;
|
2005-02-20 02:53:26 +03:00
|
|
|
|
|
|
|
j = LDBL_MANT_DIG / 32;
|
|
|
|
i = (LDBL_MANT_DIG % 32) - 1;
|
2008-04-18 00:43:56 +04:00
|
|
|
if( opal_arch_isbigendian() ) { /* big endian */
|
2005-02-20 02:53:26 +03:00
|
|
|
j = (sizeof(long double) / sizeof(unsigned int)) - j;
|
|
|
|
if( i < 0 ) {
|
|
|
|
i = 31;
|
|
|
|
j = j+1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if( i < 0 ) {
|
|
|
|
i = 31;
|
|
|
|
j = j-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (pui[j] & (1 << i) ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
static inline void opal_arch_setmask ( uint32_t *var, uint32_t mask)
|
2005-02-20 02:53:26 +03:00
|
|
|
{
|
|
|
|
*var |= mask;
|
|
|
|
}
|
|
|
|
|
2008-08-28 17:06:14 +04:00
|
|
|
END_C_DECLS
|
|
|
|
|
2008-04-18 00:43:56 +04:00
|
|
|
#endif /* OPAL_ARCH_H_HAS_BEEN_INCLUDED */
|
2005-02-20 02:53:26 +03:00
|
|
|
|