реклама на сайте
подробности

 
 
> как побороть WinAVR?, и заставить просто скомпиллить как написано
VDV
сообщение Aug 7 2008, 17:01
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 152
Регистрация: 18-03-06
Пользователь №: 15 366



написана функция:

volatile int32_t _corr[2 * 8];//result of correlations
volatile uint8_t _corr_index;//index for sample table
int8_t PROGMEM _dtmf_samples[] = {...};

int8_t d = ADCH;
for( uint8_t i = 16; i--; )
{
int16_t mul = d * pgm_read_byte( &_dtmf_samples[_corr_index] );
_corr[i] += mul;
}

в результате генерится совершенно безобразный код.
умножение производится в 32-х битном виде, хотя явно написано умножение 2-х байтов
включена оптимизация O3

если массив объявить как int8_t, то умножение делается для 2-х байтов, но!!!!
используется mul вместо muls (хотя написано, что величины знаковые!!!)
и в результате он зануляет старший байт, даже если идет приведение результата операции к int16_t

как побороть WinAVR?

что хочется:
сделать знаковое умножение 2-х байтов, получить 16-ти битное значение.
затем расширить его до 32-х бит,
сложить с 32-х битной величиной из массива и запомнить в массиве результат.

и еще:
ткните, плиз, носом где понятно написано как делать ассемблерные вставки.
собственно, непонятно, как из асма взять данные из Сишной переменной и в нужную Сишную переменную отдать
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aesok
сообщение Aug 8 2008, 06:37
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(VDV @ Aug 7 2008, 21:01) *
int8_t d = ADCH;
for( uint8_t i = 16; i--; )
{
int16_t mul = d * pgm_read_byte( &_dtmf_samples[_corr_index] );
_corr[i] += mul;
}


Макрос pgm_read_byte возвращает значение типа uint8_t (unsigned char),
переменная d имеет int8_t то есть signed char. Не смотря на то что AVR
имеет команду MULSU, avr-gcc ее не использует и вместо умножения (s)8 * (u)8
= 16, выполняет умножение 16*16=16. 8-битные умножения signed на signed и
unsigned на unsigned выполняются как 8 * 8 = 16. Вы можете попробовать
изменить тип d на uint8_t и для умножения компилятор сгенерирует код с
использованием инструкции MUL:

Код
    mul r30,r16;  30    umulqihi3    [length = 3]
    movw r24,r0
    clr r1



Вот патч для GCC для выполнения умножения 8-битных signed на unsigned с
помощью MULSU.


Код
Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md    (revision 134646)
+++ gcc/config/avr/avr.md    (working copy)
@@ -906,6 +920,17 @@
   [(set_attr "length" "3")
    (set_attr "cc" "clobber")])

