i128.c 6.42 KB

/**************************************************************************
 *                                                                        *
 *               Copyright (C) 1994, Silicon Graphics, Inc.               *
 *                                                                        *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright  law.  They  may not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *                                                                        *
 *************************************************************************/

/*
 * File:	i128.c
 * Creator:	hsa@sgi.com
 * Create Date:	Wed Mar  9 16:44:53 PST 1994
 *
 * Routines to handle 128-bit wide data.
 *
 */

#include <stdio.h>
#include "i128.h"
#include "vu.h"

/*
 * 'copy' i128 data
 */
void
Set128(i128 *x, i128 *y)
{
    int 	i;

    for (i=0; i<16; i++) {
	x->b[i] = y->b[i];
    }
}

/*
 * Generic set bytes, give a byte index and a count.
 * Aliasing of the y parameter to be an array of bytes is
 * risky programming -- this won't work on byte-swapped machines.
 */
void
Set128bytes(i128 *x, u8 *y, int elem, int count)
{
    int 	i;

    for (i=0; i<count; i++) {
	x->b[elem+i] = y[i];
    }
}

/*
 * The next bunch of routines do 'set' and 'get' by n-bit-wide elements.
 * The 0th element is in the low bits of the i128.
 */

void
Set128By8(i128 *x, u8 y, int elem)
{
    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return;
    }

    x->b[elem] = y;
}

u8
Get128By8(i128 *x, int elem)
{
    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return 0x0;
    }

    return x->b[elem];
}

void
Set128By16(i128 *x, u16 y, int elem)
{
    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return;
    }

    x->b[elem * 2 + 0] = (u8) ((y & 0xff00) >> 8);
    x->b[elem * 2 + 1] = (u8) ((y & 0x00ff) >> 0);
}

u16
Get128By16(i128 *x, int elem)
{
    u16	tmp;

    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return 0x0;
    }

    tmp = ((((u16)x->b[elem * 2 + 0]) << 8) |
	   (((u16)x->b[elem * 2 + 1]) << 0));
    return tmp;
}

void
Set128By32(i128 *x, u32 y, int elem)
{
    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return;
    }

    x->b[elem * 4 + 0] = (u8) ((y & 0xff000000) >> 24);
    x->b[elem * 4 + 1] = (u8) ((y & 0x00ff0000) >> 16);
    x->b[elem * 4 + 2] = (u8) ((y & 0x0000ff00) >>  8);
    x->b[elem * 4 + 3] = (u8) ((y & 0x000000ff) >>  0);
}

u32
Get128By32(i128 *x, int elem)
{
    u32	tmp;

    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return 0x0;
    }

    tmp = ((((u32)x->b[elem * 4 + 0]) << 24) |
	   (((u32)x->b[elem * 4 + 1]) << 16) |
	   (((u32)x->b[elem * 4 + 2]) <<  8) |
	   (((u32)x->b[elem * 4 + 3]) <<  0));
    return tmp;
}

void
Set128By64(i128 *x, u64 y, int elem)
{
    int	i;
    u64	mask, tmp;

    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return;
    }

    /* the compiler didn't like shifting the other way... */
    mask = 0x00000000000000ff;
    for (i=7; i>=0; i--) {
	tmp = y & mask;
	tmp >>= (7-i)*8;
	x->b[elem * 8 + i] = (u8) tmp;
	mask <<= 8;
    }
}

u64
Get128By64(i128 *x, int elem)
{
    int	i;
    u64	tmp;

    if (elem < 0 || elem > 15) {
	rsp_eprintf(stderr,"ERROR : vector element out of range. (%d)\n",elem);
	return 0x0;
    }

    tmp = 0x0000000000000000;
    for (i=0; i<8; i++) {
	tmp |= (((u64)x->b[elem * 8 + i]) << ((7-i)*8));
    }

    return tmp;
}

/*
 * utility to print out an i128 in hex.
 */
