Jump to content

    
jcxz

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

Recommended Posts

Обнаружил ещё один баг 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 - не помогает.

Share this post


Link to post
Share on other sites
1 час назад, jcxz сказал:

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

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

Share this post


Link to post
Share on other sites
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] 

Share this post


Link to post
Share on other sites
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" результат одинаковый.

 

 

Edited by MrBearManul

Share this post


Link to post
Share on other sites
22 минуты назад, MrBearManul сказал:

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

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

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

Share this post


Link to post
Share on other sites
3 часа назад, Arlleex сказал:

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

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

Share this post


Link to post
Share on other sites
2 минуты назад, Xenia сказал:

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

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

Share this post


Link to post
Share on other sites
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:

Share this post


Link to post
Share on other sites
13 минут назад, jcxz сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites
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:

Share this post


Link to post
Share on other sites
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 делает также

 

Edited by antis

Share this post


Link to post
Share on other sites
52 минуты назад, antis сказал:

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

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.