+(define_insn "usmulqihi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+    (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "a"))
+         (sign_extend:HI (match_operand:QI 2 "register_operand" "a"))))]
+  "AVR_HAVE_MUL"
+  "mulsu %2,%1
+    movw %0,r0
+    clr r1"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
(define_expand "mulhi3"
   [(set (match_operand:HI 0 "register_operand" "")
    (mult:HI (match_operand:HI 1 "register_operand" "")


Можно на написать aыm вставку для 8-битного умножения signed на unsigned.

Анатолий.

Сообщение отредактировал aesok - Aug 8 2008, 06:49
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 8 2008, 07:25
Сообщение #3


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(aesok @ Aug 8 2008, 10:37) *
Макрос pgm_read_byte возвращает значение типа uint8_t (unsigned char),
переменная d имеет int8_t то есть signed char. Не смотря на то что AVR
имеет команду MULSU, avr-gcc ее не использует и вместо умножения (s)8 * (u)8
= 16, выполняет умножение 16*16=16. 8-битные умножения signed на signed и
unsigned на unsigned выполняются как 8 * 8 = 16. Вы можете попробовать
изменить тип d на uint8_t и для умножения компилятор сгенерирует код с
использованием инструкции MUL:

Можно на написать asm вставку для 8-битного умножения signed на unsigned.

У него массив в PROGMEM int8_t !!!
Надо просто привести тип до умножения и будет счастье...

Код
(int8_t)pgm_read_byte(&_dtmf_samples[idx])

или написать макрос для чтения int8_t:
Код
#define pgm_read_sbyte(x)  ((int8_t)pgm_read_byte(x))


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
VDV
сообщение Aug 8 2008, 08:49
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 152
Регистрация: 18-03-06
Пользователь №: 15 366



спасибо за ответы,
я ошибся написав, что он делает 32 битное умножение, сорри, он делает 16-битное с 32-х битным результатом. при этом делает 3 умножения вместо 1!
явное приведение типов при умножении к знаковым не помогает - перепробовал все, что пришло в голову.

Os оптимизация работает плохо.
попробуйте, например, написать код:
uint16_t d = ...;
d >>= 1;
d >>= 1;
d >>= 1;

и посмотрите что он накомпиллит.
с O3 тоже не сахар, но все получше код получается.
//==================================
в общем, к сожалению, в итоге я так и не понял, как сделать так, чтобы
компиллятор сначала умножил два 8-ми битовых знаковых числа,
затем получившееся 16-ти битное значение сложил 32-х битным.
Использую WinAVR20080610 в паре с AVR studio 4.14

volatile int32_t _corr[2 * 8];//result of correlations
volatile uint8_t _corr_index;//index for sample table
int8_t PROGMEM _dtmf_samples[] = {...};

int8_t d = ADCH;
for( uint8_t i = 16; i--; )
{
int16_t mul = (int8_t)d * (int8_t)pgm_read_byte( &_dtmf_samples[_corr_index] );
_corr[i] += (int32_t)mul;
}

такой код не приводит к желаемому результату

Сообщение отредактировал VDV - Aug 8 2008, 09:08
Go to the top of the page
 
+Quote Post
ReAl
сообщение Aug 8 2008, 13:13
Сообщение #5


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(VDV @ Aug 8 2008, 11:49) *
Os оптимизация работает плохо.
попробуйте, например, написать код:
uint16_t d = ...;
d >>= 1;
d >>= 1;
d >>= 1;
и посмотрите что он накомпиллит.
с O3 тоже не сахар, но все получше код получается.
А что тут пробовать?
Для трёх сдвигов при -Os будет цикл, так как он действительно займёт меньше места, пусть и всего на одну команду.
Для -O3 будет линейный код. Для -O2 тоже.
Нет смысла для AVR использовать -O3, он слишком много разворачивает в линию, размножает тела циклов и т.п.
Разве что (я в это не очень верю, но не исключаю) для отдельных особых функций, вынесенных ради этого в отдельный файл.

Цитата(VDV @ Aug 8 2008, 11:49) *
Использую WinAVR20080610 в паре с AVR studio 4.14

volatile int32_t _corr[2 * 8];//result of correlations
volatile uint8_t _corr_index;//index for sample table
int8_t PROGMEM _dtmf_samples[] = {...};

int8_t d = ADCH;
for( uint8_t i = 16; i--; )
{
int16_t mul = (int8_t)d * (int8_t)pgm_read_byte( &_dtmf_samples[_corr_index] );
_corr[i] += (int32_t)mul;
}
такой код не приводит к желаемому результату

WinAVR-20071221
-Os
Код
    muls r30,r16
    movw r24,r0
    clr r1
    clr r26
    sbrc r25,7
    com r26
    mov r27,r26
    add r24,r20
    adc r25,r21
    adc r26,r22
    adc r27,r23
Я не стал цитировать чтение-запись массивов и организацию цикла, только умножение-суммирование.
Да, для -O2 и -O3 почему-то делает 16-битное умножение. "ну не знаю", таки недоработка оптимизатора в этих режимах. Согласен, плохо.
Повторю сказанное другими - в подавляющем большинстве случаев лучше использовать -Os.
Изредка -O2. Иногда лучше фрагмент на асме написать, чем от -Os отказываться.
-O3 явно не для AVR. Для Вашего примера разворачивать цикл на 16 проходов в одну линию, дублируя 16 раз тело цикла - нафиг, нафиг. Ускорение не стоит увеличения объёма.

Собственно, есть всего четыре варианта.
1. Использовать avr-gcc и терпеть некоторые его недостатки.
2. Использовать avr-gcc и НЕ терпеть некоторые его недостатки, включиться в работу по его улучшению.
3. Использовать спёртый IAR.
4. Использовать купленный IAR.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- VDV   как побороть WinAVR?   Aug 7 2008, 17:01
- - aesok   Цитата(VDV @ Aug 7 2008, 21:01) в результ...   Aug 7 2008, 19:36
- - demiurg_spb   Цитата(VDV @ Aug 7 2008, 21:01) что хочет...   Aug 7 2008, 20:20
- - 777777   Цитата(VDV @ Aug 7 2008, 21:01) ткните, п...   Aug 8 2008, 04:36
|- - AHTOXA   Цитата(777777 @ Aug 8 2008, 10:36) Ассемб...   Aug 8 2008, 05:59
|- - aesok   Цитата(VDV @ Aug 8 2008, 12:49) такой код...   Aug 8 2008, 13:04
- - VDV   мда.... ни с О3 ни с Os код нормально не генерит т...   Aug 8 2008, 13:39
|- - aesok   Цитата(VDV @ Aug 8 2008, 17:39) блин, а у...   Aug 8 2008, 14:04
|- - VDV   Цитата(aesok @ Aug 8 2008, 18:04) НЕВЕРЮ...   Aug 8 2008, 14:14
|- - aesok   Цитата(VDV @ Aug 8 2008, 18:14) А вот Э...   Aug 8 2008, 14:20
- - VDV   код приведен для пояснения смысла проблемы, а не о...   Aug 8 2008, 14:57
|- - AHTOXA   Цитата(VDV @ Aug 8 2008, 20:57) проигрышь...   Aug 8 2008, 16:02
- - _Pasha   Цитата(777777 @ Aug 8 2008, 08:36) Что не...   Aug 9 2008, 08:53


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 16:26
Рейтинг@Mail.ru


Страница сгенерированна за 0.01429 секунд с 7
ELECTRONIX ©2004-2016