File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / fpevent / test_inst.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:30:17 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
Power 6/32 Unix version 1.21

#include "evt_defs.h"

/**************************************************************************
*
*    		Test the current instruction
*
*   10-Apr-85 - changed the test to just check a couple of addr. modes
*   30-May-85 - added pipeline tests for A-loaded and B-loaded entries.
*   20-Jul-85 - added 3 operands for MULL3 integer overflow
**************************************************************************/
test_inst()
{
	*adr_op1_ptr = (int) adr_op1;	/* set word offset ptr #1 */
	*adr_op2_ptr = (int) adr_op2;	/* set word offset ptr #2 */
	*adr_op3_ptr = (int) adr_op3;	/* set word offset ptr #3 */
	asm("moval (sp),_monitor_sp");	/* save the stack pointer */
	asm("moval (fp),_monitor_fp");	/* save the frame pointer */
	asm("movab _test_inst_ret,_unexp_event_ret");
	error = FALSE;			/* clear error flag       */
	set_load_flag();		/* set the LOAD ACC. flag */
	if( !no_ops )
	     test_0_ops();	/* test inst w/ no operands */
	else {
	     tst_l();		/* longword displacement relative   */
	     tst_r();		/* direct register                  */
	     tst_r_d();		/* register deferred                */
	     tst_r_ld();	/* register + longword displacement */
	     tst_x_fpd();	/* FP deferred + longword index     */
	     tst_p1();		/* pipeline test #1,  LDx <op.>     */
	     if( (!load_type_inst) && (!no_fpp_wcs) )
	          tst_p2();	/* pipeline test #2,  ADDx <op.>    */
	}
	asm(".globl _test_inst_ret");
	asm("_test_inst_ret:");
	asm("movl _monitor_sp,sp");	/* restore the stack ptr.   */
	asm("movl _monitor_fp,fp");	/* restore the frame ptr.   */
}






/*******************************************************************
* LONGWORD DISPLACEMENT RELATIVE ADDRESSING:
*  instruction =  <op-code> <ef> <offset to dmp_op_1>
*                         { <ef> <offset to dmp_op_2> }
*                         { <ef> <offset to dmp_op_3> }
*******************************************************************/
tst_l()
{
	pipe_test = FALSE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	addr_mode = ADR_L_DSP;
	addr_code = addr_code2 = addr_code3 = 0xef;
	addr_size = 4;			/* longword (4 byte) ops. */
	addr_1 = os_op1 + 14;		/* offset to the data      */
	addr_2 = os_op2 + 9;
	addr_3 = os_op3 + 4;
	pack_inst();			/* pack the instr. code   */
	for( index = 0; index <= max_index; index++ ) {
	     get_current_data( adr_op1, adr_op2 );
	     run_code();		/* execute the instruction */
	}
}



/*******************************************************************
* DIRECT REGISTER ADDRESSING:
*  instruction =  <op-code> <50> { <54> <56> }
*******************************************************************/
tst_r()
{
	pipe_test = FALSE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	if( op_code == MULL3_OP_CODE )
	      exp_regs[6] = 0;		/* final op #3 should = 0 */
	addr_mode = ADR_REG;
	addr_code  = 0x50;		/* 1st op in registers 0/1 */
	addr_code2 = 0x54;		/* 2nd op in registers 4/5 */
	addr_code3 = 0x56;		/* 3rd op in registers 6   */
	addr_size = 0;			/* no addressing bytes    */
	pack_inst();			/* pack the instr. code   */
	for( index = 0; index <= max_index; index++ ) {
	          get_current_data( adr_op1, adr_op2 ); /* addr's not used */
	          load_regs[0] = dbl_value_1.m; /* set the data       */
	          load_regs[1] = dbl_value_1.l;
	          load_regs[4] = dbl_value_2.m;
	          load_regs[5] = dbl_value_2.l;
	          if( op_code == MULL2_OP_CODE )
	               exp_regs[4] = 0;		/* final op #2 should = 0 */
	          else  			/* op #2 shouldn't change */
	               exp_regs[4]  = dbl_value_2.m;
	          exp_regs[5]  = dbl_value_2.l;
	          exp_regs[1]  = dbl_value_1.l;	/* op #1's LSW won't change */
	          if( (op_code == CVFL_OP_CODE) || /* correct for sgl store */
	              (op_code == CVDL_OP_CODE) )
	               exp_regs[0] = 0;		/* ovfl results are cleared */
	          else
		       exp_regs[0] = dbl_value_1.m;
	          run_code();			/* execute the instruction  */
	}
}



