_Pasha 0 30 сентября, 2009 Опубликовано 30 сентября, 2009 · Жалоба Всем привет! Исходничег: int main(void) __attribute__ ((OS_main)); static inline uint8_t bit_swp(const uint8_t reg)__attribute__ ((always_inline)); volatile uint8_t a; int main(void) { uint8_t b = a; b = bit_swp(b); a=b; return 0; } uint8_t bit_swp(const uint8_t reg) { uint8_t www=0; if(reg & 0x80) www |= 0x20; if(reg & 0x40) www |= 0x80; if(reg & 0x20) www |= 0x02; if(reg & 0x10) www |= 0x01; return www; } Листинг вызова bit_swp() начинается с непонятного действия 86: 28 2f mov r18, r24 88: 22 1f adc r18, r18 8a: 22 27 eor r18, r18 8c: 22 1f adc r18, r18 8e: 22 95 swap r18 90: 22 0f add r18, r18 92: 20 7e andi r18, 0xE0; 224 А далее - все как должно быть if(reg & 0x40) www |= 0x80; 94: 86 fd sbrc r24, 6 96: 20 68 ori r18, 0x80 ; 128 if(reg & 0x20) www |= 0x02; 98: 85 fd sbrc r24, 5 9a: 22 60 ori r18, 0x02 ; 2 if(reg & 0x10) www |= 0x01; 9c: 84 fd sbrc r24, 4 9e: 21 60 ori r18, 0x01 ; 1 int main(void) { uint8_t b = a; b = bit_swp(B); a=b; a0: 20 93 02 01 sts 0x0102, r18 return 0; } a4: 80 e0 ldi r24, 0x00 ; 0 a6: 90 e0 ldi r25, 0x00 ; 0 a8: 08 95 ret -------- begin -------- avr-gcc (WinAVR 20090313) 4.3.2 Copyright © 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiling C: test.c C:/WinAVR-20090313/bin/avr-gcc -c -mmcu=atmega48 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wst rict-prototypes -Wa,-adhlns=./test.lst -std=gnu99 -fno-split-wide-types -mcall- prologues --param inline-call-cost=3 -fno-unroll-loops -MMD -MP -MF .dep/test.o. d test.c -o test.o Linking: test.elf C:/WinAVR-20090313/bin/avr-gcc -mmcu=atmega48 -I. -gdwarf-2 -DF_CPU=8000000UL -O s -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstric t-prototypes -Wa,-adhlns=test.o -std=gnu99 -fno-split-wide-types -mcall-prologu es --param inline-call-cost=3 -fno-unroll-loops -MMD -MP -MF .dep/test.elf.d tes t.o led7s.o --output test.elf -Wl,-Map=test.map,--cref -lm Creating load file for Flash: test.hex C:/WinAVR-20090313/bin/avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock test.elf test.hex Бага или нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 30 сентября, 2009 Опубликовано 30 сентября, 2009 · Жалоба Бага или нет?Ну вроде как не бага, но оптимизатор там сильно переклинило Кстати, а какой уровень оптимизации ? 86: 28 2f mov r18, r24 <- типа передаем параметр в временную переменную 88: 22 1f adc r18, r18 <- ставим флаг С если (www&0x80) 8a: 22 27 eor r18, r18 <- обнуляем www 8c: 22 1f adc r18, r18 <- пишем С в младший бит www 8e: 22 95 swap r18 <- переносим бит С в 4 бит(0x10) www 90: 22 0f add r18, r18 <- переносим его в 5 бит(0x20) www 92: 20 7e andi r18, 0xE0; 224 <- ну и еще маску зачем-то Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 30 сентября, 2009 Опубликовано 30 сентября, 2009 · Жалоба Ну вроде как не бага, но оптимизатор там сильно переклинило Кстати, а какой уровень оптимизации ? -Os Самое интересное: попытался поменять if(reg & 0x80) www |= 0x20; на что-нить, не связанное с инструкцией rol (т.е. не крайние биты проверять вначале) - результат тоже такой сумбурный :) Именно при входе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 30 сентября, 2009 Опубликовано 30 сентября, 2009 · Жалоба попробуйте как-нить так: uint8_t bit_swp(uint8_t reg) { reg >>= 4; if (reg & 0x08) reg |= 0x20; if (reg & 0x04) reg |= 0x80; reg &= 0xF3; return reg; } Должно быть кратко и без глюков оптимизации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 30 сентября, 2009 Опубликовано 30 сентября, 2009 · Жалоба Должно быть кратко и без глюков оптимизации. Дык стандартный же алгоритм перестановки бит! Чтоб этот момент не отягощал, можно вообще вставочку написать... я в ближайшее время покопаюсь - сдается мне, что этот глючок может выходить боком во многих ситуациях. Только я пока на уровне собачки - все понимаю, а сказать не могу. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 30 сентября, 2009 Опубликовано 30 сентября, 2009 · Жалоба 20071221 точно таким же хитрым образом выделяет бит 7 в младший бит и сдвигает его на 5 влево вместо w=0; if() w |= 0x20. Перестановка проверки/переноса страшего бита в конец функции bist_swp() uint8_t bit_swp(const uint8_t reg) { uint8_t www = 0; if (reg & 0x40) www |= 0x80; if (reg & 0x20) www |= 0x02; if (reg & 0x10) www |= 0x01; if (reg & 0x80) www |= 0x20; return www; } чудесным образом исцеляет кодогенератор от галлюцинаций на тему лёгкости выделения 7-го бита lds r18,a mov r25,r18 ldi r24,lo8(0) sbrc r18,6 ldi r24,lo8(-128); как видим, тут тоже не ori - "зачем орить, если там был 0" *) .L3: sbrc r25,5 ori r24,lo8(2) .L4: sbrc r25,4 ori r24,lo8(1) .L5: sbrc r18,7 ori r24,lo8(32) .L6: sts a,r24 *) я давно заметил какую-то странную "любовь" кодогенератора к старшему "знаковому" биту. Его легко проверить tst / brmi, его легко засунуть в перенос и оттуда высунуть. И почему-то часто вместо sbrc/sbrs используются навороты, сводящие задачу к имеющимся "лёгкостям". В данном случае, когда по первому сравнению в ранее занулённій регистр можно не "орить", а занести нужное, он решилд даже не занулять регистр, а сразу занести нужное (чё по ведру носиться, ща обкопает колодец и принесёт весь). Но даже сдвинуть на два бита вправо и замаскировать не догадался - больно "легко" старший бит получить в C сдается мне, что этот глючок может выходить боком во многих ситуациях.Да это глючок только в смысле растянутости во времени. Результат правильный :-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 6 октября, 2009 Опубликовано 6 октября, 2009 · Жалоба #include <avr/io.h> static struct Tpin_xrf { volatile void *port; uint8_t mask; } pin_xrf[5]={ {.port=&PORTB, .mask= 1}, {.port=&PORTB, .mask= 0x80}, {.port=&PORTB, .mask= 0x10}, {.port=&PORTB, .mask= 0x40}, {.port=&PORTB, .mask= 0x20}, }; int main(void) { for(uint8_t j=0;j<5;j++) { if(*((uint8_t*)pin_xrf[j].port) & pin_xrf[j].mask) PORTC |= 1; else PORTC &= ~1; } return 0; } int main(void) { 5c: a0 e0 ldi r26, 0x00 ; 0 5e: b1 e0 ldi r27, 0x01 ; 1 for(uint8_t j=0;j<5;j++) { if(*((uint8_t*)pin_xrf[j].port) & pin_xrf[j].mask) PORTC |= 1; else PORTC &= ~1; 60: ed 91 ld r30, X+ 62: fc 91 ld r31, X 64: 11 97 sbiw r26, 0x01 ; 1 66: 80 81 ld r24, Z 68: 12 96 adiw r26, 0x02 ; 2 6a: 9c 91 ld r25, X 6c: 12 97 sbiw r26, 0x02 ; 2 6e: 89 23 and r24, r25 70: 11 f0 breq .+4 ; 0x76 <main+0x1a> 72: 40 9a sbi 0x08, 0 ; 8 74: 01 c0 rjmp .+2 ; 0x78 <main+0x1c> 76: 40 98 cbi 0x08, 0 ; 8 78: 13 96 adiw r26, 0x03 ; 3 {.port=&PORTB, .mask= 0x20}, }; int main(void) { for(uint8_t j=0;j<5;j++) 7a: 81 e0 ldi r24, 0x01 ; 1 7c: af 30 cpi r26, 0x0F ; 15 7e: b8 07 cpc r27, r24 80: 79 f7 brne .-34 ; 0x60 <main+0x4> { if(*((uint8_t*)pin_xrf[j].port) & pin_xrf[j].mask) PORTC |= 1; else PORTC &= ~1; } return 0; } 82: 80 e0 ldi r24, 0x00 ; 0 84: 90 e0 ldi r25, 0x00 ; 0 86: 08 95 ret Что я хотел сказать: Доступ к полям структуры почему-то делается через Х а не через Z с использованием LDD/STD. Странноватое назначение регистровых пар. Можно ли как-то улучшить этот момент? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться