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