File : s-bitops.adb


     ------------------------------------------------------------------------------
     --                                                                          --
     --                GNU ADA RUNTIME LIBRARY (GNARL) COMPONENTS                --
     --                                                                          --
   5 --                       S Y S T E M . B I T _ O P S                        --
     --                                                                          --
     --                                 B o d y                                  --
     --                                                                          --
     --                            $Revision: 1.10 $
  10 --                                                                          --
     --         Copyright (C) 1996-2000 Free Software Foundation, Inc.           --
     --                                                                          --
     -- GNAT is free software;  you can  redistribute it  and/or modify it under --
     -- terms of the  GNU General Public License as published  by the Free Soft- --
  15 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
     -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
     -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
     -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
     -- for  more details.  You should have  received  a copy of the GNU General --
  20 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
     -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
     -- MA 02111-1307, USA.                                                      --
     --                                                                          --
     -- As a special exception,  if other files  instantiate  generics from this --
  25 -- unit, or you link  this unit with other files  to produce an executable, --
     -- this  unit  does not  by itself cause  the resulting  executable  to  be --
     -- covered  by the  GNU  General  Public  License.  This exception does not --
     -- however invalidate  any other reasons why  the executable file  might be --
     -- covered by the  GNU Public License.                                      --
  30 --                                                                          --
     -- GNAT was originally developed  by the GNAT team at  New York University. --
     -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
     --                                                                          --
     ------------------------------------------------------------------------------
  35 
     with GNAT.Exceptions;       use GNAT.Exceptions;
     with System;                use System;
     with System.Unsigned_Types; use System.Unsigned_Types;
     with Unchecked_Conversion;
  40 
     package body System.Bit_Ops is
     
        subtype Bits_Array is System.Unsigned_Types.Packed_Bytes1 (Positive);
        --  Unconstrained array used to interprete the address values. We use the
  45    --  unaligned version always, since this will handle both the aligned and
        --  unaligned cases, and we always do these operations by bytes anyway.
        --  Note: we use a ones origin array here so that the computations of the
        --  length in bytes work correctly (give a non-negative value) for the
        --  case of zero length bit strings).
  50 
        type Bits is access Bits_Array;
        --  This is the actual type into which address values are converted
     
        function To_Bits is new Unchecked_Conversion (Address, Bits);
  55 
        LE : constant := Standard'Default_Bit_Order;
        --  Static constant set to 0 for big-endian, 1 for little-endian
     
        --  The following is an array of masks used to mask the final byte, either
  60    --  at the high end (big-endian case) or the low end (little-endian case).
     
        Masks : constant array (1 .. 7) of Packed_Byte := (
          (1 - LE) * 2#1000_0000# + LE * 2#0000_0001#,
          (1 - LE) * 2#1100_0000# + LE * 2#0000_0011#,
  65      (1 - LE) * 2#1110_0000# + LE * 2#0000_0111#,
          (1 - LE) * 2#1111_0000# + LE * 2#0000_1111#,
          (1 - LE) * 2#1111_1000# + LE * 2#0001_1111#,
          (1 - LE) * 2#1111_1100# + LE * 2#0011_1111#,
          (1 - LE) * 2#1111_1110# + LE * 2#0111_1111#);
  70 
     
        -----------------------
        -- Local Subprograms --
        -----------------------
  75 
        procedure Raise_Error;
        --  Raise Constraint_Error, complaining about unequal lengths
     
        -------------
  80    -- Bit_And --
        -------------
     
        procedure Bit_And
          (Left   : Address;
  85       Llen   : Natural;
           Right  : Address;
           Rlen   : Natural;
           Result : Address)
        is
  90       LeftB   : constant Bits := To_Bits (Left);
           RightB  : constant Bits := To_Bits (Right);
           ResultB : constant Bits := To_Bits (Result);
     
        begin
  95       if Llen /= Rlen then
              Raise_Error;
           end if;
     
           for J in 1 .. (Rlen + 7) / 8 loop
 100          ResultB (J) := LeftB (J) and RightB (J);
           end loop;
        end Bit_And;
     
        ------------
 105    -- Bit_Eq --
        ------------
     
        function Bit_Eq
          (Left  : Address;
 110       Llen  : Natural;
           Right : Address;
           Rlen  : Natural)
           return  Boolean
        is
 115       LeftB  : constant Bits := To_Bits (Left);
           RightB : constant Bits := To_Bits (Right);
     
        begin
           if Llen /= Rlen then
 120          return False;
     
           else
              declare
                 BLen : constant Natural := Llen / 8;
 125             Bitc : constant Natural := Llen mod 8;
     
              begin
                 if Llen /= Rlen then
                    return False;
 130 
                 elsif LeftB (1 .. BLen) /= RightB (1 .. BLen) then
                    return False;
     
                 elsif Bitc /= 0 then
 135                return
                      ((LeftB (BLen + 1) xor RightB (BLen + 1))
                        and Masks (Bitc)) = 0;
     
                 else -- Bitc = 0
 140                return True;
                 end if;
              end;
           end if;
        end Bit_Eq;
 145 
        -------------
        -- Bit_Not --
        -------------
     
 150    procedure Bit_Not
          (Opnd   : System.Address;
           Len    : Natural;
           Result : System.Address)
        is
 155       OpndB   : constant Bits := To_Bits (Opnd);
           ResultB : constant Bits := To_Bits (Result);
     
        begin
           for J in 1 .. (Len + 7) / 8 loop
 160          ResultB (J) := not OpndB (J);
           end loop;
        end Bit_Not;
     
        ------------
 165    -- Bit_Or --
        ------------
     
        procedure Bit_Or
          (Left   : Address;
 170       Llen   : Natural;
           Right  : Address;
           Rlen   : Natural;
           Result : Address)
        is
 175       LeftB   : constant Bits := To_Bits (Left);
           RightB  : constant Bits := To_Bits (Right);
           ResultB : constant Bits := To_Bits (Result);
     
        begin
 180       if Llen /= Rlen then
              Raise_Error;
           end if;
     
           for J in 1 .. (Rlen + 7) / 8 loop
 185          ResultB (J) := LeftB (J) or RightB (J);
           end loop;
        end Bit_Or;
     
        -------------
 190    -- Bit_Xor --
        -------------
     
        procedure Bit_Xor
          (Left   : Address;
 195       Llen   : Natural;
           Right  : Address;
           Rlen   : Natural;
           Result : Address)
        is
 200       LeftB   : constant Bits := To_Bits (Left);
           RightB  : constant Bits := To_Bits (Right);
           ResultB : constant Bits := To_Bits (Result);
     
        begin
 205       if Llen /= Rlen then
              Raise_Error;
           end if;
     
           for J in 1 .. (Rlen + 7) / 8 loop
 210          ResultB (J) := LeftB (J) xor RightB (J);
           end loop;
        end Bit_Xor;
     
        -----------------
 215    -- Raise_Error --
        -----------------
     
        procedure Raise_Error is
        begin
 220       Raise_Exception (CE, "unequal lengths in logical operation");
        end Raise_Error;
     
     end System.Bit_Ops;