В переферийных регистрах очень много битовых полей и часто их надо менять по отдельности (например настройка GPIO в STM32F103). Естсетвенно это делается через Read-Modify-Write, но вот установку битового поля уже в регистре IAR как то делает совсем криво. (Смотрел листинг инициализации одной ноги на вывод для STM32)
Потом написал простейший тест для коротких и длинных полей.
Код
struct bf_s {
unsigned f1:6;
unsigned f2:2;
unsigned f3:20;
unsigned f4:4;
} bf;
void short_clear(void)
{
bf.f2 = 0;
}
void short_set(void)
{
bf.f2 = 3;
}
void short_const(void)
{
bf.f2 = 1;
}
void short_var(unsigned val)
{
bf.f2 = val;
}
void long_clear(void)
{
bf.f3 = 0;
}
void long_set(void)
{
bf.f3 = (1<<20)-1;
}
void long_const(void)
{
bf.f3 = 1;
}
void long_var(unsigned val)
{
bf.f3 = val;
}
Компилировал IAR 4.42 IAR 5.11 и RVCT 3.1
Код
"...5.0\ARM\bin\iccarm.exe" --cpu Cortex-M3 -Ohs -lCN iar511.txt bit_test.c
"...4.0\arm\bin\iccarm.exe" --cpu Cortex-M3 -s9 -lCN iar442.txt bit_test.c
"...RVCT31_616_windows\armcc" -S -O3 -Otime --cpu Cortex-M3 bit_test.c
И вот что получилось 4.42 и 5.11 дали идентичный код (в одном месте инструкции местами поменялись не принципиально) и IAR вообще не использует инструкции BFC и BFI ( после 32 битных иснтрукций вставлял пустую строку)
Код
IAR RVCT
--------------------------------------------------------------------------
Очистка LDR.N R0,??DataTable10 LDR r0,|L1.100|
По размеру кода MOVS R2,#+192 LDR r1,[r0,#0]
одинаково но IMHO LDR R1,[R0, #+0] BIC r1,r1,#0xc0
RVCT оптимальнее. BICS R1,R1,R2
Меньше R использует STR R1,[R0, #+0] STR r1,[r0,#0]
BX LR BX lr
--------------------------------------------------------------------------
Установка все 1 LDR.N R0,??DataTable10 LDR r0,|L1.100|
Идентично LDR R1,[R0, #+0] LDR r1,[r0,#0]
ORRS R1,R1,#0xC0 ORR r1,r1,#0xc0
STR R1,[R0, #+0] STR r1,[r0,#0]
BX LR BX lr
--------------------------------------------------------------------------
Константа LDR.N R0,??DataTable10 LDR r0,|L1.100|
По размеру кода MOVS R2,#+192 LDR r1,[r0,#0]
одинаково но IMHO LDR R1,[R0, #+0] BIC r1,r1,#0xc0
RVCT оптимальнее. BICS R1,R1,R2
Меньше R использует ORRS R1,R1,#0x40 ADDS r1,r1,#0x40
STR R1,[R0, #+0] STR r1,[r0,#0]
BX LR BX lr
--------------------------------------------------------------------------
Запись переменной LDR.N R1,??DataTable10 LDR r2,|L1.100|
Ну здесь про IAR MOVS R3,#+192 LDR r1,[r2,#0]
вообще NO COMENTS LDR R2,[R1, #+0] BFI r1,r0,#6,#2
ANDS R0,R3,R0, LSL #+6
STR r1,[r2,#0]
BICS R2,R2,R3 BX lr
ORRS R0,R0,R2
STR R0,[R1, #+0]
BX LR
--------------------------------------------------------------------------
Чистка больше 8 бит. LDR.N R0,??DataTable10 LDR r1,|L1.100|
У IAR больше R и LDR.N R2,??DataTable11 LDR r0,[r1,#0]
лишняя загрузка из LDR R1,[R0, #+0] BFC r0,#8,#20
памяти ANDS R2,R2,R1
STR R2,[R0, #+0] STR r0,[r1,#0]
BX LR BX lr
--------------------------------------------------------------------------
Установка все 1 LDR.N R0,??DataTable10 LDR r0,|L1.100|
Идентично LDR.N R2,??DataTable12 LDR r2,|L1.104|
LDR R1,[R0, #+0] LDR r1,[r0,#0]
ORRS R2,R2,R1 ORRS r1,r1,r2
STR R2,[R0, #+0] STR r1,[r0,#0]
BX LR BX lr
--------------------------------------------------------------------------
Константа больше 8 LDR.N R0,??DataTable10 LDR r1,|L1.100|
бит. LDR.N R2,??DataTable11 MOVS r2,#1
У IAR лишняя LDR R1,[R0, #+0] LDR r0,[r1,#0]
загрузка из памяти ANDS R2,R2,R1 BFI r0,r2,#8,#20
Да и код больше! ORRS R1,R2,#0x100
STR r0,[r1,#0]
STR R1,[R0, #+0] BX lr
BX LR
--------------------------------------------------------------------------
Переменная больше 8 LDR.N R1,??DataTable10 LDR r2,|L1.100|
бит. LDR.N R3,??DataTable11 LDR r1,[r2,#0]
Ну здесь про IAR LDR R2,[R1, #+0] BFI r1,r0,#8,#20
вообще NO COMENTS ANDS R3,R3,R2
LDR.N R2,??DataTable12 STR r1,[r2,#0]
ANDS R0,R2,R0, LSL #+8 BX lr
ORRS R0,R0,R3
STR R0,[R1, #+0]
BX LR