|
|
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;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.