jcxz 234 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба Обнаружил ещё один баг 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 - не помогает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 1 час назад, jcxz сказал: Теперь непонятно - как вообще до сих пор что-то с плавающей арифметикой на нём работало??? Спасибо за то, что поделились. Будете обновляться до 8.40? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 178 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 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] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 21 декабря, 2020 Опубликовано 21 декабря, 2020 (изменено) · Жалоба 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" результат одинаковый. Изменено 21 декабря, 2020 пользователем MrBearManul Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 178 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 22 минуты назад, MrBearManul сказал: Попробовал тоже присоединиться) Результат в данном случае, конечно, будет одинаковый, но просто интересно, почему IAR не может просто взять и сложить. Хотя кто ему под капот заглянет... P.S. Че-то у IAR бедно с доставаемостью определенных версий и релиз-справок к ним. Для Keil я так однажды очень быстро нашел свой баг как fixed. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 43 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 3 часа назад, Arlleex сказал: P.S. Че-то у IAR бедно с доставаемостью определенных версий и релиз-справок к ним. Для Keil я так однажды очень быстро нашел свой баг как fixed. На FTP, куда вы уже имеете доступ, есть все версии IAR. А "релиз-справки" по ним, как и прочие описания, можно добыть без инсталляции - для этого достаточно переименовать инсталятор из EXE в ZIP и выбрать из этого архива то, что вам нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 178 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 2 минуты назад, Xenia сказал: ...для этого достаточно переименовать инсталятор из EXE в ZIP и выбрать из этого архива то, что вам нужно. О как! Спасибо, не знал Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 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 (как минимум) будет аналогично. Похоже нужно писать в поддержку..... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
antis 1 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба А значение float отрицательное? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 27 минут назад, antis сказал: А значение float отрицательное? Конечно. На отрицательных и проявляется. PS: написал в поддержку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 13 минут назад, jcxz сказал: PS: написал в поддержку. Будьте добры обязательно поделиться ответом Действительно интересный баг, кочующий через вереницу версий компилятора... 4 часа назад, jcxz сказал: Я писал что и у меня если отсутствует умножение на степень 2 при конвертации, то тоже баг не проявляется. Виноват, был невнимателен. Завтра проверю ещё раз. Сегодня у меня уже вечер и делать ничего не хочется))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 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, и неужто никто не наступал на него до сих пор?? Просто удивительно.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
antis 1 21 декабря, 2020 Опубликовано 21 декабря, 2020 (изменено) · Жалоба 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 делает также Изменено 21 декабря, 2020 пользователем antis Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба 52 минуты назад, antis сказал: Не этот случай? Нет конечно. Смотрите внимательнее: там приведение к unsigned int, у меня - к signed int. Там ARM-компилятор всё делает правильно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 21 декабря, 2020 Опубликовано 21 декабря, 2020 · Жалоба Я думаю компилятор видит тут беззнаковое сложение. К нему и приводит. Если вот так? res32 = (int)(eeg[i]*16) + (int)B15; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться