Files
Arquivotheca.SunOS-4.1.4/diagnostics/fparel/lock.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

708 lines
20 KiB
C

/*
* "@(#)lock.c 1.1 10/31/94 Copyright Sun Microsystems";
*
*/
#include <sys/types.h>
#include "fpa.h"
#include "fpa3x.h"
u_long dps[] = {
0xE0000504, /* dp short add */
0xE000050C,
0xE0000514,
0xE000051C,
0xE0000524,
0xE000052C,
0xE0000534,
0xE000053C,
0xE0000544,
0xE000054C,
0xE0000554,
0xE000055C,
0xE0000564,
0xE000056C,
0xE0000574,
0xE000057C
};
struct dp_ext
{
u_long addr;
u_long addr_lsw;
};
struct dp_ext ext[] = {
0xE0001484, 0xE0001800, /* dp ext divide */
0xE000148C, 0xE0001808,
0xE0001494, 0xE0001810,
0xE000149C, 0xE0001818,
0xE00014A4, 0xE0001820,
0xE00014AC, 0xE0001828,
0xE00014B4, 0xE0001830,
0xE00014BC, 0xE0001838,
0xE00014C4, 0xE0001840,
0xE00014CC, 0xE0001848,
0xE00014D4, 0xE0001850,
0xE00014DC, 0xE0001858,
0xE00014E4, 0xE0001860,
0xE00014EC, 0xE0001868,
0xE00014F4, 0xE0001870,
0xE00014FC, 0xE0001878
};
u_long nxt_cmd[] = {
0x000, /* non numbers */
0x041,
0x082,
0x0C3,
0x104,
0x145,
0x186,
0x1C7,
0x208,
0x249,
0x28A,
0x2CB,
0x30C,
0x34D,
0x38E,
0x3CF,
0x410,
0x452,
0x493,
0x4D4,
0x515,
0x556,
0x597,
0x5D8,
0x619,
0x65A,
0x69B,
0x6DC,
0x71D,
0x75E,
0x79F
};
u_long cmd[] = {
0x020040,
0x030081,
0x0400C2,
0x050103,
0x060144,
0x070185,
0x0801C6,
0x090207,
0x0A0248,
0x0B0289,
0x0C02CA,
0x0D030B,
0x0E034C,
0x0F038D,
0x1003CE,
0x11040F,
0x120450,
0x130491,
0x1404D2,
0x150513,
0x160554,
0x170595,
0x1805D6,
0x190617,
0x1A0658,
0x1B0699,
0x1C06DA,
0x1D071B,
0x1E075C,
0x1F079D
};
/* ***************
* Local Globals
* ***************/
u_long res_a_msw, res_a_lsw, res_n_msw, res_n_lsw;
u_long res_i_msw, res_i_lsw;
u_long res0_msw, res0_lsw, shad_res_msw, shad_res_lsw;
u_long value_i, value_i_lsw, value_0, value_0_lsw, value_00, value_00_lsw;
lock_test()
{
/* Initialize by giving the diagnostic initialize command */
*(u_long *)DIAG_INIT_CMD = 0x0;
*(u_long *)MODE_WRITE_REGISTER = 0x2;
*(u_long *)FPA_IMASK_PTR = 0x1;
if (next_dp_short_test())
return(-1);
if (dp_short_test())
return(-1);
if (dp_ext_test())
return(-1);
if (dp_cmd_test())
return(-1);
if (next_dp_short_test())
return(-1);
if (next_dp_ext_test())
return(-1);
if (next_dp_cmd_test())
return(-1);
*(u_long *)FPA_IMASK_PTR = 0x0;
return(0);
}
next_dp_short_test()
{
int i, j;
u_long *reg0_addr, *reg0_addr_lsw;
u_long *reg_i, *reg_i_lsw, *reg_i_addr, *reg_i_addr_lsw;
u_long *shadow_j, *shadow_j_lsw;
clear_user_regs(16);
res_a_msw = 0x3FD55555; /* active result - dp 0.33333333333 */
res_a_lsw = 0x55555555;
res_n_msw = 0x3FE55555; /* next result - dp 0.6666666666 */
res_n_lsw = 0x55555555;
value_0 = 0x3FF00000;
value_0_lsw = 0x0;
value_i = 0x40000000;
value_i_lsw = 0x0;
value_00 = 0x3FCC71C7; /* computed value: reg under test = 0 */
value_00_lsw = 0x1C71C71C;
reg0_addr = (u_long *)dps[0]; /* active inst using reg0 */
reg0_addr_lsw = (u_long *)0xE0001000;
for (i = 0; i < 16; i++)
{
reg_i_addr = (u_long *)dps[i]; /* next inst using */
reg_i_addr_lsw = (u_long *)0xE0001000; /* reg under test */
reg_i = (u_long *)INS_REGFC_M(i);
reg_i_lsw = (u_long *)INS_REGFC_L(i);
for (j = 0; j < 8; j++)
{
/* reg0 = dp 1 - active stage */
*(u_long *)INS_REGFC_M(0) = value_0;
*(u_long *)INS_REGFC_L(0) = 0x0;
*reg_i = value_i; /* reg i = dp 2 - next stage */
*reg_i_lsw = 0x0;
/* Pipe will hang due to inexact error from calculation. */
*(u_long *)FPA_IMASK_PTR = 0x1;/* enable inexact errs */
*reg0_addr = 0x40080000; /* operand = dp 3 - active */
*reg0_addr_lsw = 0x0;
*reg_i_addr = 0x40080000; /* operand = dp 3 - next */
*reg_i_addr_lsw = 0x0;
/* Bus error occurs if shadow register accessed corresponds to */
/* destination register of instructions in pipeline. Driver catches */
/* bus error and forces re-calculation to obtain result in */
/* register. */
shad_res_msw = *(u_long *)SHAD_REG_M(j);
shad_res_lsw = *(u_long *)SHAD_REG_L(j);
/* Pipe needs to be cleared if shadow register accessed does not */
/* correspond to any destination register. Calculated result will */
/* not appear in destination register. */
*(u_long *)FPA_CLEAR_PIPE_PTR = 0x0;
res_i_msw = *reg_i; /* read result from reg i*/
res_i_lsw = *reg_i_lsw;
res0_msw = *(u_long *)INS_REGFC_M(0);
res0_lsw = *(u_long *)INS_REGFC_L(0);
*(u_long *)FPA_IMASK_PTR = 0x0; /* disable */
if (det_lock_res(i,j) != 0)
return(-1);
*(u_long *)INS_REGFC_M(0)= 0x0;
*(u_long *)INS_REGFC_L(0) = 0x0;
*reg_i = 0x0;
*reg_i_lsw = 0x0;
}
}
return(0);
}
next_dp_ext_test()
{
int i, j;
u_long *reg0_addr, *reg0_addr_lsw;
u_long *reg_i, *reg_i_lsw, *reg_i_addr, *reg_i_addr_lsw;
u_long *shadow_j, *shadow_j_lsw;
clear_user_regs(16);
res_a_msw = 0x3FD55555; /* active result - dp 0.33333333333 */
res_a_lsw = 0x55555555;
res_n_msw = 0x3FE55555; /* next result - dp 0.6666666666 */
res_n_lsw = 0x55555555;
value_0 = 0x3FF00000;
value_0_lsw = 0x0;
value_i = 0x40000000;
value_i_lsw = 0x0;
value_00 = 0x3FCC71C7;
value_00_lsw = 0x1C71C71C;
reg0_addr = (u_long *)ext[0].addr; /* active inst using reg0 */
reg0_addr_lsw = (u_long *)ext[0].addr_lsw;
for (i = 0; i < 16; i++)
{
reg_i_addr = (u_long *)ext[i].addr; /* next inst using */
reg_i_addr_lsw = (u_long *)ext[i].addr_lsw;/* reg under test */
reg_i = (u_long *)INS_REGFC_M(i);
reg_i_lsw = (u_long *)INS_REGFC_L(i);
for (j = 0; j < 8; j++)
{
/* reg0 = dp 1 - active stage */
*(u_long *)INS_REGFC_M(0) = 0x3FF00000;
*(u_long *)INS_REGFC_L(0) = 0x0;
*reg_i = 0x40000000; /* reg i = dp 2 - next stage */
*reg_i_lsw = 0x0;
/* Pipe will hang due to inexact error from calculation. */
*(u_long *)FPA_IMASK_PTR = 0x1;/* enable inexact errs */
*reg0_addr = 0x40080000; /* operand = dp 3 - active */
*reg0_addr_lsw = 0x0;
*reg_i_addr = 0x40080000; /* operand = dp 3 - next */
*reg_i_addr_lsw = 0x0;
/* Bus error occurs if shadow register accessed corresponds to */
/* destination register of instructions in pipeline. Driver catches */
/* bus error and forces re-calculation to obtain result in */
/* register. */
shad_res_msw = *(u_long *)SHAD_REG_M(j);
shad_res_lsw = *(u_long *)SHAD_REG_L(j);
/* Pipe needs to be cleared if shadow register accessed does not */
/* correspond to any destination register. Calculated result will */
/* not appear in destination register. */
*(u_long *)FPA_CLEAR_PIPE_PTR = 0x0;
res_i_msw = *reg_i; /* read result from reg i*/
res_i_lsw = *reg_i_lsw;
res0_msw = *(u_long *)INS_REGFC_M(0);
res0_lsw = *(u_long *)INS_REGFC_L(0);
*(u_long *)FPA_IMASK_PTR = 0x0; /* disable */
if (det_lock_res(i,j) != 0)
return(-1);
*(u_long *)INS_REGFC_M(0) = 0x0;
*(u_long *)INS_REGFC_L(0) = 0x0;
*reg_i = 0x0;
*reg_i_lsw = 0x0;
}
}
return(0);
}
next_dp_cmd_test()
{
int i, j;
u_long *reg0_addr, *reg0_addr_lsw;
u_long *reg_i, *reg_i_lsw, *reg_i_addr, *reg_i_addr_lsw;
u_long *shadow_j, *shadow_j_lsw;
clear_user_regs(32);
res_a_msw = 0x1; /* active result - dp 0.33333333333 */
res_a_lsw = 0x0;
res_n_msw = 0x2; /* next result - dp 0.6666666666 */
res_n_lsw = 0x0;
value_0 = 0x1;
value_0_lsw = 0x0;
value_i = 0x2;
value_i_lsw = 0x0;
value_00 = value_i;
value_00_lsw = value_i_lsw;
reg0_addr = (u_long *)0xE0000AC4; /* active inst */
reg_i_addr =(u_long *)0xE0000AC4; /* weitek direct dp add: op + 0 */
for (i = 0; i < 31; i++)
{
reg_i = (u_long *)INS_REGFC_M(i);
reg_i_lsw = (u_long *)INS_REGFC_L(i);
for (j = 0; j < 8; j++)
{
/* reg0 = dp 1 - active stage */
*(u_long *)INS_REGFC_M(0) = value_0;
*(u_long *)INS_REGFC_L(0) = 0x0;
*reg_i = value_i; /* reg i = dp 2 - next stage */
*reg_i_lsw = 0x0;
/* Pipe will hung due to inexact error from calculation. */
*(u_long *)FPA_IMASK_PTR = 0x1;/* enable inexact errs */
*reg0_addr = nxt_cmd[0]; /* nota # + 0 weitek op */
*reg_i_addr = nxt_cmd[i]; /* nota # + 0 weitek op */
/* Bus error occurs if shadow register accessed corresponds to */
/* destination register of instructions in pipeline. Driver catches */
/* bus error and forces re-calculation to obtain result in */
/* register. */
shad_res_msw = *(u_long *)SHAD_REG_M(j);
shad_res_lsw = *(u_long *)SHAD_REG_L(j);
/* Pipe needs to be cleared if shadow register accessed does not */
/* correspond to any destination register. Calculated result will */
/* not appear in destination register. */
*(u_long *)FPA_CLEAR_PIPE_PTR = 0x0;
res_i_msw = *reg_i; /* read result from reg i*/
res_i_lsw = *reg_i_lsw;
res0_msw = *(u_long *)INS_REGFC_M(0);
res0_lsw = *(u_long *)INS_REGFC_L(0);
*(u_long *)FPA_IMASK_PTR = 0x0; /* disable */
if (det_lock_res(i,j) != 0)
return(-1);
*(u_long *)INS_REGFC_M(0) = 0x0;
*(u_long *)INS_REGFC_L(0) = 0x0;
*reg_i = 0x0;
*reg_i_lsw = 0x0;
}
}
return(0);
}
det_lock_res(i,j)
int i;
int j;
{
if ((j == 0) && (j == i)) { /* 2 div 9 */
if ((shad_res_msw != value_00) ||
(res_i_msw!= value_00) ||
(res0_msw != value_00))
return(-1);
if ((shad_res_lsw != value_00_lsw) ||
(res_i_lsw != value_00_lsw) ||
(res0_lsw != value_00_lsw))
return(-1);
}
else if ((j == 0) && (j != i)) {
if ((shad_res_msw != res_a_msw) ||
(res_i_msw != res_n_msw)
|| (res0_msw != res_a_msw))
return(-1);
if ((shad_res_lsw != res_a_lsw) ||
(res_i_lsw != res_n_lsw)
|| (res0_lsw != res_a_lsw))
return(-1);
}
else if((j != 0) && (j == i)) {
if ((shad_res_msw != res_n_msw) ||
(res_i_msw != res_n_msw)
|| (res0_msw != res_a_msw))
return(-1);
if ((shad_res_lsw != res_n_lsw) ||
(res_i_lsw != res_n_lsw)
|| (res0_lsw != res_a_lsw))
return(-1);
}
else if ((j != 0) && (j != i)) {
if (i == 0) {
if ((shad_res_msw != 0x0)||
(res_i_msw != value_i) ||
(res0_msw != value_i))
return(-1);
if ((shad_res_lsw != 0x0)||
(res_i_lsw != value_i_lsw) ||
(res0_lsw != value_i_lsw))
return(-1);
}
else {
if ((shad_res_msw != 0x0) ||
(res_i_msw != value_i) ||
(res0_msw != value_0))
return(-1);
if ((shad_res_lsw != 0x0) ||
(res_i_lsw != value_i_lsw) ||
(res0_lsw != value_0_lsw))
return(-1);
}
}
return(0);
}
dp_short_test()
{
u_long i, j;
u_long *reg_i, *reg_i_lsw, *reg_i_addr, *reg_i_addr_lsw;
clear_user_regs(16);
value_i = 0x3FD55555; /* result = 0.3333333333333333 */
value_i_lsw = 0x55555555;
for (i = 0; i < 8; i++)
{
reg_i_addr = (u_long *)dps[i]; /* dp short divide */
reg_i_addr_lsw = (u_long *)0xE0001000; /* w/ reg under test */
reg_i = (u_long *)INS_REGFC_M(i); /* reg under test */
reg_i_lsw = (u_long *)INS_REGFC_L(i);
for (j = 0; j < 8; j++)
{
*reg_i = 0x3FF00000; /* reg i = dp 1 */
*reg_i_lsw = 0x0;
/* Pipe will hang due to inexact error from calculation. */
*(u_long *)FPA_IMASK_PTR = 0x1;/* enable inexact errs */
*reg_i_addr = 0x40080000; /* operand = dp 3 */
*reg_i_addr_lsw = 0x0;
/* Bus error occurs if shadow register accessed corresponds to */
/* destination register of instruction in pipeline. Driver catches */
/* bus error and forces re-calculation to obtain result in */
/* register. */
shad_res_msw = *(u_long *)SHAD_REG_M(j);
shad_res_lsw = *(u_long *)SHAD_REG_L(j);
/* Pipe needs to be cleared if shadow register accessed does not */
/* correspond to destination register. Calculated result will */
/* not appear in destination register. */
*(u_long *)FPA_CLEAR_PIPE_PTR = 0x0;
res_i_msw = *reg_i; /* read the result from the reg */
res_i_lsw = *reg_i_lsw;
*(u_long *)FPA_IMASK_PTR = 0x0; /* disable */
if (i == j) {
if ((value_i != res_i_msw) ||
(value_i != shad_res_msw))
return(-1);
if ((value_i_lsw != res_i_lsw) ||
(value_i_lsw != shad_res_lsw))
return(-1);
}
if (i != j) {
if ((shad_res_msw != 0x0) ||
(res_i_msw != 0x3FF00000))
return(-1);
if ((shad_res_lsw != 0x0) ||
(res_i_lsw != 0x0))
return(-1);
}
}
*reg_i = 0x0;
*reg_i_lsw = 0x0;
}
return(0);
}
dp_ext_test()
{
u_long i, j;
u_long *reg_i, *reg_i_lsw, *reg_i_addr, *reg_i_addr_lsw;
clear_user_regs(16);
value_i = 0x3FD55555; /* the result is always dp value 0.33333333 */
value_i_lsw = 0x55555555;
for (i = 0; i < 16; i++)
{
reg_i_addr = (u_long *)ext[i].addr;
reg_i_addr_lsw = (u_long *)ext[i].addr_lsw;
reg_i = (u_long *)INS_REGFC_M(i);
reg_i_lsw = (u_long *)INS_REGFC_L(i);
for (j = 0; j < 8; j++)
{
*reg_i = 0x3FF00000; /* reg i = dp 1 */
*reg_i_lsw = 0x0;
/* Pipe will hang due to inexact error from calculation. */
*(u_long *)FPA_IMASK_PTR = 0x1;/* enable inexact errs */
*reg_i_addr = 0x40080000; /* operand = dp 3 */
*reg_i_addr_lsw = 0x0;
/* Bus error occurs if shadow register accessed corresponds to */
/* destination register of instructions in pipeline. Driver catches */
/* bus error and forces re-calculation to obtain result in */
/* register. */
shad_res_msw = *(u_long *)SHAD_REG_M(j);
shad_res_lsw = *(u_long *)SHAD_REG_L(j);
/* Pipe needs to be cleared if shadow register accessed does not */
/* correspond to destination register. Calculated result will */
/* not appear in destination register. */
*(u_long *)FPA_CLEAR_PIPE_PTR = 0x0;
res_i_msw = *reg_i; /* read the result from the reg */
res_i_lsw = *reg_i_lsw;
*(u_long *)FPA_IMASK_PTR = 0x0; /* disable */
if (i == j) {
if ((value_i != res_i_msw) &&
(value_i != shad_res_msw))
return(-1);
if ((value_i_lsw != res_i_lsw) &&
(value_i_lsw != shad_res_lsw))
return(-1);
}
else {
if ((shad_res_msw != 0x0) ||
(res_i_msw != 0x3FF00000))
return(-1);
if ((shad_res_lsw != 0x0) ||
(res_i_lsw != 0x0))
return(-1);
}
}
*reg_i = 0x0;
*reg_i_lsw = 0x0;
}
return(0);
}
dp_cmd_test()
{
u_long i, j, k, l;
u_long *reg_i, *reg_i_lsw, *reg_i_addr, *reg_i_addr_lsw;
u_long *reg_k, *reg_k_lsw, *reg_l, *reg_l_lsw;
clear_user_regs(32);
value_i = 0x3FD55555; /* result = dp 0.3333333333 */
value_i_lsw = 0x55555555;
for (i = 0; i < 30; i++)
{
reg_i_addr = (u_long *)0xE0000A34; /* dp div w/ weitek spec */
reg_i = (u_long *)INS_REGFC_M(i);
reg_i_lsw = (u_long *)INS_REGFC_L(i);
k = i + 1;
l = i + 2;
reg_k = (u_long *)INS_REGFC_M(k);
reg_k_lsw = (u_long *)INS_REGFC_L(k);
reg_l = (u_long *)INS_REGFC_M(l);
reg_l_lsw = (u_long *)INS_REGFC_L(l);
for (j = 0; j < 8; j++)
{
*reg_k = 0x3FF00000; /* register has dp value 1 */
*reg_k_lsw = 0x0;
*reg_l = 0x40080000; /* register has dp value 3 */
*reg_l_lsw = 0x0;
/* Pipe will hang due to inexact error from calculation. */
*(u_long *)FPA_IMASK_PTR = 0x1;/* enable inexact errs */
*reg_i_addr = cmd[i];
/* Bus error occurs if shadow register accessed corresponds to */
/* destination register of instructions in pipeline. Driver catches */
/* bus error and forces re-calculation to obtain result in */
/* register. */
shad_res_msw = *(u_long *)SHAD_REG_M(j);
shad_res_lsw = *(u_long *)SHAD_REG_L(j);
/* Pipe needs to be cleared if shadow register accessed does not */
/* correspond to destination register. Calculated result will */
/* not appear in destination register. */
*(u_long *)FPA_CLEAR_PIPE_PTR = 0x0;
res_i_msw = *reg_i; /* read the result from the reg */
res_i_lsw = *reg_i_lsw;
*(u_long *)FPA_IMASK_PTR = 0x0; /* disable */
if (i == j) {
if ((value_i != res_i_msw) ||
(value_i != shad_res_msw))
return(-1);
if ((value_i_lsw != res_i_lsw) ||
(value_i_lsw != shad_res_lsw))
return(-1);
}
else if (j == k) {
if ((res_i_msw != 0x0) ||
(shad_res_msw != 0x3FF00000))
return(-1);
if ((res_i_lsw != 0x0) ||
(shad_res_lsw != 0x0))
return(-1);
}
else if (j == l) {
if ((res_i_msw != 0x0) ||
(shad_res_msw != 0x40080000))
return(-1);
if ((res_i_lsw != 0x0) ||
(shad_res_lsw != 0x0))
return(-1);
}
*reg_i = 0x0;
*reg_i_lsw = 0x0;
}
}
return(0);
}
clear_user_regs(reg_cnt)
int reg_cnt; /* num of user regs to clear */
{
int i;
for (i = 0; i < reg_cnt; i++)
{
*(u_long *)INS_REGFC_M(i) = 0x0;
*(u_long *)INS_REGFC_L(i) = 0x0;
}
}