/*******************************************************************
* REGISTER DEFERRED ADDRESSING:
*  instruction =  <op-code> <60> { <61> <62> }
*******************************************************************/
tst_r_d()
{
	pipe_test = FALSE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	addr_mode  = ADR_REG_DEF;
	addr_code  = 0x60;
	addr_code2 = 0x61;
	addr_code3 = 0x62;
	addr_size  = 0;			/* no address byte(s)   */
	load_regs[0] = (int) adr_op1;	/* get addr of op. 1    */
	load_regs[1] = (int) adr_op2;	/* get addr of op. 2    */
	load_regs[2] = (int) adr_op3;	/* get addr of op. 3    */
	exp_regs[0] = load_regs[0];
	exp_regs[1] = load_regs[1];
	exp_regs[2] = load_regs[2];
	pack_inst();			/* pack the instr. code */
	for( index = 0; index <= max_index; index++ ) {
	          get_current_data( adr_op1, adr_op2 );
	          run_code();		     /* execute the instruction */
	}
}




/*******************************************************************
* REGISTER + LONGWORD DISPLACEMENT DEFERRED ADDRESSING:
*  instruction =  <op-code> <f4> <(longword &ptr_to_op_1 -r4)>
*                         { <f5> <(longword &ptr_to_op_2 -r5)> }
*                         { <f6> <(longword &ptr_to_op_3 -r6)> }
*******************************************************************/
tst_r_ld()
{
	pipe_test = FALSE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	addr_mode    = ADR_REG_L_DEF;
	addr_code    = 0xf4;		/* addr 1 is offset by r4 */
	addr_code2   = 0xf5;		/* addr 2 is offset by r5 */
	addr_code3   = 0xf6;		/* addr 3 is offset by r6 */
	addr_size    = 4;		/* longword (4 byte) op.  */
	addr_1 = (int) adr_op1_ptr - 123;	/* set the 1st offset */
	addr_2 = (int) adr_op2_ptr - 212;	/* set the 2nd offset */
	addr_3 = (int) adr_op3_ptr - 256;	/* set the 3rd offset */
	pack_inst();			/* pack the instr. code    */
	load_regs[4] = 123;		/* reg 4 = 123             */
	load_regs[5] = 212;		/* reg 5 = 212             */
	load_regs[6] = 256;		/* reg 5 = 212             */
	exp_regs[4]  = load_regs[4];
	exp_regs[5]  = load_regs[5];
	exp_regs[6]  = load_regs[6];
	for( index = 0; index <= max_index; index++ ) {
	     get_current_data( adr_op1, adr_op2 );
	     run_code();		/* execute the instruction */
	}
}



