vst.c 6.94 KB
/****************************************************************
  WHAT:	RSP SCALAR UNIT TEST GENERATOR FOR VECTOR LOAD INSTRUCTIONS
  SCCS: %W% %G%
  PTLS: $Id: vst.c,v 1.1.1.1 2002/05/02 03:29:15 blythe Exp $
   WHO:	Project Reality - Evan Y. Wang
   (C):	1994 Silicon Graphics, Inc.
 ****************************************************************/
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "software.h"
#include "gen.h"
#include "suregre.h"

#define MAX_TCS	MAX_VST_TCS

#define GenCase()						  \
    fprintf(outp,			/* output file handle	*/\
	    /* ChkVst(  n,Op,   rA,   rB,   rR,   rT,   vA,   vB,   vC,   vT,     AH,     AL,     BH,     BL,     RH,     RL,   Offs,   El,    VCC)*/\
	    "\tChkVst(%2d,%s,r%-2d,r%-2d,r%-2d,r%-2d,v%-2d,v%-2d,v%-2d,v%-2d,0x%4.4X,0x%4.4X,0x%4.4X,0x%4.4X,0x%4.4X,0x%4.4X,0x%4.4X,e%-2d,0x%4.4X)\n",\
	    CurTcNo,			/* test case number	*/\
	    ip->name,			/* instruction name	*/\
	    rA,				/* pt to exp'd result	*/\
	    rB,				/* base register	*/\
	    rR,				/* used to check VCC	*/\
	    rT,				/* hold expected VCC	*/\
	    vA,				/* used to check test	*/\
	    vB,				/* used to check test	*/\
	    vC,				/* used to check test	*/\
	    vT,				/* used to test		*/\
	    HHW(OpA), LHW(OpA),		/* rA value		*/\
	    HHW(OpB), LHW(OpB),		/* rB value		*/\
	    HHW(Res), LHW(Res),		/* rB value		*/\
	    LHW(Imm),			/* offset to rB		*/\
	    El,				/* element		*/\
	    VCC);			/* expected VCC (rT)	*/\

int VstGen(outp, ip)
    FILE *outp;
    I_TABLE *ip;
{
    int i;
    int elinc;
    int baseinc;
    int baselmt;
    int offsinc;
    int datasize;

    switch (ip->vec) {
      case VLS_BYTE: elinc = 1; baseinc = 1; baselmt = 16; offsinc = 0; datasize =  1; break;
      case VLS_SHRT: elinc = 2; baseinc = 1; baselmt = 16; offsinc = 1; datasize =  2; break;
      case VLS_WORD: elinc = 4; baseinc = 1; baselmt = 16; offsinc = 2; datasize =  4; break;
      case VLS_DBLE: elinc = 8; baseinc = 1; baselmt = 16; offsinc = 3; datasize =  8; break;
      case VLS_QUAD: elinc = 0; baseinc = 1; baselmt = 16; offsinc = 4; datasize = 16; break;
      case VLS_REST: elinc = 0; baseinc = 1; baselmt = 16; offsinc = 4; datasize = 16; break;
      case VLS_PACK: elinc = 0; baseinc = 1; baselmt = 16; offsinc = 3; datasize =  8; break;
      case VLS_UPCK: elinc = 0; baseinc = 1; baselmt = 16; offsinc = 3; datasize =  8; break;
      case VLS_HALF: elinc = 0; baseinc = 1; baselmt =  2; offsinc = 4; datasize = 15; break;
      case VLS_FRTH: elinc = 8; baseinc = 1; baselmt =  4; offsinc = 4; datasize = 13; break;
    }

    /************************************************************
      Generate Test Cases
     ************************************************************/
    VCC = 0xFF;		/* we expect all result cmp's to match	*/
    OpA = DMEM_BASE + MEMSIZE;

    do {
	OpB = DMEM_BASE + MEMSIZE/2;		/* exercise base value	*/
        for (i=0,El=0; i < baselmt; i++) {
	    /* A simple case of zero offset */
	    Imm = 0;
	    FILE_SPLIT {
		(void) ip->proc(outp,ip->vec);
		GenCase();
		UpdRegTABR();
		UpdRegID();
		UpdVRegID();
		OpA = OpA + 0x30;
	    }
	    CurTcNo++;

	    /* A case of one unit offset */
	    El = (El+elinc)%16;
	    Imm = 1 << offsinc;
	    FILE_SPLIT {
		(void) ip->proc(outp,ip->vec);
		GenCase();
		UpdRegTABR();
		UpdRegID();
		UpdVRegID();
		OpA = OpA + 0x30;
	    }
	    CurTcNo++;

	    /* A case of minus one unit offset */
	    El = (El+elinc)%16;
	    Imm = -1 << offsinc;
	    FILE_SPLIT {
		(void) ip->proc(outp,ip->vec);
		GenCase();
		UpdRegTABR();
		UpdRegID();
		UpdVRegID();
		OpA = OpA + 0x30;
	    }
	    CurTcNo++;

	    /* A case of maximum manageable positive offset */
	    El = (El+elinc)%16;
	    Imm = (((DMEM_BASE+MEMSIZE-OpB)-datasize) & 0x3F) >> offsinc << offsinc;
	    FILE_SPLIT {
		(void) ip->proc(outp,ip->vec);
		GenCase();
		UpdRegTABR();
		UpdRegID();
		UpdVRegID();
		OpA = OpA + 0x30;
	    }
	    CurTcNo++;

	    /* A case of maximum manageable negative offset */
	    El = (El+elinc)%16;
	    Imm = ((OpB-DMEM_BASE-MEMSIZE) >> offsinc << offsinc) | ~0x3F;
	    FILE_SPLIT {
		(void) ip->proc(outp,ip->vec);
		GenCase();
		UpdRegTABR();
		UpdRegID();
		UpdVRegID();
		OpA = OpA + 0x30;
	    }
	    CurTcNo++;

	    El = (El+elinc)%16;
	    OpB = OpB + baseinc;
	}

    } while (CurTcNo < 36);			/* minimally cycle thru all regs*/

    return CurTcNo = 0;

}   /* VstGen */

