vmul.c 6.76 KB
#include <stdio.h>
#include "vudefs.h"
/**************************************************************************
 * used by all the mul instructions
 *	   ========================= 
 *
 * Check_Vmul(tno, Op, rMp,vS,vT,vT_El,vD,vDexp,vTemp,vAccl,vAccm,vAcch,
 *                                 vAcclExp,vAccmExp,vAcchExp,v4000,v0001)
 **************************************************************************/
char *Templ_vmul_frmt = "( %2d, %s, $26, $v%-d, $v%-d, $v%-d%-s, $v%-d, $v%-d, $v%-d, $v%-d, $v%-d, $v%-d, $v%-d, $v%-d, $v%-d,$v%-d, $v%-d)\n";


vmulfu(fp)
FILE *fp;
  {
    int         i,j,doaccu,type_f,type_u; 
    i16         si, ti;
    i64         tacc, clamp_mask;
    

    clamp_mask = 0xffffffff80000000;
    doaccu = optab[opindex].enu_name==VMACF||optab[opindex].enu_name==VMACU;
    type_f = optab[opindex].enu_name==VMULF||optab[opindex].enu_name==VMACF;
    type_u = optab[opindex].enu_name==VMULU||optab[opindex].enu_name==VMACU;

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

        si = (i16) vs[i];
	ti = get_ti(i);

	tacc = (i64) ((i64)si * (i64)ti);


        tacc <<= 1;     /*normalize*/
	tacc += (doaccu) ? vacc[i] : 32768;  /*add Accum, round*/
	fix_acc(&tacc);
	vacc[i] = tacc;
	
	/* Clamping and shifting*/
	   if (tacc>0 && (tacc & clamp_mask))
		vd[i] = (type_f) ? 0x7fff : 0xffff;
           else
	   if (tacc<0 && (~tacc & clamp_mask) && type_f)
		vd[i] = -32768;
           else
	   if (tacc<0 && type_u)
	        vd[i] =  0;
	   else
	        vd[i] =  (tacc>>16) & 0xffff;

    } /*for loop*/

    mul_output(fp);
	
}

vmuldbl(fp)
FILE *fp;
  {
    int         i,j,doaccu,low, high, mdl_m, mdl_n; 
    i16         si, ti;
    u16         su, tu;
    i64         tacc, clamp_mask;
    

    clamp_mask = 0xffffffff80000000;
    doaccu = optab[opindex].enu_name==VMADL || 
	     optab[opindex].enu_name==VMADM ||
	     optab[opindex].enu_name==VMADN ||
	     optab[opindex].enu_name==VMADH  ;

    low   = optab[opindex].enu_name==VMUDL||optab[opindex].enu_name==VMADL; 
    high  = optab[opindex].enu_name==VMUDH||optab[opindex].enu_name==VMADH; 
    mdl_m = optab[opindex].enu_name==VMUDM||optab[opindex].enu_name==VMADM; 
    mdl_n = optab[opindex].enu_name==VMUDN||optab[opindex].enu_name==VMADN; 

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

	if (low) {
	   su = (u16) (vs[i]     & 0xffff);
	   tu = (u16) (get_ti(i) & 0xffff);
	   tacc = (i64) ((u64)su * (u64)tu);
	   tacc >>= 16;
	   }
	else
	if (mdl_m) {
	   si = (i16) vs[i];
	   tu = (u16) (get_ti(i) & 0xffff);
	   tacc = (i64) ((i64)si * (u64)tu);
	   }
	else
	if (mdl_n) {
	   su = (u16) (vs[i]     & 0xffff);
	   ti = (i16) get_ti(i);
	   tacc = (i64) ((u64)su * (i64)ti);
	   }
	else {
	   si = (i16) vs[i];
	   ti = (i16) get_ti(i);
	   tacc = (i64) ((i64)si * (i64)ti);
	   tacc <<= 16;
	   }
	  
	if (doaccu) tacc = vacc[i] + tacc;  /*add Accum*/

	fix_acc(&tacc);
	vacc[i] = tacc;
	
	/* Clamping and shifting*/
	   if (tacc>0 && (tacc & clamp_mask))
		vd[i] = (low | mdl_n) ? 0xffff : 0x7fff;
           else
	   if (tacc<0 && (~tacc & clamp_mask))
		vd[i] = (low | mdl_n) ? 0x0 : -32768;
           else
	        vd[i] =  (low||mdl_n) ? tacc&0xffff : (tacc>>16) & 0xffff;
    } /*for loop*/
	
    mul_output(fp);
}

