--
--      Inmos Libraries
--      Copyright (C) 1988, 1989, 1990, 1991, 1993  Inmos Limited
--
--      This library is free software; you can redistribute it and/or
--      modify it under the terms of the GNU Lesser General Public
--      License as published by the Free Software Foundation; either
--      version 2 of the License, or (at your option) any later version.
--
--      This library is distributed in the hope that it will be useful,
--      but WITHOUT ANY WARRANTY; without even the implied warranty of
--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--      Lesser General Public License for more details.
--
--      You should have received a copy of the GNU Lesser General Public
--      License along with this library; if not, write to the Free Software
--      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
--

--** @module forall

#IF (TARGET.BITS.PER.WORD = 16)

--{{{  #options and #comments
#OPTION "E V"  -- no compiler libs, no vector space
#COMMENT "T2 compiler library, V1.3 11/01/93"
#COMMENT "(c) Copyright INMOS Limited 1988"
--}}}

#PRAGMA TRANSLATE INT32DIVREM "INT32DIVREM%CHK"
#PRAGMA TRANSLATE INT32DIV "INT32DIV%CHK"
#PRAGMA TRANSLATE INT32REM "INT32REM%CHK"

--{{{  INT32DIVREM
--{{{  INT32DIVREM -- T2
INT32, INT32 FUNCTION INT32DIVREM (VAL INT32 Dvd, VAL INT32 Dvsr)

  --{{{  comments
  -- Calculates the quotient and remainder from Dvd and Dvsr.  Note
  -- that Dvd is the dividend and Dvsr is the divisor, and in a fraction
  -- it is the dividend that is the numerator and the divisor that is the
  -- denominator.
  
  -- NOTE:  Because (MOSTNEG INT32) REM (-1(INT32)) is valid (and equal to 0),
  -- but (MOSTNEG INT32) / (-1(INT32)) is invalid, this routine, as it is
  -- asked for both quotient and remainder, must leave it to the caller to
  -- fault the division: if given the arguments MOSTNEG INT32 and -1, then
  -- this routine will give the correct answer for the remainder, but rubbish
  -- for the quotient.
  --}}}

  --{{{  history
  -- Function version (10 Jun 87)
  -- V1.1 21/02/89
  -- V1.2 06/04/90 SRH
  -- V1.3 11/01/93 SRH: bug fix TS/2020 - moved check for
  -- (MOSTNEG INT32) / (-1(INT32)) from INT32DIVREM into INT32DIV so that
  -- remainder can be calculated correctly.
  --}}}

  INT32 Quot, Rem :
  VALOF
    -- signed divide from Knuth (algorithm D, section 4.3.1 - vol 2, pp 257).
    --{{{  DEFs
    VAL MaxInt  IS #FFFF :
    VAL SignBit IS #8000 :
    --}}}
    --{{{  PROC INT32UnsDiv
    PROC INT32UnsDiv ([2]INT Quot, Rem, VAL [2]INT Dvd, Dvsr)
      --Unsigned divide primitive implemeted using Knuth's divide
      --algorithm, with error checking.
      INT Count, X :
      [3] INT U :
      PLACE U IN WORKSPACE :
      [3] INT W :
      PLACE W IN WORKSPACE :
      [2] INT V :
      PLACE V IN WORKSPACE :
      IF
        --{{{  Dvsr = 0
        (Dvsr [0] = 0) AND (Dvsr [1] = 0) --divide by zero
          CAUSEERROR()
        --}}}
        --{{{  Dvsr [1] = 0
        Dvsr [1] = 0                      --do double by single
          SEQ
            Quot [1],  U [1] := LONGDIV ( 0,  Dvd [1],  Dvsr [0])
            Quot [0],  Rem [0] := LONGDIV ( U [1],  Dvd [0],  Dvsr [0])
            Rem [1] := 0
        --}}}
        --{{{  TRUE
        TRUE                              --double by double
          SEQ
            Count,  V [1],  V [0] := NORMALISE ( Dvsr [1],  Dvsr [0])
            IF
              --{{{  Count = 0
              Count = 0                   --already normalised
                SEQ
                  U [2] := 0
                  U [1] := Dvd [1]
                  U [0] := Dvd [0]
              --}}}
              --{{{  TRUE
              TRUE                        --shift dividend too
                SEQ
                  U [2],  X := SHIFTLEFT ( 0,  Dvd [1],  Count)
                  U [1],  U [0] := SHIFTLEFT ( Dvd [1],  Dvd [0],  Count)
              --}}}
            Quot [1] := 0
            IF                            --last digit place
              --{{{  U[2] = V[1]
              U [2] = V [1]
                Quot [0] := MaxInt
              --}}}
              --{{{  TRUE
              TRUE
                Quot [0],  X := LONGDIV ( U [2],  U [1],  V [1])
              --}}}
            IF
              --{{{  Quot [0] <> 0
              Quot [0] <> 0
                SEQ                       --evaluate in case overflow
                  W [1],  W [0] := LONGPROD ( Quot [0],  V [0],  0)
                  W [2],  W [1] := LONGPROD ( Quot [0],  V [1],  W [1])
                  X,  U [0] := LONGDIFF ( U [0],  W [0],  0)
                  X,  U [1] := LONGDIFF ( U [1],  W [1],  X)
                  X,  U [2] := LONGDIFF ( U [2],  W [2],  X)
                  WHILE (U [2] /\ SignBit) <> 0         --add back as required
                    SEQ
                      Quot [0] := Quot [0] - 1
                      X,  U [0] := LONGSUM ( U [0],  V [0],  0)
                      X,  U [1] := LONGSUM ( U [1],  V [1],  X)
                      X,  U [2] := LONGSUM ( U [2],  0,  X)
              --}}}
              --{{{  TRUE
              TRUE
                SKIP
              --}}}
            IF
              --{{{  Count = 0
              Count = 0
                SEQ
                  Rem [0] := U [0]
                  Rem [1] := U [1]
              --}}}
              --{{{  TRUE
              TRUE
                Rem [1],  Rem [0] := SHIFTRIGHT ( U [1],  U [0],  Count)
              --}}}
        --}}}
    :
    --}}}
    [2]INT Quot RETYPES Quot :
    [2]INT Rem RETYPES Rem :
    VAL [2]INT Dvd RETYPES Dvd :
    VAL [2]INT Dvsr RETYPES Dvsr :
    INT Borrow :
    BOOL NegRem, NegQuot :
    [2] INT U :
    PLACE U IN WORKSPACE :
    [2] INT V :
    PLACE V IN WORKSPACE :
    SEQ
      --{{{  Test Dvd negative
      IF
        --{{{  Dvd negative
        (Dvd [1] /\ SignBit) <> 0          --sort out signs
          SEQ
            NegRem := TRUE
            Borrow,  U [0] := LONGDIFF ( 0,  Dvd [0],  0)
            Borrow,  U [1] := LONGDIFF ( 0,  Dvd [1],  Borrow)
        --}}}
        --{{{  Dvd zero or positive
        TRUE
          SEQ
            NegRem := FALSE
            U [0] := Dvd [0]
            U [1] := Dvd [1]
        --}}}
      --}}}
      --{{{  Test Dvsr negative
      IF
        --{{{  Dvsr negative
        (Dvsr [1] /\ SignBit) <> 0
          SEQ
            NegQuot := NOT NegRem
            Borrow,  V [0] := LONGDIFF ( 0,  Dvsr [0],  0)
            Borrow,  V [1] := LONGDIFF ( 0,  Dvsr [1],  Borrow)
        --}}}
        --{{{  Dvsr zero or positive
        TRUE
          SEQ
            NegQuot := NegRem
            V [0] := Dvsr [0]
            V [1] := Dvsr [1]
        --}}}
      --}}}
      INT32UnsDiv (Quot, Rem, U, V)
      --{{{  Check if result has negative quotient
      IF
        --{{{  NegQuot
        NegQuot
          SEQ
            Borrow,  Quot [0] := LONGDIFF ( 0,  Quot [0],  0)
            Borrow,  Quot [1] := LONGDIFF ( 0,  Quot [1],  Borrow)
        --}}}
        --{{{  TRUE
        TRUE
          SKIP
        --}}}
      --}}}
      --{{{  Check if result has negative remainder
      IF
        --{{{  NegRem
        NegRem
          SEQ
            Borrow,  Rem [0] := LONGDIFF ( 0,  Rem [0],  0)
            Borrow,  Rem [1] := LONGDIFF ( 0,  Rem [1],  Borrow)
        --}}}
        --{{{  TRUE
        TRUE
          SKIP
        --}}}
      --}}}
    RESULT Quot, Rem
:
--}}}
--}}}

