comp.lang.ada
 help / color / mirror / Atom feed
From: Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP>
Subject: Re: Forcing GNAT to use 32-bit load/store instructions on ARM?
Date: Tue, 1 Jul 2014 20:40:31 +0000 (UTC)
Date: 2014-07-01T20:40:31+00:00	[thread overview]
Message-ID: <lov6bu$j0s$1@dont-email.me> (raw)
In-Reply-To: ca6f05d3-c469-4abc-92df-54aa605f41ba@googlegroups.com

On 2014-07-01, daniel.dmk@googlemail.com <daniel.dmk@googlemail.com> wrote:
> Thank you everyone for your suggestions and comments. 
>
> On Tuesday, 1 July 2014 13:03:30 UTC+1, Simon Clubley  wrote:
>> 
>> 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]
>

This is the exact same issue I encountered when I tried to use bitfields
in C instead of bitmasks. The difference here is that Ada's Atomic pragma
is supposed to stop this type of code from being generated.

> 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]
>

This is exactly the kind of ARM code I would expect to see generated.

> 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?
>

Yes, big time.

The Atomic pragma is making a guarantee which is not being honoured by
the gcc ARM code generator.

> 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.
>

You would need to use a temporary variable anyway if you need to update
multiple bitfields at the same time as part of an atomic register update.

> 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).

If you need to do things like manipulate the CPSR or the ARM coprocessor
registers, then this might not be possible.

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world

  reply	other threads:[~2014-07-01 20:40 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
2014-07-01 20:40     ` Simon Clubley [this message]
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