comp.lang.ada
 help / color / mirror / Atom feed
From: daniel.dmk@googlemail.com
Subject: Re: Forcing GNAT to use 32-bit load/store instructions on ARM?
Date: Tue, 1 Jul 2014 12:52:25 -0700 (PDT)
Date: 2014-07-01T12:52:25-07:00	[thread overview]
Message-ID: <ca6f05d3-c469-4abc-92df-54aa605f41ba@googlegroups.com> (raw)
In-Reply-To: <lou82i$7u2$1@dont-email.me>

Thank you everyone for your suggestions and comments. 

On Tuesday, 1 July 2014 13:03:30 UTC+1, Simon Clubley  wrote:
> 
> In the general case, you need to initialise those reserved bits to known
> 
> values; to not do this is too dangerous. I always do this in C and if I
> 
> was doing embedded code in Ada I would do the same thing in Ada as well.

Thanks for this suggestion, I'll define the reserved bits in the register, and use static checks to enforce that they are not modified from their reset value in the code.

> > However, this makes it more "clunky" to use in my opinion. I would prefer to
> 
> > be able to modify the bits directly, and have the compiler always use 32-bit
> 
> > load/store instructions.
> 
> >
> 
> > Does anyone else have any ideas that I could try?
> 
> >
> 
> 
> 
> Pragma Atomic _should_ have given you the guarantee you needed.
> 
> Are you double checked how it's being used in the code ?

So I've set up a project to demonstrate only this problem. I've created a package called "Test" which contains the structure definition, and the definition of the register itself at the fixed address:

   with System;

   package Test is
      type Bits_1 is mod 2**1 with Size => 1;
      type Bits_2 is mod 2**2 with Size => 2;
      type Bits_28 is mod 2**28 with Size => 28;
      
      type CR_Register is
         record
            Reserved_1 : Bits_2;
            RNGEN      : Bits_1;
            IE         : Bits_1;
            Reserved_2 : Bits_28;
         end record;
      for CR_Register use
         record
            Reserved_1 at 0 range 0 .. 1;
            RNGEN      at 0 range 2 .. 2;
            IE         at 0 range 3 .. 3;
            Reserved_2 at 0 range 4 .. 31;
         end record;
      for CR_Register'Size use 32;

      CR : CR_Register with
        Volatile,
          Atomic,
          Address => System'To_Address(16#5006_0800#);
   end Test;

So I've now defined the reserved bits in the register, and I have added "Atomic" to the CR register.

In my main procedure I have the following:

   with System;
   with Test;

   procedure Main
     with SPARK_Mode => On
   is
      pragma Priority(System.Priority'First);
      
   begin
      
      Test.CR.RNGEN := 1;
      
      loop
         null;
      end loop;

   end Main;

The line where I assign the RNGEN bit produces the following assembly code (using no optimization: -O0):

   mov.w   r3, #2048       ; 0x800
   movt    r3, #20486      ; 0x5006
   ldrb    r2, [r3, #0]
   orr.w   r2, r2, #4
   strb    r2, [r3, #0]

As you can see, it is using byte load/store instructions.

So even when using Atomic, and when defining the other bits in the register it is still using the byte load/store instructions. The same assmebly code is generated at all optimization levels.

For reference, here's the code when I use a temporary copy of the register:

   declare
      Temp : Test.CR_Register;
   begin
      Temp := Test.CR;
      Temp.RNGEN := 1;
      Test.CR := Temp;
   end;

produces the following assembly code (the 3 segements of asm correspond to each of the 3 lines of code):

   mov.w   r3, #2048       ; 0x800
   movt    r3, #20486      ; 0x5006
   ldr     r3, [r3, #0]
   str     r3, [r7, #4]
   
   ldr     r3, [r7, #4]
   orr.w   r3, r3, #4
   str     r3, [r7, #4]
   
   mov.w   r3, #2048       ; 0x800
   movt    r3, #20486      ; 0x5006
   ldr     r2, [r7, #4]
   str     r2, [r3, #0]

In this case, it is always using the word load/store instructions (ldr and str). Here is the same code when optimization is enabled (-O1):

   mov.w   r3, #2048       ; 0x800
   movt    r3, #20486      ; 0x5006
   ldr     r2, [r3, #0]
   orr.w   r2, r2, #4
   str     r2, [r3, #0]

So could there be a problem with GNAT's Atomic on ARM?

I think the approach that I will take for the time being is to always use a temporary when reading/writing the registers. I can hide the registers behind procedures to enforce this access, and to also add pre/post conditions to enforce that the reserved bits are not modified from their reset value.

I would like to avoid machine code insertions if possible, since I would like to remain inside SPARK 2014 as much as possible (machine code insertions are not in SPARK 2014).


  reply	other threads:[~2014-07-01 19:52 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-30 22:11 Forcing GNAT to use 32-bit load/store instructions on ARM? daniel.dmk
2014-06-30 23:41 ` Jeffrey Carter
2014-07-01 12:06   ` Simon Clubley
2014-07-01 15:44     ` Niklas Holsti
2014-07-01 17:26       ` Simon Clubley
2014-07-01 17:18     ` Simon Wright
2014-07-01 19:43       ` Simon Wright
2014-07-01 17:28     ` Jeffrey Carter
2014-07-01  0:55 ` anon
2014-07-01  4:30 ` Niklas Holsti
2014-07-01  8:11 ` Dmitry A. Kazakov
2014-07-01 12:09   ` Simon Clubley
2014-07-01 12:20     ` Dmitry A. Kazakov
2014-07-01 17:00       ` Simon Clubley
2014-07-01 19:36         ` Dmitry A. Kazakov
2014-07-01 20:08           ` Simon Clubley
2014-07-02 22:24             ` Randy Brukardt
2014-07-06 20:40               ` MatthiasR
2014-07-07  0:25                 ` Simon Clubley
2014-07-07 22:38                 ` Randy Brukardt
2014-07-08  6:51                   ` Simon Wright
2014-07-10 11:47                     ` Simon Wright
2014-07-10 13:06                       ` Simon Clubley
2014-07-11 18:05                         ` Simon Wright
2014-07-11 20:22                           ` Simon Clubley
2014-07-08  8:50                   ` Brian Drummond
2014-07-08 12:12                   ` Simon Clubley
2014-07-08 13:26                     ` G.B.
2014-07-08 17:13                       ` Simon Clubley
2014-07-08 15:36                     ` Adam Beneschan
2014-07-08 15:40                       ` Adam Beneschan
2014-07-08 20:34                     ` Randy Brukardt
2014-07-09  7:31                       ` Dmitry A. Kazakov
2014-07-10  0:11                         ` Simon Clubley
2014-07-20 11:35                   ` MatthiasR
2014-07-20 15:49                     ` Simon Clubley
2014-07-26 11:05                       ` MatthiasR
2014-08-10 11:20                         ` MatthiasR
2014-07-01 12:03 ` Simon Clubley
2014-07-01 19:52   ` daniel.dmk [this message]
2014-07-01 20:40     ` Simon Clubley
2014-07-01 20:55       ` Simon Clubley
2014-07-01 21:01       ` Niklas Holsti
2014-07-01 21:20         ` Simon Clubley
2014-07-01 22:38           ` Niklas Holsti
2014-07-02 16:49             ` Simon Clubley
2014-07-01 21:55         ` daniel.dmk
2014-07-02  7:30     ` Simon Wright
2014-07-02 18:52       ` daniel.dmk
2014-07-04 23:51       ` Niklas Holsti
2014-07-05  0:18         ` Niklas Holsti
replies disabled

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