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=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,7a58195927ccb785 X-Google-Attributes: gid103376,public From: dewar@merv.cs.nyu.edu (Robert Dewar) Subject: Re: Not intended for use in medical devices Date: 1997/05/10 Message-ID: #1/1 X-Deja-AN: 240537626 References: <3.0.32.19970504232023.006f5c8c@mail.4dcomm.com> <5kn99d$jje@top.mitre.org> Organization: New York University Newsgroups: comp.lang.ada Date: 1997-05-10T00:00:00+00:00 List-Id: Matthew Heaney said <> The safest way to do memory mapped I/O is to create appropriate abstractions, and then program them up using machine insertions so you get *exactly* the instructions you know you need. If you have a friendly Ada compiler that implements machine intrinsics and inlining in an effective manner (GNAT meets these requirements for example), then you do not introduce an efficiency penalty by doing this, and you KNOW exactly what you are getting. There are cases where the use of address clauses for memory mapped I/O make sense, a notable example is in mapping into the display buffer on the original IBM/PC. On the other hand, if you did this, without introducing an abstraction layer, you have a program that is unnecessarily hard to port to other environments. There are many reasons why address clauses were put in. Certainly MMIO was one motivation, but there are others, in particular mapping into system data structures at spsecific addresses (e.g. getting hold of the BIOS data area on a PC). The critical point here is that when you use address clauses for MMIO, youa are doing something that is inherently risky, you are assuming you know, and relying on your knowledge of, the exact way that the compiler will generate instructions for loads and stores. Let's give another example, suppose I have a byte that is memory mapped on an x86 x : character; for x'address use ... pragma Atomic (x); -- don't forget atomic if possible, or else volatile! now I am pretty safe in doing x := x + 1; and assuming byte load/store or am I???? A compiler aimed at the high end x86 might well decide that it is better to keep everything in 32 bits unless specified otherwise or when space is noticable as in arrays, so it might allocate 32 bits -- and we have yet another surprising portability disaster. OK, so put in the size clause, but let's change the example a bit: type xt is mod 2**8; x : xt; for x'address use ... pragma Atomic (x); for x'size use 8; and after that mouthful, we write: if (x and 2#0100#) then .. to test some status bit, and sure enough we get a nice byte load, which is what the hardware requires: but now we optimize and the program blows, why? because the optimizer now changes this to be a test bit instruction -- and the MMIO does not expect or react properly to this change because of some hardware peculiarity. Bottom line, it is true that address clauses and MMIO often go nicely together, but it is a good idea to wrap the access in inlined abstractions, rather than let them spread around the program, if you must use this combination.