|
как побороть WinAVR?, и заставить просто скомпиллить как написано |
|
|
|
Aug 7 2008, 17:01
|
Частый гость
 
Группа: Участник
Сообщений: 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-х битной величиной из массива и запомнить в массиве результат.
и еще: ткните, плиз, носом где понятно написано как делать ассемблерные вставки. собственно, непонятно, как из асма взять данные из Сишной переменной и в нужную Сишную переменную отдать
|
|
|
|
|
 |
Ответов
|
Aug 8 2008, 06:37
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Aug 8 2008, 07:25
|

неотягощённый злом
     
Группа: Свой
Сообщений: 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))
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Aug 8 2008, 08:49
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Aug 8 2008, 13:13
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 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.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
Сообщений в этой теме
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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|