vlogic.c 7.15 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:	vlogic.c
 * Creator:	hsa@sgi.com
 * Create Date:	Thu Apr 28 15:52:14 PDT 1994
 *
 * This file holds the logical instructions for the VU.
 *
 */

#include <stdio.h>
#include "rsp.h"
#include "i128.h"
#include "rspctl.h"
#include "opcode.h"
#include "vu.h"
#include "trace_print.h"

#define ACC_LOW(indx,val)       ((rsp_ACC[indx] & ~0xffffLL) | (val & 0xffff))


rsp_vuPipe_t	vu_LogicPipe[rsp_VUPIPEDEPTH+1];

/* 16-bit vector and */
static void
vand(rsp_vuPipe_t *mp)
{
    int		element, i;
    u16		su, tu;
    u32		du;

    for (i=0; i<8; i++) {

	element = ((i & cmask_tab[(mp->format & 0x0e) >> 1]) + 
		   (mp->format & emask_tab[(mp->format & 0x0e) >> 1]));

	su = (u16) Get128By16(&(rsp_VUR[mp->rs]), i);
	tu = (u16) Get128By16(&(rsp_VUR[mp->rt]), element);
	du = su & tu;

        rsp_ACC[i] = ACC_LOW(i,du); /* HW compatibility */

	Set128By16(&(mp->result), (u16) du, i);
    }
}

/* 16-bit vector nand */
static void
vnand(rsp_vuPipe_t *mp)
{
    int		element, i;
    u16		su, tu;
    u32		du;

    for (i=0; i<8; i++) {

	element = ((i & cmask_tab[(mp->format & 0x0e) >> 1]) + 
		   (mp->format & emask_tab[(mp->format & 0x0e) >> 1]));

	su = (u16) Get128By16(&(rsp_VUR[mp->rs]), i);
	tu = (u16) Get128By16(&(rsp_VUR[mp->rt]), element);
	du = ~(su & tu);

        rsp_ACC[i] = ACC_LOW(i,du); /* HW compatibility */

	Set128By16(&(mp->result), (u16) du, i);
    }
}

/* 16-bit vector or */
static void
vor(rsp_vuPipe_t *mp)
{
    int		element, i;
    u16		su, tu;
    u32		du;

    for (i=0; i<8; i++) {

	element = ((i & cmask_tab[(mp->format & 0x0e) >> 1]) + 
		   (mp->format & emask_tab[(mp->format & 0x0e) >> 1]));

	su = (u16) Get128By16(&(rsp_VUR[mp->rs]), i);
	tu = (u16) Get128By16(&(rsp_VUR[mp->rt]), element);
	du = su | tu;

        rsp_ACC[i] = ACC_LOW(i,du); /* HW compatibility */

	Set128By16(&(mp->result), (u16) du, i);
    }
}

/* 16-bit vector nor */
static void
vnor(rsp_vuPipe_t *mp)
{
    int		element, i;
    u16		su, tu;
    u32		du;

    for (i=0; i<8; i++) {

	element = ((i & cmask_tab[(mp->format & 0x0e) >> 1]) + 
		   (mp->format & emask_tab[(mp->format & 0x0e) >> 1]));

	su = (u16) Get128By16(&(rsp_VUR[mp->rs]), i);
	tu = (u16) Get128By16(&(rsp_VUR[mp->rt]), element);
	du = ~(su | tu);

        rsp_ACC[i] = ACC_LOW(i,du); /* HW compatibility */

	Set128By16(&(mp->result), (u16) du, i);
    }
}

/* 16-bit vector xor */
static void
vxor(rsp_vuPipe_t *mp)
{
    int		element, i;
    u16		su, tu;
    u32		du;

    for (i=0; i<8; i++) {

	element = ((i & cmask_tab[(mp->format & 0x0e) >> 1]) + 
		   (mp->format & emask_tab[(mp->format & 0x0e) >> 1]));

	su = (u16) Get128By16(&(rsp_VUR[mp->rs]), i);
	tu = (u16) Get128By16(&(rsp_VUR[mp->rt]), element);
	du = su ^ tu;

        rsp_ACC[i] = ACC_LOW(i,du); /* HW compatibility */

	Set128By16(&(mp->result), (u16) du, i);
    }
}

/* 16-bit vector nxor */
static void
vnxor(rsp_vuPipe_t *mp)
{
    int		element, i;
    u16		su, tu;
    u32		du;

    for (i=0; i<8; i++) {

	element = ((i & cmask_tab[(mp->format & 0x0e) >> 1]) + 
		   (mp->format & emask_tab[(mp->format & 0x0e) >> 1]));

	su = (u16) Get128By16(&(rsp_VUR[mp->rs]), i);
	tu = (u16) Get128By16(&(rsp_VUR[mp->rt]), element);
	du = ~(su ^ tu);

        rsp_ACC[i] = ACC_LOW(i,du); /* HW compatibility */

	Set128By16(&(mp->result), (u16) du, i);
    }
}

