Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: EWARM странные операции со стеком.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Artem_Petrik
Вот и у меня на горизонте замаячил проектик, который видимо желательно реализовывать на MCU семейства ARM. Так что я приступил к их освоению.
Имею (вредную?) привычку после компиляции смотреть листинг, чтобы оценить насколько результат близок к тому, что я написал бы на ассемблере. И, как всегда, смотрю, и сердце кровью обливается. Это даже при том, что я в армовском ассемблере почти ничего не понимаю. Поначалу у меня была сравнительно старая версия иара - 4.40A, и я решил что неоптимальность связанна именно с этим. Поэтому скачал 5.11. Код действительно стал лучше, но не на много. Наиболее непонятны для меня некоторые операции со стеком, которые компилятор вставляет при входе/выходе из процедуры при компиляции в режиме THUMB. Вот достаточно простой пример:
Код
      3          void putchar( char a)
      4          {
   \                     putchar:
   \   00000000   01B5               PUSH     {R0,LR}
      5            AT91PS_USART pUSART = AT91C_BASE_US0;
      6            
      7            while( !(pUSART->US_CSR & AT91C_US_TXRDY) );
   \                     ??putchar_0:
   \   00000002   0449               LDR      R1,??putchar_1  ;; 0xfffc0014
   \   00000004   0968               LDR      R1,[R1, #+0]
   \   00000006   8907               LSLS     R1,R1,#+30
   \   00000008   FBD5               BPL      ??putchar_0
      8            pUSART->US_THR = a;
   \   0000000A   0249               LDR      R1,??putchar_1  ;; 0xfffc0014
   \   0000000C   8860               STR      R0,[R1, #+8]
      9          }
   \   0000000E   08BC               POP      {R3}
   \   00000010   01BC               POP      {R0}
   \   00000012   0047               BX       R0              ;; return
   \                     ??putchar_1:
   \   00000014   1400FCFF           DC32     0xfffc0014

Несмотря на то, что в функции не происходит вызова других функций, зачем-то в стек сохраняется LR. Более того, с ним за компанию сохраняется параметр, передаваемый в функцию, который потом восстанавливается в r3 07.gif Зачем????. Насколько я понимаю в данной функции все push/pop можно просто выбросить, без ущерба функциональности. Это у меня результат компиляции с максимальной оптимизацией по размеру. Если же оптимизировать по скорости, то меняется только PUSH {R0,LR} на PUSH {R3,LR}. Здесь R3 сохранили, и его же восстановили. Но зачем?
Это кривость компилятора? или я чего-то не так делаю? Пугает то, что даже такую простую функцию откомпилить нормально не получается. Это чтож будет на реальных программах. Так недолго довести производительность ARM до уровня AVR 05.gif . Как заставить компилятор генерить более оптимальный код? Или переходить на другой компилятор? Переходить не хотелось бы, привык к ИАРу за годы работы с АВР-ками.
zltigo
Цитата(Artem_Petrik @ Jun 15 2008, 15:58) *
...я чего-то не так делаю? Пугает то, что даже такую простую функцию откомпилить нормально не получается. Это чтож будет на реальных программах.

Вот и пишите реальные программы smile.gif. А то взяли две строчки, где компилятору хорошо умеющему делать глобальные оптимизаци и развернутся негде. Зато вынужденному соблюдать определенные правила компилятотору дополнительно заморочили голову прямым приказом создать совершенно не нужную локальную переменую....
Уберите для начала вот эту хрень:
AT91PS_USART pUSART = AT91C_BASE_US0;
ну THUMB, зачем Вам сдался? Экономить Flash любой ценой? Тогда не жалуйтесь на "цену".
Artem_Petrik
Цитата(zltigo @ Jun 15 2008, 19:16) *
Вот и пишите реальные программы smile.gif. А то взяли две строчки, где компилятору хорошо умеющему делать глобальные оптимизаци и развернутся негде. Зато вынужденному соблюдать определенные правила компилятотору дополнительно заморочили голову прямым приказом создать совершенно не нужную локальную переменую....
Уберите для начала вот эту хрень:
AT91PS_USART pUSART = AT91C_BASE_US0;
ну THUMB, зачем Вам сдался? Экономить Flash любой ценой? Тогда не жалуйтесь на "цену".


Конечно реальные программы я писать буду, никуда не денусь. Уже занимаюсь. Но согласитесь, что если бы я вам тут привел листинг на 1500 строк вам было бы сложнее его читать, и давать советы. Кроме того, будь функция побольше, вы бы сказали: "ой, ну три лишних инструкции из 100, че вы придираетесь!" и были бы в чем то правы. Но я хочу чтобы этих лишних команд не было! Согласитесь, в данном конкретном случае их быть не должно, более того, именно ТАКИЕ лишние команды совсем не к лицу хоть сколько-нибудь оптимизирующему компилятору. Ведь они СОВСЕМ ничего не делают!
"Хрень" можно убрать, это ничего не меняет. Вставлена она в результате попытки "подсказать" компилятору как сделать код короче. Чтоб он не грузил значение LDR-ом два раза, а использовал загруженное единожды. Правда все равно не помогло, ну да это я еще могу простить. А вот АБСОЛЮТНО ненужные команды меня просто бесят.
Flash я экономлю, но вовсе не "любой ценой". Очень часто, и в данном примере в частности, компиляция в ARM и THUMB дает одинаковое количество команд, иногда в тхумбе всего на пару команд больше. Так что экономия выходит не любой ценой, а "нахаляву". Кроме того атмеловские процы на высоких частотах ядра THUMB команды выполняют быстрее (не так проявляется ограничения из-за медленной флеши). Так что, на мой взгляд, использование THUMB инструкций во многих случаях очень даже уместно.
zltigo
Повторятся трижды было уж слишком smile.gif
Цитата
Но я хочу чтобы этих лишних команд не было!

Продолжайте хотеть smile.gif.
Цитата
Согласитесь, в данном конкретном случае их быть не должно, более того, именно ТАКИЕ лишние команды совсем не к лицу хоть сколько-нибудь оптимизирующему компилятору. Ведь они СОВСЕМ ничего не делают!

Не пишите такие грандиозные "фунции", ползуйтесь inline.
Цитата
А вот АБСОЛЮТНО ненужные команды меня просто бесят.

Займитесь чем-нибудь другим smile.gif, например, выращиванием капусты, говорят успокаивает.
Смотрим на аналогичную функцию:
Код
     43          void testputchar( char ch )
     44          {
     45              while( !(U0LSR & LSR_TEMT) );
   \                     testputchar:
   \                     ??testputchar_0:
   \   00000000   E014A0E3           MOV      R1,#-536870912
   \   00000004   C01C81E3           ORR      R1,R1,#0xC000
   \   00000008   1420D1E5           LDRB     R2,[R1, #+20]
   \   0000000C   400012E3           TST      R2,#0x40
   \   00000010   FAFFFF0A           BEQ      ??testputchar_0
     46              U0THR = ch;
   \   00000014   0000C1E5           STRB     R0,[R1, #+0]
     47          }
   \   00000018   0EF0A0E1           MOV      PC,LR         ;; return


Цитата
Так что экономия выходит не любой ценой, а "нахаляву".

В реальной жизни и в реальном программировании халаявы не бывает. В отдельные кусочках можно добиться выигыша. В сколь-нибудь реальных - нет.
GetSmart
Цитата(zltigo)
Смотрим на аналогичную функцию:
... в ARM-режиме sad.gif
Artem_Petrik в чём-то прав. Трудно объяснить такое поведение компилятора.
zltigo
Цитата(GetSmart @ Jun 15 2008, 20:51) *
... в ARM-режиме sad.gif

Ага, и без interwork. И без халявы.
Цитата
Artem_Petrik в чём-то прав. Трудно объяснить такое поведение компилятора.

Для этого наверное стоит смотреть более подробно, какие общие правила игры были навязаны компилятору.
Thumb:
Код
     43          __thumb void testputchar( char ch )
     44          {
   \                     testputchar:
   \   00000000   4021               MOVS     R1,#+64
   \   00000002   034A               LDR      R2,??testputchar_0;; 0xffffffffe000c000
     45              while( !(U0LSR & LSR_TEMT) );
   \                     ??testputchar_1:
   \   00000004   137D               LDRB     R3,[R2, #+20]
   \   00000006   0B42               TST      R3,R1
   \   00000008   FCD0               BEQ      ??testputchar_1
     46              U0THR = ch;
   \   0000000A   1070               STRB     R0,[R2, #+0]
     47          }
   \   0000000C   7047               BX       LR
   \   0000000E   C046               Nop      
   \                     ??testputchar_0:
   \   00000010   00C000E0           DC32     0xffffffffe000c000
Artem_Petrik
Цитата(zltigo @ Jun 15 2008, 21:37) *
Повторятся трижды было уж слишком smile.gif
Смотрим на аналогичную функцию:
Код
     43          void testputchar( char ch )
     44          {
     45              while( !(U0LSR & LSR_TEMT) );
   \                     testputchar:
   \                     ??testputchar_0:
   \   00000000   E014A0E3           MOV      R1,#-536870912
   \   00000004   C01C81E3           ORR      R1,R1,#0xC000
   \   00000008   1420D1E5           LDRB     R2,[R1, #+20]
   \   0000000C   400012E3           TST      R2,#0x40
   \   00000010   FAFFFF0A           BEQ      ??testputchar_0
     46              U0THR = ch;
   \   00000014   0000C1E5           STRB     R0,[R1, #+0]
     47          }
   \   00000018   0EF0A0E1           MOV      PC,LR          ;; return


Пардон, что то сегодня у меня инет жутко глючит. Пол часа ответ посылал. Кликаю отправить - думает пару минут, и выдает ошибку. Оказывается три раза все же прошло.
Надо отметить, что ваш пример выглядит красиво. А под какой это проц? Дело в том, что я обратил внимание на то, что атмеловские инклуды с описанием периферии радикально отличаются от инклудов других производителей. И пока у меня была версия 4.40А именно с этим были связаны многие проколы в оптимизации. Так при записи в регистры одной и той же периферии, вместо адресации со смещением компилятор грузил адрес LDR-ом каждый раз. Впрочем, вроде в версии 5.11 это прошло. Но может не совсем?
Кстати, нашол у себя древний (даже про SAM7X не знает еще) кейловский микровижн. Пока с инета (медленно sad.gif )качается более новая версия, решил скомпилить под ним. CARM тоже генерит чертий-что, а вот real view выдал такое
Код
                          THUMB
                  putchar PROC
;;;4      void putchar( char a)
;;;5      {
000000  4902              LDR      r1,|L2.12|
;;;6        AT91PS_USART pUSART = AT91C_BASE_US0;
;;;7        
;;;8        while( !(pUSART->US_CSR & AT91C_US_TXRDY) );
                  |L2.2|
000002  694a              LDR      r2,[r1,#0x14]
000004  0792              LSLS     r2,r2,#30
000006  d5fc              BPL      |L2.2|
;;;9        pUSART->US_THR = a;
000008  61c8              STR      r0,[r1,#0x1c]
;;;10     }
00000a  4770              BX       lr
                  |L2.12|
00000c  fffc0000          DCD      0xfffc0000
                          ENDP


Кажись покороче будет чем даже ваш пример! Так что при нормальном компиляторе "жаловаться на цену" не приходится.
GetSmart
Цитата(zltigo)
Thumb:
Ну, это другое дело smile.gif
А кто-нить знает, почему использована команда MOVS R1,#+64, а не MOV R1,#+64 ???
zltigo
Цитата(Artem_Petrik @ Jun 15 2008, 21:35) *
Так что при нормальном компиляторе "жаловаться на цену" не приходится.

Только не увлекайтесь выбором компиляторов по отдельным тестовым примерам и уж тем более состоящих из нескольких строк.
Цитата
Надо отметить, что ваш пример выглядит красиво. А под какой это проц?

LPC2xxx. Хидеры обычно пишу/дописываю свои, дабы иметь переносимые не зависеть от компилятора.
Atmel-овский стиль, конечно максимально дебильный из всех возможных sad.gif
Artem_Petrik
Цитата(zltigo @ Jun 15 2008, 22:53) *
Только не увлекайтесь выбором компиляторов по отдельным тестовым примерам и уж тем более состоящих из нескольких строк.

LPC2xxx. Хидеры обычно пишу/дописываю свои, дабы иметь переносимые не зависеть от компилятора.
Atmel-овский стиль, конечно максимально дебильный из всех возможных sad.gif


Да я пока не очень то увлекаюсь выбором компиляторов. Есть сильное желание все-же пользоваться ИАР-ом. Просто он иногда меня сильно удивляет. Впрочем ваш LPC-шный пример выглядит прилично, так что возможно и впрямь проблема в неадекватном хидере. У меня AT91SAM7X256.
Правда идея самому писать хидер меня несколько пугает. На мой взгляд, более идиотсое занятие себе вообще трудно придумать. Но слегка подправить попробую, вдруг поможет.
Конечно соглашусь, что данный пример вовсе не является показателем. Просто на данном этапе освоения данного семейства контроллеров я пока пишу такие вот небольшие подпрограммки, не столько с целью их дальнейшего использования, сколько с целью выработать стиль написания, который не будет сильно запутывать компилятор, и позволит ему генерировать нормальный код, без маразмов. Вот это-то у меня пока и не получается sad.gif
zltigo
Цитата(Artem_Petrik @ Jun 15 2008, 22:28) *
Да я пока не очень то увлекаюсь выбором компиляторов. Есть сильное желание все-же пользоваться ИАР-ом.

Пользуйтесь. V5 очень приличный. V4 часто немного проигрывал тому-же Keil (который АРМ smile.gif ), особенно на библиотеках, то теперь идут практически ноздря в ноздрю. До кучи к ним GCC - тоже нормальный. Остальные явно отстают от этой троицы.
Цитата
правда идея самому писать хидер меня несколько пугает. На мой взгляд, более идиотсое занятие себе вообще трудно придумать.

Почему? Все сразу писать не надо. А постепенно, да еше имея какую-никакую болванку пороблем не вижу, тем более, что читать все равно надо smile.gif.
aaarrr
Цитата(Artem_Petrik @ Jun 16 2008, 00:28) *
Да я пока не очень то увлекаюсь выбором компиляторов. Есть сильное желание все-же пользоваться ИАР-ом. Просто он иногда меня сильно удивляет. Впрочем ваш LPC-шный пример выглядит прилично, так что возможно и впрямь проблема в неадекватном хидере. У меня AT91SAM7X256.

Насчет RealView советую серьёзно подумать. Особенно если нет стойкой привычки к IAR'у smile.gif

Дело не столько в хидерах, сколько в стиле написания программы:
Код
AT91PS_USART pUSART = AT91C_BASE_US0;

while( !(pUSART->US_CSR & AT91C_US_TXRDY));


Код
while( !(AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY));


Код
while( !(*AT91C_US0_CSR & AT91C_US_TXRDY));


Цитата(Artem_Petrik @ Jun 16 2008, 00:28) *
Правда идея самому писать хидер меня несколько пугает. На мой взгляд, более идиотсое занятие себе вообще трудно придумать. Но слегка подправить попробую, вдруг поможет.

Это вполне нормальное занятие, к тому же довольно легко поддающееся автоматизации.
А у Atmel'а в хидерах и ошибки встречаются (не на SAM7X256).
Artem_Petrik
Стоп! Что-то у меня лыжи не едут! Откомпилил у себя ваш вариант под ЛПЦ, (правда у меня не поняло выражение LSR_TEMT, пришлось заменить на 0x40) Сейчас у меня EWARM-EW-WEB 5.11
Код
#include "iolpc2131.h"

__thumb void testputchar( char ch )
{
   while( !(U0LSR & 0x40) );
   U0THR = ch;
}


и получил тот же маразм:
Код
  \                                 In section .text, align 4, keep-with-next
     13          __thumb void testputchar( char ch )
     14          {
   \                     testputchar:
   \   00000000   01B5               PUSH     {R0,LR}
   \   00000002   0349               LDR      R1,??testputchar_0 ;; 0xe000c000
     15             while( !(U0LSR & 0x40) );
   \                     ??testputchar_1:
   \   00000004   0A7D               LDRB     R2,[R1, #+20]
   \   00000006   5206               LSLS     R2,R2,#+25
   \   00000008   FCD5               BPL      ??testputchar_1
     16             U0THR = ch;
   \   0000000A   0870               STRB     R0,[R1, #+0]
     17          }
   \   0000000C   08BD               POP      {R3,PC}         ;; return
   \   0000000E   C046               Nop      
   \                     ??testputchar_0:
   \   00000010   00C000E0           DC32     0xe000c000

Значит у меня все же что-то или с настройками компилятора, или одно из двух.
Подскажите какая у вас версия и настройки компилятора. Не успокоюсь, пока не получу у себя такойже код как у вас!
aaarrr
Оптимизация-то включена вообще?
Artem_Petrik
Цитата(aaarrr @ Jun 15 2008, 23:51) *
Оптимизация-то включена вообще?


Да, Level = High, все галочки стоят. От варианта Speed/size/balanced практически ничего не меняется.
zltigo
Цитата(Artem_Petrik @ Jun 15 2008, 22:49) *
Стоп! Что-то у меня лыжи не едут!
...
Сейчас у меня EWARM-EW-WEB 5.11

По началу Вы на V4 жаловались, вот я и 4.42 и компильнул. Ну у V5 действительно такие фокусы с push/pop в Thumb. Но тем не менее он глобально лучше smile.gif в ARM компилит.
Artem_Petrik
Цитата(zltigo @ Jun 16 2008, 00:11) *
По началу Вы на V4 жаловались, вот я и 4.42 и компильнул. Ну у V5 действительно такие фокусы с push/pop в Thumb. Но тем не менее он глобально лучше smile.gif в ARM компилит.


У меня была версия 4.40A, там были такие же пуши и попы. И много других идиотизмов, в том числе и в ARM режиме. Грешил я в основном на букву A в версии, думал может что-то совсем сырое попалось. Из нового скачал сразу последнюю версию. Эх, разочарован я. Буду серьезно думать насчет RealView smile.gif . Ну ничего, оно и к лучшему. Значит пришло время мне привыкнуть к какому-либо компиляторонезависимому редактору типа слика, чтобы больше не привыкать то к одной ИДЕ, то к другой, а писать все в одном редакторе. И компилить чем душе угодно smile.gif
zltigo
Цитата(Artem_Petrik @ Jun 15 2008, 23:27) *
Значит пришло время мне привыкнуть к какому-либо компиляторонезависимому редактору типа слика, чтобы больше не привыкать то к одной ИДЕ, то к другой, а писать все в одном редакторе. И компилить чем душе угодно smile.gif

Так это есть обязательнейшее условие нормальной работы! Только 'привыкать' не надо - надо делать под себя.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.