comp.lang.ada
 help / color / mirror / Atom feed
* Rep Specs
@ 1996-10-07  0:00 Doug Shipler
  1996-10-08  0:00 ` Stephen Leake
  0 siblings, 1 reply; 6+ messages in thread
From: Doug Shipler @ 1996-10-07  0:00 UTC (permalink / raw)



I am using SunAda83 version 1.1k on a SunOS Sparc 5.  I have a record
that is rep speced into 32 bit long words.  One of the words is
split up into several fields, one is a 16 bit integer, and the
others are bit flags.  The interesting part is that when I try to
access one of the bit flags, the compiler fetches the wrong bit, it
gets a bit from the 16 bit integer field.  

In this example, Flag3 accesses a bit inside Value.

for My_Record_Typ use
     record at mod 32;
          Value at 0 * 4 range 16 .. 31;
          Flag1 at 0 * 4 range 15 .. 15;
          Flag2 at 0 * 4 range 13 .. 14;
          Unused1 at 0 * 4 range 10 .. 12;
          Flag3 at 0 * 4 range 9 .. 9;
          Flag4 at 0 * 4 range 8 .. 8;
          Unused2 at 0 * 4 range 4 .. 7;
          OtherVal at 0 * 4 range 0 .. 3;
          ........

Any ideas are greatly appreciated!




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Rep Specs
  1996-10-07  0:00 Rep Specs Doug Shipler
@ 1996-10-08  0:00 ` Stephen Leake
  1996-10-09  0:00   ` Rep Specs,endian,ncohen Peter Hermann
  1996-10-13  0:00   ` Rep Specs Robert Dewar
  0 siblings, 2 replies; 6+ messages in thread
From: Stephen Leake @ 1996-10-08  0:00 UTC (permalink / raw)



Doug Shipler wrote:
> 
> I am using SunAda83 version 1.1k on a SunOS Sparc 5.  I have a record
> that is rep speced into 32 bit long words.  One of the words is
> split up into several fields, one is a 16 bit integer, and the
> others are bit flags.  The interesting part is that when I try to
> access one of the bit flags, the compiler fetches the wrong bit, it
> gets a bit from the 16 bit integer field.
> 
> In this example, Flag3 accesses a bit inside Value.
> 
> for My_Record_Typ use
>      record at mod 32;
>           Value at 0 * 4 range 16 .. 31;
>           Flag1 at 0 * 4 range 15 .. 15;
>           Flag2 at 0 * 4 range 13 .. 14;
>           Unused1 at 0 * 4 range 10 .. 12;
>           Flag3 at 0 * 4 range 9 .. 9;
>           Flag4 at 0 * 4 range 8 .. 8;
>           Unused2 at 0 * 4 range 4 .. 7;
>           OtherVal at 0 * 4 range 0 .. 3;
>           ........
> 
> Any ideas are greatly appreciated!

I ran into a similar problem. The cause is that the Sparc is
little-bit-endian; it stores the least significant bit in the highest
numbered bit slot.

This is how I solved the problem in a (so far) portable way:

------------ for Intel/gnat ---------------
with System;
package Endianness
  -- Purpose:
  --    define constants to reflect hardware bit and word endianness in
  --    record representation clauses (in Ada83). Obviously, this file
is
  --    highly system-dependent (Ada95 solves this much more nicely!).
is
  -- this is for gnat on an Intel 386 compatible processor
  System_Name : System.NAME := System.SYSTEM_NAME_GNAT;

  Bit_Order : constant := 1;
  High_Bit_First : constant := 1;
  Low_Bit_First : constant := 0;
  MSBit : constant := 7;
  LSBit : constant := 0;

  type Byte_Order_Type is (BIG_ENDIAN, LITTLE_ENDIAN);
  Byte_Order : constant Byte_Order_Type := LITTLE_ENDIAN;

end Endianness;

------------------- for Sparc/SunAda --------------------
with System;

package Endianness

  -- Purpose:

  --    define constants to reflect hardware bit and word endianness in

  --    record representation clauses (in Ada83). Obviously, this file
is

  --    highly system-dependent (Ada95 solves this much more nicely!).

is

  -- this is for Sun (Verdix) Ada on a Sparc processor

  System_Name : System.NAME := System.SUN4_UNIX;



  Bit_Order : constant := -1;

  High_Bit_First : constant := 0;

  Low_Bit_First : constant := 1;

  MSBit : constant := 0;

  LSBit : constant := 7;



  type Byte_Order_Type is (BIG_ENDIAN, LITTLE_ENDIAN);

  Byte_Order : constant Byte_Order_Type := BIG_ENDIAN;



end Endianness;