/*
 * decode and execute a logical instruction
 */
static void
rsp_VULogicalExec(rsp_vuPipe_t *mp)
{
    int		opKey;

    /* decode instruction */
    opKey = ExtractBits(mp->inst, 5, 0);
    mp->format = ExtractBits(mp->inst, 24, 21);
    mp->rt = ExtractBits(mp->inst, 20, 16);
    mp->rs = ExtractBits(mp->inst, 15, 11);
    mp->rd = ExtractBits(mp->inst, 10,  6);
    rsp_VURegLock(mp->rd, mp->pc);

    /* check for stall. If okay, execute and decrement delay field */
    if (rsp_VURegIsLocked(mp->rt, mp->pc) || rsp_VURegIsLocked(mp->rs, mp->pc)) {
	/* can't do anything right now... */
	mp->stalled = TRUE;
	rsp_VUStalled = TRUE;
	rsp_Verbose(stderr,"VU logic stalled... (%08x)\n",mp->pc);
    } else {
	/* execute */
	switch (opKey) {
	  case rsp_VAND:
	    strcpy(mp->opString, "vand");
	    vand(mp);
	    break;

	  case rsp_VNAND:
	    strcpy(mp->opString, "vnand");
	    vnand(mp);
	    break;

	  case rsp_VOR:
	    strcpy(mp->opString, "vor");
	    vor(mp);
	    break;

	  case rsp_VNOR:
	    strcpy(mp->opString, "vnor");
	    vnor(mp);
	    break;

	  case rsp_VXOR:
	    strcpy(mp->opString, "vxor");
	    vxor(mp);
	    break;

	  case rsp_VNXOR:
	    strcpy(mp->opString, "vnxor");
	    vnxor(mp);
	    break;

	}

	mp->stalled = FALSE;
	mp->delay--;
    }
}


/* PUBLIC FUNCTIONS */

/*
 * check logical pipeline for stalls
 * returns TRUE is stalled.
 */
boolean
rsp_VULogicalCheckStall(void)
{
    int		i;

    for (i=0; i<rsp_VUPIPEDEPTH; i++) {
	if (vu_LogicPipe[i].delay > 0 && vu_LogicPipe[i].stalled)
	    return TRUE;
    }

    return FALSE;
}

/*
 * install a VU instruction into the pipeline
 */
void
rsp_VULogicalInstall(u32 inst, u32 pc)
{
    int		i;

    for (i=0; i<rsp_VUPIPEDEPTH; i++) {
	if (vu_LogicPipe[i].delay == 0 || VUZeroPipe) {
	    vu_LogicPipe[i].inst = inst;
	    vu_LogicPipe[i].pc = pc;
	    vu_LogicPipe[i].delay = (VUZeroPipe) ? 1 : rsp_VUPIPEDEPTH;
	    vu_LogicPipe[i].stalled = FALSE;
            strcpy(vu_LogicPipe[i].opString,"?");

	    if (VUZeroPipe) rsp_VULogicalPipeStep();
	    break;
	}
    }
}

/*
 * this function is called once per clock, advances the logical
 * pipeline one step.
 */
boolean
rsp_VULogicalPipeStep(void)
{
    int		i;

    /* advance all the things in the pipe */
    for (i=0; i<rsp_VUPIPEDEPTH; i++) {
	if (vu_LogicPipe[i].delay > 0) {

	    if (vu_LogicPipe[i].delay == rsp_VUPIPEDEPTH-1 || VUZeroPipe) {
		/* do decode and exec, if possible */
		rsp_VULogicalExec(&(vu_LogicPipe[i]));
	    } else {
		/*
		 * fakes pipelining by waiting to write-back answer
		 */
               if (rsp_VUStalled==FALSE ||
                         vu_LogicPipe[i].delay<rsp_VUPIPE_STAGE_EX)
		vu_LogicPipe[i].delay--;
	    }

	    if (vu_LogicPipe[i].delay == 0) {
		/* do write-back */
		rsp_Verbose(stderr,"VU LOGIC-OP (%s) did write-back. (v%d)\n",
			    vu_LogicPipe[i].opString, vu_LogicPipe[i].rd);
		Set128(&(rsp_VUR[vu_LogicPipe[i].rd]), &(vu_LogicPipe[i].result));
		traceVUbyVU(vu_LogicPipe[i].rd,0xff,&(vu_LogicPipe[i].result),
						vu_LogicPipe[i].pc);

		/* mark registers not in use */
		rsp_VURegUnLock(vu_LogicPipe[i].rd, vu_LogicPipe[i].pc);
	    }
	}
    }
}