Оптимизация на С

Обсуждаем контроллеры компании Atmel.
Ответить
anb
Родился
Сообщения: 15
Зарегистрирован: Сб янв 05, 2008 00:15:51

Сообщение anb »

Ранее программировал на асме, сейчас начал изучать С.
Возникла задача расположить биты в байте в обратном порядке с максимальным быстродействием.
Ранее на асме сделал бы используя сдвиг через флаг переноса и это бы заняло 16 команд (не считая сохранения регистров и загрузки данных в них).
На C сделал следующее:

Код: Выделить всё

uint8_t inverse(uint8_t c){
	return
		((c&0x01)<<7)|
		((c&0x02)<<5)|
		((c&0x04)<<3)|
		((c&0x08)<<1)|
		((c&0x10)>>1)|
		((c&0x20)>>3)|
		((c&0x40)>>5)|
		((c&0x80)>>7);	
}
Откомпилированный код выполняется более чем за 90 команд.
Вопрос к знатокам C, можно ли как то по другому это реализовать чтобы быстрее работало,
а то почти шестикратный проигрыш в скорости выполнения вызывает проблемы.
Среда AVR Studio 5.1, целевой процессор XMega128A1.
Реклама
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

1. обращение к таблице с заранее посчитанными данными.
2. ассемблерная вставка если с асмом все так хорошо.
Реклама
anb
Родился
Сообщения: 15
Зарегистрирован: Сб янв 05, 2008 00:15:51

Сообщение anb »

Идея с таблицей, думаю, подойдет, даже быстрее будет выполнять.
Спасибо.
anb
Родился
Сообщения: 15
Зарегистрирован: Сб янв 05, 2008 00:15:51

Сообщение anb »

Может кому пригодится:

Код: Выделить всё

uint8_t inverse2(uint8_t c){
  uint8_t tab_i[256]={0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72,
					  200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 
					  164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 
					  236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 
					  146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 
					  218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 
					  182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 
					  254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 
					  73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 
					  37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 
					  109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 
					  147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 
					  219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 
					  119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255};
	
	return	tab_i[c];	
}
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Код: Выделить всё

uint8_t inverse(uint8_t a)
{
  uint8_t r=0;
  if(a & 0x80) r |= 0x01;
  if(a & 0x40) r |= 0x02;
  if(a & 0x20) r |= 0x04;
  if(a & 0x10) r |= 0x08;
  if(a & 0x08) r |= 0x10;
  if(a & 0x04) r |= 0x20;
  if(a & 0x02) r |= 0x40;
  if(a & 0x01) r |= 0x80;
  return r;
}
для mega8 с оптимизацией 2 и получилось порядка 16 команд в худшем случае:

Код: Выделить всё

uint8_t inverse(uint8_t a)
{
  38:	98 2f       	mov	r25, r24
  3a:	99 1f       	adc	r25, r25
  3c:	99 27       	eor	r25, r25
  3e:	99 1f       	adc	r25, r25
  uint8_t r=0;
  if(a & 0x80) r |= 0x01;
  if(a & 0x40) r |= 0x02;
  40:	86 fd       	sbrc	r24, 6
  42:	92 60       	ori	r25, 0x02	; 2
  if(a & 0x20) r |= 0x04;
  44:	85 fd       	sbrc	r24, 5
  46:	94 60       	ori	r25, 0x04	; 4
  if(a & 0x10) r |= 0x08;
  48:	84 fd       	sbrc	r24, 4
  4a:	98 60       	ori	r25, 0x08	; 8
  if(a & 0x08) r |= 0x10;
  4c:	83 fd       	sbrc	r24, 3
  4e:	90 61       	ori	r25, 0x10	; 16
  if(a & 0x04) r |= 0x20;
  50:	82 fd       	sbrc	r24, 2
  52:	90 62       	ori	r25, 0x20	; 32
  if(a & 0x02) r |= 0x40;
  54:	81 fd       	sbrc	r24, 1
  56:	90 64       	ori	r25, 0x40	; 64
  if(a & 0x01) r |= 0x80;
  58:	80 fd       	sbrc	r24, 0
  5a:	90 68       	ori	r25, 0x80	; 128
  return r;
}
  5c:	89 2f       	mov	r24, r25
  5e:	08 95       	ret
Реклама
anb
Родился
Сообщения: 15
Зарегистрирован: Сб янв 05, 2008 00:15:51

Сообщение anb »

Да, мне еще нужно учиться и учиться мыслить на C правильно. :)
Спасибо за идеи, табличный вариант будет все же быстрее,
а при наличии 128к памяти (в данном проекте), выделить 256 байт на хранение таблицы - не проблема.
Реклама
Ответить

Вернуться в «AVR»