174 lines
4.6 KiB
C
174 lines
4.6 KiB
C
/***************************************************************************
|
|
*cr
|
|
*cr (C) Copyright 1995-2016 The Board of Trustees of the
|
|
*cr University of Illinois
|
|
*cr All Rights Reserved
|
|
*cr
|
|
***************************************************************************/
|
|
/***************************************************************************
|
|
* RCS INFORMATION:
|
|
*
|
|
* $RCSfile: endianswap.h,v $
|
|
* $Author: johns $ $Locker: $ $State: Exp $
|
|
* $Revision: 1.7 $ $Date: 2016/11/28 05:01:53 $
|
|
*
|
|
***************************************************************************
|
|
* DESCRIPTION:
|
|
* Byte swapping routines used in various plugins
|
|
* There are two versions of each routine, one that's safe to use in
|
|
* all cases (but is slow) and one that is only safe to use on memory
|
|
* addresses that are aligned to the word size that's being byte-swapped
|
|
* but are much much much faster. Use the aligned versions of these
|
|
* routines whenever possible. The 'ndata' length count parameters and
|
|
* internal loops should be safe to use on huge memory arrays on 64-bit
|
|
* machines.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#ifndef ENDIAN_SWAP_H
|
|
#define ENDIAN_SWAP_H
|
|
|
|
/* works on unaligned 2-byte quantities */
|
|
static void swap2_unaligned(void *v, long ndata) {
|
|
long i;
|
|
char * dataptr = (char *) v;
|
|
char tmp;
|
|
|
|
for (i = 0; i < ndata-1; i += 2) {
|
|
tmp = dataptr[i];
|
|
dataptr[i] = dataptr[i+1];
|
|
dataptr[i+1] = tmp;
|
|
}
|
|
}
|
|
|
|
|
|
/* works on unaligned 4-byte quantities */
|
|
static void swap4_unaligned(void *v, long ndata) {
|
|
long i;
|
|
char *dataptr;
|
|
char tmp;
|
|
|
|
dataptr = (char *) v;
|
|
for (i=0; i<ndata; i++) {
|
|
tmp = dataptr[0];
|
|
dataptr[0] = dataptr[3];
|
|
dataptr[3] = tmp;
|
|
tmp = dataptr[1];
|
|
dataptr[1] = dataptr[2];
|
|
dataptr[2] = tmp;
|
|
dataptr += 4;
|
|
}
|
|
}
|
|
|
|
|
|
/* works on unaligned 8-byte quantities */
|
|
static void swap8_unaligned(void *v, long ndata) {
|
|
char *data = (char *) v;
|
|
long i;
|
|
char byteArray[8];
|
|
char *bytePointer;
|
|
|
|
for (i=0; i<ndata; i++) {
|
|
bytePointer = data + (i<<3);
|
|
byteArray[0] = *bytePointer;
|
|
byteArray[1] = *(bytePointer+1);
|
|
byteArray[2] = *(bytePointer+2);
|
|
byteArray[3] = *(bytePointer+3);
|
|
byteArray[4] = *(bytePointer+4);
|
|
byteArray[5] = *(bytePointer+5);
|
|
byteArray[6] = *(bytePointer+6);
|
|
byteArray[7] = *(bytePointer+7);
|
|
|
|
*bytePointer = byteArray[7];
|
|
*(bytePointer+1) = byteArray[6];
|
|
*(bytePointer+2) = byteArray[5];
|
|
*(bytePointer+3) = byteArray[4];
|
|
*(bytePointer+4) = byteArray[3];
|
|
*(bytePointer+5) = byteArray[2];
|
|
*(bytePointer+6) = byteArray[1];
|
|
*(bytePointer+7) = byteArray[0];
|
|
}
|
|
}
|
|
|
|
|
|
/* Only works with aligned 2-byte quantities, will cause a bus error */
|
|
/* on some platforms if used on unaligned data. */
|
|
static void swap2_aligned(void *v, long ndata) {
|
|
short *data = (short *) v;
|
|
long i;
|
|
short *N;
|
|
|
|
for (i=0; i<ndata; i++) {
|
|
N = data + i;
|
|
*N=(((*N>>8)&0xff) | ((*N&0xff)<<8));
|
|
}
|
|
}
|
|
|
|
|
|
/* Only works with aligned 4-byte quantities, will cause a bus error */
|
|
/* on some platforms if used on unaligned data. */
|
|
static void swap4_aligned(void *v, long ndata) {
|
|
int *data = (int *) v;
|
|
long i;
|
|
int *N;
|
|
for (i=0; i<ndata; i++) {
|
|
N = data + i;
|
|
*N=(((*N>>24)&0xff) | ((*N&0xff)<<24) |
|
|
((*N>>8)&0xff00) | ((*N&0xff00)<<8));
|
|
}
|
|
}
|
|
|
|
|
|
/* Only works with aligned 8-byte quantities, will cause a bus error */
|
|
/* on some platforms if used on unaligned data. */
|
|
static void swap8_aligned(void *v, long ndata) {
|
|
/* Use int* internally to prevent bugs caused by some compilers */
|
|
/* and hardware that would potentially load data into an FP reg */
|
|
/* and hose everything, such as the old "jmemcpy()" bug in NAMD */
|
|
int *data = (int *) v;
|
|
long i;
|
|
int *N;
|
|
int t0, t1;
|
|
|
|
for (i=0; i<ndata; i++) {
|
|
N = data + (i<<1);
|
|
t0 = N[0];
|
|
t0=(((t0>>24)&0xff) | ((t0&0xff)<<24) |
|
|
((t0>>8)&0xff00) | ((t0&0xff00)<<8));
|
|
|
|
t1 = N[1];
|
|
t1=(((t1>>24)&0xff) | ((t1&0xff)<<24) |
|
|
((t1>>8)&0xff00) | ((t1&0xff00)<<8));
|
|
|
|
N[0] = t1;
|
|
N[1] = t0;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
/* Other implementations that might be faster in some cases */
|
|
|
|
/* swaps the endianism of an eight byte word. */
|
|
void mdio_swap8(double *i) {
|
|
char c;
|
|
char *n;
|
|
n = (char *) i;
|
|
c = n[0];
|
|
n[0] = n[7];
|
|
n[7] = c;
|
|
c = n[1];
|
|
n[1] = n[6];
|
|
n[6] = c;
|
|
c = n[2];
|
|
n[2] = n[5];
|
|
n[5] = c;
|
|
c = n[3];
|
|
n[3] = n[4];
|
|
n[4] = c;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|