/****************************************************************
  vst(..) - instruction model.  This routine computes the correct
  answer for the test, stores the answer into our model, and
  write out the answer as data in the data segment.
 ****************************************************************/
u32 vst(outp,vec)
    FILE *outp;
    int vec;
{
    int i;
    u32 adr;

    /* Initialize vT with some random value */
    for (i=0; i<4; i++)
	VReg[vT][i].w = (u32) (rand()<<16|rand());

    /* Put initialization vAlue into DMEM so we can load it */
    fprintf(outp, "\n");
    for (i=0; i<4; i++)
	fprintf(outp, "\t.word\t0x%8.8lX\n", VReg[vT][i].w);
    fprintf(outp, "\n");

    /* Perform test op and update scratch DMEM */
    switch (vec) {
      case VLS_BYTE:
	adr = OpB + Imm - DMEM_BASE;
	assert(!(El&~0xF));
	*BMem[adr] = *(&VReg[vT][El>>2].u.h.u.hb + (El&3));
	break;
      case VLS_SHRT:
	adr = OpB + Imm - DMEM_BASE;
	assert(!(El&~0xE));
	*BMem[adr]   = *(&VReg[vT][El>>2].u.h.u.hb+(El&3));
	*BMem[adr+1] = *(&VReg[vT][El>>2].u.h.u.hb+(El&3)+1);
	break;
      case VLS_WORD:
	adr = OpB + Imm - DMEM_BASE;
	assert(!(El&~0xC));
	for (i=0; i<4; i++)
	    *BMem[adr+i] = *(&VReg[vT][El>>2].u.h.u.hb+i);
	break;
      case VLS_DBLE:
	adr = OpB + Imm - DMEM_BASE;
	assert(!(El&~0x8));
	for (i=0; i<8; i++)
	    *BMem[adr+i] = *(&VReg[vT][El>>2].u.h.u.hb+i);
	break;
      case VLS_QUAD:
	adr = OpB + Imm - DMEM_BASE;
	assert(!El);
	i = 0;
	do {
	    *BMem[adr+i] = *(&VReg[vT][0].u.h.u.hb+i);
	} while (i++, ((i+adr)&0xF) != 0);
	break;
      case VLS_REST:
	adr = OpB + Imm - DMEM_BASE;
	assert(!El);
	for (i=15; ((i+adr)&0xF) != 0xF; i--)
	    *BMem[adr-16+i] = *(&VReg[vT][0].u.h.u.hb+i);
	break;
      case VLS_PACK:
	adr = OpB + Imm - DMEM_BASE;
	assert(!El);
	for (i=0; i<8; i++)
	    *BMem[adr+i] = *(&VReg[vT][0].u.h.hw+i) >> 8;
	break;
      case VLS_UPCK:
	adr = OpB + Imm - DMEM_BASE;
	assert(!El);
	for (i=0; i<8; i++)
	    *BMem[adr+i] = *(&VReg[vT][0].u.h.hw+i) >> 7;
	break;
      case VLS_HALF:
	adr = OpB + Imm - DMEM_BASE;
	assert(!El);
	assert(!(adr&0xE));
	for (i=0; i<8; i++)
	    *BMem[adr+2*i] = *(&VReg[vT][0].u.h.hw+i) >> 7;
	break;
      case VLS_FRTH:
	adr = OpB + Imm - DMEM_BASE;
	assert(!(El&~0x8));
	assert(!(adr&0xC));
	for (i=0; i<4; i++)
	    *BMem[adr+4*i] = *(&VReg[vT][El>>2].u.h.hw+i) >> 7;
	break;
    }
    
    Res = adr>>4;
    if (adr+0x10 >= MEMSIZE)	Res = (Res-1) << 2;	/* mem boundary	*/
    else			Res =  Res << 2;

    for (i=0; i<8; i++)
	fprintf(outp, "\t.word\t0x%8.8lX\n", *WMem[Res+i]);
    fprintf(outp, "\n");

    Res = (Res << 2) + DMEM_BASE;	/* return to byte address */

    return 0;

}   /* vst */