* Query on portable bit extraction @ 2001-10-26 16:49 Mark Johnson 2001-10-26 17:08 ` Lutz Donnerhacke 2001-10-27 0:06 ` Jeffrey Carter 0 siblings, 2 replies; 9+ messages in thread From: Mark Johnson @ 2001-10-26 16:49 UTC (permalink / raw) We have code that we want to run on both a big (sgi) and little (pc) endian machine. As an example, the layout of the data in memory is... [big_endian bit order] Byte 0 1 2 3 4 5 6 7 21 - X X X Y Y Y Y Y 22 - Y Y Z Z Z Z Z Z where we need to extract XXX as the "wait code", YYYYYYY as the "value", and ZZZZZZ is a pad area (don't care). On the big endian machine it was coded like this... Wait := (byte 21) / 2**5; T1 := (move bytes from bytes 21 & 22) T2 := T1 / 2**6; T1 := T2 / 2**7; T1 := T1 * 2**7; Value := T2-T1; which won't work on the PC unless we swap the bytes in the first assignment to T1 and looks ugly as all get out. Thinking of records & representation specifications, I'd like to be able to do something like this... subtype Wv is Natural range 0..7; subtype Vv is Natural range 0..127; subtype Pv is Natural range 0..63; type Wait_Value is record Wait : Wv; Value : Vv; Pad : Pv; end record; for Wait_Value use record Wait at 0 range 0..2; Value at 0 range 3..9; Pad at 1 range 2..7; end record; for Wait_Value'Bit_Order use System.High_Order_First; which looks pretty reasonable until I get the following GNAT error messages on the PC... error: attempt to specify non-contiguous field not permitted error: (caused by non-standard Bit_Order specified) Hmm. After drawing it out on the white board - sure enough, the bits are not contiguous, a byte swap is needed. Assuming I do a byte swap somewhere, I recode the representation specification to be... for Wait_Value use record Wait at 1 range 5..7; Value at 0 range 6..12; Pad at 0 range 0..5; end record; (assuming System.Low_Order_First bit order) which works as expected. So - I can probably code up a portable version based on... - byte swap or not based on System.Default_Bit_Order - representation specification also based on System.Default_Bit_Order but is this the best way to do it or should I stick w/ the original code? Thanks. --Mark Johnson <mailto:Mark_H_Johnson@Raytheon.com> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Query on portable bit extraction 2001-10-26 16:49 Query on portable bit extraction Mark Johnson @ 2001-10-26 17:08 ` Lutz Donnerhacke 2001-10-27 0:06 ` Jeffrey Carter 1 sibling, 0 replies; 9+ messages in thread From: Lutz Donnerhacke @ 2001-10-26 17:08 UTC (permalink / raw) * Mark Johnson wrote: >We have code that we want to run on both a big (sgi) and little (pc) >endian machine. As an example, the layout of the data in memory is... >[big_endian bit order] >Byte 0 1 2 3 4 5 6 7 >21 - X X X Y Y Y Y Y >22 - Y Y Z Z Z Z Z Z >where we need to extract XXX as the "wait code", YYYYYYY as the "value", >and ZZZZZZ is a pad area (don't care). >Thinking of records & representation specifications, I'd like to be able >to do something like this... > subtype Wv is Natural range 0..7; > subtype Vv is Natural range 0..127; > subtype Pv is Natural range 0..63; > type Wait_Value is > record > Wait : Wv; > Value : Vv; > Pad : Pv; > end record; > for Wait_Value use > record > Wait at 0 range 0..2; > Value at 0 range 3..9; > Pad at 1 range 2..7; > end record; > for Wait_Value'Bit_Order use System.High_Order_First; Incorrect code: Value does cross a Storage_Element boundary. Split it into two parts and combine them later. Example: http://www.iks-jena.de/mitarb/lutz/ada/net/ --> i.e. IPV4 Header >which looks pretty reasonable until I get the following GNAT error >messages on the PC... > error: attempt to specify non-contiguous field not permitted > error: (caused by non-standard Bit_Order specified) Correct. for xx'Bit_Order use ... does only define the direction of counting. It does not swap or correct alignments. >somewhere, I recode the representation specification to be... > for Wait_Value use > record > Wait at 1 range 5..7; > Value at 0 range 6..12; > Pad at 0 range 0..5; > end record; >(assuming System.Low_Order_First bit order) which works as expected. On both systems? Very strange. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Query on portable bit extraction 2001-10-26 16:49 Query on portable bit extraction Mark Johnson 2001-10-26 17:08 ` Lutz Donnerhacke @ 2001-10-27 0:06 ` Jeffrey Carter 2001-10-27 4:23 ` Steven Deller 1 sibling, 1 reply; 9+ messages in thread From: Jeffrey Carter @ 2001-10-27 0:06 UTC (permalink / raw) I would recommend using a collection of bytes and ensuring that the same bytes contain the same values on all platforms. Then extract the desired parts of the desired bytes, combining them as required. You can also, if you're sure the same bytes have the same values, combine bytes into larger values using type conversions and shifts or multiplications: T1 := Shift_Left (Unsigned_16 (Byte_21), 8) or Unsigned_16 (Byte_22); T2 := Shift_Right (T1, 6) and 2#0111_1111#; -- YYY_YYYY Both work correctly regardless of endianness; -- Jeff Carter "I wave my private parts at your aunties." Monty Python & the Holy Grail ^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: Query on portable bit extraction 2001-10-27 0:06 ` Jeffrey Carter @ 2001-10-27 4:23 ` Steven Deller 2001-10-27 16:31 ` Nick Roberts 0 siblings, 1 reply; 9+ messages in thread From: Steven Deller @ 2001-10-27 4:23 UTC (permalink / raw) To: comp.lang.ada The issue with byte ordering actually has more to do with how you got the data. If you get the data as a byte stream and define an array of bytes, then the only issue is bit order within each byte. On the other hand, if you get the data 4-bytes at a time "in parallel", you will need to do byte swapping to get the fields to be adjacent. If you get the data one-bit at a time, then no byte swapping is needed and fields will always be adjacent bits, regardless of the architecture. I'm *guessing* that for the problem at hand, you received the data byte by byte on a little-endian machine where you *defined* adjacent bits (across bytes) using little-endian definitions of what it means to cross a byte boundary. If you now take that data 4-bytes at a time and send that to big-endian machine, you will have to do byte swapping (end for end) across the word to get fields that are adjacent (and if fields cross 4-byte boundaries, you will have to do word swapping). Once you have done that, you need only count in the correct direction to see the fields. Its hard to describe in email, but you can probably figure it out if you realize that size of units when exchanging data determines what type of byte swapping is necessary (none, 2-byte pairs, 4-byte quads, 8-byte octets, etc). That is why this is a hard problem. There is no *general* solution until you know your channel width. Regards, Steve > -----Original Message----- > From: comp.lang.ada-admin@ada.eu.org > [mailto:comp.lang.ada-admin@ada.eu.org] On Behalf Of Jeffrey Carter > Sent: Friday, October 26, 2001 8:07 PM > To: comp.lang.ada@ada.eu.org > Subject: Re: Query on portable bit extraction > > > I would recommend using a collection of bytes and ensuring > that the same bytes contain the same values on all platforms. > Then extract the desired parts of the desired bytes, > combining them as required. > > You can also, if you're sure the same bytes have the same > values, combine bytes into larger values using type > conversions and shifts or > multiplications: > > T1 := Shift_Left (Unsigned_16 (Byte_21), 8) or Unsigned_16 > (Byte_22); T2 := Shift_Right (T1, 6) and 2#0111_1111#; -- YYY_YYYY > > Both work correctly regardless of endianness; > > -- > Jeff Carter > "I wave my private parts at your aunties." > Monty Python & the Holy Grail > _______________________________________________ > comp.lang.ada mailing list > comp.lang.ada@ada.eu.org > http://ada.eu.org/mailman/listinfo/comp.lang.ad> a ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Query on portable bit extraction 2001-10-27 4:23 ` Steven Deller @ 2001-10-27 16:31 ` Nick Roberts 2001-10-28 1:30 ` Jeffrey Carter 2001-10-29 1:25 ` Query on portable bit extraction Robert Dewar 0 siblings, 2 replies; 9+ messages in thread From: Nick Roberts @ 2001-10-27 16:31 UTC (permalink / raw) To be frank, I think RM95 13.5.3 shows confusion as to what 'big-endian' and 'little-endian' really mean. The RM speaks in terms of storage elements, but these Swiftian terms - although always informal - have really always referred to the order of bytes (not bits). A big-endian machine's (16-bit, 32-bit, and sometimes 64-bit) integers have the most significant byte at the lower/lowest address; a little-endian machine's integers have the least significant byte at the lower/lowest address. I think the terms don't sensibly apply to machines whose Storage_Unit is not a multiple of 8. I think those machines whose Storage_Unit is 16, 32, or 64 can be treated as big-endian if they read bytes from byte-oriented peripherals in the order most significant byte first. The AARM (13.5.3 (5.b)) wants to imply that on a big-endian 32-bit machine with byte memory addressing, bit 0 of byte 3 (the lowest addressed and most significant byte) is the most significant bit (bit 31) of the word. This is wrong! By every convention I've ever come across, bit 0 of byte 3 is always interpreted as bit 24 of the word; it is bit 7 of byte 3 that is bit 31 of the word. I believe the documentation of processor manufacturers will bear this out. In other words, ALL architectures (both big-endian and little-endian) are in fact Low_Order_First. AI95-133 confirm's this thread's view that the Bit_Order attribute is purely about how to interpret bit numbers in a record representation clause. As such, I'm afraid I think it was misconceived. There's no need for it on any machine, and it doesn't solve the problem that needs solving (that of big and little endianness). Does anyone have an example where Bit_Order was actually useful (or vital)? Perhaps the next revision could introduce a representation attribute Octet_Order, which would only apply to discrete types of a size which is a multiple of 8 and greater than 8 (and would have nothing to do with record representation clauses). The System package would define: type Octet_Order is (Low_Octet_First, High_Octet_First); Default_Octet_Order: constant Octet_Order; Although I am pretty certain about my comments in this case, I seem to be prone to egregious error at times, so please someone put me out of your misery if I have committed another blunder. Should I send a comment to ada-comment about this? Another facility that I believe would be useful would be to be able to specify multiple places for a component in a record representation clause. Engineers (being engineers, poor devils ;-) often like to split up a field returned by their equipment into lots of little pieces dotted around all over the place. E.g.: type Table_Descriptor is record Limit: Unsigned_20; Base: Unsigned_32; Typ: Descriptor_Type; Is_Segment: Boolean; DPL: Privilege_Level; Is_Present: Boolean; Is_32_Bit: Boolean; Is_Coarse: Boolean; end record; pragma Assert(System.Storage_Size = 8); for Table_Descriptor use record Limit at all (0..7 => 0 range 0..7, 8..15 => 1 range 0..7, 16..19 => 6 range 0..3); Base at all (0..7 => 2 range 0..7, 8..15 => 3 range 0..7, 16..23 => 4 range 0..7, 24..31 => 7 range 0..7); Typ at 5 range 0..4; ... end record; This suggested syntax may not be the best way to do it. Implementations could impose a limit on the number of different places specifiable for one component. As per the AARM, the storage place attributes would not apply to discontiguous components. -- Nick Roberts "Steven Deller" <deller@smsail.com> wrote in message news:mailman.1004156810.28692.comp.lang.ada@ada.eu.org... > The issue with byte ordering actually has more to do with how you got > the data. If you get the data as a byte stream and define an array of > bytes, then the only issue is bit order within each byte. On the other > hand, if you get the data 4-bytes at a time "in parallel", you will need > to do byte swapping to get the fields to be adjacent. If you get the > data one-bit at a time, then no byte swapping is needed and fields will > always be adjacent bits, regardless of the architecture. > > I'm *guessing* that for the problem at hand, you received the data byte > by byte on a little-endian machine where you *defined* adjacent bits > (across bytes) using little-endian definitions of what it means to cross > a byte boundary. If you now take that data 4-bytes at a time and send > that to big-endian machine, you will have to do byte swapping (end for > end) across the word to get fields that are adjacent (and if fields > cross 4-byte boundaries, you will have to do word swapping). Once you > have done that, you need only count in the correct direction to see the > fields. > > Its hard to describe in email, but you can probably figure it out if you > realize that size of units when exchanging data determines what type of > byte swapping is necessary (none, 2-byte pairs, 4-byte quads, 8-byte > octets, etc). > > That is why this is a hard problem. There is no *general* solution > until you know your channel width. > > Regards, > Steve > > > -----Original Message----- > > From: comp.lang.ada-admin@ada.eu.org > > [mailto:comp.lang.ada-admin@ada.eu.org] On Behalf Of Jeffrey Carter > > Sent: Friday, October 26, 2001 8:07 PM > > To: comp.lang.ada@ada.eu.org > > Subject: Re: Query on portable bit extraction > > > > > > I would recommend using a collection of bytes and ensuring > > that the same bytes contain the same values on all platforms. > > Then extract the desired parts of the desired bytes, > > combining them as required. > > > > You can also, if you're sure the same bytes have the same > > values, combine bytes into larger values using type > > conversions and shifts or > > multiplications: > > > > T1 := Shift_Left (Unsigned_16 (Byte_21), 8) or Unsigned_16 > > (Byte_22); T2 := Shift_Right (T1, 6) and 2#0111_1111#; -- YYY_YYYY > > > > Both work correctly regardless of endianness; > > > > -- > > Jeff Carter > > "I wave my private parts at your aunties." > > Monty Python & the Holy Grail > > _______________________________________________ > > comp.lang.ada mailing list > > comp.lang.ada@ada.eu.org > > http://ada.eu.org/mailman/listinfo/comp.lang.ad> a > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Query on portable bit extraction 2001-10-27 16:31 ` Nick Roberts @ 2001-10-28 1:30 ` Jeffrey Carter 2001-10-28 19:07 ` Bit_Order useful [was Query on portable bit extraction] Nick Roberts 2001-10-29 1:25 ` Query on portable bit extraction Robert Dewar 1 sibling, 1 reply; 9+ messages in thread From: Jeffrey Carter @ 2001-10-28 1:30 UTC (permalink / raw) Nick Roberts wrote: > > AI95-133 confirm's this thread's view that the Bit_Order attribute is purely > about how to interpret bit numbers in a record representation clause. As > such, I'm afraid I think it was misconceived. There's no need for it on any > machine, and it doesn't solve the problem that needs solving (that of big > and little endianness). Does anyone have an example where Bit_Order was > actually useful (or vital)? I think you're mistaken. I recall (a) processor(s?) on which bit 1 was the MSB and bit 8 the LSB of a byte. Many big-endian machines use lowest bit # = MSB. -- Jeff Carter "I unclog my nose towards you." Monty Python & the Holy Grail ^ permalink raw reply [flat|nested] 9+ messages in thread
* Bit_Order useful [was Query on portable bit extraction] 2001-10-28 1:30 ` Jeffrey Carter @ 2001-10-28 19:07 ` Nick Roberts 2001-10-29 1:23 ` Robert Dewar 0 siblings, 1 reply; 9+ messages in thread From: Nick Roberts @ 2001-10-28 19:07 UTC (permalink / raw) I know there are some big-endian machines (the more recent ones, perhaps) whose manufacturers' documentation number the LSB as 0 and the MSB as 31 or 63. Maybe some of the older ones are as Jeff suggests, although this scheme strikes me as weird mathematically: doesn't it make sense to have a bit numbering where the value of bit n (that it contributes, when it is 1, to the value of the integer it is part of) is 2^n? In fact, having said that, I think I've managed to convince myself that Bit_Order is useful anyway. In the RFCs, the sformat of the IP, TCP, UDP etc headers are (mostly?) defined in terms of 32-bit words, and the bit numbers in the diagrams have bit 0 as the MSB and 31 as the LSB. I guess the RFCs can't be considered too esoteric, and in this case Bit_Order helps one to make the definition of a record representation clause, e.g.: type IP_Header is record Version: ... IHL: ... ToS: ... Length: ... Ident: ... Flags: ... Offset: ... TTL: ... Protocol: ... Checksum: ... Source: Internet_Address; Destination: Internet_Address; end record; for IP_Header'Bit_Order use High_Order_First; W32: constant := 32 / System.Storage_Unit; pragma Assert(System.Storage_Unit mod 8 = 0); for IP_Header use record Version at W32*0 range 0..3; IHL at W32*0 range 4..7; ToS at W32*0 range 8..15; Length at W32*0 range 16..31; Ident at W32*1 range 0..15; Flags at W32*1 range 16..18; Offset at W32*1 range 19..31; TTL at W32*2 range 0..7; ... end record; And I think this clause will work on any implementation regardless of its default bit order, and provided its storage unit is a multiple of 8. Useful enough for me. Again, someone please say if I'm wrong about this, having just proved once again that I (often :-) make mistakes. Otherwise, my apologies. May I please emphasise that my criticism was not malicious (and never is). Finally, there's still a need (in terms of significant convenience) for something like my proposed Octet_Order isn't there? PS: Bit_Order doesn't solve the problem of a 1-based bit numbering scheme. Do we need a Bit_Numbering_Base? -- Nick Roberts "Jeffrey Carter" <jrcarter@acm.org> wrote in message news:3BDB5FB6.94899C3C@acm.org... > Nick Roberts wrote: > > > > AI95-133 confirm's this thread's view that the Bit_Order attribute is purely > > about how to interpret bit numbers in a record representation clause. As > > such, I'm afraid I think it was misconceived. There's no need for it on any > > machine, and it doesn't solve the problem that needs solving (that of big > > and little endianness). Does anyone have an example where Bit_Order was > > actually useful (or vital)? > > I think you're mistaken. I recall (a) processor(s?) on which bit 1 was > the MSB and bit 8 the LSB of a byte. Many big-endian machines use lowest > bit # = MSB. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Bit_Order useful [was Query on portable bit extraction] 2001-10-28 19:07 ` Bit_Order useful [was Query on portable bit extraction] Nick Roberts @ 2001-10-29 1:23 ` Robert Dewar 0 siblings, 0 replies; 9+ messages in thread From: Robert Dewar @ 2001-10-29 1:23 UTC (permalink / raw) "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message news:<9rhlhr$u11j3$1@ID-25716.news.dfncis.de>... > I know there are some big-endian machines (the more recent ones, perhaps) > whose manufacturers' documentation number the LSB as 0 and the MSB as 31 or > 63. This is highly confused if it happens. Bit numbering must match byte ordering, or you get into a mess. The 68K was notoriously messed up on this point (see the discussion of this point in my book on microprocessors). Certainly in Ada, the bit numbering should match the byte ordering, or you will end up with non-contiguous fields and a big mess. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Query on portable bit extraction 2001-10-27 16:31 ` Nick Roberts 2001-10-28 1:30 ` Jeffrey Carter @ 2001-10-29 1:25 ` Robert Dewar 1 sibling, 0 replies; 9+ messages in thread From: Robert Dewar @ 2001-10-29 1:25 UTC (permalink / raw) "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message news:<9req9o$tlsg8$1@ID-25716.news.dfncis.de>... > Should I send a comment to ada-comment about this? Not before carefully checking the archives for previous discussions, or you will just recycle. For sure you need to read Norm Cohen's article. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2001-10-29 1:25 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-10-26 16:49 Query on portable bit extraction Mark Johnson 2001-10-26 17:08 ` Lutz Donnerhacke 2001-10-27 0:06 ` Jeffrey Carter 2001-10-27 4:23 ` Steven Deller 2001-10-27 16:31 ` Nick Roberts 2001-10-28 1:30 ` Jeffrey Carter 2001-10-28 19:07 ` Bit_Order useful [was Query on portable bit extraction] Nick Roberts 2001-10-29 1:23 ` Robert Dewar 2001-10-29 1:25 ` Query on portable bit extraction Robert Dewar
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox