From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=BAYES_00,INVALID_MSGID, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,251afb8f1c322bf0 X-Google-Attributes: gid103376,public From: dkristol@see-my.sig (David Kristola) Subject: Memory mapped registers (was Re: Caching & Annex C.6) Date: 1999/09/09 Message-ID: <7r7ljl$sdi6@svlss.lmms.lmco.com>#1/1 X-Deja-AN: 522844738 Distribution: world References: <7r5mb7$c4d$1@nnrp1.deja.com> Organization: heaps of stacks Reply-To: dkristol@see-my.sig Newsgroups: comp.lang.ada Date: 1999-09-09T00:00:00+00:00 List-Id: In article 1@nnrp1.deja.com, Robert Dewar () writes: >In article <7r4ted$e892@svlss.lmms.lmco.com>, > dkristol@see-my.sig wrote: >> This eliminated >> the compiler's optimization which inadvertently read and >> wrote bytes on either side of the register. Those bytes >> happened to be parts of other registers, and the hardware >> did not handle byte access properly. That particular bug >> took a while to track down. > >That is not an optimization, it is a perfectly reasonable >and valid translation of the Ada code. It is always very >risky, and very implementation dependent, to assume you >know exactly what machine instructions the compiler will >generate for a given construct. A 32 bit record was located on a proper word boundary, and the compiler generated (MIPS) instructions to read 4 bytes from two different words (LWL, LWR if i remember the mnemonic correctly) so that it could save a shift to get to the bit it was interested in (it shifted the address instead). It may not have been an optimization. As far as i could tell, it was a less efficient way to get the desired bit from and then back out to memory. >If you need an exact load/store instruction, it is really >much more appropriate to use an asm insertion to specify >the exact instruction you need, rather than coax the >compiler into generating the instruction you want. The >latter is often highly non-portable, and can introduce >insufficiently documented implementation dependencies >in innocent looking code. Who would think that > > A := 0; > >could be a highly target dependent piece of code? Memory_Mapped_Register := Convert(Register_Record); The name and purpose of the package would give away the fact that it is not portable code. How many serial I/O boards (made for our program's concept of RS-422) are made equal? >One of the worst cases I saw of this was the following, >someone had: > Size : integer := 31; > ... > type x is array (0 .. Size) of Boolean; > pragma Pack (x); > for x use at bla bla; > >so far, so good, a typical memory mapped I/O specification. > >The code had things like > > Status := x (13); > >This worked fine on compiler V, but blew up on GNAT. Why? >Because on the machine in question there were both word >and byte loads and stores, neither being particularly >preferred. > > Compiler V did a word load and a bit mask. > GNAT did a byte load and a bit mask > >But the hardware had been built only to recognize word loads, >and it blew up at the hardware level for a byte load, delivering >random data to the bus (wonderful eh?) Been there, stepped through it in a debugger or watched it on the DAS, scratched my head, but never got the T-shirt. >Needless to say this was hard to find. The kludge put in to fix >this was to make the size constant, in which case GNAT now knows >that the variable in question is exactly 32 bits long, and >happens to do a word load, but this is really a very brittle >way of "fixing" this. Much better would be to issue the exact >instruction required. I suppose i could have come up with a generic to read/write 32 bit registers and had the body explicitly perform the correct assembly code, then instantiate it for all of the different registers. Would this be portable from compiler to compiler? >That being said, the suggestion of using integer is probably >a good one, and this wlil likely minimize the possibility of >unexpected code generation. Integers are atomic, and of the proper size. It did work well with that compiler (probably "V"). ><< That particular bug took a while to track down >> > >Yes, indeed bugs like this in Ada code are devilish hard >to find. And all too often people decide that their code >cannot be at fault because it worked once upon a time. We >have too often encountered situations where managers have >been sold on the fiction that because their code is in >Ada, it will be zero effort to port it to new platforms >or new compilers :-( My apologies to Bruce, it was his hardware, and i did blame him for a long time. In the end, it was excellent hardware. I wish we were reusing it on this project, it would solve one of my current dilemmas. Porting code is usually not an issue. There aren't too many uses for the special software/hardware that gets developed around here. There is a growing awareness of the usefulness of reuse, and an effort to actually start reusing software. Only it is a slow process. If more hardware were reused, there would be more call for software reuse. :-( --djk, keeper of arcane lore & trivial fluff Home: David95037 at aol dot com Spam: goto.hades@welovespam.com