Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблемка с IAR 6.30.1 для Cortex
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
VslavX
Попробовал IAR 6.30.1 для Cortex-M3, нарисовалась проблема.
Есть такой код:
CODE
#define b0_l(L) ((unsigned char)((L) & 0xFF))
#define b1_l(L) ((unsigned char)(((L)>>8) & 0xFF))
#define b2_l(L) ((unsigned char)(((L)>>16) & 0xFF))
#define b3_l(L) ((unsigned char)(((L)>>24) & 0xFF))

unsigned long IsDate(unsigned long d)
{
if ( (b0_l(d)<1) || (b0_l(d)>31)
|| (b1_l(d)<1) || (b1_l(d)>12)
|| (b2_l(d)>21) || (b3_l(d)!=0))
{
return 0;
}
if (d == 0x101)
{
return 0;
}
return 1;
}

Функция просто предварительно проверяет значение даты, упакованной в unsigned long.
При наличии ключей оптимизации -Om (или -Ohz, другую не пробовал) превращается в такое:
CODE
\ In section .text, align 2, keep-with-next
49 unsigned long IsDate(unsigned long d)
50 {
51 if ( (b0_l(d)<1) || (b0_l(d)>31)
52 || (b1_l(d)<1) || (b1_l(d)>12)
53 || (b2_l(d)>21) || (b3_l(d)!=0))
\ IsDate:
\ 00000000 0x1E41 SUBS R1,R0,#+1
\ 00000002 0x291F CMP R1,#+31
\ 00000004 0xBF3E ITTT CC
\ 00000006 0x0A01 LSRCC R1,R0,#+8
\ 00000008 0x1E49 SUBCC R1,R1,#+1
\ 0000000A 0x290C CMPCC R1,#+12
\ 0000000C 0xBF3E ITTT CC
\ 0000000E 0x0C01 LSRCC R1,R0,#+16
\ 00000010 0xB2C9 UXTBCC R1,R1
\ 00000012 0x2916 CMPCC R1,#+22
\ 00000014 0xD205 BCS.N ??IsDate_0
\ 00000016 0x0E01 LSRS R1,R0,#+24
\ 00000018 0xD103 BNE.N ??IsDate_0
54 {
55 return 0;
56 }
57 if (d == 0x101)
\ 0000001A 0xF240 0x1101 MOVW R1,#+257
\ 0000001E 0x4288 CMP R0,R1
\ 00000020 0xD101 BNE.N ??IsDate_1
58 {
59 return 0;
\ ??IsDate_0:
\ 00000022 0x2000 MOVS R0,#+0
\ 00000024 0x4770 BX LR
60 }
61 return 1;
\ ??IsDate_1:
\ 00000026 0x2001 MOVS R0,#+1
\ 00000028 0x4770 BX LR ;; return
62 }


И не работает правильно.
На версии 5.41 компилируется в рабочий код. Вопрос такой - это я C плоховато знаю или таки глюк компилятора?
upd: привел пример к стандартным типам (убрал typedef свои), чтобы не путались
KRS
Да - в оптимизации явно глюк!
Возможно связан с тем что в макросе лишняя операция :
& 0xff
и
(unsigned char) преобразование типа к байту

можно оставить что то одно!
Лучше убрать (unsigned char) так производительность выше!
Потому что если локальная переменная в регистре байтовая ей ARM компилер постоянно чистит старшие биты!
VslavX
Цитата(KRS @ Nov 4 2011, 22:46) *
Да - в оптимизации явно глюк!
Возможно связан с тем что в макросе лишняя операция :
& 0xff
и
(unsigned char) преобразование типа к байту

можно оставить что то одно!

Да, если убрать преобразование типа (unsigned char) в макросах, то именно это место компилируется правильно. Беда в том, что этим макросам лет 20, и страшно представить сколько кода на данный момент на них основано - для 8-битных AVR, 16-битных x86 и для 32-битных ARM. Поэтому поменять макросы малореально.
scifi
Может расскажете, где именно в дизассемблере неправильно? Я смотрел, но ничего особенного не увидел...

Update:
Кажется, увидел. На первой же инструкции делает вычитание из 32-битного аргумента, а должен был сначала отрезать старшие 24 бита.
KRS
Цитата(VslavX @ Nov 5 2011, 01:07) *
8-битных AVR, 16-битных x86 и для 32-битных ARM. Поэтому поменять макросы малореально.

Есть же
#ifdef

к тому же если убрать одну из операций, оптимальнее преобразование типа - макросы все равно будут рабочими и более оптимальными.

VslavX
Цитата(KRS @ Nov 4 2011, 23:57) *
Есть же #ifdef
к тому же если убрать одну из операций, оптимальнее преобразование типа - макросы все равно будут рабочими и более оптимальными.

1. Убирание "& 0xFF" ситуацию не исправляет - компилируется с той же ошибкой, глючит именно на unsigned char.
2. #ifdef не поможет скомпилировать желаемое для выражений подразумевающих что макрос bx_l() имеет тип unsigned char. То есть - эти выражения все надо будет патчить в куче мест, вставляя явное приведение типа (которое Вы предлагаете выбросить из макроса). Пример - код типа: "unsigned char var1 = b0_l((unsigned long)var2);" даст предупреждение.
dvb
Цитата(VslavX @ Nov 5 2011, 21:58) *
1. Убирание "& 0xFF" ситуацию не исправляет - компилируется с той же ошибкой, глючит именно на unsigned char.
2. #ifdef не поможет скомпилировать желаемое для выражений подразумевающих что макрос bx_l() имеет тип unsigned char. То есть - эти выражения все надо будет патчить в куче мест, вставляя явное приведение типа (которое Вы предлагаете выбросить из макроса). Пример - код типа: "unsigned char var1 = b0_l((unsigned long)var2);" даст предупреждение.


Основная проблема не в том, что определенными телодвижениями можно замести это под ковер, и заставить код работать правильно. А в том, что этот код правильно компилировался десятком разных компиляторов, начиная с BC3.1 и заканчивая IAR 5.41. И не факт, что где-нибудь компилятор не оставит незаметную мину, которая сработает в очень редко вызываемой ветке программы в самый неподходящий момент.

Пока от версии IAR 6.30 пришлось отказаться.
KRS
а у IAR периодически вылезают баги с количеством битов при преобразованиях типов и &
скоро вылечат!
Относительно недавно на подобный баг натыкался, поэтому сразу и понял что проблема в преобразовании типов.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.