/*******************************************************************
* FRAME POINTER DEFERRED + LONGWORD INDEX ADDRESSING:
*  instruction =  <op-code> <44> <6d> { <45> <6d>   <46> <6d> }
* 
*  The indeces used will be either quadword indeces ( for DBL operands )
*  of longword indeces ( for SGL operands ).
*
* NOTE: 
*  dmp_op_2 is exactly 4 pages away from dmp_op_1. (200 hex quadwords)
*   IF THIS RELATIVE DISPLACEMENT IS CHANGED THEN THE R5 INDEX MUST
*   BE CHANGED IN THIS CODE!!! ( used by CMPF2, CMPD2, MULL2, MULL3 )
*  dmp_op_3 is exactly 5 pages and 4 bytes away from dmp_op_1 (501 hex
*   longwords). This is needed for MULL3.
*******************************************************************/
tst_x_fpd()
{
	pipe_test = FALSE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	addr_mode  = ADR_I_FP_DEF;
	addr_code  = 0x44;		/* code for reg. 4 index  */
	addr_code2 = 0x45;		/* code for reg. 5 index  */
	addr_code3 = 0x46;		/* code for reg. 6 index  */
	addr_codeB = 0x6d;		/* code for FP deferred   */
	addr_size = 0;			/* no addr. field per se  */
	pack_inst();			/* pack the instr. code   */
/*
 * set the frame pointer to '&operand_1 - 16 bytes' (2 quad-words)
*/
	sgl_dummy1 = (int) adr_op1;	/* get the addr of op #1  */
	load_regs[13] = sgl_dummy1-16;	/* FP = op 1's addr - 16  */
	exp_regs[13] = load_regs[13];
	if( (sgl_op) || 		/* Should we use a longword */
	    (op_code == LDFD_OP_CODE) ||    /* or a quadword index? */
	    (op_code == CVLD_OP_CODE) ) {
	    load_regs[4] = 4;		/* FP to op_1 (longwords) */
	    load_regs[5] = 0x404;	/* FP to op_2 (longwords) */
	    load_regs[6] = 0x505;	/* FP to op_3 (longwords) */
	} else {
	    load_regs[4] = 2;		/* FP to op_1 (quadwords) */
	    load_regs[5] = 0x202;	/* FP to op_2 (quadwords) */
	}
	exp_regs[4] = load_regs[4];
	exp_regs[5] = load_regs[5];
	exp_regs[6] = load_regs[6];
	for( index = 0; index <= max_index; index++ ) {
	     get_current_data( adr_op1, adr_op2 );
	     run_code();		/* execute the instruction */
	}
}




/*******************************************************************
* PIPELINE TEST #1 -LOAD THE ACCUMULATOR JUST BEFORE THE OPERATION
*  instruction =  <ldx> <62> <op-code> <50> { <54> <56> }
*******************************************************************/
tst_p1()
{
	pipe_test = 1;			/* pipeline test #1       */
	if( acc_ld_size == DBL )
	     pipe_inst1 = LDD_OP_CODE;
	else
	     pipe_inst1 = LDF_OP_CODE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	if( op_code == MULL3_OP_CODE )
	     exp_regs[6]  = 0;		/* op 3 s/b = 0 if MULL3 */
	addr_code_p1 = 0x62;		/* piped load is via reg 2 */
	load_regs[2] = (int)&dbl_ld_acc; /* point R2 to the load data */
	exp_regs[2] =  (int)&dbl_ld_acc;
	addr_mode = ADR_REG;
	addr_code  = 0x50;		/* 1st op in registers 0/1 */
	addr_code2 = 0x54;		/* 2nd op in registers 4/5 */
	addr_code3 = 0x56;		/* 3rd op in register  6   */
	addr_size = 0;			/* no addressing bytes    */
	pack_inst();			/* pack the instr. code   */
	for( index = 0; index <= max_index; index++ ) {
	          get_current_data( adr_op1, adr_op2 ); /* addr's not used */
	          load_regs[0] = dbl_value_1.m; /* set the data       */
	          load_regs[1] = dbl_value_1.l;
	          load_regs[4] = dbl_value_2.m;
	          load_regs[5] = dbl_value_2.l;
		  if( op_code == MULL2_OP_CODE )
	  	       exp_regs[4] = 0;		/* op 2 s/b = 0 if MULL2 */
	          else
		       exp_regs[4] = dbl_value_2.m;
	          exp_regs[5]  = dbl_value_2.l;
	          exp_regs[1]  = dbl_value_1.l;	/* op #1's LSW won't change */
	          if( (op_code == CVFL_OP_CODE) || /* correct for sgl store */
	              (op_code == CVDL_OP_CODE) )
	               exp_regs[0] = 0;		/* fault results are cleared */
	          else
		       exp_regs[0] = dbl_value_1.m;
	          run_code();			/* execute the instruction  */
	}
	pipe_test = FALSE;
}