Then, a rep clause looks like:
  type Out_Health_Flags_Type is record
    User_Ephemeris_Needed       : BOOLEAN;
    Approximate_GPS_Time_Needed : BOOLEAN;
    Self_Survey_Data_Needed     : BOOLEAN;
    Almanac_Not_Current         : BOOLEAN;
    Operational_Status          : OPERATIONAL_STATUS_TYPE;
  end record;
  for Out_Health_Flags_Type use record
    User_Ephemeris_Needed       at 0 
	range LSBit + Bit_Order * 0 .. LSBit + Bit_Order * 0;
    Approximate_GPS_Time_Needed at 0 
	range LSBit + Bit_Order * 1 .. LSBit + Bit_Order * 1;
    Self_Survey_Data_Needed     at 0 
	range LSBit + Bit_Order * 2 .. LSBit + Bit_Order * 2;
    Almanac_Not_Current         at 0 
	range LSBit + Bit_Order * 3 .. LSBit + Bit_Order * 3;
    Operational_Status          at 0 range
      High_Bit_First * (LSBit + Bit_Order * 4) +  
	Low_Bit_First * (LSBit + Bit_Order * 7) ..
      Low_Bit_First  * (LSBit + Bit_Order * 4) + 
	High_Bit_First * (LSBit + Bit_Order * 7);
  end record;
  for Out_Health_Flags_Type'Size use 8;

As long as you include the proper version of Endianness in your library,
the rep clause is correct for either little-bit-endian (Sparc) or
big-bit-endian (Intel).

Note that the issue of byte-endianness doesn't show up in the rep
clause; that's handled by the `at 0', as long as Storage_Unit is 8 bits.
Byte-endianness shows up when converting multi-byte values to byte
arrays:

  function To_2_Byte is new Unchecked_Conversion
    (TARGET => Byte_Array_2_Type,
     SOURCE => Geode_Types.INTEGER);

  procedure To_Network
    (Item : in Geode_Types.INTEGER;
     Buffer : out Geode_Types.BYTE_ARRAY;
     Last : in out Geode_Types.INTEGER)
  is
    use Geode_Types;
  begin
    case Byte_Order is
    when BIG_ENDIAN =>
      Buffer (Last+1  .. Last+2) := To_2_Byte (Item);
    when LITTLE_ENDIAN =>
      declare
        Temp : constant BYTE_ARRAY (1 .. 2) := To_2_Byte (Item);
      begin
        Buffer (Last+1) := Temp (2);
        Buffer (Last+2) := Temp (1);
      end;
    end case;
    Last := Last+2;
  end To_Network;

You MUST test this code for each compiler/hardware combination; some may
do the integer <> byte array unchecked conversion differently.

-- 
- Stephe




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Rep Specs,endian,ncohen
  1996-10-08  0:00 ` Stephen Leake
@ 1996-10-09  0:00   ` Peter Hermann
  1996-10-10  0:00     ` Norman H. Cohen
  1996-10-13  0:00   ` Rep Specs Robert Dewar
  1 sibling, 1 reply; 6+ messages in thread
From: Peter Hermann @ 1996-10-09  0:00 UTC (permalink / raw)



: I ran into a similar problem. The cause is that the Sparc is
: little-bit-endian; it stores the least significant bit in the highest
: numbered bit slot.
: This is how I solved the problem in a (so far) portable way:

I remember Norman H. Cohen has written an essay about the endian
/portability problem somewhere in AdaLetters(?).

--
Peter Hermann  Tel:+49-711-685-3611 Fax:3758 ph@csv.ica.uni-stuttgart.de
Pfaffenwaldring 27, 70569 Stuttgart Uni Computeranwendungen
Team Ada: "C'mon people let the world begin" (Paul McCartney)




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Rep Specs,endian,ncohen
  1996-10-09  0:00   ` Rep Specs,endian,ncohen Peter Hermann
@ 1996-10-10  0:00     ` Norman H. Cohen
  1996-10-11  0:00       ` Stephen Leake
  0 siblings, 1 reply; 6+ messages in thread
From: Norman H. Cohen @ 1996-10-10  0:00 UTC (permalink / raw)



Peter Hermann wrote:

> I remember Norman H. Cohen has written an essay about the endian
> /portability problem somewhere in AdaLetters(?).

"Endian-Independent Record Representation Clauses", Ada Letters XIV, No.
1 (January/February 1994), pp. 27-29

Stephen Leake's solution appears to be an instance of the approach
suggested in the article.  The article gives the general recipe for
constructing the component clauses.

Note that the problem being solved here is the porting of the source
text for record-representation clauses, NOT the run-time translation of
a byte stream from one endianness to another.

Please disregard the assertion in the article that this problem would be
solved in Ada 9X by an attribute definition clause for the 'Bit_Order
attribute.  The implementation advice in RM95-13.5.3(8) allows a
compiler to reject an attribute-definition clause for the nondefault bit
order in all the useful cases.  

Compilers are generally allowed to reject nondefault 'Bit_Order
definitions because the designers of Ada 95 believed that component
clauses interpreted according to the nondefault bit order could specify
noncontiguous bit fields, an implementation nightmare.  However, that
depends on how you interpret the meaning of a bit offset in a
nondefault-endian component clause.  If you insist that

   at B range 10 .. 12

be synonymous, assuming 8-bit bytes, with

   at B+1 range 2 .. 4

then you do indeed get noncontiguous bit fields.  But another
interpretation is to look at the highest bit number, say b, specified
with a given byte offset, and to view all component clauses with that
byte offset as specifying a contiguous range of bits within the
smallest  "loadable storage unit" (byte, halfword, word, or doubleword
on a typical 32-bit or 64-bit machine) having at least b+1 bits.  For
example, given the component clauses

   A at 0 range 0 .. 5;
   B at 0 range 6 .. 11;
   C at 0 range 12 .. 15;

and no other "at 0" component clauses, we would assume that A, B, and C
reside within a 16-bit loadable storage unit at offset 0, and that when
this 16-bit field is loaded into a register, B is a contiguous field of
bits somewhere in the middle of this 16-bit unit.  Whether A is at the
high-order end or the low-order end of the 16-bit unit depends on which
bit ordering applies to the record type, but either way, there is a
sensible interpretation with B specifying a field that is contiguous
when loaded.  

Given this interpretation of bit offsets, there is a one-to-one
correspondence between record representation clauses that specify a
given layout when interpreted as big-endian clauses and other record
representation clauses that specify the "same" layout when interpreted
as little-endian representation clauses.  (I explain below what I mean
when I say that layouts are the "same".)  Thus it would be practical to
require all compilers to support nondefault-endian record-representation
clauses, with an attribute-definition clause for T'Bit_Order determining
how the record-representation clause for type T is to be interpreted. 
This would solve the source portability problem by allowing the
programmer to arbitrarily specify a layout in his favorite bit order,
knowing that a compiler that is big-endian by default and a compiler
that is little-endian by default will interpret the
record-representation clause the "same" way.  

When I say that a layout on a big-endian machine and a layout on a
little-endian machine are the "same", I mean that the layout is divided
into "loadable storage units" with the same sizes and byte offsets, and
that the left-to-right bit position of each record component within
corresponding loadable storage units is the same.  These are the only
properties of a layout that can be usefully preserved among
opposite-endian machines.

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Rep Specs,endian,ncohen
  1996-10-10  0:00     ` Norman H. Cohen
@ 1996-10-11  0:00       ` Stephen Leake
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Leake @ 1996-10-11  0:00 UTC (permalink / raw)



Norman H. Cohen wrote:
> 
> Peter Hermann wrote:
> 
> > I remember Norman H. Cohen has written an essay about the endian
> > /portability problem somewhere in AdaLetters(?).
> 
> "Endian-Independent Record Representation Clauses", Ada Letters XIV, No.
> 1 (January/February 1994), pp. 27-29
> 
> Stephen Leake's solution appears to be an instance of the approach
> suggested in the article.  The article gives the general recipe for
> constructing the component clauses.

Yes, it is, and I apologize for not giving proper credit. I couldn't
remember where I had learned the technique!

-- 
- Stephe




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Rep Specs
  1996-10-08  0:00 ` Stephen Leake
  1996-10-09  0:00   ` Rep Specs,endian,ncohen Peter Hermann
@ 1996-10-13  0:00   ` Robert Dewar
  1 sibling, 0 replies; 6+ messages in thread
From: Robert Dewar @ 1996-10-13  0:00 UTC (permalink / raw)



Stephen Lake said, responding to Doug Shipler's problem:

  "I ran into a similar problem. The cause is that the Sparc is
  little-bit-endian; it stores the least significant bit in the highest
  numbered bit slot."

  and then follows a very contorted work around!

No, that's not the cause. The quoted code is quite correct, and should
work on either a little endian or big-endian machine. If it does not
you have run into a compiler bug. Your suggestion might be reasonable
as a work around, but we should not leave the impression that this
work around is neccessary on a correctly functioning Ada compiler!





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~1996-10-13  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-10-07  0:00 Rep Specs Doug Shipler
1996-10-08  0:00 ` Stephen Leake
1996-10-09  0:00   ` Rep Specs,endian,ncohen Peter Hermann
1996-10-10  0:00     ` Norman H. Cohen
1996-10-11  0:00       ` Stephen Leake
1996-10-13  0:00   ` Rep Specs Robert Dewar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox