AVR C -- они все издеваются что ли?!. - Page 3

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
Re: AVR C -- они все издеваются что ли?!.
10-Feb-05 20:52 Michael Ryazanov wrote to Alex Mogilnikov:

 AM>> какая-то последовательность данных. А записываться другая
 AM>> последовательность. Исключив любое из обращений, компилятор эту
 AM>> последовательность нарушит.

MR>    Очень часто для того, чтобы прочитать из регистра какого-то устройства
MR> осмысленное значение, необходимо действительно выполнить определённую
MR> последовательность. Hапример, дождаться, пока в регистре состояния будет
MR> сброшен некоторый флаг, записать в индексный регистр номер того, что
MR> собираемся
MR> читать, выждать некоторое время, после чего считать из регистра данных
MR> младший
MR> байт, потом оттуда же считать старший байт... Желательно ещё, чтобы эта
MR> последовательность ничем не прерывалась. И всякие прочие штучки. Hикакой
MR> модификатор volatile здесь не поможет,
 И вот как раз БЕЗ volatile при применении такой последовательности
в цикле оптимизатор имеет право зачитать регистр данных ОДИН раз
перед телом цикла в регистр и дальше использовать содержимое этого
регистра.

MR> и придуман он вовсе не для этого.
 А для чего?
 Если бы ты сказал "не только для этого" - я бы ещё понял.


MR>    Hо код должен получаться соответствующий стандарту и, желательно,
MR> разумный.
 Со стандартом вопрос тёмный.
 Посмотри обсуждение в SU.C_CPP - меня они не убедили. Хотя бы тем,
что не показали мне ошибку в выстроенных мной цепочках цитат из стандарта.

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Re: AVR C -- они все издеваются что ли?!.
27-Jan-05 22:35 Michael Ryazanov wrote to All:

MR>    Существуют в природе хоть какие-нибудь нормальные компиляторы C для
MR> AVR?
MR> Посмотрел пока что CodeVisionAVR, который (без Automatic Register
MR> Allocation)
MR> делает такое:

MR> ;      40 led_status<<=1;
MR>    LDS  R30,_led_status
MR>    LSL  R30
MR>    STS  _led_status,R30
MR> ;      41 led_status|=1;
MR>    ORI  R30,1
MR>    STS  _led_status,R30

MR> И avr-gcc, который со всякими ключами оптимизациями делает вообще такое:

MR>   5a: 80 91 60 00    lds   r24, 0x0060
MR>   5e: 99 27          eor   r25, r25
MR>   60: 00 97          sbiw  r24, 0x00   ; 0
MR>   62: 19 f0          breq  .+6         ; 0x6a

MR>   6a: 80 91 61 00    lds   r24, 0x0061
MR>   6e: 90 91 62 00    lds   r25, 0x0062
MR>   72: 01 96          adiw  r24, 0x01   ; 1
MR>   74: 90 93 62 00    sts   0x0062, r25
MR>   78: 80 93 61 00    sts   0x0061, r24
MR>   7c: 80 91 61 00    lds   r24, 0x0061
MR>   80: 90 91 62 00    lds   r25, 0x0062
MR>   84: 8f 5f          subi  r24, 0xFF   ; 255
MR>   86: 93 40          sbci  r25, 0x03   ; 3
MR>   88: a9 f4          brne  .+42        ; 0xb4

Нельзя ли привести C-шный исходник, из которого gcc сделал приведенный код?
Это ведь совершенно другое, чем то, что компилировалось CodeVision.
Я не говорю, что gcc во всём хорош, он иногда слишком увлекается соблюдением
integer promotion rules из стандарта C и недочищает посл еэтого явно
ненужные хвосты.
Но что касается куска с led_status:
#include  <inttypes.h>

extern uint8_t led_status;

void foo(void) {
        led_status <<= 1;
        led_status |= 1;
}

С оптимизацией -O2

   5:foo.c         **** void foo(void) {
  53                    .LM1:
  54                    /* prologue: frame size=0 */
  55                    /* prologue end (size=0) */
   6:foo.c         ****         led_status <<= 1;
  57                    .LM2:
  58 0000 8091 0000             lds r24,led_status
  59 0004 880F                  lsl r24
   7:foo.c         ****         led_status |= 1;
  61                    .LM3:
  62 0006 8160                  ori r24,lo8(1)
  63 0008 8093 0000             sts led_status,r24
  64                    /* epilogue: frame size=0 */
  65 000c 0895                  ret

Без оптимизации функция выходит больше, но только за счёт
ненужных пролога и эпилога, а именно эти две строки с led_status
компилируются точно так же.
Худшего кода я смог *добиться* только комбинацией знаковой переменной
с квалификатором volatile:
volatile int8_t led_status;
Тогда перед выполнением сдвига остаётся преобразование со знаком
к знаковому 16-битному значению и сдвиг 16-битного значения. И несмотря
на ненужность старшего байта оптимизатор этот хвост не подчистил:
   5:foo.c         **** void foo(void) {
  53                    .LM1:
  54                    /* prologue: frame size=0 */
  55                    /* prologue end (size=0) */
   6:foo.c         ****         led_status <<= 1;
  57                    .LM2:
  58 0000 8091 0000             lds r24,led_status
  59 0004 9927                  clr r25
  60 0006 87FD                  sbrc r24,7
  61 0008 9095                  com r25
  62 000a 880F                  lsl r24
  63 000c 991F                  rol r25
  64 000e 8093 0000             sts led_status,r24
   7:foo.c         ****         led_status |= 1;
  66                    .LM3:
  67 0012 8091 0000             lds r24,led_status
  68 0016 8160                  ori r24,lo8(1)
  69 0018 8093 0000             sts led_status,r24
  70                    /* epilogue: frame size=0 */
  71 001c 0895                  ret

В любом случае приведенный тобой код соответствует совсем другому исходнику.

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Site Timeline