/*******************************************************************
* PIPELINE TEST #2 -ADD TO THE ACCUMULATOR JUST BEFORE THE OPERATION
*  instruction =  <addx> <62> <op-code> <50> { <54> <56> }
*******************************************************************/
tst_p2()
{
	pipe_test = 2;			/* pipeline test #2       */
	if( acc_ld_size == DBL )
	     pipe_inst1 = ADDD_OP_CODE;
	else
	     pipe_inst1 = ADDF_OP_CODE;
	fill_reg_buf( load_regs );	/* set data for registers */
	fill_reg_buf( exp_regs );	/* set data for registers */
	addr_code_p1 = 0x62;		/* piped load is via reg 2 */
	load_regs[2] = (int)&dbl_ld_acc; /* point R2 to the load data */
	exp_regs[2] =  (int)&dbl_ld_acc;
	if( op_code == MULL3_OP_CODE )
	     exp_regs[6] = 0;		/* op 3 s/b = 0 */
	addr_mode = ADR_REG;
	addr_code  = 0x50;		/* 1st op in registers 0/1 */
	addr_code2 = 0x54;		/* 2nd op in registers 4/5 */
	addr_code3 = 0x56;		/* 3rd op in register  6   */
	addr_size = 0;			/* no addressing bytes    */
	pack_inst();			/* pack the instr. code   */
	for( index = 0; index <= max_index; index++ ) {
	          get_current_data( adr_op1, adr_op2 ); /* addr's not used */
	          load_regs[0] = dbl_value_1.m; /* set the data       */
	          load_regs[1] = dbl_value_1.l;
	          load_regs[4] = dbl_value_2.m;
	          load_regs[5] = dbl_value_2.l;
		  if( op_code == MULL2_OP_CODE )
	               exp_regs[4] = 0;		/* op 2 s/b = 0 */
		  else
	               exp_regs[4] = dbl_value_2.m;  /* op #2 s/n change */
	          exp_regs[5]  = dbl_value_2.l;
	          exp_regs[1]  = dbl_value_1.l;	/* op #1's LSW won't change */
	          if( (op_code == CVFL_OP_CODE) || /* correct for sgl store */
	              (op_code == CVDL_OP_CODE) )
	               exp_regs[0] = 0;		/* fault results are cleared */
	          else
		       exp_regs[0] = dbl_value_1.m;
	          run_code();			/* execute the instruction  */
	}
	pipe_test = FALSE;
}







/***************************************************************************
*		Get the Current Data Values
*
* In most cases the first operand is loaded into the accumulator.
* If we're testing Reserved Operands then, unless it's LOGF, we'd better not
* load the Accumulator with the Resop before executing the instruction.
* Ergo and towit, we'll use a dummy Acc. for those cases. 
* The 4 instructions currently tested that have 2 or more operands are:
* CMPF2, CMPD2, MULL2, MULL3. None of these accesses the accumulator so we'll 
* use dummy accumulator data for these too.
***************************************************************************/
get_current_data( dptr_1, dptr_2 )
struct u64 *dptr_1;				/* pointer to 1st operand */
struct u64 *dptr_2;				/* pointer to 2nd operand */
{
	if( (no_ops >= 2) ||
	    ((test_event == RESOP_CODE) && (op_code != LOGF_OP_CODE)) ) {
	     dbl_ld_acc   = acc_data[ index ];
	     dbl_value_1  = data_ptr[ index ].op_1;
	     dbl_value_2  = data_ptr[ index ].op_2;
	} else {
	     dbl_ld_acc   = data_ptr[ index ].op_1;
	     dbl_value_1  = data_ptr[ index ].op_2;
	     dbl_value_2  = dbl_value_1;
	}
	*dptr_1 = dbl_value_1;			/* set 1st operand */
	*dptr_2 = dbl_value_2;			/* set 2nd operand */
}




/*
 ***************************************************************************
 *
 *	Set or reset the LOAD_ACCUMULATOR flag
 *
 *  If the current instruction loads the accumulator then set the flag.
 ***************************************************************************
*/
set_load_flag()
{
	if( (op_code == LDF_OP_CODE)  ||	/* load SGL Acc. */
	    (op_code == LNF_OP_CODE)  ||	/* load / negate SGL Acc. */
	    (op_code == LDD_OP_CODE)  ||	/* load SGL Acc. */
	    (op_code == LND_OP_CODE)  ||	/* load / negate SGL Acc. */
	    (op_code == LDFD_OP_CODE) )		/* load SGL to DBL Acc. */
	     load_type_inst = TRUE;
	else
	     load_type_inst = FALSE;
}


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.