! File: MULDIV.B11 ! ! This work was supported by the Advanced Research ! Projects Agency of the Office of the Secretary of ! Defense (F44620-73-C-0074) and is monitored by the ! Air Force Office of Scientific Research. MODULE MULDIV= BEGIN %< The BLISS-11 out of line multiply, divide, and mod routines >% ! Both multiply and divide operations are defined only on ! signed, two's complement integers. The multiply routine uses ! the time-honored "shift and add" algorithm, terminating when ! either the multiplier or the multiplicand becomes zero. The ! divide/mod routine uses a "shift and subtract" algorithm ! after first converting the operands to positive values and ! remembering the signs. Sign of the quotient is determined by ! the rules of algebra. The MOD operator is defined here as ! the remainder after division, and the sign of the result is ! made the same as that of the dividend (consistent with ! PDP-11/45 hardware divide definition). ! ! December 1972 ! R. Johnsson GLOBAL ROUTINE MUL(XA,XB)= BEGIN REGISTER S,A,B; S_0; A_.XA; B_.XB; WHILE 1 DO BEGIN IF .B THEN S_.S+.A; IF (A_.A*2) EQL 0 THEN EXITLOOP; IF (B_.B/2) EQL 0 THEN EXITLOOP; END; .S END; ROUTINE DIVMOD(S,R,RET,W)= ! W=0 for DIV, 1 for MOD ! RET is the return address for DIVR or MODR ! ! This routine returns .A/.B or .A MOD .B, sample values are: ! ! 4 / 3 = 1 4 MOD 3 = 1 ! -4 / -3 = 1 -4 MOD -3 = -1 ! -4 / 3 = -1 -4 MOD 3 = -1 ! 4 / -3 = -1 4 MOD -3 = 1 ! ! In general, B*(A/B) + (A MOD B) = A ! BEGIN LOCAL ANEG,BNEG,C; REGISTER Q,A,B; IF (A_.S) EQL 0 THEN RETURN 0; IF (B_.R) EQL 0 THEN RETURN 0; ANEG_BNEG_0; IF .A LSS 0 THEN (A_-.A; ANEG_.ANEG+1); IF .B LSS 0 THEN (B_-.B; BNEG_.BNEG+1); C_0; UNTIL .B GEQ .A OR .B<14,1> DO (B_.B*2; C_.C+1); Q_0; WHILE 1 DO BEGIN Q_.Q*2; IF .B LEQ .A THEN (Q_.Q+1; IF (A_.A-.B) EQL 0 THEN EXITLOOP); IF (C_.C-1) LSS 0 THEN EXITLOOP; B_.B/2; END; IF .W NEQ 0 THEN (IF .ANEG NEQ 0 THEN A_-.A; RETURN .A); IF .ANEG NEQ .BNEG THEN Q_-.Q; UNTIL (C_.C-1) LSS 0 DO Q_.Q*2; .Q END; GLOBAL ROUTINE DIVR=DIVMOD(0); GLOBAL ROUTINE MODR=DIVMOD(.PC); END