Хоть я и откланялся, но господину sonycman'у отвечу, потому как тема имеет тенденцию сдвигаться в немного другую область, нежели IAR vs GCC.
Цитата
Неважнецки получается у GCC работа со структурой в нижеприведённой функции.
Вообщем-то философия оптимизации данной функции гнусем понятна - загрузить в регистры все что можно и на выходе выгрузить. Подход правильный, основанный на общей идеологии RISC и Load-Store. Но в данном случае он немного не оправдывает себя.
IAR подходит к проблеме утилизации Load-Store с более сдержанных позиций, он выполняет эти операции в более локальной окрестности действий с полями структуры. С другой стороны, это позволяет кодеру помочь компилятору в ручном указании, какие переменные стоит загрузить в самом начале (и сохранить в самом конце), какие - нет. Я пришел к следующей эмпирической оценке - оцениваю количество обращений к переменной. Если их больше 3, то имеет смысл переносить переменную в регистр. Причем, чем больше обращений (с учетом циклов), тем выше приоритет переменной на перенос в регистр. Ну и не забывать, что операция a=b++ - суть 2 обращения, а иногда и 3.
Можно ли так подсказать гнусю - я затрудняюсь ответить, необходимо проверять.
Кроме того, я бы флаги ошибок собрал бы в битовой структуре. Так проще. В результате, получился бы примерно следующий код (IAR)
Код
typedef struct
{
byte frame_err:1,ovrun_err:1,parity_err:1,length_err:1,lock_err:1,chksum_err:1,unknown_command:1;
} USART_ERRORS;
struct usart_rx_status
{
byte counter;
byte mode;
volatile byte data_available;
USART_ERRORS err;
} statusRx;
#pragma vector=USART_RX_vect
__interrupt void ISR_USART_RX(void)
{
static __flash byte sign[] = {'S','N'};
static byte save_length;
byte data, state;
USART_ERRORS err=statusRx.err;
byte length=save_length;
byte counter=statusRx.counter;
do
{
state = UCSR0A;
data = UDR0;
if (statusRx.data_available)
{
err.lock_err = TRUE;
continue;
}
if (state & ((1<<FE0)|(1<<DOR0)|(1<<UPE0)))
{
if (state & (1<<FE0)) err.frame_err = TRUE;
if (state & (1<<DOR0)) err.ovrun_err = TRUE;
if (state & (1<<UPE0)) err.parity_err = TRUE;
statusRx.mode = RX_SEEK;
counter = 0;
continue;
}
else
{
err.frame_err = 0;
err.ovrun_err = 0;
err.parity_err = 0;
err.length_err = 0;
err.lock_err = 0;
err.chksum_err = 0;
}
switch(statusRx.mode)
{
case RX_SEEK:
if (counter < sizeof(sign))
{
if (data == sign[counter])
{
counter++;
}
else
{
counter = 0;
}
}
else
{
counter = 0;
if (data >= sizeof(rx_buffer) || data == 0)
{
err.length_err = TRUE;
break;
}
rx_buffer[counter++] = data;
length = ++data;
statusRx.mode = RX_RUNNING;
}
break;
case RX_RUNNING:
rx_buffer[counter++] = data;
length--;
if (!length)
{
statusRx.data_available = TRUE;
statusRx.mode = RX_SEEK;
counter = 0;
}
break;
}
}while(UCSR0A & (1<<RXC0));
save_length=length;
statusRx.err=err;
statusRx.counter=counter;
}
и результат
Код
// 27 __interrupt void ISR_USART_RX(void)
ISR_USART_RX:
// 28 {
ST -Y, R27
ST -Y, R26
ST -Y, R31
ST -Y, R30
ST -Y, R22
ST -Y, R21
ST -Y, R20
ST -Y, R19
ST -Y, R18
ST -Y, R17
ST -Y, R16
IN R22, 0x3F
// 29 static __flash byte sign[] = {'S','N'};
// 30 static byte save_length;
// 31 byte data, state;
// 32 USART_ERRORS err=statusRx.err;
LDI R26, LOW(statusRx)
LDI R27, (statusRx) >> 8
MOVW R31:R30, R27:R26
LDD R16, Z+3
// 33 byte length=save_length;
LDD R19, Z+4
// 34 byte counter=statusRx.counter;
LD R18, X
// 35
// 36 do
// 37 {
// 38 state = UCSR0A;
??ISR_USART_RX_0:
LDS R21, 192
// 39 data = UDR0;
LDS R17, 198
// 40 if (statusRx.data_available)
MOVW R31:R30, R27:R26
LDD R20, Z+2
TST R20
BREQ ??ISR_USART_RX_1
// 41 {
// 42 err.lock_err = TRUE;
ORI R16, 0x10
// 43 continue;
RJMP ??ISR_USART_RX_2
// 44 }
// 45 if (state & ((1<<FE0)|(1<<DOR0)|(1<<UPE0)))
??ISR_USART_RX_1:
MOV R20, R21
ANDI R20, 0x1C
BREQ ??ISR_USART_RX_3
// 46 {
// 47 if (state & (1<<FE0)) err.frame_err = TRUE;
BST R21, 4
BRTC ??ISR_USART_RX_4
ORI R16, 0x01
// 48 if (state & (1<<DOR0)) err.ovrun_err = TRUE;
??ISR_USART_RX_4:
BST R21, 3
BRTC ??ISR_USART_RX_5
ORI R16, 0x02
// 49 if (state & (1<<UPE0)) err.parity_err = TRUE;
??ISR_USART_RX_5:
BST R21, 2
BRTC ??ISR_USART_RX_6
ORI R16, 0x04
// 50 statusRx.mode = RX_SEEK;
RJMP ??ISR_USART_RX_6
// 51 counter = 0;
// 52 continue;
// 53 }
// 54 else
// 55 {
// 56 err.frame_err = 0;
// 57 err.ovrun_err = 0;
// 58 err.parity_err = 0;
// 59 err.length_err = 0;
// 60 err.lock_err = 0;
// 61 err.chksum_err = 0;
??ISR_USART_RX_3:
ANDI R16, 0xC0
// 62 }
// 63 switch(statusRx.mode)
LDD R20, Z+1
SUBI R20, 0
BREQ ??ISR_USART_RX_7
DEC R20
BREQ ??ISR_USART_RX_8
RJMP ??ISR_USART_RX_2
// 64 {
// 65 case RX_SEEK:
// 66 if (counter < sizeof(sign))
??ISR_USART_RX_7:
CPI R18, 2
BRCC ??ISR_USART_RX_9
// 67 {
// 68 if (data == sign[counter])
LDI R31, 0
MOV R30, R18
SUBI R30, LOW((-(??sign) & 0xFFFF))
SBCI R31, (-(??sign) & 0xFFFF) >> 8
LPM R20, Z
CP R17, R20
BRNE ??ISR_USART_RX_10
// 69 {
// 70 counter++;
INC R18
RJMP ??ISR_USART_RX_2
// 71 }
// 72 else
// 73 {
// 74 counter = 0;
// 75 }
// 76 }
// 77 else
// 78 {
// 79 counter = 0;
??ISR_USART_RX_9:
LDI R18, 0
// 80 if (data >= sizeof(rx_buffer) || data == 0)
CPI R17, 100
BRCC ??ISR_USART_RX_11
TST R17
BRNE ??ISR_USART_RX_12
// 81 {
// 82 err.length_err = TRUE;
??ISR_USART_RX_11:
ORI R16, 0x08
// 83 break;
RJMP ??ISR_USART_RX_2
// 84 }
// 85 rx_buffer[counter++] = data;
??ISR_USART_RX_12:
STS rx_buffer, R17
LDI R18, 1
// 86 length = ++data;
MOV R19, R17
INC R19
// 87 statusRx.mode = RX_RUNNING;
STD Z+1, R18
RJMP ??ISR_USART_RX_2
// 88 }
// 89 break;
// 90 case RX_RUNNING:
// 91 rx_buffer[counter++] = data;
??ISR_USART_RX_8:
LDI R31, 0
MOV R30, R18
SUBI R30, LOW((-(rx_buffer) & 0xFFFF))
SBCI R31, (-(rx_buffer) & 0xFFFF) >> 8
ST Z, R17
INC R18
// 92 length--;
DEC R19
// 93 if (!length)
TST R19
BRNE ??ISR_USART_RX_2
// 94 {
// 95 statusRx.data_available = TRUE;
LDI R17, 1
MOVW R31:R30, R27:R26
STD Z+2, R17
// 96 statusRx.mode = RX_SEEK;
??ISR_USART_RX_6:
LDI R17, 0
STD Z+1, R17
// 97 counter = 0;
??ISR_USART_RX_10:
LDI R18, 0
// 98 }
// 99 break;
// 100 }
// 101
// 102 }while(UCSR0A & (1<<RXC0));
??ISR_USART_RX_2:
LDS R17, 192
SBRC R17, 7
RJMP ??ISR_USART_RX_0
// 103 save_length=length;
MOVW R31:R30, R27:R26
STD Z+4, R19
// 104 statusRx.err=err;
STD Z+3, R16
// 105 statusRx.counter=counter;
ST X, R18
// 106 }
OUT 0x3F, R22
LD R16, Y+
LD R17, Y+
LD R18, Y+
LD R19, Y+
LD R20, Y+
LD R21, Y+
LD R22, Y+
LD R30, Y+
LD R31, Y+
LD R26, Y+
LD R27, Y+
RETI
....
// 218 bytes in segment CODE
Попробуйте сделать аналогичный финт с гнусем, посмотрим, как он себя поведет.