Перейти к содержанию
    

WinAVR-20090313. Непонятная бага

Всем привет!

Исходничег:

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

 

Бага или нет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Бага или нет?
Ну вроде как не бага, но оптимизатор там сильно переклинило

Кстати, а какой уровень оптимизации ?

 

  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  <- ну и еще маску зачем-то

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вроде как не бага, но оптимизатор там сильно переклинило

Кстати, а какой уровень оптимизации ?

-Os

Самое интересное: попытался поменять if(reg & 0x80) www |= 0x20; на что-нить, не связанное с инструкцией rol (т.е. не крайние биты проверять вначале) - результат тоже такой сумбурный :) Именно при входе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

попробуйте как-нить так:

uint8_t bit_swp(uint8_t reg)
{
  reg >>= 4;
  if (reg & 0x08) reg |= 0x20;
  if (reg & 0x04) reg |= 0x80;
  reg &= 0xF3;
  return reg;
}

Должно быть кратко и без глюков оптимизации.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Должно быть кратко и без глюков оптимизации.

Дык стандартный же алгоритм перестановки бит! Чтоб этот момент не отягощал, можно вообще вставочку написать... я в ближайшее время покопаюсь - сдается мне, что этот глючок может выходить боком во многих ситуациях. Только я пока на уровне собачки - все понимаю, а сказать не могу. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

 

сдается мне, что этот глючок может выходить боком во многих ситуациях.
Да это глючок только в смысле растянутости во времени. Результат правильный :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#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. Странноватое назначение регистровых пар. Можно ли как-то улучшить этот момент?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...