Перейти к содержанию
    

Баг IAR 7.80.4 (ARM) при работе с float.

Обнаружил ещё один баг IAR 7.80.4.  :sad::sad::sad:

Наблюдается при конвертировании float->int.

     adcVkt.in0 = __SSAT((int)(eegEmu[c] * 8), 12) + B15;   
0x.... 0x....      ADR.W    R1,eegEmu                       
0xEB01 0x0180      ADD      R1,R1,R0, LSL #+2               
0xED91 0x0A00      VLDR     S0,[R1, #0]                     
0xEEBF 0x0AEE      VCVT.U32.F32 S0,S0,#+3                   
0xEE10 0x1A10      VMOV     R1,S0                           
0xF301 0x010B      SSAT     R1,#+12,R1                      
0xF5A1 0x4100      SUB      R1,R1,#+32768                   
0x81A9             STRH     R1,[R5, #+12]

или то же самое:

     adcVkt.in0 = (int)(eegEmu[c] * 8) + B15; 
0x.... 0x....      ADR.W    R1,eegEmu         
0xEB01 0x0180      ADD      R1,R1,R0, LSL #+2 
0xED91 0x0A00      VLDR     S0,[R1, #0]       
0xEEBF 0x0A66      VCVT.U16.F32 S0,S0,#+3     
0xEE10 0x1A10      VMOV     R1,S0             
0xF5A1 0x4100      SUB      R1,R1,#+32768     
0x81A9             STRH     R1,[R5, #+12]

где:

uint c;
float const eegEmu[];

Ожидается, что (int)(eegEmu[c] * 8) выполнит конвертирование float->int. Но IAR почему-то делает VCVT.U32.F32 S0,S0,#+3, а это float->unsigned int!  :sad::sad::sad:

Очень серьёзный баг. Теперь непонятно - как вообще до сих пор что-то с плавающей арифметикой на нём работало???  :russian_ru:

 

Если убрать умножение на 8, то всё ок:

     adcVkt.in0 = (int)eegEmu[c] + B15;       
0x.... 0x....      ADR.W    R1,eegEmu         
0xEB01 0x0180      ADD      R1,R1,R0, LSL #+2 
0xED91 0x0A00      VLDR     S0,[R1, #0]       
0xEEBD 0x0AC0      VCVT.S32.F32 S0,S0         
0xEE10 0x1A10      VMOV     R1,S0             
0xF5A1 0x4100      SUB      R1,R1,#+32768     
0x81A9             STRH     R1,[R5, #+12]

Явное приведение (int)8 - не помогает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, jcxz сказал:

Теперь непонятно - как вообще до сих пор что-то с плавающей арифметикой на нём работало???

Спасибо за то, что поделились. Будете обновляться до 8.40?:acute:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, jcxz сказал:

0xF5A1 0x4100 SUB R1, R1, #+32768

Как у Вас B15 определен и adcVkt.in0? Не смог заставить Keil сгенерировать вычитание (да и откуда оно тут?).

#define B15 (1u << 15)

void func(void)
{
  unsigned int n    = getN();
  const float  f[2] = {1.2f, 3.4f};
  signed short r    = (int)f[n] + B15;
}
  r = (int)f[n] + B15;
0x08000374 EB000084 ADD          r0, r0, r4, LSL #2
0x08000378 ED900A00 VLDR         s0, [r0, #0x00]
0x0800037C EEBD0AC0 VCVT.S32.F32 s0, s0
0x08000380 EE100A10 VMOV         r0, s0
0x08000384 F5004000 ADD          r0, r0, #0x8000
0x08000388 F8AD0000 STRH         r0, [sp, #0x00] 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 минут назад, Arlleex сказал:

Не смог заставить Keil сгенерировать вычитание (да и откуда оно тут?).

Попробовал тоже присоединиться)

#define B15 (1u << 15)

void func( void ) {
    unsigned int n    = getN();
    const float  f[2] = {1.2f, 3.4f};
    signed short r    = (int)f[n] + B15;
}

Листинг

     74              signed short r    = (int)f[n] + B15;
                                  ^
Warning[Pe177]: variable "r" was declared but never referenced
   \       0x12   0x4669             MOV      R1,SP
   \       0x14   0xEB01 0x0180      ADD      R1,R1,R0, LSL #+2
   \       0x18   0xED91 0x0A00      VLDR     S0,[R1, #0]
   \       0x1C   0xEEBD 0x0AC0      VCVT.S32.F32 S0,S0
   \       0x20   0xEE10 0x1A10      VMOV     R1,S0
   \       0x24   0xF5B1 0x4100      SUBS     R1,R1,#+32768
     75          }
   \       0x28   0xBD13             POP      {R0,R1,R4,PC}    ;; return

Как видно, у меня тоже вычитание. Но команда сопроцессору даётся правильная. IAR 8.40.1. Без оптимизации и с оптимизацией "Low" результат одинаковый.

 

 

Изменено пользователем MrBearManul

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 минуты назад, MrBearManul сказал:

Попробовал тоже присоединиться)

Результат в данном случае, конечно, будет одинаковый, но просто интересно, почему IAR не может просто взять и сложить. Хотя кто ему под капот заглянет...:smile:

P.S. Че-то у IAR бедно с доставаемостью определенных версий и релиз-справок к ним. Для Keil я так однажды очень быстро нашел свой баг как fixed.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Arlleex сказал:

P.S. Че-то у IAR бедно с доставаемостью определенных версий и релиз-справок к ним. Для Keil я так однажды очень быстро нашел свой баг как fixed.

На FTP, куда вы уже имеете доступ, есть все версии IAR. А "релиз-справки" по ним, как и прочие описания, можно добыть без инсталляции - для этого достаточно переименовать инсталятор из EXE в ZIP и выбрать из этого архива то, что вам нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, Xenia сказал:

...для этого достаточно переименовать инсталятор из EXE в ZIP и выбрать из этого архива то, что вам нужно.

О как! Спасибо, не знал:smile:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 часов назад, MrBearManul сказал:

Спасибо за то, что поделились. Будете обновляться до 8.40?:acute:

А почему 8.40? Есть же давно >8.50. Или с 8.50 какие-то проблемы?

5 часов назад, Arlleex сказал:

Как у Вас B15 определен и adcVkt.in0? Не смог заставить Keil сгенерировать вычитание (да и откуда оно тут?).

#define B15 0x00008000ul

А какая разница? Там по коду без разницы - вычитание или сложение, поэтому думаю так и генерится. Не в этом проблема.

4 часа назад, MrBearManul сказал:

Как видно, у меня тоже вычитание. Но команда сопроцессору даётся правильная. IAR 8.40.1. Без оптимизации и с оптимизацией "Low" результат одинаковый.

Посмотрите мои примеры внимательнее. Я писал что и у меня если отсутствует умножение на степень 2 при конвертации, то тоже баг не проявляется. Он проявляется только когда есть умножение на степень 2. И даже в этих случаях - не всегда. На другом участке этой же самой программы есть похожая операция (float->int с умножением на степень 2) и там IAR ставит правильную команду. Я так и не смог определить какие точно условия приводят к багу. Оптимизация и пр. - никак не влияют, в одной и той же программе (с одинаковыми ключами компиляции для всех файлов) в разных её местах подобный код может компилиться как правильно, так и с багом.

 

PS: Только что попробовал скомпилить этот код в установленном "IAR ANSI C/C++ Compiler V8.50.4.261/W32 for ARM". Результат:

     adcVkt.in0 = (int)(eegEmu[c] * 8) + B15;
0x....'....        ADR.W    R1,eegEmu        
0xEB01 0x0180      ADD      R1,R1,R0, LSL #+2
0xED91 0x0A00      VLDR     S0,[R1, #0]      
0xEEBF 0x0A66      VCVT.U16.F32 S0,S0,#+3    
0xEE10 0x1A10      VMOV     R1,S0            
0xF5A1 0x4100      SUB      R1,R1,#+32768    
0x81A9             STRH     R1,[R5, #+12]

всё то же самое. :sad::sad::sad::sad::sad:

И видимо во всех версиях 7.80.4...8.50.4 (как минимум) будет аналогично.

Похоже нужно писать в поддержку..... :russian_ru:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

27 минут назад, antis сказал:

А значение float отрицательное?

Конечно. На отрицательных и проявляется.

 

PS: написал в поддержку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 минут назад, jcxz сказал:

PS: написал в поддержку.

Будьте добры обязательно поделиться ответом:blum: Действительно интересный баг, кочующий через вереницу версий компилятора...

4 часа назад, jcxz сказал:

Я писал что и у меня если отсутствует умножение на степень 2 при конвертации, то тоже баг не проявляется.

Виноват, был невнимателен. Завтра проверю ещё раз. Сегодня у меня уже вечер и делать ничего не хочется)))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, MrBearManul сказал:

Будьте добры обязательно поделиться ответом:blum: Действительно интересный баг, кочующий через вереницу версий компилятора...

Веду переписку с поддержкой. Создал для них проект, где этот баг проявляется. Цепляю его сюда, чтобы любой желающий мог у себя проверить.  fw_00235910.zip

 

Это для "IAR V8.50.4.261/W32", но похоже и в промежуточных версиях будет то же самое.

Баги видны в main.lst:

0xEEBF 0x0A66      VCVT.U16.F32 S0,S0,#+3    

0xEEBF 0x0ACE      VCVT.U32.F32 S0,S0,#+4

Т.е. - и для слов и для полуслов он возникает.

 

PS: У меня в связи с этим возник вопрос: Получается баг этот имеется уже давно (много лет, много версий IAR), куча народу пользуется IAR-ом. И неужели за всё это время никто на него не наступал? :scratch_one-s_head:

Как такое может быть??? Не понимаю....

Я - понятное дело - я ранее почти не работал с плавучкой на Cortex-M (только отдельные редкие случаи), поэтому и не наступал (он ещё и проявляется не всегда, а в определённых условиях). Но ведь я так понимаю - куча народу работает с float на CM4/CM7, и неужто никто не наступал на него до сих пор?? Просто удивительно....  :scratch_one-s_head:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, jcxz сказал:

Конечно. На отрицательных и проявляется.

 

PS: написал в поддержку.

Не этот случай?

https://stackoverflow.com/questions/2490600/iphone-floats-cast-to-unsigned-ints-get-set-to-0-if-they-are-negative

https://stackoverflow.com/questions/10541200/is-the-behaviour-of-casting-a-negative-double-to-unsigned-int-defined-in-the-c-s

 

Если, да, то gcc делает также

 

Изменено пользователем antis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

52 минуты назад, antis сказал:

Не этот случай?

Нет конечно. Смотрите внимательнее: там приведение к unsigned int, у меня - к signed int.

Там ARM-компилятор всё делает правильно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я думаю компилятор видит тут беззнаковое сложение. К нему и приводит. Если вот так?

res32 = (int)(eeg[i]*16) + (int)B15;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...