void
Print128(FILE *out, i128 x)
{
    int		i;

    for (i=0; i<16; i++) {
	rsp_eprintf(out,"%02x%s",x.b[i], (i&rsp_VUSpacing)?" ":"");
    }
}

#ifdef DUMPMODE
/*
 * standalone program for testing.
 */
void
main(int argc, char *argv[])
{
    u8	x8;
    u16	x16;
    u32	x32;
    u64	x64;
    i128	reg;
    int	i;

    while ((argc > 1) && (argv[1][0] == '-')) {
	switch(argv[1][1]) {
	}
	argc--;
	argv++;
    }

    Set128By64(&reg, 0x0, 0);
    Set128By64(&reg, 0x0, 1);

    fprintf(stdout,"\nInitial reg  = 0x");
    Print128(stdout, reg);
    fprintf(stdout,"\n");
    fprintf(stdout,"\n");

    Set128By8(&reg, 0xb0, 0);
    Set128By8(&reg, 0xb1, 1);
    Set128By8(&reg, 0xb2, 2);
    Set128By8(&reg, 0xb3, 3);
    Set128By8(&reg, 0xb4, 4);
    Set128By8(&reg, 0xb5, 5);
    Set128By8(&reg, 0xb6, 6);
    Set128By8(&reg, 0xb7, 7);
    Set128By8(&reg, 0xb8, 8);
    Set128By8(&reg, 0xb9, 9);
    Set128By8(&reg, 0xba, 10);
    Set128By8(&reg, 0xbb, 11);
    Set128By8(&reg, 0xbc, 12);
    Set128By8(&reg, 0xbd, 13);
    Set128By8(&reg, 0xbe, 14);
    Set128By8(&reg, 0xbf, 15);

    fprintf(stdout,"Set128By8()  = 0x");
    Print128(stdout, reg);
    fprintf(stdout,"\nGet128By8()  = 0x");

    for (i=0; i<16; i++) {
	x8 = Get128By8(&reg, i);
	fprintf(stdout,"%02x",x8);
    }
    fprintf(stdout,"\n\n");

    Set128By16(&reg, 0xbee0, 0);
    Set128By16(&reg, 0xbee1, 1);
    Set128By16(&reg, 0xbee2, 2);
    Set128By16(&reg, 0xbee3, 3);
    Set128By16(&reg, 0xbee4, 4);
    Set128By16(&reg, 0xbee5, 5);
    Set128By16(&reg, 0xbee6, 6);
    Set128By16(&reg, 0xbee7, 7);

    fprintf(stdout,"Set128By16() = 0x");
    Print128(stdout, reg);
    fprintf(stdout,"\nGet128By16() = 0x");

    for (i=0; i<8; i++) {
	x16 = Get128By16(&reg, i);
	fprintf(stdout,"%04x",x16);
    }
    fprintf(stdout,"\n\n");

    Set128By32(&reg, 0xbeef0000, 0);
    Set128By32(&reg, 0xbeef0001, 1);
    Set128By32(&reg, 0xbeef0002, 2);
    Set128By32(&reg, 0xbeef0003, 3);

    fprintf(stdout,"Set128By32() = 0x");
    Print128(stdout, reg);
    fprintf(stdout,"\nGet128By32() = 0x");

    for (i=0; i<4; i++) {
	x32 = Get128By32(&reg, i);
	fprintf(stdout,"%08x",x32);
    }
    fprintf(stdout,"\n\n");

    Set128By64(&reg, 0x0a00deadbeef0000, 0);
    Set128By64(&reg, 0x0b00deadbeef0001, 1);

    fprintf(stdout,"Set128By64() = 0x");
    Print128(stdout, reg);
    fprintf(stdout,"\nGet128By64() = 0x");

    for (i=0; i<2; i++) {
	x64 = Get128By64(&reg, i);
	fprintf(stdout,"%016llx",x64);
    }
    fprintf(stdout,"\n\n");

}
#endif