--{{{  INT32DIV
--{{{  INT32DIV -- T2
INT32 FUNCTION INT32DIV (VAL INT32 Dvd, VAL INT32 Dvsr)

  --  Function version (10 Jun 87)

  INT32 Quot :
  VALOF
    SEQ
      --{{{  CAUSEERROR if overflow (MinInt/-1)
      IF
        --{{{  CAUSEERROR if overflow: (MOSTNEG INT32) / -1
        (Dvd = (MOSTNEG INT32)) AND (Dvsr = (-1(INT32)))
          CAUSEERROR() -- answer not expressible in two's complement
        --}}}
        --{{{  TRUE
        TRUE
          SKIP
        --}}}
      --}}}
      INT32 Dummy :
      Quot, Dummy := INT32DIVREM (Dvd, Dvsr)
    RESULT Quot
:
--}}}
--}}}

--{{{  INT32REM
--{{{  INT32REM -- T2
INT32 FUNCTION INT32REM (VAL INT32 Dvd, VAL INT32 Dvsr)

  --  Function version (10 Jun 87)

  INT32 Rem :
  VALOF
    INT32 Dummy :
    Dummy, Rem := INT32DIVREM (Dvd, Dvsr)
    RESULT Rem
:
--}}}
--}}}

#ENDIF
