Files
Arquivotheca.SunOS-4.1.4/usr.etc/gp/pp/squareroot.pp.u
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

101 lines
3.7 KiB
Plaintext

| "@(#)squareroot.pp.u 1.1 94/10/31"
| Copyright 1986 by Sun Microsystems, Inc.
| Written by Stuart Levy
| Result is in r[7], number to be square-rooted is in r[5] and r[6], where r[6]
| must be zeroed out if not used. Note that first instruction needs condition code to be
| set by calling routine, are checking if squares is 0.
#define dvsr acc
#define mod acc
#define dvdnd r[0]
#define t r[0]
#define divlow r[0]
#define thigh r[1]
#define divhigh r[1]
#define quot r[2]
#define reshigh r[3]
#define x2 r[4]
#define squares r[5]
#define sqhigh r[6]
#define result r[7]
sqrt: sub2nw,s 0,squares,r[0]; ; cjp, zer sqzero; | Will return zero if squares 0 or 1.
movw squares,result; ; cjp, zer sqzero; |
testw (sqhigh); ; ; | Check if need to do double precision.
movw squares,t; ; cjp, ~zer sqdbl; | Jump if need to use double precision.
sqshft: sr0w,s t,t; 17->am; ; | while (t>>=2) x>>=1.
sr0w,s t,t; ; cjp, zer sqrt2; |
sr0w result,result; ; cjp, ~zer sqshft; |
slqw result,result; ; ; | Shift back once, using qlink (MSB).
sqrt2: incw result,result; ; ; |
sqloop: movw result,dvsr; ; ; |
movw squares,dvdnd; ; cjs, go divide; |
movw quot,y; am->am; ; | quot = n/x. Q is in d-latch.
sqloop2: rsubw,s d,result,y; ; ; | Compute (q-x). Will jump if (x <= q).
; ; cjp, neg squpx; | if (x <= q) => x2 = x+2
add2nw 1,result,x2; am->am; ; |
subw,s d,quot,y; ; ; | Check if (q < x2), ie (q-x2) < 0.
movw quot,y; am->am; crtn, neg; | Return if (q < x2).
testw (mod); ; cjp, ~zer squpx; | Continue if q != x2.
; ; crtn, zer; | Return if (q == x2 && mod2==0). Q in d-latch.
squpx: addw d,result,result; ; ; | x = (x + q) >> 1.
sr0w result,result; ; cjp, go sqloop; |
#undef mod
| Double precision squareroot routine. Note that mod moves to r[1] now.
#define mod r[1]
sqdbl: movw sqhigh,thigh; ; ; | Double precision squareroot.
movw sqhigh,reshigh; ; ; |
sqdshft: sr0w,s thigh,thigh; ; ; | While (t>>=2) x>>=1.
srqw t,t; ; cjp, zer sqrshft2; |
sr0w,s thigh,thigh; ; ; | Shift down upper word of t again.
srqw t,t; ; cjp, zer sqrres; | Shift LSB of upper into MSB of lower.
sr0w,s reshigh,reshigh; ; ; | Here we know res is still double prec.
srqw result,result; ; cjp, go sqdshft; | Loop.
sqrshft: sr0w t,t; ; ; | T is single prec., res is still double.
sqrshft2: sr0w t,t; ; ; |
sqrres: sr0w,s reshigh,reshigh; ; ; | Res should be single before t = 0. CHECK!
srqw result,result; ; cjp, ~zer sqrshft; | Loop as long as res is still double prec.
sqsshft: sr0w,s t,t; 17->am; ; | Code same as single prec. until divide!!
sr0w,s t,t; ; cjp, zer sqrtd2; |
sr0w result,result; ; cjp, ~zer sqsshft; |
slqw result,result; ; ; | Shift back once, using qlink (MSB).
sqrtd2: incw result,result; ; ; | x++
sqdloop: movw result,dvsr; ; ; |
movw sqhigh,divhigh; ; ; | Load upper word in upper dividend word.
movw squares,divlow; ; cjs, go divlong; | Load lower word in dividend.
movw quot,y; am->am; ; | Make sure can assume result is 16 bits.
sqdloop2: rsubw,s d,result,y; ; ; | Compute (q-x). Will jump if (x <= q).
; ; cjp, neg squdpx; | if (x <= q) => x2 = x+2
add2nw 1,result,x2; am->am; ; |
rsubw,s d,quot,y; ; ; | Will return if (q <= x2), ie (x2 - q) >= 0.
movw quot,y; am->am; crtn, ~neg; |
squdpx: addw d,result,result; ; ; | x = (x + q) >> 1.
sr0w result,result; ; cjp, go sqdloop; |
sqzero: movw 0,result; ; crtn, go; | Move 0 to result if number is 0 or 1.
#undef dvsr
#undef x2
#undef mod
#undef dvdnd
#undef divlow
#undef divhigh
#undef quot
#undef squares
#undef sqhigh
#undef result
#undef reshigh
#undef t
#undef thigh