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

#define error_hdl0 error
#define error_hdl2 error
#define ediv_errhdl error

extern long scoplp;
extern long force_lp;

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

/*	DIV instructions		*/


/* Some global variables */

static long flag_msk, divr, quo, rem, psl, quotient, divd[2];



div()
{
	asm("movl	$2,_no_opr");
	divl2();		/* DIVIDE LONG WITH 2 OPERANDS */
	divl3();		/* DIVIDE LONG WITH 3 OPERANDS */
/*	divl2u();	*/	/* DIVIDE LONG WITH 2 UNSIGNED OPERANDS */
/*	divl3u();	*/	/* DIVIDE LONG WITH 3 UNSIGNED OPERANDS */
	exdiv();		/* EXTENDED DIVISION */
	asm("jmp *return");
}

static divl2()
{
	long exp_psw;
	int unsign, no_op;

	unsign = 0;	/* signed division */
	no_op = 2;	/* 2 operands      */

	asm("d1:	movab	d1,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;
	divr = 0x47;
	quo = 0x5678ffff;
	divl(unsign,no_op,0x137c9ea,exp_psw);
	
	asm("d2:	movab	d2,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = N|V|C;		/* set all flags except Z */
	exp_psw = exp_psw | Z | C;
	divr = 1234;
	quo = 0;
	divl(unsign,no_op,0,exp_psw);

	asm("d3:	movab	d3,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|V|C;		/* set all flags except N */
	exp_psw = exp_psw | N | C;
	divr = 4;
	quo = -80;
	divl(unsign,no_op,-20,exp_psw);

	/* test V bit 			*/
	asm("d4:	movab	d4,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|C;			/* set Z,C flags  */
	exp_psw = exp_psw | (V|C);
	/* divide largest negative no. by -1 */
	divr = -1;
	quo = 0x80000000;
	divl(unsign,no_op,0x80000000,exp_psw);

}

static divl3()
{
	long exp_psw;
	int unsign, no_op;

	unsign = 0;	/* signed division */
	no_op = 3;	/* 3 operands      */

	asm("d5:	movab	d5,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;
	divr = 0x47;
	quo = 0x5678ffff;
	divl(unsign,no_op,0x137c9ea,exp_psw);
	
	asm("d6:	movab	d6,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = N|V|C;		/* set all flags except Z */
	exp_psw = exp_psw | Z | C;
	divr = 1234;
	quo = 0;
	divl(unsign,no_op,0,exp_psw);

	asm("d7:	movab	d7,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|V|C;		/* set all flags except N */
	exp_psw = exp_psw | N | C;
	divr = 4;
	quo = -80;
	divl(unsign,no_op,-20,exp_psw);

	/* test V bit 			*/
	asm("d8:	movab	d8,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|C;			/* set Z,C flags  */
	exp_psw = exp_psw | (V|C);
	/* divide largest negative no. by -1 */
	divr = -1;
	quo = 0x80000000;
	divl(unsign,no_op,0x80000000,exp_psw);

}


static exdiv()
{
	long exp_rem,  exp_psw;

	/* EXTENDED DIVISION 		*/
	asm("d9:	movab	d9,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = N|Z|V|C;		/* set all flags	*/
	divd[0] = 0;
	divd[1] = 0xfffffff;
	divr = 0xffffff0;
	ediv(1,0xf,exp_psw);

	asm("d10:	movab	d10,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = N|V|C;		/* set N,V,C flags	*/
	exp_psw = exp_psw | Z | C;
	divd[0] = 0;
	divd[1] = 0;
	divr = 4;
	ediv(0,0,exp_psw);

	asm("d11:	movab	d11,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|V|C;		/* set Z,V,C flags	*/
	exp_psw = exp_psw | N | C;
	divd[0] = 0xffffffff;
	divd[1] = -4005;
	divr = 50;
	ediv(-80,-5,exp_psw);

	asm("d12:	movab	d12,_stpc");
	flag_msk = exp_psw = C;
	flag_msk = Z|N|C;		/* set Z,N,C flags  */
	exp_psw = exp_psw | N | C;
	divd[0] = 0x6000;
	divd[1] = 0xb000;	/* divd = 0x60000000b000 */
	divr =  0xaeaeaeae;
	ediv(0xfffed1c8,0x48482a10,exp_psw);


	/* check overflow bit on extended division */
	asm("d13:	movab	d13,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|C;			/* set Z,C flags  */
	exp_psw = exp_psw | (Z|V|C);
	/* divide largest negative no. by -1 */
	divd[0] = 0x80000000;
	divd[1] = 0;		/* divd = 0x8000000000000000 */
	divr = -1;
	ediv(0,0,exp_psw);

	asm("d14:	movab	d14,_stpc");
	flag_msk = exp_psw = 0;
	flag_msk = Z|N|C;		/* set Z,N,C flags  */
	exp_psw = exp_psw | (Z|V|C);
	divd[0] = 0xff;
	divd[1] = 0;		/* divd = 0x000000ff00000000 */
	divr = 2;
	ediv(0,0,exp_psw);


}

/*	THIS ROUTINE EXECUTE DIVL2,DIVL3,DIVL2U,DIVL3U INSTRUCTIONS 	*/

static divl(unsign,no_op,exp_result,exp_psw)
long exp_result,exp_psw;
int unsign, no_op;
{	
	long op1, op2, op3, psw, type;

   flag_msk = flag_msk << 16;
   op1 = divr;
   op2 = quo;
   for(;;)
        {
	for (type=0;type<8;type++)
	{
	divr = op1;
	quo = op2;

  	    if (no_op==2)  {
		    if (type==0)  {	/* Memory to memory */
			setjmp();
			asm("movl	$1,_subtst");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl2  _divr,_quo");
			asm("movpsl _psl");	/* save PSL */
			quotient = quo;
				 }
		    if (type==1) {	/* Register to register */
			setjmp();
			asm("movl	$2,_subtst");
			asm("movl _divr,r3");
			asm("movl _quo,r4");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl2  r3,r4");
			asm("movpsl _psl");	/* save PSL */
			asm("movl r4,_quo");
			quotient = quo;
				 }
		    if (type==2) {	/* Register to Memory */
			setjmp();
			asm("movl	$3,_subtst");
			asm("movl _divr,r3");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl2  r3,_quo");
			asm("movpsl _psl");	/* save PSL */
			quotient = quo;
				 }
		    if (type==3) {	/* Memory to Register */
			setjmp();
			asm("movl	$4,_subtst");
			asm("movl _quo,r4");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl2  _divr,r4");
			asm("movpsl _psl");	/* save PSL */
			asm("movl r4,_quo");
			quotient = quo;
				 }
		      
		    }
		    if (type==0) {	/* Memory to memory  to memory */
			setjmp();
			asm("movl	$5,_subtst");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  _divr,_quo,_quotient");
			asm("movpsl _psl");	/* save PSL */
				 }
		    if (type==1) {	/* Register to register  to memory */
			setjmp();
			asm("movl	$6,_subtst");
			asm("movl _divr,r3");
			asm("movl _quo,r4");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  r3,r4,_quotient");
			asm("movpsl _psl");	/* save PSL */
				 }
		    if (type==2) {	/* Register to Memory  to memory */
			setjmp();
			asm("movl	$7,_subtst");
			asm("movl _divr,r3");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  r3,_quo,_quotient");
			asm("movpsl _psl");	/* save PSL */
				 }
		    if (type==3) {	/* Memory to Register  to register */
			setjmp();
			asm("movl	$8,_subtst");
			asm("movl _quo,r4");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  _divr,r4,r5");
			asm("movpsl _psl");	/* save PSL */
			asm("movl r5,_quotient");
				 }
		    if (type==4) {	/* Register to register to register */
			setjmp();
			asm("movl	$9,_subtst");
			asm("movl _divr,r3");
			asm("movl _quo,r4");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  r3,r4,r5");
			asm("movpsl _psl");	/* save PSL */
			asm("movl r5,_quotient");
				 }
		    if (type==5) {	/* Register to memory to register */
			setjmp();
			asm("movl	$0xa,_subtst");
			asm("movl _divr,r3");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  r3,_quo,r5");
			asm("movpsl _psl");	/* save PSL */
			asm("movl r5,_quotient");
		    		 }
		    if (type==6) {	/* Memory to  memory to Register */
			setjmp();
			asm("movl	$0xb,_subtst");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  _divr,_quo,r5");
			asm("movpsl _psl");	/* save PSL */
			asm("movl r5,_quotient");
			 	 }
		    if (type==7) {	/* Memory to Register to memory */
			setjmp();
			asm("movl	$0xc,_subtst");
			asm("movl _quo,r4");
			asm("bicpsw $0xf");		/* clear all flags */
			asm("bispsw _flag_msk");	/* set flags	   */
			asm("divl3  _divr,r4,_quotient");
			asm("movpsl _psl");	/* save PSL */
				 }
		}
	psw =  psl & 0xf;

	/*  check flags */
	if (psw != exp_psw) 
		{
		asm("movl	$2,_ercode");
		if (scoplp) longjmp();
		error_hdl2(psw,exp_psw,op1,op2);
		}

	if (divr != op1)
		{
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		error_hdl2(divr,op1,op1,op2);
		}
	if (no_op == 3)
		{
		if (quo != op2)
		   {
			asm("movl	$3,_ercode");
			if (scoplp) longjmp();
			error_hdl2(quo,op2,op1,op2);
		   }
		}
	if (quotient != exp_result)
		{
		asm("movl	$1,_ercode");
		if (scoplp) longjmp();
		error_hdl2(quotient,exp_result,op1,op2);
		}
		if (force_lp) longjmp();
	break;
	}
}


static ediv(exp_quo,exp_rem,exp_psw)
long exp_quo, exp_rem, exp_psw;
{	
	long op1, op2[2], psw, type;

   flag_msk = flag_msk << 16;
   op1 = divr;
   op2[0] = divd[0];
   op2[1] = divd[1];
   for(;;)
        {
	for (type=0;type<4;type++) {
	divr = op1;
	divd[0] = op2[0];
	divd[1] = op2[1];

	if (type==0) {		/* Memory to memory to memory to register */
		setjmp();
		asm("movl	$0xd,_subtst");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("ediv  _divr,_divd,_quo,r7");
		asm("movpsl _psl");		/* save PSL */
		asm("movl r7,_rem");
		}
	if (type==1) {	/* Register to register to register to register */
		setjmp();
		asm("movl	$0xe,_subtst");
		asm("movl _divr,r3");
		asm("movl _divd,r4");
		asm("movl _divd+4,r5");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("ediv  r3,r4,r6,r7");
		asm("movpsl _psl");		/* save PSL */
		asm("movl r6,_quo");
		asm("movl r7,_rem");
		}
	if (type==2) {	/* Register to memory to register to register */
		setjmp();
		asm("movl	$0xf,_subtst");
		asm("movl _divr,r3");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("ediv  r3,_divd,r6,r7");
		asm("movpsl _psl");		/* save PSL */
		asm("movl r6,_quo");
		asm("movl r7,_rem");
		}
	if (type==3) {	/* Memory to register to memory to register */
		setjmp();
		asm("movl	$0x10,_subtst");
		asm("movl _divd,r4");
		asm("movl _divd+4,r5");
		asm("bicpsw $0xf");		/* clear all flags */
		asm("bispsw _flag_msk");	/* set flags	   */
		asm("ediv  _divr,r4,_quo,r6");
		asm("movpsl _psl");		/* save PSL */
		asm("movl r6,_rem");
		}

	psw =  psl & 0xf;
	if (quo != exp_quo)
		{		/* error in multiply operation */
		asm("movl	$1,_ercode");
		if (scoplp) longjmp();
		ediv_errhdl(quo,exp_quo,op1,op2);
		}

	/*  check flags */
	if  (psw != exp_psw) 
		{
		asm("movl	$2,_ercode");
		if (scoplp) longjmp();
		ediv_errhdl(psw,exp_psw,op1,op2);
		}

	if (divr != op1)
		{
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		ediv_errhdl(divr,op1,op1,op2);
		}
	if ( (divd[0]!=op2[0]) || (divd[1]!=op2[1]) )
		{
		asm("movl	$3,_ercode");
		if (scoplp) longjmp();
		error_hdl0(divd,op2,op1,op2);
		}
	if (rem != exp_rem)
		{
		asm("movl	$1,_ercode");
		if (scoplp) longjmp();
		ediv_errhdl(rem,exp_rem,op1,op2);
		}
		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.