From: Per Jakobsen <pdj@knaldgas.dk>
Subject: Odd AVR-Ada code generation issue with constant record type
Date: Fri, 5 Jul 2019 01:57:41 -0700 (PDT)
Date: 2019-07-05T01:57:41-07:00 [thread overview]
Message-ID: <b78a975c-8ef1-41ac-b4c2-c1c07675765a@googlegroups.com> (raw)
I'm trying to demonstrate some of Ada's strengths with regard to low-level programming, and ran into the following issue:
Having a byte-record consisting of bit-fields of different types (typical microcontroller register definitions). Compiling the below Ada code using avr-ada 1.2.2 (avr-gnat 4.9.3) gives some odd assembly code.
Summary:
All assignments is really constants that ought to be calculated in full at compile time.
1) Clearing all bitfields in the byte as one assignment, it loads, clears and stores for each field even though the result is constant. *Very* inefficient and even dangerous if the bitfields are assumed to be set atomically!!!
2) Setting one field (any), a calculated byte constant is stored directly.
3) Setting more than one field, a calculated byte constant is initialized in SRAM and used during execution. Inefficient.
4) Clearing a non-composite byte is done directly.
5) Setting a non-composite byte is done directly.
Is there an option or pragma I need to set, or is this something more fundamental with the compiler?
Code:
------------------------------------
### main.adb, compiled with Makefile and build.gpr from uart_echo in avr-ada package.
with AVR;
with System;
with Interfaces;
procedure Main is
use AVR;
use Interfaces;
type Enum_Type is (B00, B01, B10, B11);
for Enum_Type use (B00 => 0,
B01 => 1,
B10 => 2,
B11 => 3);
type List_Type is array (0 .. 4) of Boolean with Pack;
type Reg_Type is record
Enum : Enum_Type;
Bool : Boolean;
List : List_Type;
end record;
for Reg_Type use record
Enum at 0 range 6 .. 7;
Bool at 0 range 5 .. 5;
List at 0 range 0 .. 4;
end record;
for Reg_Type'Size use 8;
-- Reg_A --
Reg_A : Reg_Type;
for Reg_A'Address use System.Address (16#7a#);
pragma Volatile (Reg_A);
-- Reg_B --
Reg_B : Reg_Type;
for Reg_B'Address use System.Address (16#7b#);
pragma Volatile (Reg_B);
-- Reg_C --
Reg_C : Reg_Type;
for Reg_C'Address use System.Address (16#7c#);
pragma Volatile (Reg_C);
-- Reg_D --
Reg_D : Unsigned_8;
for Reg_D'Address use System.Address (16#7d#);
pragma Volatile (Reg_D);
-- Reg_E --
Reg_E : Unsigned_8;
for Reg_E'Address use System.Address (16#7e#);
pragma Volatile (Reg_E);
begin
-- Set composite with resulting zero-byte.
Reg_A := (Enum => B00,
Bool => False,
List => (others => False));
-- Generated assembly:
-- ldi r30, 0x7A ; Set address of register
-- ldi r31, 0x00
-- ld r24, Z ; Load
-- andi r24, 0xE0 ; Clear List.
-- st Z, r24 ; Store
-- ld r18, Z ; Load
-- andi r18, 0xDF ; Clear Bool.
-- st Z, r18 ; Store
-- ld r19, Z ; Load
-- andi r19, 0x3F ; Clear Enum.
-- st Z, r19 ; Store
-- Result : 22 bytes code, 0 bytes SRAM, 17 cycles
-- Optimal: 4 bytes code, 0 bytes SRAM, 2 cycles
-- Set composite with resulting non-zero-byte (any one field is set, others zero).
Reg_B := (Enum => B00,
Bool => True,
List => (others => False));
-- Generated assembly:
-- ldi r20, 0x20 ; Set register bits
-- sts 0x007B, r20 ; Store
-- Result: 6 bytes code, 0 bytes SRAM, 3 cycles
-- Is optimal!
-- Set composite with resulting non-zero-byte (multiple fields is set).
Reg_C := (Enum => B11,
Bool => True,
List => (others => True));
-- Generated assembly:
-- lds r21, 0x0100 ; Load pre-initialized SRAM-stored constant.
-- sts 0x007C, r21 ; Store
-- Result : 8 bytes code, 1 bytes SRAM, 4 cycles, requires initialization.
-- Optimal: 6 bytes code, 0 bytes SRAM, 3 cycles, no initialization.
-- Clear Unsigned_8 directly.
Reg_D := 16#00#;
-- Generated assembly:
-- sts 0x007D, r1 ; Store with "reserved" zero-register.
-- Result: 4 bytes code, 0 bytes SRAM, 2 cycles
-- Is optimal!
-- Setting Unsigned_8 directly.
Reg_E := 16#FF#;
-- Generated assembly:
-- ldi r22, 0xFF ; Load constant.
-- sts 0x007E, r22 ; Store
-- Result: 6 bytes code, 0 bytes SRAM, 3 cycles
-- Is optimal!
end Main;
next reply other threads:[~2019-07-05 8:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-05 8:57 Per Jakobsen [this message]
2019-07-05 9:24 ` Odd AVR-Ada code generation issue with constant record type Mark Lorenzen
2019-07-05 12:19 ` Per Jakobsen
2019-07-08 14:49 ` Stéphane Rivière
2019-07-09 12:12 ` Per Jakobsen
2019-07-09 15:30 ` Simon Wright
2019-07-09 18:10 ` Per Jakobsen
2019-07-09 18:46 ` Per Jakobsen
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox