Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: По-моему, глюк компилятора
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Непомнящий Евгений
Компилятор IAR AVR 4.30.1.3
Процессор ATMEGA2560
С++, максимальная оптимизация по скорости.
Полный текст приведен во вложении, там же lst - файл.
Проблема в функции tpzBINtoBCD, в следующем ее фрагменте:
Код
while(true)
{
   bool isLim = res.loc == bcd;  
   ...
}

res.loc и bcd - это объекты типа TBCDLocation (фактически - "указатель на тетраду байта", т.е. указатель на байт + признак старший\младший). Оператор == для них перегружен так:
Код
INLINE bool TBCDLocation::operator==(const TBCDLocation& b)
{
  return buf==b.buf && isFH==b.isFH;
}

Впрочем, если "проинлайнить" его руками, т.е. написать bool isLim = res.loc.buf == bcd.buf && res.loc.isFH==bcd.isFH - ничего не изменится.
Так вот, этот кусочек компилится так:
Код
250:                  bool isLim = res.loc == bcd;  
+0000011A:   1502        CP      R16,R2           Compare
+0000011B:   0513        CPC     R17,R3           Compare with carry
+0000011C:   F429        BRNE    PC+0x06          Branch if not equal
+0000011D:   2F12        MOV     R17,R18          Copy register       <<<<<
+0000011E:   1514        CP      R17,R4           Compare
+0000011F:   F411        BRNE    PC+0x03          Branch if not equal
+00000120:   E0E1        LDI     R30,0x01         Load immediate
+00000121:   C001        RJMP    PC+0x0002        Relative jump
+00000122:   E0E0        LDI     R30,0x00         Load immediate
+00000123:   2E5E        MOV     R5,R30           Copy register

res.loc лежит в трех регистрах: 17,16 - указатель на байт и 18 - признак старший\младший.
В указанной строчке 17 регистр перетирается 18-м и больше нигде не восстанавливается. Соответственно, при следующем обращении к res.loc получается бяка.
Если переписать функцию tpzBINtoBCD так, чтобы loc и isOverflow лежали в отдельных переменных и "собирались вместе" перед return, все прекрасно работает (этот вариант функции закомментирован в прилагаемом файле).
При этом получается такой ассемблерный код:
Код
313:                  bool isLim = msBCD == bcd;  
+00000112:   1768        CP      R22,R24          Compare
+00000113:   0779        CPC     R23,R25          Compare with carry
+00000114:   F421        BRNE    PC+0x05          Branch if not equal
+00000115:   16BB        CP      R11,R27          Compare
+00000116:   F411        BRNE    PC+0x03          Branch if not equal
+00000117:   E0E1        LDI     R30,0x01         Load immediate
+00000118:   C001        RJMP    PC+0x0002        Relative jump
+00000119:   E0E0        LDI     R30,0x00         Load immediate
+0000011A:   2E3E        MOV     R3,R30           Copy register

С точностью до номеров регистров все так же, как и выше, но нехорошего MOV уже нет.
Без оптимизации все работает и в первом варианте.

PS. программка тестовая, соответственно прерывания не включались.
PPS. пробовал скомпилировать под ATMEGA128 - проблема осталась.
rezident
А вы не пробовали пользоваться скобками, чтобы более доступно объяснить компилятору, чего же вы от него хотите?
Непомнящий Евгений
Цитата(rezident @ Nov 11 2007, 16:19) *
А вы не пробовали пользоваться скобками, чтобы более доступно объяснить компилятору, чего же вы от него хотите?


Не понял вашего предложения: a==b && c==d - сначала проверка на равенство, потом and. Счас ради интереса попробовал ( a ==b ) && (c == d), не помогло.
alexander55
Цитата(Непомнящий Евгений @ Nov 12 2007, 08:10) *
Не понял вашего предложения: a==b && c==d - сначала проверка на равенство, потом and. Счас ради интереса попробовал ( a ==b ) && (c == d), не помогло.

Имеется ввиду
INLINE bool TBCDLocation::operator==(const TBCDLocation& cool.gif
{
return ((buf==b.buf) && (isFH==b.isFH));
}
Непомнящий Евгений
Цитата(alexander55 @ Nov 12 2007, 08:57) *
Имеется ввиду
INLINE bool TBCDLocation::operator==(const TBCDLocation& b )
{
return ((buf==b.buf) && (isFH==b.isFH));
}


Я собственно это и сделал. Ничего не дало. Да и с какой радости должно дать - приоритет == больше, чем у &&.
alexander55
Цитата(Непомнящий Евгений @ Nov 12 2007, 12:49) *
Я собственно это и сделал. Ничего не дало. Да и с какой радости должно дать - приоритет == больше, чем у &&.

Когда, что-то не работает проверяется все. Попробуйте отключить оптимизацию для начала.
Непомнящий Евгений
Цитата(alexander55 @ Nov 12 2007, 13:19) *
Когда, что-то не работает проверяется все. Попробуйте отключить оптимизацию для начала.

Без оптимизации работает. Второй вариант работает и с оптимизацией и без, собственно им я и пользуюсь. Просто странно как-то. Первый раз напоролся на четкий глюк smile.gif
alexander55
Цитата(Непомнящий Евгений @ Nov 12 2007, 13:42) *
Без оптимизации работает. Второй вариант работает и с оптимизацией и без, собственно им я и пользуюсь. Просто странно как-то. Первый раз напоролся на четкий глюк smile.gif

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