|
EWARM странные операции со стеком. |
|
|
|
Jun 15 2008, 13:58
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Вот и у меня на горизонте замаячил проектик, который видимо желательно реализовывать на 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  Зачем????. Насколько я понимаю в данной функции все push/pop можно просто выбросить, без ущерба функциональности. Это у меня результат компиляции с максимальной оптимизацией по размеру. Если же оптимизировать по скорости, то меняется только PUSH {R0,LR} на PUSH {R3,LR}. Здесь R3 сохранили, и его же восстановили. Но зачем? Это кривость компилятора? или я чего-то не так делаю? Пугает то, что даже такую простую функцию откомпилить нормально не получается. Это чтож будет на реальных программах. Так недолго довести производительность ARM до уровня AVR  . Как заставить компилятор генерить более оптимальный код? Или переходить на другой компилятор? Переходить не хотелось бы, привык к ИАРу за годы работы с АВР-ками.
|
|
|
|
|
Jun 15 2008, 16:16
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Artem_Petrik @ Jun 15 2008, 15:58)  ...я чего-то не так делаю? Пугает то, что даже такую простую функцию откомпилить нормально не получается. Это чтож будет на реальных программах. Вот и пишите реальные программы  . А то взяли две строчки, где компилятору хорошо умеющему делать глобальные оптимизаци и развернутся негде. Зато вынужденному соблюдать определенные правила компилятотору дополнительно заморочили голову прямым приказом создать совершенно не нужную локальную переменую.... Уберите для начала вот эту хрень: AT91PS_USART pUSART = AT91C_BASE_US0; ну THUMB, зачем Вам сдался? Экономить Flash любой ценой? Тогда не жалуйтесь на "цену".
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 15 2008, 18:26
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Цитата(zltigo @ Jun 15 2008, 19:16)  Вот и пишите реальные программы  . А то взяли две строчки, где компилятору хорошо умеющему делать глобальные оптимизаци и развернутся негде. Зато вынужденному соблюдать определенные правила компилятотору дополнительно заморочили голову прямым приказом создать совершенно не нужную локальную переменую.... Уберите для начала вот эту хрень: AT91PS_USART pUSART = AT91C_BASE_US0; ну THUMB, зачем Вам сдался? Экономить Flash любой ценой? Тогда не жалуйтесь на "цену". Конечно реальные программы я писать буду, никуда не денусь. Уже занимаюсь. Но согласитесь, что если бы я вам тут привел листинг на 1500 строк вам было бы сложнее его читать, и давать советы. Кроме того, будь функция побольше, вы бы сказали: "ой, ну три лишних инструкции из 100, че вы придираетесь!" и были бы в чем то правы. Но я хочу чтобы этих лишних команд не было! Согласитесь, в данном конкретном случае их быть не должно, более того, именно ТАКИЕ лишние команды совсем не к лицу хоть сколько-нибудь оптимизирующему компилятору. Ведь они СОВСЕМ ничего не делают! "Хрень" можно убрать, это ничего не меняет. Вставлена она в результате попытки "подсказать" компилятору как сделать код короче. Чтоб он не грузил значение LDR-ом два раза, а использовал загруженное единожды. Правда все равно не помогло, ну да это я еще могу простить. А вот АБСОЛЮТНО ненужные команды меня просто бесят. Flash я экономлю, но вовсе не "любой ценой". Очень часто, и в данном примере в частности, компиляция в ARM и THUMB дает одинаковое количество команд, иногда в тхумбе всего на пару команд больше. Так что экономия выходит не любой ценой, а "нахаляву". Кроме того атмеловские процы на высоких частотах ядра THUMB команды выполняют быстрее (не так проявляется ограничения из-за медленной флеши). Так что, на мой взгляд, использование THUMB инструкций во многих случаях очень даже уместно.
|
|
|
|
|
Jun 15 2008, 18:37
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Повторятся трижды было уж слишком  Цитата Но я хочу чтобы этих лишних команд не было! Продолжайте хотеть  . Цитата Согласитесь, в данном конкретном случае их быть не должно, более того, именно ТАКИЕ лишние команды совсем не к лицу хоть сколько-нибудь оптимизирующему компилятору. Ведь они СОВСЕМ ничего не делают! Не пишите такие грандиозные "фунции", ползуйтесь inline. Цитата А вот АБСОЛЮТНО ненужные команды меня просто бесят. Займитесь чем-нибудь другим  , например, выращиванием капусты, говорят успокаивает. Смотрим на аналогичную функцию: Код 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 Цитата Так что экономия выходит не любой ценой, а "нахаляву". В реальной жизни и в реальном программировании халаявы не бывает. В отдельные кусочках можно добиться выигыша. В сколь-нибудь реальных - нет.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 15 2008, 18:58
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(GetSmart @ Jun 15 2008, 20:51)  ... в ARM-режиме  Ага, и без 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
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 15 2008, 19:35
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Цитата(zltigo @ Jun 15 2008, 21:37)  Повторятся трижды было уж слишком  Смотрим на аналогичную функцию: Код 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 не знает еще) кейловский микровижн. Пока с инета (медленно  )качается более новая версия, решил скомпилить под ним. 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 Кажись покороче будет чем даже ваш пример! Так что при нормальном компиляторе "жаловаться на цену" не приходится.
|
|
|
|
|
Jun 15 2008, 19:53
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Artem_Petrik @ Jun 15 2008, 21:35)  Так что при нормальном компиляторе "жаловаться на цену" не приходится. Только не увлекайтесь выбором компиляторов по отдельным тестовым примерам и уж тем более состоящих из нескольких строк. Цитата Надо отметить, что ваш пример выглядит красиво. А под какой это проц? LPC2xxx. Хидеры обычно пишу/дописываю свои, дабы иметь переносимые не зависеть от компилятора. Atmel-овский стиль, конечно максимально дебильный из всех возможных
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 15 2008, 20:28
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Цитата(zltigo @ Jun 15 2008, 22:53)  Только не увлекайтесь выбором компиляторов по отдельным тестовым примерам и уж тем более состоящих из нескольких строк. LPC2xxx. Хидеры обычно пишу/дописываю свои, дабы иметь переносимые не зависеть от компилятора. Atmel-овский стиль, конечно максимально дебильный из всех возможных  Да я пока не очень то увлекаюсь выбором компиляторов. Есть сильное желание все-же пользоваться ИАР-ом. Просто он иногда меня сильно удивляет. Впрочем ваш LPC-шный пример выглядит прилично, так что возможно и впрямь проблема в неадекватном хидере. У меня AT91SAM7X256. Правда идея самому писать хидер меня несколько пугает. На мой взгляд, более идиотсое занятие себе вообще трудно придумать. Но слегка подправить попробую, вдруг поможет. Конечно соглашусь, что данный пример вовсе не является показателем. Просто на данном этапе освоения данного семейства контроллеров я пока пишу такие вот небольшие подпрограммки, не столько с целью их дальнейшего использования, сколько с целью выработать стиль написания, который не будет сильно запутывать компилятор, и позволит ему генерировать нормальный код, без маразмов. Вот это-то у меня пока и не получается
|
|
|
|
|
Jun 15 2008, 20:41
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Artem_Petrik @ Jun 15 2008, 22:28)  Да я пока не очень то увлекаюсь выбором компиляторов. Есть сильное желание все-же пользоваться ИАР-ом. Пользуйтесь. V5 очень приличный. V4 часто немного проигрывал тому-же Keil (который АРМ  ), особенно на библиотеках, то теперь идут практически ноздря в ноздрю. До кучи к ним GCC - тоже нормальный. Остальные явно отстают от этой троицы. Цитата правда идея самому писать хидер меня несколько пугает. На мой взгляд, более идиотсое занятие себе вообще трудно придумать. Почему? Все сразу писать не надо. А постепенно, да еше имея какую-никакую болванку пороблем не вижу, тем более, что читать все равно надо  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 15 2008, 20:43
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Artem_Petrik @ Jun 16 2008, 00:28)  Да я пока не очень то увлекаюсь выбором компиляторов. Есть сильное желание все-же пользоваться ИАР-ом. Просто он иногда меня сильно удивляет. Впрочем ваш LPC-шный пример выглядит прилично, так что возможно и впрямь проблема в неадекватном хидере. У меня AT91SAM7X256. Насчет RealView советую серьёзно подумать. Особенно если нет стойкой привычки к IAR'у  Дело не столько в хидерах, сколько в стиле написания программы: Код 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).
|
|
|
|
|
Jun 15 2008, 20:49
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Стоп! Что-то у меня лыжи не едут! Откомпилил у себя ваш вариант под ЛПЦ, (правда у меня не поняло выражение 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 Значит у меня все же что-то или с настройками компилятора, или одно из двух. Подскажите какая у вас версия и настройки компилятора. Не успокоюсь, пока не получу у себя такойже код как у вас!
|
|
|
|
|
Jun 15 2008, 20:56
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Цитата(aaarrr @ Jun 15 2008, 23:51)  Оптимизация-то включена вообще? Да, Level = High, все галочки стоят. От варианта Speed/size/balanced практически ничего не меняется.
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|