ASMB,L,C
* 
*  **************************************************************** 
*  * (C) COPYRIGHT HEWLETT-PACKARD COMPANY 1979.  ALL RIGHTS      * 
*  * RESERVED.  NO PART OF THIS PROGRAM MAY BE PHOTOCOPIED,       * 
*  * REPRODUCED OR TRANSLATED TO ANOTHER PROGRAM LANGUAGE WITHOUT * 
*  * THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY.        * 
*  **************************************************************** 
* 
*   NAME: PART OF MATH LIBRARY
*   SOURCE:  24998-18XXX  SEE NAM FOR LAST THREE DIGITS 
*   RELOC: PART OF 24998-12001
*   PGMR: BG & JTS
* 
      HED ".DDI" - DOUBLE INTEGER DIVIDE. 
      NAM .DDI,7 24998-1X040 REV.2001 781021
* 
      ENT .DDI,.DDIR
      EXT FLOAT 
* 
A     EQU 0 
B     EQU 1 
      SUP 
* 
*     .DDI TAKES THE QUOTIENT OF TWO DOUBLE INTEGERS.  SEE ".DADS"
*     FOR THE NUMBER FORMAT.  NOTE:  THE INSTRUCTION "DIV" IS NOT 
*     COMPATIBLE WITH .DDI .
* 
*     CALLING SEQUENCE: 
* 
*                   DLD <ARG 1> 
*                   JSB <.DDI OR .DDIR> 
*                   DEF <ARG2>
*                   <RETURN>        RESULT IN (A,B) 
* 
*     FOR ".DDI", THE RESULT IS ARG1/ARG2.  FOR ".DDIR" THE RESULT IS 
*     ARG2/ARG1.  THE OVERFLOW BIT IS SET IFF THE DIVISOR IS ZERO OR
*     THE DIVIDEND IS -2**31 AND THE DIVISOR IS -1.  IN THIS CASE 
*     THE VALUE RETURNED IS (077777,177777).  THE E-BIT IS PRESERVED. 
      SPC 2 
*                   ENTRY.  COPY ARGS, DETERMINE SIGN OF RESULT, TAKE ABS VALUES. 
* 
.DDI  NOP 
      STA D1        REMEMBER SIGN OF NUMERATOR. 
      ERA           REMEMBER "E"
      STA E 
      LDA D1
      SSA,RSS       TAKE ABS VALUE. 
      JMP DIVA
      CMA 
      CMB,INB,SZB,RSS 
      INA 
DIVA  STA N1        (N1,N2) = ABS NUMERATOR 
      STB N2
      LDB .DDI,I    GET DENOM ADDR. 
      ISZ .DDI
      LDA B,I       COMPUTE SIGN OF RESULT. 
      XOR D1
      IOR =B77777   = -1 IFF SIGN RESULT IS "-".
      STA SIGN
      DLD B,I 
      SSA,RSS       TAKE ABS VALUE
      JMP DIVB
      CMA 
      CMB,INB,SZB,RSS 
      INA 
DIVB  STA D1        (D1,D2) = ABS VALUE DENOMINATOR 
      STB D2
      SKP 
*                   DETERMINE IF EASY OR HARD. IF EASY, DO IT.
* 
      SWP 
      ASL 16        DOES DENOM FIT IN ONE WORD ?
      SOC 
      JMP DIV2      NO. 
      CLB           YES. USE EASY WAY.
      LDA N1        UPPER DIVIDE. 
      DIV D2
      SOC           DIVIDE BY ZERO ?
      JMP SPEC2     YES. [ALSO (MAX NEG)/(+-1)] 
      SSA           CORRECT FOR DENOM = 2**15.
      CMA,INA 
      STA Q1        UPPER RESULT. 
      SSB           CORRECT FOR DENOM = 2**15.
      CMB,INB 
      LDA N2        FORM FULL REMAINDER.
      ASR 1         CAN ONLY GENERATE 15 BITS.
      DIV D2        FORM THEM.
      RAL           POSITION. 
      STA Q2
      LDA N2        FORM REMAINDER. 
      ERA           E = LAST BIT QUOTIENT.
      ELB           TACK ON TO REM. 
      CMB,INB       FORM DIVISOR - REMAINDER. 
      ADB D2
      CMB,SSB,INB,SZB REM >= DIV ?  (B = REM - DIV) 
      RSS           NO. 
      ISZ Q2        YES. Q <-- Q + 1
      JMP FINIS     GO ATTACH SIGN. 
      SPC 4 
*                   .DDIR - REVERSE DIVIDE. 
* 
.DDIR NOP 
      STA Q1        JUST SET UP CALL TO .DDI
      STB Q2
      LDA .DDIR,I 
      ISZ .DDIR 
      DLD A,I 
      JSB .DDI
      DEF Q1
      JMP .DDIR,I 
      SKP 
*                   DIVISOR DOES NOT FIT IN ONE WORD. DO HARD WAY.
* 
DIV2  STA Q1        ZERO OUT UPPER RESULT (A=0) 
      STA Q2        & LOWER IN CASE HAVE 2**15 BIT. 
      LDA D1        GET SHIFT COUNT TO MAKE DIVISOR SINGLE. 
      JSB FLOAT 
      RBR           B = COUNT - 1 
      CPB =D15      WHOLE WORD ?
      JMP DIV10     YES, BIG DIVISOR, HANDLE SEPARATELY.
      ADB LSR01     NO. FORM "LSR N"
      STB DIV3      WILL USE IT FOUR TIMES. 
      STB DIV4
      STB DIV5
      STB DIV6
      LDB D1        RIGHT SHIFT DENOMINATOR.
      LDA D2
