|
|
  |
Оптимизация алгоритма на С, вопрос к знатокам компиляторов |
|
|
|
Aug 24 2006, 20:45
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(µµC @ Aug 25 2006, 00:20)  Цитата(singlskv @ Aug 24 2006, 23:35)  Если несложно, то просимулируйте для 7 байт(как в изначальной задаче), и напишите сколько получилось тактов для этих двух вариантов.
Код #define U8 unsigned char
U8 code[8] = {0x01, 0xd0, 0x5e, 0x3c, 0x0d, 0x00, 0x00, 0x84};
U8 crc8_1(U8 *buff, U8 num) { U8 i, tmp, val, crc = 0; do { val = *buff++; i = 8; do { tmp = (val ^ crc); crc >>= 1; val >>= 1; if (tmp & 0x01) crc ^= 0x8c; } while (--i); } while (--num); return crc; }
U8 crc8_2(U8 *buff, U8 num) { U8 val, crc = 0; do { val = *buff++; val ^= crc; crc = 0; if(val & 0x01) crc ^= 0x5e; if(val & 0x02) crc ^= 0xbc; if(val & 0x04) crc ^= 0x61; if(val & 0x08) crc ^= 0xc2; if(val & 0x10) crc ^= 0x9d; if(val & 0x20) crc ^= 0x23; if(val & 0x40) crc ^= 0x46; if(val & 0x80) crc ^= 0x8c; } while (--num); return crc; }
volatile U8 result[4];
void main(void) { while (1) { result[0] = crc8_1(code, 7); //649 result[1] = crc8_2(code, 7); //265 result[2] = crc8_1(code, 7); result[3] = crc8_2(code, 7); } } IAR, opt = max speed, остальные опции выкл. 649 циклов к 265. 649 уже намного ближе к правде (если не сложно, листинг в студию), но у WinAVR 544. 265 - отличный результат, но мы обсуждаем алгоритм(оптимизацию компилятором) в общем виде (таблицой из 256 значений как в даташите "1-wire" все равно быстрее).
|
|
|
|
|
Aug 24 2006, 21:00
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(µµC @ Aug 24 2006, 23:41)  Цитата(singlskv @ Aug 25 2006, 00:29)  Лучший компилятор это человек.
Не спорю, лучший. Только слишком дорогой и медленный.. и 'ломается' на больших кусках кода :-( Цитата(singlskv @ Aug 24 2006, 23:45)  в общем виде (таблицой из 256 значений как в даташите "1-wire" все равно быстрее). Быстрее :-) сопроцессор поставить.... Код //--------------------------------------------------------------------------- // Verilog module containing a synthesizable CRC8 function // - Polynomial: (8 5 4 0) // - Data width: 8 // - CRC width : 8 // - Mirror //--------------------------------------------------------------------------- module CRC8_8540;
function [7:0] nextCRC;
input [7:0] Data; input [7:0] CRC;
reg [7:0] D; reg [7:0] C; reg [7:0] xCRC;
begin
D = Data; C = CRC;
// Mirror DATA and final CRC xCRC[7] = D[1]^D[3]^D[4]^D[7]^C[7]^C[4]^C[3]^C[1]; xCRC[6] = D[0]^D[2]^D[3]^D[6]^C[6]^C[3]^C[2]^C[0]; xCRC[5] = D[1]^D[2]^D[5]^C[5]^C[2]^C[1]; xCRC[4] = D[0]^D[1]^D[4]^C[4]^C[1]^C[0]; xCRC[3] = D[0]^D[1]^D[4]^D[7]^C[7]^C[4]^C[1]^C[0]; xCRC[2] = D[0]^D[1]^D[4]^D[6]^D[7]^C[7]^C[6]^C[4]^C[1]^C[0]; xCRC[1] = D[0]^D[3]^D[5]^D[6]^C[6]^C[5]^C[3]^C[0]; xCRC[0] = D[2]^D[4]^D[5]^C[5]^C[4]^C[2];
nextCRC = xCRC;
end
endfunction
endmodule Извините :-( Настроение сегодня такое :-). А верилоговский код рабочий под Dallas - вдруг кому пригодится. Использую я его, поскольку полином хорош для любых небольших пакетов.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 24 2006, 21:03
|
Участник

Группа: Новичок
Сообщений: 44
Регистрация: 2-05-06
Пользователь №: 16 710

|
Цитата(singlskv @ Aug 25 2006, 00:45)  если не сложно, листинг в студию NAME crc8 RSEG CSTACK:DATA:NOROOT(0) RSEG RSTACK:DATA:NOROOT(0) EXTERN ?need_segment_init PUBWEAK `?<Segment init: TINY_I>` PUBWEAK `?<Segment init: TINY_Z>` PUBWEAK __?EEARL PUBWEAK __?EECR PUBWEAK __?EEDR PUBLIC code PUBLIC crc8_1 PUBLIC crc8_2 PUBLIC main PUBLIC result RSEG TINY_I:DATA:NOROOT(0) REQUIRE `?<Segment init: TINY_I>` // 49 U8 code[8] = {0x01, 0xd0, 0x5e, 0x3c, 0x0d, 0x00, 0x00, 0x84}; code: DS 8 REQUIRE `?<Initializer for code>` // 50 RSEG CODE:CODE:NOROOT(1) // 51 U8 crc8_1(U8 *buff, U8 num) crc8_1: // 52 { // 53 U8 i, tmp, val, crc = 0; LDI R19, 0 // 54 // 55 do { // 56 val = *buff++; ??crc8_1_0: MOV R30, R16 LD R21, Z+ MOV R16, R30 // 57 i = 8; LDI R18, 8 // 58 do { // 59 tmp = (val ^ crc); ??crc8_1_1: MOV R20, R19 EOR R20, R21 // 60 crc >>= 1; LSR R19 // 61 val >>= 1; LSR R21 // 62 if (tmp & 0x01) crc ^= 0x8c; BST R20, 0 BRTC ??crc8_1_2 LDI R20, 140 EOR R19, R20 // 63 } while (--i); ??crc8_1_2: DEC R18 BRNE ??crc8_1_1 // 64 } while (--num); DEC R17 BRNE ??crc8_1_0 // 65 return crc; MOV R16, R19 RET // 66 } // 67 RSEG CODE:CODE:NOROOT(1) // 68 U8 crc8_2(U8 *buff, U8 num) crc8_2: // 69 { // 70 U8 val, crc = 0; LDI R18, 0 // 71 // 72 do { // 73 val = *buff++; ??crc8_2_0: MOV R30, R16 LD R20, Z+ MOV R16, R30 // 74 val ^= crc; EOR R20, R18 // 75 crc = 0; LDI R18, 0 // 76 if(val & 0x01) crc ^= 0x5e; BST R20, 0 BRTC ??crc8_2_1 LDI R18, 94 // 77 if(val & 0x02) crc ^= 0xbc; ??crc8_2_1: BST R20, 1 BRTC ??crc8_2_2 LDI R19, 188 EOR R18, R19 // 78 if(val & 0x04) crc ^= 0x61; ??crc8_2_2: BST R20, 2 BRTC ??crc8_2_3 LDI R19, 97 EOR R18, R19 // 79 if(val & 0x08) crc ^= 0xc2; ??crc8_2_3: BST R20, 3 BRTC ??crc8_2_4 LDI R19, 194 EOR R18, R19 // 80 if(val & 0x10) crc ^= 0x9d; ??crc8_2_4: BST R20, 4 BRTC ??crc8_2_5 LDI R19, 157 EOR R18, R19 // 81 if(val & 0x20) crc ^= 0x23; ??crc8_2_5: BST R20, 5 BRTC ??crc8_2_6 LDI R19, 35 EOR R18, R19 // 82 if(val & 0x40) crc ^= 0x46; ??crc8_2_6: BST R20, 6 BRTC ??crc8_2_7 LDI R19, 70 EOR R18, R19 // 83 if(val & 0x80) crc ^= 0x8c; ??crc8_2_7: BST R20, 7 BRTC ??crc8_2_8 LDI R19, 140 EOR R18, R19 // 84 } while (--num); ??crc8_2_8: DEC R17 BRNE ??crc8_2_0 // 85 return crc; MOV R16, R18 RET // 86 } // 87 RSEG TINY_Z:DATA:NOROOT(0) REQUIRE `?<Segment init: TINY_Z>` // 88 volatile U8 result[4]; result: DS 4 // 89 RSEG CODE:CODE:NOROOT(1) // 90 void main(void) main: ??main_0: // 91 { // 92 while (1) { // 93 result[0] = crc8_1(code, 7); //649 LDI R17, 7 LDI R16, code RCALL crc8_1 LDI R30, result ST Z, R16 // 94 result[1] = crc8_2(code, 7); //265 LDI R17, 7 LDI R16, code RCALL crc8_2 LDI R30, result STD Z+1, R16 // 95 result[2] = crc8_1(code, 7); LDI R17, 7 LDI R16, code RCALL crc8_1 LDI R30, result STD Z+2, R16 // 96 result[3] = crc8_2(code, 7); LDI R17, 7 LDI R16, code RCALL crc8_2 LDI R30, result STD Z+3, R16 RJMP ??main_0 // 97 } // 98 } ASEGN ABSOLUTE:DATA:NOROOT,01cH __?EECR: ASEGN ABSOLUTE:DATA:NOROOT,01dH __?EEDR: ASEGN ABSOLUTE:DATA:NOROOT,01eH __?EEARL: RSEG TINY_ID:CODE:NOROOT(0) `?<Initializer for code>`: DB 1, 208, 94, 60, 13, 0, 0, 132 RSEG INITTAB:CODE:NOROOT(0) `?<Segment init: TINY_I>`: DB SFE(TINY_I) - SFB(TINY_I) DB SFB(TINY_I) DW SFB(TINY_ID) REQUIRE ?need_segment_init RSEG INITTAB:CODE:NOROOT(0) `?<Segment init: TINY_Z>`: DB SFE(TINY_Z) - SFB(TINY_Z) DB SFB(TINY_Z) DW 0 REQUIRE ?need_segment_init END
|
|
|
|
|
Aug 24 2006, 21:20
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(µµC @ Aug 25 2006, 01:03)  Цитата(singlskv @ Aug 25 2006, 00:45)  если не сложно, листинг в студию
..................... ..................... LDI R20, 140 EOR R19, R20 ..................... ..................... Ну вот она, похоже основная ошибка IAR, он загружает 0x8c много раз подряд. И еще какие-то лишние mov делает. Это код WinAVR(-o3): Код @00000045: crc8_2 20: { +00000045: 2FF9 MOV R31,R25 Copy register +00000046: 2FE8 MOV R30,R24 Copy register 21: unsigned char i=num,j,tmp,data,crc=0; +00000047: E090 LDI R25,0x00 Load immediate 22: for (;i>0;i--) { +00000048: 2366 TST R22 Test for Zero or Minus +00000049: F069 BREQ PC+0x0E Branch if equal +0000004A: E84C LDI R20,0x8C Load immediate 23: data=*buff++; +0000004B: 9121 LD R18,Z+ Load indirect and postincrement 24: for (j=8;j>0;j--) { +0000004C: E038 LDI R19,0x08 Load immediate 25: tmp=1&(data^crc); +0000004D: 2F82 MOV R24,R18 Copy register +0000004E: 2789 EOR R24,R25 Exclusive OR 26: crc>>=1; +0000004F: 9596 LSR R25 Logical shift right 27: data>>=1; +00000050: 9526 LSR R18 Logical shift right 28: if (tmp!=0) crc^=0x8c; +00000051: FD80 SBRC R24,0 Skip if bit in register cleared +00000052: 2794 EOR R25,R20 Exclusive OR +00000053: 5031 SUBI R19,0x01 Subtract immediate +00000054: F7C1 BRNE PC-0x07 Branch if not equal +00000055: 5061 SUBI R22,0x01 Subtract immediate +00000056: F7A1 BRNE PC-0x0B Branch if not equal 32: } +00000057: 2F89 MOV R24,R25 Copy register +00000058: 2799 CLR R25 Clear Register +00000059: 9508 RET Subroutine return
|
|
|
|
|
Aug 24 2006, 21:50
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Aug 25 2006, 01:00)  Быстрее :-) сопроцессор поставить.... Код //--------------------------------------------------------------------------- // Verilog module containing a synthesizable CRC8 function // - Polynomial: (8 5 4 0) // - Data width: 8 // - CRC width : 8 // - Mirror //--------------------------------------------------------------------------- module CRC8_8540;
function [7:0] nextCRC;
input [7:0] Data; input [7:0] CRC;
reg [7:0] D; reg [7:0] C; reg [7:0] xCRC;
begin
D = Data; C = CRC;
// Mirror DATA and final CRC xCRC[7] = D[1]^D[3]^D[4]^D[7]^C[7]^C[4]^C[3]^C[1]; xCRC[6] = D[0]^D[2]^D[3]^D[6]^C[6]^C[3]^C[2]^C[0]; xCRC[5] = D[1]^D[2]^D[5]^C[5]^C[2]^C[1]; xCRC[4] = D[0]^D[1]^D[4]^C[4]^C[1]^C[0]; xCRC[3] = D[0]^D[1]^D[4]^D[7]^C[7]^C[4]^C[1]^C[0]; xCRC[2] = D[0]^D[1]^D[4]^D[6]^D[7]^C[7]^C[6]^C[4]^C[1]^C[0]; xCRC[1] = D[0]^D[3]^D[5]^D[6]^C[6]^C[5]^C[3]^C[0]; xCRC[0] = D[2]^D[4]^D[5]^C[5]^C[4]^C[2];
nextCRC = xCRC;
end
endfunction
endmodule Ну, это уже из пушки по воробьям Хотя, если есть свободные ресурсы, то почему бы и нет
|
|
|
|
Guest_Serg79_*
|
Aug 25 2006, 06:07
|
Guests

|
В таких случаях поступают намного проше, пишут функцию на ASM и не ломают голову на счет компилятора. Код /** \ingroup util_crc Optimized Dallas (now Maxim) iButton 8-bit CRC calculation.
Polynomial: x^8 + x^5 + x^4 + 1 (0x8C)<br> Initial value: 0x0
See http://www.maxim-ic.com/appnotes.cfm/appnote_number/27
The following is the equivalent functionality written in C.
\code uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data) { uint8_t i;
crc = crc ^ data; for (i = 0; i < 8; i++) { if (crc & 0x01) crc = (crc >> 1) ^ 0x8C; else crc >>= 1; }
return crc; } \endcode */
static __inline__ uint8_t _crc_ibutton_update(uint8_t __crc, uint8_t __data) { uint8_t __i, __pattern; __asm__ __volatile__ ( " eor %0, %4" "\n\t" " ldi %1, 8" "\n\t" " ldi %2, 0x8C" "\n\t" "1: bst %0, 0" "\n\t" " lsr %0" "\n\t" " brtc 2f" "\n\t" " eor %0, %2" "\n\t" "2: dec %1" "\n\t" " brne 1b" "\n\t" : "=r" (__crc), "=d" (__i), "=d" (__pattern) : "0" (__crc), "r" (__data)); return __crc; } И я так думаю, что эта функция будет работать быстрее приведенных выше. Реализация функции взята из заголовочного файла "crc16.h" компилятора WinAVR. А принцип простой: не изобретай велосипед. Лучше направить свои усилия на что то новое, чем пытаться заново писать стандартные функции, реализованные в библиотеках идущих вместе с компилятором.
|
|
|
|
|
Aug 25 2006, 06:13
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата(singlskv @ Aug 24 2006, 22:24)  очень повеселил этот код: Код MOVW R31:R30, R17:R16 LD R22, Z+ MOVW R17:R16, R31:R30 и так 7 раз подряд  Хорошо поможет Код __z unsigned char crc8_2(unsigned char *buff,unsigned char num) А циклы ОЧЕНЬ желательно делать Код do{}while(--var); это помогает почти всем компиляторам и процессорам, обычно архитектура процессора позволяет изготовить нечто такое: Код DEC var JUMP_IF_NZ label
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 25 2006, 08:24
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Serg79 @ Aug 25 2006, 10:07)  В таких случаях поступают намного проше, пишут функцию на ASM и не ломают голову на счет компилятора. Код /** \ingroup util_crc Optimized Dallas (now Maxim) iButton 8-bit CRC calculation.
Polynomial: x^8 + x^5 + x^4 + 1 (0x8C)<br> Initial value: 0x0
See http://www.maxim-ic.com/appnotes.cfm/appnote_number/27
The following is the equivalent functionality written in C.
\code uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data) { uint8_t i;
crc = crc ^ data; for (i = 0; i < 8; i++) { if (crc & 0x01) crc = (crc >> 1) ^ 0x8C; else crc >>= 1; }
return crc; } \endcode */
static __inline__ uint8_t _crc_ibutton_update(uint8_t __crc, uint8_t __data) { uint8_t __i, __pattern; __asm__ __volatile__ ( " eor %0, %4" "\n\t" " ldi %1, 8" "\n\t" " ldi %2, 0x8C" "\n\t" "1: bst %0, 0" "\n\t" " lsr %0" "\n\t" " brtc 2f" "\n\t" " eor %0, %2" "\n\t" "2: dec %1" "\n\t" " brne 1b" "\n\t" : "=r" (__crc), "=d" (__i), "=d" (__pattern) : "0" (__crc), "r" (__data)); return __crc; } И я так думаю, что эта функция будет работать быстрее приведенных выше. Реализация функции взята из заголовочного файла "crc16.h" компилятора WinAVR. А принцип простой: не изобретай велосипед. Лучше направить свои усилия на что то новое, чем пытаться заново писать стандартные функции, реализованные в библиотеках идущих вместе с компилятором. Думать не нужно, надо пробовать (С). Выполните Ваш код для 7 байтов, а потом внимательно перечитайте весь топик. Цитата(Rst7 @ Aug 25 2006, 10:13)  Цитата(singlskv @ Aug 24 2006, 22:24)  очень повеселил этот код: Код MOVW R31:R30, R17:R16 LD R22, Z+ MOVW R17:R16, R31:R30 и так 7 раз подряд  Хорошо поможет Код __z unsigned char crc8_2(unsigned char *buff,unsigned char num) Вот это ОЧЕНЬ ценный совет Цитата(Rst7 @ Aug 25 2006, 10:13)  А циклы ОЧЕНЬ желательно делать Код do{}while(--var); это помогает почти всем компиляторам и процессорам, обычно архитектура процессора позволяет изготовить нечто такое: Код DEC var JUMP_IF_NZ label Ну с этим никто и не спорит, только это уже получается не "оптимизирующий" компилятор, а "оптимизируемый пользователем" компилятор.
|
|
|
|
|
Aug 25 2006, 08:42
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата(singlskv @ Aug 25 2006, 11:24)  Ну с этим никто и не спорит, только это уже получается не "оптимизирующий" компилятор, а "оптимизируемый пользователем" компилятор. А вдруг завтра прийдется что-то написать для другого проца с совсем другим компилятором? А? Это в крови должно быть  О чем многие тут и толкуют... Почитайте темы про "идеальные компиляторы"... PS Кстати, IAR 4.40 для ARM такие циклы for переделывает в do{}while как 2 пальца... А вот для AVR видно старый оптимизатор внутри, хоть и 4.20... Переделка эта ведь перед code-генератором происходит, так что вполне мог бы и на AVR делать такое...
Сообщение отредактировал Rst7 - Aug 25 2006, 08:43
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 25 2006, 11:17
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(singlskv @ Aug 24 2006, 23:29)  Цитата(µµC @ Aug 24 2006, 23:24)  Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.
Лучший компилятор это человек. на ASM у меня получилось 530 тактов: Код crc8:;Input: X - buffer; r17 - number of bytes ;Output: r16 = CRC
ldi r16,0;CRC ldi r20,0x8c crc8_1: ld r18,X+ ldi r19,8 crc8_2: lsr r16 brbc 0,crc8_3 eor r16,r20 crc8_3: sbrc r18,0 eor r16,r20 lsr r18 crc8_4: dec r19 brne crc8_2 dec r17 brne crc8_1
ret НО, надо отдать должное WinAVR(gcc) ИТОГО: Код CRC8_1 CRC8_2 WinAVR(-o1) 620 556 WinAVR(-o2) 620 556 WinAVR(-o3) 606 544
IAR 986 774
ASM 530 У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл. Приятно удививший результат А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при оптимизации? Вся проблема в том, что компилятор использует определенные соглашения по передаче параметров и использованию регистров. Ваша функция под соглашения, принятые, например, в IAR, не попадает. Для стыковки с Си-шными функциями ее потребуется изменить с принятыми в компиляторе соглашениями. А это приведет к увеличению и размера кода, и увеличением времени его выполнения.
Сообщение отредактировал _Bill - Aug 25 2006, 11:33
|
|
|
|
|
Aug 25 2006, 11:26
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(_Bill @ Aug 25 2006, 15:17)  Цитата(singlskv @ Aug 24 2006, 23:29)  Цитата(µµC @ Aug 24 2006, 23:24)  Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.
Лучший компилятор это человек. на ASM у меня получилось 530 тактов: Код crc8:;Input: X - buffer; r17 - number of bytes ;Output: r16 = CRC
ldi r16,0;CRC ldi r20,0x8c crc8_1: ld r18,X+ ldi r19,8 crc8_2: lsr r16 brbc 0,crc8_3 eor r16,r20 crc8_3: sbrc r18,0 eor r16,r20 lsr r18 crc8_4: dec r19 brne crc8_2 dec r17 brne crc8_1
ret НО, надо отдать должное WinAVR(gcc) ИТОГО: Код CRC8_1 CRC8_2 WinAVR(-o1) 620 556 WinAVR(-o2) 620 556 WinAVR(-o3) 606 544
IAR 986 774
ASM 530 У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл. Приятно удививший результат А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при оптимизации? Вся проблема в том, что компилятор использует определенные соглашения по передаче параметров и использованию регистров. Ваша функция под соглашения, принятые, например, в IAR, не попадает. Для стыковки с Си-шными функциями ее потребуется изменить с принятыми в компиляторе соглашениями. А это приведет к увеличению и размера кода, и увеличением времени его выполнения. Цитата(singlskv @ Aug 24 2006, 23:29)  Цитата(µµC @ Aug 24 2006, 23:24)  Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.
Лучший компилятор это человек. на ASM у меня получилось 530 тактов: Код crc8:;Input: X - buffer; r17 - number of bytes ;Output: r16 = CRC
ldi r16,0;CRC ldi r20,0x8c crc8_1: ld r18,X+ ldi r19,8 crc8_2: lsr r16 brbc 0,crc8_3 eor r16,r20 crc8_3: sbrc r18,0 eor r16,r20 lsr r18 crc8_4: dec r19 brne crc8_2 dec r17 brne crc8_1
ret НО, надо отдать должное WinAVR(gcc) ИТОГО: Код CRC8_1 CRC8_2 WinAVR(-o1) 620 556 WinAVR(-o2) 620 556 WinAVR(-o3) 606 544
IAR 986 774
ASM 530 У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл. Приятно удививший результат А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при оптимизации? Вся проблема в том, что компилятор использует определенные соглашения по передаче параметров и использованию регистров. Ваша функция под соглашения, принятые, например, в IAR, не попадает. Для стыковки с Си-шными функциями ее потребуется изменить с принятыми в компиляторе соглашениями. А это приведет к увеличению и размера кода, и увеличением времени его выполнения. такты я считал по возможности честно, т.е. не учитывая такты потраченные на передачу параметров. А мой ASM код можно легко переписать под нужные регистры.  Да и разница в тактах что-то великовата, что бы ее объяснять только передачей параметров.
Сообщение отредактировал singlskv - Aug 25 2006, 11:39
|
|
|
|
|
Aug 25 2006, 11:47
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(singlskv @ Aug 25 2006, 14:26)  такты я считал по возможности честно, т.е. не учитывая такты потраченные на передачу параметров. А мой ASM код можно легко переписать под нужные регистры.  Не сомневаюсь, но код все равно получится длиннее. И, опять же, если Вы используете свои собственные соглашения по передаче параметров и использованию регистров в ваших модулях на ассемблере, то Вы будете вынуждены писать Ваши функции в соответствии с принятыми Вами соглашениями. А это неизбежно приведет к увеличению кода аналогично тому, как это делается компилятором. В свое время я написал небольшой опус на эту тему. К сожалению, он и сейчас далек от завершения.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|