skubi%decprl.DEC@DECWRL.DEC.COM (05/12/89)
Cc: Gnu C should differentiate between ordinary RAM cells and hardware registers mapped into (virtual or not) memory. THE PROBLEM I would like to suggest you a feature which seems to be necessary if you want to write hardware drivers in optimized Gnu C. When a program is optimized, the compiler performs a data flow analyzis which makes certain variables not to be read/written the number of times requested by the programmer. This is very suitable when the variable is a true RAM word, but it changes the program semantics when the variable addresses a hardware register mapped into virtual memory. Example: do { res_brut = *adr; } while (res_brut & 0x60000); waits until a particular bit of a hardware device becomes equal to 0. And, if I understand well your documentation, gcc considers it as equivalent to: res_brut = *adr; do { } while (res_brut & 0x60000); which is a non-sense. So, following your specifications, I have no way to get sure that my hadware driver will be compiled correctly by "gcc -O". WHAT IS REQUIRED In the program optimization, the compiler should consider accessing hardware registers exactly as it considers calls to functions (other than so-called constant functions): A hardware register access has side effects and its value appears different each time it is read. A SOLUTION It should be possible to qualify any type as "hardware". For instance, we could have "unsigned long int" as well as "hardware unsigned long int" variables. "hardware" and ordinary types would follow exactly the same rules, except for optimisation: the data flow analyzer would consider reading and writing of hardware values as special, the compiler would not permute or remove such operations. Examples: /* the example above, modified */ hardware long int adr*; do { res_brut = *adr; } while (res_brut & 0x60000); /* when the device's address is known in advance */ * ((hardware unsigned char *)0x123456) = 'a'; if * ((hardware unsigned char *)0x123456) printf ("error\n"); /* when the device's address is computed in a complicated way: array contains the addresses of a few 2-word hardware registers. */ static hardware long int *(array[5]); int i; for (i=0; i<5; i++) { array [i][0] = 0; array [i][1] = 1; } /* typeof (array [i][0]) = hardware long int */ Friendly, Marcin Skubiszewski. skubi@decprl.dec.com PS. Best wishes to GNU software, which is excellent.
grunwald@flute.cs.uiuc.edu (05/12/89)
substitute ``volatile'' for ``hardware'' and check the Gnu C manual - this feature already exists, and is ANSI C standard. -- Dirk Grunwald Univ. of Illinois grunwald@flute.cs.uiuc.edu
mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) (05/12/89)
In article <8905111829.AA18182@decwrl.dec.com> skubi%decprl.DEC@DECWRL.DEC.COM writes: >Gnu C should differentiate between ordinary RAM cells and hardware registers >mapped into (virtual or not) memory. > >Examples: > > /* the example above, modified */ > hardware long int adr*; > do { > res_brut = *adr; > } while (res_brut & 0x60000); The example that you gave is precisely the reason that the ANSI X3J11 commitee added the "volatile" keyword. Volatile is to be used when the compiler should not optimize away variable references since they may be required to latch devices, or to read constantly changing memory. I think that if you change your example above to read: volatile long int *adr; do { res_brut = *adr; } while (res_brut & 0x60000); You will get the results that you want. -- Mark H. Colburn mark@jhereg.mn.org Minnetech Consulting, Inc.
brooks@vette.llnl.gov (Eugene Brooks) (05/13/89)
In article <8905111829.AA18182@decwrl.dec.com> skubi%decprl.DEC@DECWRL.DEC.COM writes: >Cc: > > >Gnu C should differentiate between ordinary RAM cells and hardware registers >mapped into (virtual or not) memory. Try using the ANSI C keyword volatile, this is what it is there for. brooks@maddog.llnl.gov, brooks@maddog.uucp
stripes@wam.UMD.EDU (05/24/89)
> >substitute ``volatile'' for ``hardware'' and check the Gnu C manual - >this feature already exists, and is ANSI C standard. >-- >Dirk Grunwald >Univ. of Illinois >grunwald@flute.cs.uiuc.edu I have been looking over an ANSI C book from the Waite Group (I forget the name, it's very small and is a kind-of refrence). Anyway it says that volatile registers are NOT restored after a longjmp(), nor are register variables, but auto variables are. GCC documation seems to say that only volatile variables are restored. Do I understand the GCC docs correctly? Is the Waite Group book wrong, or is GCC, or what? -- stripes@wam.umd.edu Josh_Osborne@Real_World,The "The dyslexic porgramer"