DIV3  LSR 16
      LDB D2
      STA D1
      CLA 
DIV4  LSR 16
      STA D2
      LDB N2        RIGHT SHIFT NUMERATOR.
      CLA 
DIV5  LSR 16
      LDB N2
      STA N2
      LDA B 
      LDB N1
DIV6  LSR 16
* 
*                   (B,A) = (N0,N1).  FORM TENTATIVE QUOTIENT.
* 
DIV7  STB N0
      STA N1
      DIV D1        FORM IT.
      SOS           OFL ? 
      JMP DIV8      NO. 
      LDB N0        YES.  GEN FIRST 15 BITS, THEN REST. 
      LDA N1
      ASR 15
      DIV D1
      RAR,SLA       IS 1 OR 2: IF 2,
      JMP SPEC1       (MAX NEG) / (+-32768, +-32769)
      STA Q2        WAS 1.  VALUE IS 2**15. 
      LDA N1        FORM REMAINDER. 
      CLE,ERB 
      RAL,ERA 
      JMP DIV7      TRY AGAIN. (IT BETTER WORK THIS TIME) 
      SKP 
*                   FORM TRUE REMAINDER.
* 
DIV8  IOR Q2        ADD 2**15 BIT IF PRESENT. 
      STA Q2        TENTATIVE QUOTIENT. 
      STB N1        (N1,N2) = REMAINDER.
      MPY D2        ADJUST FOR D2: SUBTRACT Q2*D2 FROM REM. 
      STA N0        (UNSIGNED MPY: UNDO CORRECTIONS FOR SIGNS)
      LDA Q2
      SSA 
      ADB D2
      LDA D2
      SSA 
      ADB Q2
      LDA N0
      CMB,CLE       NEGATE Q2*D2
      CMA,INA       (E = CARRY) 
      ADA N2        + (N1,N2) 
      SEZ 
      INB 
      ADB N1        (B,A) = TENTATIVE REMAINDER.
* 
*                   IF REM < 0, DECREMENT QUOTIENT & ADD DIV TO REM.
* 
DIV8B CLE,SSB,RSS   REM < 0 ? 
      JMP FINIS     NO. 
      ADA D2        YES. ADD DIVISOR. 
      SEZ 
      INB 
      ADB D1
      STB N1        FIX QUOTIENT. 
      CCB 
      ADB Q2
      STB Q2
      LDB N1        GO RECHECK. 
      JMP DIV8B 
* 
*                   ATTACH SIGN.  (B = RESULT LOWER)
* 
FINIS LDB Q2        (B = 2ND WD RESULT) 
FINI0 LDA Q1        (A = 1ST WD RESULT) 
      ISZ SIGN      POS ? 
      JMP FINI1     YES.
      CMA           NO, NEGATE. 
      CMB,INB,SZB,RSS 
      INA 
FINI1 CLO           "O" CLEARED.
FINI2 STA Q1        RESTORE "E" & EXIT. 
      LDA E 
      ELA 
      LDA Q1        (A,B) = RESULT. 
      JMP .DDI,I    EXIT. 
      SKP 
*                   DIVISOR IN [-2**31,-2**30) OR [2**30,2**31).
* 
DIV10 CLB           DO DIVISION. D1 MAX BE MAX NEG. 
      LDA N1
      DIV D1        (0,N1) / D1 
      SSA           SPECIAL CASE: (MAX NEG) / (MAX NEG) 
      CMA,INA       (JUST LET IT GO THRU) 
      JMP DIV8
* 
*                   SPECIAL CASE: (MAX NEG) / (32768) = 65536. [REM=0]
*                                 (MAX NEG) / (32769) = 65534. [REM=2]
* 
SPEC1 LDB D2        0 IF 32768, 100000 IF 32769.
      SSB,RSS       IF 32768, 
      ISZ Q1          UPPER WORD = 1. (65536) 
      ASR 14        LOWER WORD: 0 OR 65534. 
      JMP FINI0     FINISH UP.
* 
*                   SPECIAL CASE: DIV BY ZERO 
*                                 (MAX NEG) / (+-1)  [REM=0]
* 
SPEC2 LDB SIGN      SEE IF OFL OR NOT.
      LDA D2
      CPA =D1       D2 MUST BE 1. 
      INB,SZB       AND SIGN MUST BE < 0. 
      JMP OFL       NOPE. 
      RAR           (MAX NEG) / 1, RESULT = MAX NEG.
      JMP FINI1 
* 
*                   OFL.  DIV BY ZERO OR (MAX NEG) / (-1) 
* 
OFL   LDA =B77777   (A,B) = MAX POS.
      CCB 
      STO           "O" SET.
      JMP FINI2     RESTORE "E" & EXIT. 
* 
*                   LOCALS. 
* 
N0    BSS 1         NUMERATOR & REMAINDER.
N1    BSS 1 
N2    BSS 1 
D1    BSS 1         DENOMINATOR.
D2    BSS 1 
Q1    BSS 1         QUOTIENT. 
Q2    BSS 1 
E     BSS 1         "E" 
SIGN  BSS 1         SIGN OF RESULT. 
LSR01 LSR 1         CONSTANT. 
      UNS 
      END 
                                                                                                                                                                                                                                                        