jcxz 5 Posted December 21, 2020 · Report post Обнаружил ещё один баг IAR 7.80.4. Наблюдается при конвертировании 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! Очень серьёзный баг. Теперь непонятно - как вообще до сих пор что-то с плавающей арифметикой на нём работало??? Если убрать умножение на 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 - не помогает. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
MrBearManul 0 Posted December 21, 2020 · Report post 1 час назад, jcxz сказал: Теперь непонятно - как вообще до сих пор что-то с плавающей арифметикой на нём работало??? Спасибо за то, что поделились. Будете обновляться до 8.40? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Arlleex 1 Posted December 21, 2020 · Report post 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] Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
MrBearManul 0 Posted December 21, 2020 (edited) · Report post 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 December 21, 2020 by MrBearManul Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Arlleex 1 Posted December 21, 2020 · Report post 22 минуты назад, MrBearManul сказал: Попробовал тоже присоединиться) Результат в данном случае, конечно, будет одинаковый, но просто интересно, почему IAR не может просто взять и сложить. Хотя кто ему под капот заглянет... P.S. Че-то у IAR бедно с доставаемостью определенных версий и релиз-справок к ним. Для Keil я так однажды очень быстро нашел свой баг как fixed. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Xenia 0 Posted December 21, 2020 · Report post 3 часа назад, Arlleex сказал: P.S. Че-то у IAR бедно с доставаемостью определенных версий и релиз-справок к ним. Для Keil я так однажды очень быстро нашел свой баг как fixed. На FTP, куда вы уже имеете доступ, есть все версии IAR. А "релиз-справки" по ним, как и прочие описания, можно добыть без инсталляции - для этого достаточно переименовать инсталятор из EXE в ZIP и выбрать из этого архива то, что вам нужно. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Arlleex 1 Posted December 21, 2020 · Report post 2 минуты назад, Xenia сказал: ...для этого достаточно переименовать инсталятор из EXE в ZIP и выбрать из этого архива то, что вам нужно. О как! Спасибо, не знал Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jcxz 5 Posted December 21, 2020 · Report post 9 часов назад, MrBearManul сказал: Спасибо за то, что поделились. Будете обновляться до 8.40? А почему 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] всё то же самое. И видимо во всех версиях 7.80.4...8.50.4 (как минимум) будет аналогично. Похоже нужно писать в поддержку..... Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
antis 0 Posted December 21, 2020 · Report post А значение float отрицательное? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jcxz 5 Posted December 21, 2020 · Report post 27 минут назад, antis сказал: А значение float отрицательное? Конечно. На отрицательных и проявляется. PS: написал в поддержку. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
MrBearManul 0 Posted December 21, 2020 · Report post 13 минут назад, jcxz сказал: PS: написал в поддержку. Будьте добры обязательно поделиться ответом Действительно интересный баг, кочующий через вереницу версий компилятора... 4 часа назад, jcxz сказал: Я писал что и у меня если отсутствует умножение на степень 2 при конвертации, то тоже баг не проявляется. Виноват, был невнимателен. Завтра проверю ещё раз. Сегодня у меня уже вечер и делать ничего не хочется))) Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jcxz 5 Posted December 21, 2020 · Report post 2 часа назад, MrBearManul сказал: Будьте добры обязательно поделиться ответом Действительно интересный баг, кочующий через вереницу версий компилятора... Веду переписку с поддержкой. Создал для них проект, где этот баг проявляется. Цепляю его сюда, чтобы любой желающий мог у себя проверить. 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-ом. И неужели за всё это время никто на него не наступал? Как такое может быть??? Не понимаю.... Я - понятное дело - я ранее почти не работал с плавучкой на Cortex-M (только отдельные редкие случаи), поэтому и не наступал (он ещё и проявляется не всегда, а в определённых условиях). Но ведь я так понимаю - куча народу работает с float на CM4/CM7, и неужто никто не наступал на него до сих пор?? Просто удивительно.... Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
antis 0 Posted December 21, 2020 (edited) · Report post 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 December 21, 2020 by antis Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jcxz 5 Posted December 21, 2020 · Report post 52 минуты назад, antis сказал: Не этот случай? Нет конечно. Смотрите внимательнее: там приведение к unsigned int, у меня - к signed int. Там ARM-компилятор всё делает правильно. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
VladislavS 0 Posted December 21, 2020 · Report post Я думаю компилятор видит тут беззнаковое сложение. К нему и приводит. Если вот так? res32 = (int)(eeg[i]*16) + (int)B15; Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...