|
|
Power 6/32 Unix version 1.21
#include "fpp_defs.h"
/*****************************************************************************
*
* TSTD - DOUBLE PRECISION FLOATING POINT TEST ACC. TEST
*
* IMPLEMENTATION NOTE: If the "no-fpp WCS" is loaded then the status bits
* set will be based on the INTEGER value of the loaded data's most significant
* longword. Ergo and towit, if we're running without an FPP and a "bad 0" is
* loaded then the PSL will show POSITIVE rather than ZERO. A "bad 0" is any
* number with a zero exponent and non zero fraction (00000001 - 007fffff).
*****************************************************************************/
tstd()
{
asm(".globl _tstd_t");
asm("_tstd_t:"); /* entry address */
if( ( cycle == 1 ) && ( prt_hdrs ) ) /* print headers on 1st pass */
writes(" TSTD");
tstd_1(); /* PSL flags test */
tstd_2(); /* register stability */
tstd_3(); /* accumulator stability */
asm("jmp *return"); /* return to the test monitor */
}
/************************************************************************
*
* SUBTEST 1 - Check for PSL corruption
*
************************************************************************/
tstd_1()
{
force_loop = FALSE; /* clear force_loop flg */
subtest = 1;
for( index = 0; index < max_tstd_1_index; index++ ) {
dbl_ld_acc = tstd_1_data[index].ld; /* get value to load */
sgl_expected = tstd_1_data[index].exp; /* get expected flags*/
for( status_index = 0; status_index < 3; status_index++ ) {
sgl_dummy1 = status_array[status_index]; /* status = +,-,0 */
/*
* If LOOP ON ERROR is set, this is the loop for this subtest.
* The force loop flag is set after the first error.
*/
asm("ldd _dbl_ld_acc"); /* load the initial value */
asm("_tstd_1_lp1:");
asm("tstl _sgl_dummy1"); /* set the PSL status */
asm("movpsl _init_psl"); /* save the initial PSL */
asm("tstd"); /* test the accmulator */
asm("nop");
asm("movpsl _psl_val"); /* save the final PSL */
asm("std _dbl_st_acc"); /* save the final Acc. */
if( force_loop )
asm("brb _tstd_1_lp1");; /* loop on the error */
/*
* Now compare the final PSL to the initial PSL -they should be the same
*/
exp_psl = init_psl; /* get the initial PSL */
exp_psl &= 0xfffffff3; /* clear ZERO, NEGATIVE */
if( sgl_expected == ZERO ) {
/* if( (!no_fpp_wcs) || (!dbl_ld_acc.m) ) /* */
exp_psl |= PSL_Z; /* expect the ZERO bit set */
}
if( sgl_expected == NEGATIVE )
exp_psl |= PSL_N; /* expect the NEG bit set */
if( psl_val != exp_psl ) {
errcnt++; /* bump the error count */
if( prt_error ) {
writes(" \n"); /* start new print line */
writes("cycle: ");
writed( cycle );
writes(" TSTD test ");
writed( test_no );
writes(", subtest 1 - BAD FINAL PSL\n");
print_tstd_data(); /* print the operands */
writes(", index = ");
writed( index );
writec('\n');
writes("initial PSL = ");
write32h( init_psl );
writes(", final PSL = ");
write32h( psl_val );
writes(", expected PSL = ");
write32h( exp_psl );
writes("\n");
}
if( halt_flg )
tstd_er_halt( BAD_PSL_HLT ); /* halt on error */
if( loop_on_err ) {
force_loop = TRUE; /* set force loop flag */
asm("brw _tstd_1_lp1"); /* loop on the error */
} /* end of loop on error */
} /* end of PSL corruption error */
} /* end of initial status WHILE loop */
} /* end of data pattern WHILE loop */
} /* end of subtest 1 */
/************************************************************************
*
* SUBTEST 2 - Check for register corruption
*
************************************************************************/
tstd_2()
{
force_loop = FALSE; /* clear force_loop flg */
subtest = 2;
fill_reg_buf( load_regs ); /* get patterns for regs */
for( index = 0; index < max_tstd_1_index; index++ ) {
dbl_ld_acc = tstd_1_data[index].ld; /* get value to load */
sgl_expected = tstd_1_data[index].exp; /* get expected flags*/
for( status_index = 0; status_index < 3; status_index++ ) {
sgl_dummy1 = status_array[status_index]; /* status = +,-,0 */
/*
* If LOOP ON ERROR is set, this is the loop for this subtest.
* The force loop flag is set after the first error.
*/
asm("_tstd_2_lp1:");
asm("ldd _dbl_ld_acc"); /* load the Acc. */
asm("loadr $0x1fff,_load_regs"); /* load regs 0 - 12 */
asm("nop");
asm("tstd"); /* test the acc. */
asm("nop");
asm("storer $0x1fff,_store_regs"); /* store regs 0 - 12 */
asm("std _dbl_st_acc"); /* save the acc. */
if( force_loop )
asm("brb _tstd_2_lp1");; /* loop on the error */
/*
* Now compare the stored register values to those that were loaded
*/
index2 = 0;
while( (load_regs[index2] == store_regs[index2]) &&
(index2 < 13) )
index2++; /* check reg values */
if( index2 < 13 ) { /* error if index2 < 13 */
errcnt++; /* bump the error count */
if( prt_error ) {
writes(" \n"); /* start a new print line */
writes("cycle: ");
writed( cycle );
writes(" TSTD test ");
writed( test_no );
writes(", subtest 2 - A REGISTER WAS MODIFIED\n");
print_tstd_data(); /* print the operands */
writes("\n");
writes("register "); /* print the information */
writed( index2 ); /* about the corrupted */
writes(" = "); /* register */
write32h( store_regs[index2] );
writes(", should be = ");
write32h( load_regs[index2] );
writes("\n");
}
if( halt_flg )
tstd_er_halt( BAD_REG_HLT ); /* halt on error */
if( loop_on_err ) {
force_loop = TRUE; /* set force loop flag */
asm("brw _tstd_2_lp1"); /* loop on the error */
} /* end of loop on error */
} /* end of register corruption error */
} /* end of initial PSL WHILE loop */
} /* end of tstd data WHILE loop */
} /* end of subtest 2 */
/************************************************************************
*
* SUBTEST 3 - Check for accumulator corruption
*
************************************************************************/
tstd_3()
{
force_loop = FALSE; /* clear force_loop flg */
subtest = 3;
for( index = 0; index < max_tstd_1_index; index++ ) {
dbl_ld_acc = tstd_1_data[index].ld; /* get value to load */
if( !(dbl_ld_acc.m & 0x7f800000) ) {
dbl_expected.m = 0;
dbl_expected.l = 0; /* ignore bad 0's */
} else
dbl_expected = dbl_ld_acc;
/*
* If LOOP ON ERROR is set, this is the loop for this subtest.
* The force loop flag is set after the first error.
*/
asm("_tstd_3_lp1:");
asm("ldd _dbl_ld_acc");
asm("nop");
asm("tstd"); /* test the accumulator */
asm("nop");
asm("std _dbl_st_acc"); /* save the accumulator */
if( force_loop )
asm("brb _tstd_3_lp1");; /* loop on the error */
/*
* Now compare the stored register values to those that were loaded
*/
if( (dbl_st_acc.m != dbl_expected.m ) || /* Acc corrupted? */
(dbl_st_acc.l != dbl_expected.l) ) {
errcnt++; /* bump error count */
if( prt_error ) {
writes(" \n"); /* start a new line */
writes("cycle: ");
writed( cycle );
writes(" TSTD test ");
writed( test_no );
writes(", subtest 3 - THE ACC WAS MODIFIED\n");
print_tstd_data(); /* print the operands */
writes(", index = ");
writed( index );
writec('\n');
writes(" expected Acc = ");
write32h( dbl_expected.m );
writec(' ');
write32h( dbl_expected.l );
writes("\n");
}
if( halt_flg )
tstd_er_halt( BAD_ACC_HLT ); /* halt on error */
if( loop_on_err ) {
force_loop = TRUE; /* set force loop flag */
asm("brw _tstd_3_lp1"); /* loop on the error */
} /* end of loop on error */
} /* end of register corruption error */
} /* end of tstd data WHILE loop */
} /* end of subtest 3 */
/**************************************************************************
*
* PRINT THE DATA AND STORE RESULTS
*
* initial Acc = xxxxxxxx xxxxxxxx, final Acc = xxxxxxxx xxxxxxxx, index = xx
**************************************************************************/
print_tstd_data()
{
writes("initial Acc = ");
write32h( dbl_ld_acc.m );
writec(' ');
write32h( dbl_ld_acc.l );
writes(", final Acc = ");
write32h( dbl_st_acc.m );
writec(' ');
write32h( dbl_st_acc.l );
}
/**************************************************************************
*
* HALT ON ERROR ROUTINE
*
**************************************************************************/
tstd_er_halt( halt_code )
int halt_code;
{
sgl_dummy1 = halt_code; /* get the error type */
asm("movl _test_no,r0"); /* r0 = test number */
asm("movl _subtest,r1"); /* r1 = subtest number */
asm("movl _sgl_dummy1,r2"); /* r2 = error code */
asm("movl _cycle,r3"); /* r3 = cycle count */
asm("movl _dbl_ld_acc,r4"); /* r4 = MS of init Acc */
asm("movl _dbl_ld_acc+4,r5"); /* r5 = LS of init Acc */
asm("movl _psl_val,r6"); /* r6 = final PSL */
if( halt_code == BAD_ACC_HLT ) {
asm("movl _dbl_st_acc,r7"); /* r7 = MS of final Acc */
asm("movl _dbl_st_acc+4,r8"); /* r8 = LS of final Acc */
asm("movl _dbl_expected,r9"); /* r9 = MS of expected */
asm("movl _dbl_expected+4,r10"); /* r10 = LS of expected */
} else
if( halt_code == BAD_REG_HLT ) {
sgl_dummy1 = load_regs[index2];
sgl_dummy2 = store_regs[index2];
asm("movl _index2,r7"); /* r7 = bad register # */
asm("movl _sgl_dummy2,r8"); /* r8 = actual value */
asm("movl _sgl_dummy1,r9"); /* r9 = expected value */
} else
if( halt_code == BAD_PSL_HLT ) {
asm("movl _exp_psl,r7"); /* r7 = expected PSL */
asm("movl _index,r8"); /* r8 = data index */
};
asm("halt"); /* HALT ... */
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.