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

#define error_hdl2 error
#define error_hdl3 error

#define C	0x1
#define V	0x2
#define Z	0x4
#define N	0x8

extern long scoplp;
extern long force_lp;

/*	MUL instruction		*/

/* some global variables used in ASM */
static long flag_msk, psl, product, mult, muld, mulp, add, prod1, prod2;
static long exp_reslt1, exp_reslt2;

mul()
{
	asm("movl	$2,_no_opr");	/* number of operands in use */
	mull2(); 			/* Test MULL2 instruction */
	mull3();			/* Test MULL3 instruction */
	exmul(); 			/* Test EMUL instruction */
	asm("jmp *return");
}

static mull2()
{	long exp_psw , ix;

	/* multiply long with 2 operands */
for(ix=0;ix<2;ix++)
	{
	setjmp();
	asm("m1:	movab	m1,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;
	if (ix==0) {
		mult = 0xabcde;
		mulp = 0xaba; }
	    else   {
		mulp = 0xabcde;
		mult = 0xaba; }
	mull(2,0x732de54c,exp_psw); 
	}
	
for(ix=0;ix<2;ix++)
	{
	asm("m2:	movab	m2,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;
	if (ix==0) {
		mult = -200;
		mulp = -1000; }
	    else   {
		mulp = -200;
		mult = -1000; }
	mull(2,200000,exp_psw);
	}

for(ix=0;ix<2;ix++)
	{
	asm("m3:	movab	m3,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|V|C;		/* set all flags except N */
	exp_psw =  N | C; 
	if (ix==0) {
		mult = 1234;
		mulp = -500; }
	     else  {
		mulp = 1234;
		mult = -500; }
	mull(2,-617000,exp_psw);
	}

for(ix=0;ix<2;ix++)
	{
	asm("m4:	movab	m4,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = N|V|C;		/* set all flags except Z */
	exp_psw =  Z | C;
	if (ix==0) {
		mult = 0x1234;
		mulp = 0;  }
	      else {
		mulp = 0x1234;
		mult = 0;  }
	mull(2,0,exp_psw);
	}

	/* test V bit, Overflow */
for(ix=0;ix<2;ix++)
	{
	asm("m5:	movab	m5,_stpc");
	flag_msk = exp_psw = 0;
	exp_psw = (V);			/* any other flags may be set */
	if (ix==0) {
		mult = 0x80000000;	/* Max negative no. */
		mulp = -1; }
	      else {
		mulp = 0x80000000;
		mult = -1; }
	mull(2,0,exp_psw);
	}

for(ix=0;ix<2;ix++)
	{
	asm("m6:	movab	m6,_stpc");
	flag_msk = exp_psw = 0;
	exp_psw = (V);			/* any other flags may be set */
	if (ix==0) {
		mult = -65646;
		mulp = 65646; }
	      else {
		mulp = -65646;
		mult = 65646; }
	mull(2,0,exp_psw);
	}
}

static mull3()
{	long exp_psw , ix;

	/* multiply long with 3 operands */
for(ix=0;ix<2;ix++)
	{
	asm("m7:	movab	m7,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;
	if (ix==0) {
		mult = 0x12345;
		mulp = 0xbff; }
	    else {
		mulp = 0x12345;
		mult = 0xbff; }
	mull(3,0xda618bb,exp_psw);
	} 
 
for(ix=0;ix<2;ix++)
	{
	asm("m8:	movab	m8,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;
	if (ix==0) {
		mult = -3001;
		mulp = -300; }
	     else  {
		mulp = -3001;
		mult = -300; }
	mull(3,900300,exp_psw);
	}
	
for(ix=0;ix<2;ix++)
	{
	asm("m9:	movab	m9,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|V|C;		/* set all flags except N */
	exp_psw =  N | C;
	if (ix==0) {
		mult = 1234;
		mulp = -500; }
	     else  {
		mulp = 1234;
		mult = -500; }
	mull(3,-617000,exp_psw);
	}

for(ix=0;ix<2;ix++)
	{
	asm("m10:	movab	m10,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = N|V;		/* set all flags except Z,C */
	exp_psw = Z | C;
	if (ix==0) {
		mult = 0x1234;
		mulp = 0; }
	     else  {
		mulp = 0x1234;
		mult = 0; }
	mull(3,0,exp_psw);
	}

	/* test V bit 			*/
for(ix=0;ix<2;ix++)
	{
	asm("m11:	movab	m11,_stpc");
	flag_msk = exp_psw = 0;
	exp_psw = (V);			/* any other flags may be set */
	if (ix==0) {
		mult = 0x80000000;	/* Max negative no. */
		mulp = -1; }
	      else {
		mulp = 0x80000000;	/* Max negative no. */
		mult = -1; }
	mull(3,0,exp_psw);
	}

for(ix=0;ix<2;ix++)
	{
	asm("m12:	movab	m12,_stpc");
	flag_msk = exp_psw = 0;
	exp_psw = (V);			/* any other flags may be set */
	if (ix==0) {
		mult = -65646;
		mulp = 65646; }
	    else   {
		mulp = -65646;
		mult = 65646; }
	mull(3,0,exp_psw);
	}
}

static exmul()
{	long exp_psw ;

	/* extended multiply		*/

	asm("m13:	movab	m13,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = N|V|C;		/* set N,V,C flags	*/
	exp_psw =  Z | C;
	exp_reslt1 = 0;
	exp_reslt2 = 0;
/*	mult = -4;		*/
	asm("movl $-4,_mult");		/* so not to use mnegl */
	muld = 5;
	add = 20;
	emul(exp_psw);

	asm("m14:	movab	m14,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|V|C;		/* set Z,V,C flags	*/
	exp_psw =  N | C;
	asm("movl $0xffffffff,_exp_reslt1");
	asm("movl $0xffffffff,_exp_reslt2");
/*	exp_reslt1 = 0xffffffff;
	exp_reslt2 = 0xffffffff;	*/

	/* Expected result is a quad : 0xffffffffffffffff  (-1) */
	mult = -4000;
	muld = 50;
	add = 199999;
	emul(exp_psw);

	asm("m15:	movab	m15,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;		/* set all flags	*/
	exp_reslt2 = 0x60000000 ;
	exp_reslt1 = 0x01000000 ;

	/* Expected result is a quad : 0x0100000060000000 */
	mult = 0xfffffff;
	muld = 0xfffffff;	
	add = 0x7fffffff;
	emul(exp_psw);
}

/*	ROUTINE TO EXECUTE MULL2 AND MULL3	*/

static mull(type,exp_result,exp_psw)
long  exp_result,  exp_psw, type;
{
	long op1, op2, psw, ix;
	char *msg1, *msg2;

   flag_msk = flag_msk << 16;
   op1 = mult;
   op2 = mulp;
   for(;;)
        {
	for (ix=0;ix<8;ix++) 
	{
	mult = op1;
	mulp = op2;

	/*  set flags  */
	if (type == 2) {
		if (ix==0) {		/* Memory to memory */
			setjmp();
			asm("movl	$1,_subtst");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull2  _mult,_mulp");
			asm("movpsl _psl");		/* save PSL */
			product = mulp;
			}
		if (ix==1) {		/* Register to register */
			setjmp();
			asm("movl	$2,_subtst");
			asm("movl _mult,r3");
			asm("movl _mulp,r4");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull2  r3,r4");
			asm("movpsl _psl");		/* save PSL */
			asm("movl r4,_mulp");
			product = mulp;
			}
		if (ix==2) {		/* Memory to register */
			setjmp();
			asm("movl	$3,_subtst");
			asm("movl _mulp,r4");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull2  _mult,r4");
			asm("movpsl _psl");		/* save PSL */
			asm("movl r4,_mulp");
			product = mulp;
			}
		if (ix==3) {		/* Register to memory */
			setjmp();
			asm("movl	$4,_subtst");
			asm("movl _mult,r3");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull2  r3,_mulp");
			asm("movpsl _psl");		/* save PSL */
			product = mulp;
			}
		}
	    else {
		if (ix==0) {		/* Memory to memory to memory */
			setjmp();
			asm("movl	$5,_subtst");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  _mult,_mulp,_product");
			asm("movpsl _psl");		/* save PSL */
			}
		if (ix==1) {		/* Register to register to register */
			setjmp();
			asm("movl	$6,_subtst");
			asm("movl _mult,r3");
			asm("movl _mulp,r4");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  r3,r4,r6");
			asm("movpsl _psl");		/* save PSL */
			asm("movl r6,_product");
			}
		if (ix==2) {		/* Memory to register to memory */
			setjmp();
			asm("movl	$7,_subtst");
			asm("movl _mulp,r4");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  _mult,r4,_product");
			asm("movpsl _psl");		/* save PSL */
			}
		if (ix==3) {		/* Register to memory to register */
			setjmp();
			asm("movl	$8,_subtst");
			asm("movl _mult,r3");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  r3,_mulp,r6");
			asm("movpsl _psl");		/* save PSL */
			asm("movl r6,_product");
			}
		if (ix==4) {		/* Register to register to memory */
			setjmp();
			asm("movl	$9,_subtst");
			asm("movl _mult,r3");
			asm("movl _mulp,r4");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  r3,r4,_product");
			asm("movpsl _psl");		/* save PSL */
			}
		if (ix==5) {		/* Memory to register to register */
			setjmp();
			asm("movl	$0xa,_subtst");
			asm("movl _mulp,r4");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  _mult,r4,r6");
			asm("movpsl _psl");		/* save PSL */
			asm("movl r6,_product");
			}
		if (ix==6) {		/* Register to memory to memory */
			setjmp();
			asm("movl	$0xb,_subtst");
			asm("movl _mult,r3");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  r3,_mulp,_product");
			asm("movpsl _psl");		/* save PSL */
			}
		if (ix==7) {		/* Memory to memory to register */
			setjmp();
			asm("movl	$0xc,_subtst");
			asm("bicpsw $0xf");
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("mull3  _mult,_mulp,r6");
			asm("movpsl _psl");		/* save PSL */
			asm("movl r6,_product");
			}
		}
	psw =  psl & 0xf;	/* mask out high order word of PSL */

	/*  check flags */

	if (exp_psw & V){	/* On expected overflows */
	  if( !(psw & V) ) {	/* We only look at the (V) flag */
		asm("movl	$2,_ercode");
		if (scoplp) longjmp();
		error_hdl2(psw,exp_psw,op1,op2);
	  }
	continue;			/* skip other checks */
	}
	else if  (psw != exp_psw)  
		{
		asm("movl	$2,_ercode");
		if (scoplp) longjmp();
		error_hdl2(psw,exp_psw,op1,op2);
		}
	if (mult != op1)
		{
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		error_hdl2(mult,op1,op1,op2);
		}
	if (type == 3)
		{
		if (mulp != op2)
		    {
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
			error_hdl2(mulp,op2,op1,op2);
		    }
		}
	if (product != exp_result)
		{		/* error in multiply operation */
		asm("movl	$1,_ercode");
		if (scoplp) longjmp();
		error_hdl2(product,exp_result,op1,op2);
		}
		if (force_lp) longjmp();
	}
	break;
	}
}

/*	ROUTINE TO EXECUTE EMUL		*/

static emul(exp_psw)
long exp_psw;
{	
	long op1, op2, op3, psw, type;
	char *msg1, *msg2;

   flag_msk = flag_msk << 16;
   op1  = mult;
   op2  = muld;
   op3  = add;
   for(;;)
        {
	msg1 = "** Test EMUL **\n";
	for(type=0;type<8;type++)
	{
	mult = op1;
	muld = op2;
	add = op3;

	if (type==0)  { 	/* Memory memory memory memory */
		asm("movl	$0xd,_subtst");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  _mult,_muld,_add,_prod1");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		}
	if (type==1)  { 	/* Register,register,register register */
		asm("movl	$0xe,_subtst");
		asm("movl _mult,r3");
		asm("movl _muld,r4");
		asm("movl _add,r5");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  r3,r4,r5,r6");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		asm("movl r6,_prod1");
		asm("movl r7,_prod2");
		}
	if (type==2)  { 	/* Register register Memory memory */
		asm("movl	$0xf,_subtst");
		asm("movl _mult,r3");
		asm("movl _muld,r4");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  r3,r4,_add,_prod1");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		}
	if (type==3)  { 	/* Register memory Memory register */
		asm("movl	$0x10,_subtst");
		asm("movl _mult,r3");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  r3,_muld,_add,r6");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		asm("movl r6,_prod1");
		asm("movl r7,_prod2");
		}
	if (type==4)  { 	/* Memory memory register memory */
		asm("movl	$0x11,_subtst");
		asm("movl _add,r5");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  _mult,_muld,r5,_prod1");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		}
	if (type==5)  { 	/* Register memory register memory */
		asm("movl	$0x12,_subtst");
		asm("movl _mult,r3");
		asm("movl _add,r5");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  r3,_muld,r5,_prod1");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		}
	if (type==6)  { 	/* Memory register register memory */
		asm("movl	$0x13,_subtst");
		asm("movl _muld,r4");
		asm("movl _add,r5");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  _mult,r4,r5,_prod1");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		}
	if (type==7)  { 	/* Memory register memory register */
		asm("movl	$0x14,_subtst");
		asm("movl _muld,r4");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("emul  _mult,r4,_add,r6");
		asm("movpsl _psl");		/* save PSL */
		psw =  psl & 0xf;
		asm("movl r6,_prod1");
		asm("movl r7,_prod2");
		}

	if ( prod1 != exp_reslt1)
		{		/* error in ext. multiply operation */
		asm("movl	$1,_ercode");
		if (scoplp) longjmp();
		error(prod1,exp_reslt1,op1,op2);
		}
	if ( prod2 != exp_reslt2 )
		{		/* error in ext. multiply operation */
		asm("movl	$1,_ercode");
		if (scoplp) longjmp();
		error(prod2,exp_reslt2,op1,op2);
		}
	/*  check flags */
	if (psw!=exp_psw) 
		{
		asm("movl	$3,_no_opr");
		asm("movl	$2,_ercode");
		if (scoplp) longjmp();
		error_hdl3(psw,exp_psw,op1,op2,op3);
		}

	if (mult != op1)
		{
		asm("movl	$3,_no_opr");
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		error_hdl3(mult,op1,op1,op2,op3);
		}
	if (muld != op2)
		{
		asm("movl	$3,_no_opr");
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		error_hdl3(muld,op2,op1,op2,op3);
		}
	if (add != op3)
		{
		asm("movl	$3,_no_opr");
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		error_hdl3(add,op3,op1,op2,op3);
		}
		if (force_lp) longjmp();
	}
	break;
	}
}



unix.superglobalmegacorp.com

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