vmulq(fp)
FILE *fp;
  {
    int         i,j,doaccu,bit21;
    i16         si, ti;
    i64         tacc, clamp_mask;
    i32		macq_bits;
    

    clamp_mask = 0xffffffff00000000;


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


	if (optab[opindex].enu_name==VMULQ)
	  {
           si = (i16) vs[i];
	   ti = get_ti(i);
	   tacc = (i64) ((i64)si * (i64)ti);
 
	   tacc <<= 16;
 
	   if (tacc<0) tacc += (31<<16);
	  }
	else /*macq*/
	  {
           bit21 = (vacc[i]>>21) & 0x1;
	   macq_bits = (vacc[i]>>22);

	        if (macq_bits<0 && bit21==0) tacc = vacc[i] + ( 32<<16);
	   else if (macq_bits>0 && bit21==0) tacc = vacc[i] + (-32<<16);
	   else 			     tacc = vacc[i];

	   vs[i] = ((0x1234 * (i+1))^(0xabcd * (i+4))) & 0xfff; 
	   vt[i] = ((0xfedc * (i+2))^(0x3498 * (i+6))) & 0xfff; 
	  }

	fix_acc(&tacc);
	vacc[i] = tacc;
	
	/* Clamping and shifting*/
	   if (tacc>0 && (tacc & clamp_mask))
		vd[i] = 0x7fff & 0xfff0;
           else
	   if (tacc<0 && (~tacc & clamp_mask))
		vd[i] = -32768 & 0xfff0;
           else
	        vd[i] = (tacc >> 17 ) & 0xfff0;

    } /*for loop*/
	
    mul_output(fp);
	
}

vrndpn(fp)
FILE *fp;
  {
    int         i,j,doaccu,rndp;
    i16         si, ti;
    i64         tacc, clamp_mask,round;
    

    clamp_mask = 0xffffffff80000000;
    rndp = optab[opindex].enu_name==VRNDP;


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

	ti = get_ti(i);

	/* calculate rounding value*/
	     if (regtab[SRC].rnum==1) round = (i64) ((i64)ti<<16);
	else 			      round = (i64) ti;

	/* round */
	if ((vacc[i]>=0 && rndp) || (vacc[i]<0 && !rndp)) 
	   tacc = vacc[i] + round;
	else
	   tacc = vacc[i];

	fix_acc(&tacc);
	vacc[i] = tacc;

	/* Clamping and shifting*/
	   if (tacc>0 && (tacc & clamp_mask))
		vd[i] = 0x7fff;
           else
	   if (tacc<0 && (~tacc & clamp_mask))
		vd[i] = -32768;
           else
	        vd[i] = (tacc >> 16 ) & 0xffff;
    } /*for loop*/
	
    mul_output(fp);
	
}

mul_output(fp)
FILE *fp;
  {
    int i;


       if (data_pntr < (2048 - 100))
         {
           /* initidLize data segment starting at data_pntr */
           /* SRC, TRGT, RES, RES_ACCH, RES_ACCM, RES_ACCL */
           for (i=0;i<8;i++) {data[data_pntr++] = vs[i];}
           for (i=0;i<8;i++) {data[data_pntr++] = vt[i];}
           for (i=0;i<8;i++) {data[data_pntr++] = vd[i];}
           for (i=0;i<8;i++) data[data_pntr++] = (u16)(vacc_B[i]    )&0xffff;
           for (i=0;i<8;i++) data[data_pntr++] = (u16)(vacc_B[i]>>16)&0xffff;
           for (i=0;i<8;i++) data[data_pntr++] = (u16)(vacc_B[i]>>32)&0xffff;
           for (i=0;i<8;i++) data[data_pntr++] = (u16)(vacc[i]    )&0xffff;
           for (i=0;i<8;i++) data[data_pntr++] = (u16)(vacc[i]>>16)&0xffff;
           for (i=0;i<8;i++) data[data_pntr++] = (u16)(vacc[i]>>32)&0xffff;
         }

         fprintf(fp,optab[opindex].op_tmplt);
         fprintf(fp,Templ_vmul_frmt,
                        test_num,
			optab[opindex].name,
                        regtab[SRC].rnum,
                        regtab[TRG].rnum,
                        regtab[TRG].rnum,el_sf,
                        regtab[DST].rnum,
                        regtab[DST_EXP].rnum,
                        regtab[TEMP].rnum,
                        regtab[ACCL].rnum,
                        regtab[ACCM].rnum,
                        regtab[ACCH].rnum,
                        regtab[ACCL_EXP].rnum,
                        regtab[ACCM_EXP].rnum,
                        regtab[ACCH_EXP].rnum,
                        regtab[V4000].rnum,
                        regtab[V0001].rnum
                );
  }

fix_acc(i64 *tacc)
{
   int bit47;

   bit47 = (*tacc >> 47) & 0x1;

   if (bit47) 
	*tacc = 0xffff000000000000 | (*tacc&0xffffffffffff);
   else
	*tacc = (*tacc&0xffffffffffff);
}